# @shield-acl/react

<div align="center">
  <img src="https://raw.githubusercontent.com/andersondrosa/andersondrosa/refs/heads/main/images/shield-acl.png" alt="Shield ACL React" width="400" />
</div>

<div align="center">
  <p><strong>Componentes e hooks React para integração com Shield ACL</strong></p>
  <p>API declarativa e hooks modernos para controle de permissões em aplicações React.</p>
</div>

## Características

- 🎨 **Componentes Declarativos**: Can, Cannot, CanAny, CanAll para renderização condicional
- 🪝 **Hooks Modernos**: useCan, usePermissions, useACL e muitos outros
- ⚡ **Performance Otimizada**: Memoização inteligente e re-renders mínimos
- 🎯 **TypeScript First**: Totalmente tipado com IntelliSense completo
- 🔄 **React 19 Ready**: Compatível com React 16.8+ até React 19
- 🧩 **Extensível**: Sistema de componentes e hooks customizáveis

## Instalação

```bash
npm install @shield-acl/react @shield-acl/core
# ou
yarn add @shield-acl/react @shield-acl/core
# ou
pnpm add @shield-acl/react @shield-acl/core
```

## Uso Rápido

### 1. Setup do Provider

```tsx
import { ACL } from '@shield-acl/core'
import { ACLProvider } from '@shield-acl/react'

// Criar instância do ACL
const acl = new ACL()

// Definir roles
acl.defineRole({
  name: 'admin',
  permissions: [{ action: '*', resource: '*' }]
})

acl.defineRole({
  name: 'user',
  permissions: [
    { action: 'read', resource: 'posts' },
    { action: 'create', resource: 'posts' }
  ]
})

// Wrap sua aplicação
function App() {
  const [user] = useState({
    id: 1,
    roles: ['user']
  })

  return (
    <ACLProvider acl={acl} user={user}>
      <YourApp />
    </ACLProvider>
  )
}
```

### 2. Componentes de Renderização Condicional

```tsx
import { Can, Cannot, CanAny, CanAll } from '@shield-acl/react'

function PostList() {
  return (
    <div>
      {/* Renderiza apenas se pode ler posts */}
      <Can action="read" resource="posts">
        <PostGrid />
      </Can>

      {/* Renderiza se NÃO pode deletar */}
      <Cannot action="delete" resource="posts">
        <p>Você não tem permissão para deletar posts</p>
      </Cannot>

      {/* Renderiza se tem QUALQUER uma das permissões */}
      <CanAny permissions={[
        { action: 'create', resource: 'posts' },
        { action: 'edit', resource: 'posts' }
      ]}>
        <EditButton />
      </CanAny>

      {/* Renderiza se tem TODAS as permissões */}
      <CanAll permissions={[
        { action: 'read', resource: 'users' },
        { action: 'manage', resource: 'roles' }
      ]}>
        <AdminPanel />
      </CanAll>
    </div>
  )
}
```

### 3. Hooks

```tsx
import { useCan, usePermissions, useACL } from '@shield-acl/react'

function PostEditor({ post }) {
  // Hook básico
  const canEdit = useCan('edit', 'posts', {
    resource: { authorId: post.authorId }
  })

  // Múltiplas permissões
  const permissions = usePermissions()
  const canModerate = permissions.some(p => 
    p.action === 'moderate' && p.resource === 'posts'
  )

  // Acesso direto ao ACL
  const { engine, user } = useACL()

  if (!canEdit) {
    return <p>Sem permissão para editar</p>
  }

  return <Editor post={post} />
}
```

## API Completa

### Componentes

#### `<Can>`
Renderiza children apenas se o usuário tem a permissão.

```tsx
<Can 
  action="edit" 
  resource="posts" 
  context={{ authorId: userId }}
  fallback={<NoPermission />}
>
  <EditForm />
</Can>
```

#### `<Cannot>`
Renderiza children apenas se o usuário NÃO tem a permissão.

```tsx
<Cannot action="delete" resource="posts">
  <p>Você não pode deletar posts</p>
</Cannot>
```

#### `<CanAny>`
Renderiza se o usuário tem QUALQUER uma das permissões.

```tsx
<CanAny permissions={[
  { action: 'create', resource: 'posts' },
  { action: 'edit', resource: 'posts' }
]}>
  <ActionButton />
</CanAny>
```

#### `<CanAll>`
Renderiza se o usuário tem TODAS as permissões.

```tsx
<CanAll permissions={[
  { action: 'read', resource: 'analytics' },
  { action: 'export', resource: 'reports' }
]}>
  <ExportButton />
</CanAll>
```

### Hooks Principais

#### `useCan(action, resource?, context?)`
Verifica uma permissão específica.

```tsx
const canDelete = useCan('delete', 'posts')
const canEdit = useCan('edit', 'posts', { resource: post })
```

#### `usePermissions()`
Retorna todas as permissões do usuário atual.

```tsx
const permissions = usePermissions()
const isAdmin = permissions.some(p => p.action === '*')
```

#### `useACL()`
Acesso direto ao engine ACL e usuário.

```tsx
const { engine, user, setUser } = useACL()
```

#### `useEvaluate(action, resource?, context?)`
Retorna resultado detalhado da avaliação.

```tsx
const result = useEvaluate('publish', 'posts')
// { allowed: true, reason: 'Matched role permission', matchedRule: {...} }
```

### Hooks Avançados

#### `useCanMultiple(permissions)`
Verifica múltiplas permissões de uma vez.

```tsx
const results = useCanMultiple([
  { action: 'read', resource: 'posts' },
  { action: 'create', resource: 'comments' }
])
// { 'read:posts': true, 'create:comments': false }
```

#### `useCanAny(permissions)`
Verifica se tem QUALQUER uma das permissões.

```tsx
const canEditContent = useCanAny([
  { action: 'edit', resource: 'posts' },
  { action: 'edit', resource: 'pages' }
])
```

#### `useCanAll(permissions)`
Verifica se tem TODAS as permissões.

```tsx
const isFullAdmin = useCanAll([
  { action: 'manage', resource: 'users' },
  { action: 'manage', resource: 'roles' }
])
```

#### `useRoleHierarchy()`
Obtém a hierarquia completa de roles do usuário.

```tsx
const hierarchy = useRoleHierarchy()
// ['user', 'moderator', 'admin']
```

#### `usePermissionChange(callback, dependencies)`
Monitora mudanças nas permissões.

```tsx
usePermissionChange(() => {
  console.log('Permissões mudaram!')
}, ['posts'])
```

## Componentes Utilitários

### HOC withCan

```tsx
const ProtectedButton = withCan(Button, {
  action: 'delete',
  resource: 'posts',
  fallback: <DisabledButton />
})
```

### PermissionClass

```tsx
<PermissionClass
  action="publish"
  resource="posts"
  className="can-publish"
  deniedClassName="cannot-publish"
>
  <article className="post">...</article>
</PermissionClass>
```

## Performance

### Memoização Automática

Todos os hooks são otimizados com memoização:

```tsx
// Só re-renderiza se o resultado mudar
const canEdit = useCan('edit', 'posts')

// Context é memoizado profundamente
const canDelete = useCan('delete', 'posts', {
  resource: { id: post.id, authorId: post.authorId }
})
```

### Batch Updates

Mudanças no usuário ou permissões são batched:

```tsx
// Uma única re-renderização
setUser({
  ...user,
  roles: ['admin'],
  permissions: [...]
})
```

## Testes

```bash
# Rodar testes
pnpm test

# Coverage
pnpm test:coverage

# Watch mode
pnpm test:watch
```

## Documentação Adicional

- [Documentação Completa dos Hooks](./docs/REACT-HOOKS.md) - Guia detalhado de todos os hooks disponíveis
- [Roadmap de Implementação](./TODO-REACT-HOOKS.md) - Status de desenvolvimento dos hooks

## Compatibilidade

- React 16.8+ (precisa de hooks)
- React 17.x
- React 18.x
- React 19.x (totalmente compatível)
- TypeScript 4.5+

## Licença

MIT © Anderson D. Rosa