@luminix/mui-cms 0.2.13 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -22
- package/bundle/mui-cms.bundle.iife.js +42 -36
- package/dist/mui-cms.js +2765 -2367
- package/docs/acoes.md +196 -0
- package/docs/componentes.md +147 -0
- package/docs/configuracao.md +117 -0
- package/docs/extensibilidade.md +216 -0
- package/docs/facades.md +183 -0
- package/docs/hooks.md +307 -0
- package/docs/index.md +25 -0
- package/docs/instalacao.md +95 -0
- package/docs/introducao.md +72 -0
- package/docs/tipos.md +238 -0
- package/package.json +15 -5
- package/tsconfig.json +1 -0
- package/tsconfig.test.json +16 -0
- package/vitest.config.ts +22 -0
- package/types/main.dev.d.ts +0 -0
package/docs/acoes.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Ações
|
|
2
|
+
|
|
3
|
+
O sistema de ações permite adicionar comportamentos às telas de listagem dos modelos. Existem três tipos:
|
|
4
|
+
|
|
5
|
+
| Tipo | Contexto | Exemplo de uso |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| **Estáticas** | Nível de listagem, sem item selecionado | "Criar novo post" |
|
|
8
|
+
| **De instância** | Por linha da tabela | "Editar", "Excluir" |
|
|
9
|
+
| **Em massa** | Múltiplos itens selecionados | "Excluir selecionados", "Restaurar" |
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## ActionCallbackEvent
|
|
14
|
+
|
|
15
|
+
Todo callback de ação recebe um objeto `ActionCallbackEvent` com utilitários prontos:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
type ActionCallbackEvent = {
|
|
19
|
+
navigate: (path: string) => void; // navega para uma rota interna
|
|
20
|
+
refresh: () => void; // recarrega a listagem atual
|
|
21
|
+
notify: NotifyFunction; // (notification: string | Notification) => void
|
|
22
|
+
dialog: DialogFunction; // (message: string | DialogMessage) => Promise<boolean | string>
|
|
23
|
+
t: TFunction; // função de tradução (i18next)
|
|
24
|
+
};
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Ações de instância recebem também `item: ModelType` (o registro da linha):
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
type InstanceActionCallbackEvent = ActionCallbackEvent & {
|
|
31
|
+
item: Model;
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Ações em massa recebem `selected: Collection<Model>` (todos os itens selecionados):
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
type MassActionCallbackEvent = ActionCallbackEvent & {
|
|
39
|
+
selected: Collection<Model>;
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Ações estáticas (StaticAction)
|
|
46
|
+
|
|
47
|
+
Aparecem na barra de ferramentas da listagem (ex.: botão "Criar").
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
type StaticAction = {
|
|
51
|
+
key?: string;
|
|
52
|
+
label: string;
|
|
53
|
+
icon?: React.ReactNode;
|
|
54
|
+
callback: (e: ActionCallbackEvent) => void;
|
|
55
|
+
};
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Padrão registrado:** "Create {Model}" — navega para a rota de criação quando a aba ativa não é "trashed".
|
|
59
|
+
|
|
60
|
+
### Adicionar uma ação estática global
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { Cms } from '@luminix/mui-cms';
|
|
64
|
+
|
|
65
|
+
Cms.reducer('staticActions', (actions, ModelClass, tab) => [
|
|
66
|
+
...actions,
|
|
67
|
+
{
|
|
68
|
+
key: 'export',
|
|
69
|
+
label: 'Exportar CSV',
|
|
70
|
+
callback: ({ notify }) => {
|
|
71
|
+
// lógica de exportação
|
|
72
|
+
notify('Exportação iniciada!', 'info');
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Adicionar ação apenas para um modelo específico
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
Cms.reducer('staticPostActions', (actions, ModelClass, tab) => [
|
|
82
|
+
...actions,
|
|
83
|
+
{
|
|
84
|
+
key: 'publish-all',
|
|
85
|
+
label: 'Publicar todos',
|
|
86
|
+
callback: async ({ refresh, notify }) => {
|
|
87
|
+
await fetch('/api/posts/publish-all', { method: 'POST' });
|
|
88
|
+
refresh();
|
|
89
|
+
notify('Posts publicados!', 'success');
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
]);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Ações de instância (InstanceAction)
|
|
98
|
+
|
|
99
|
+
Aparecem no menu de contexto de cada linha da tabela.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
type InstanceAction = {
|
|
103
|
+
key?: string;
|
|
104
|
+
label: string;
|
|
105
|
+
icon?: React.ReactNode;
|
|
106
|
+
callback: (e: InstanceActionCallbackEvent) => void;
|
|
107
|
+
};
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Padrão registrado:**
|
|
111
|
+
- "Send to trash" / "Delete permanently" — para modelos com/sem soft deletes.
|
|
112
|
+
- "Restore" + "Delete permanently" — quando a aba ativa é "trashed".
|
|
113
|
+
|
|
114
|
+
### Adicionar ação de instância
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import { Cms } from '@luminix/mui-cms';
|
|
118
|
+
|
|
119
|
+
Cms.reducer('instanceActions', (actions, ModelClass, tab) => [
|
|
120
|
+
...actions,
|
|
121
|
+
{
|
|
122
|
+
label: 'Ver detalhes',
|
|
123
|
+
callback: ({ item, navigate }) => {
|
|
124
|
+
navigate(`/posts/${item.getKey()}/detalhes`);
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
]);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Ações em massa (MassAction)
|
|
133
|
+
|
|
134
|
+
Aparecem quando um ou mais itens estão selecionados na tabela.
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
type MassAction = {
|
|
138
|
+
key: string; // obrigatório — identificador único
|
|
139
|
+
label: string;
|
|
140
|
+
callback: (e: MassActionCallbackEvent) => void;
|
|
141
|
+
};
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Padrão registrado:**
|
|
145
|
+
- "Send to trash" / "Delete permanently" — conforme soft deletes e aba ativa.
|
|
146
|
+
- "Restore" + "Delete permanently" — na aba "trashed".
|
|
147
|
+
|
|
148
|
+
### Adicionar ação em massa
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
import { Cms } from '@luminix/mui-cms';
|
|
152
|
+
import { Http } from '@luminix/core';
|
|
153
|
+
|
|
154
|
+
Cms.reducer('massActions', (actions, ModelClass, tab) => [
|
|
155
|
+
...actions,
|
|
156
|
+
{
|
|
157
|
+
key: 'archive',
|
|
158
|
+
label: 'Arquivar selecionados',
|
|
159
|
+
callback: async ({ selected, refresh, notify, dialog }) => {
|
|
160
|
+
const confirmed = await dialog({
|
|
161
|
+
title: 'Arquivar itens',
|
|
162
|
+
message: `Deseja arquivar ${selected.count()} itens?`,
|
|
163
|
+
type: 'confirm',
|
|
164
|
+
});
|
|
165
|
+
if (confirmed) {
|
|
166
|
+
const ids = selected.map(item => item.getKey()).toArray();
|
|
167
|
+
await Http.post('/api/posts/archive', { ids });
|
|
168
|
+
refresh();
|
|
169
|
+
notify('Itens arquivados!');
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
]);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Ações padrão (comportamento automático)
|
|
179
|
+
|
|
180
|
+
O `CmsServiceProvider` registra automaticamente as ações padrão com prioridade `0`. Suas ações customizadas podem ser adicionadas com prioridade maior (padrão `undefined`) para aparecerem antes ou depois das padrão.
|
|
181
|
+
|
|
182
|
+
Para remover uma ação padrão, filtre pelo `key`:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
Cms.reducer('staticActions', (actions) =>
|
|
186
|
+
actions.filter(a => a.key !== 'create')
|
|
187
|
+
);
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Próximos passos
|
|
193
|
+
|
|
194
|
+
- [Extensibilidade](extensibilidade.md) — redutores em profundidade e como encadear transformações
|
|
195
|
+
- [Hooks](hooks.md) — `useActionEvent` para montar o evento manualmente em componentes customizados
|
|
196
|
+
- [Volta ao índice](index.md)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Componentes
|
|
2
|
+
|
|
3
|
+
## LuminixCms
|
|
4
|
+
|
|
5
|
+
Componente raiz da aplicação. Deve ser renderizado uma única vez no ponto de entrada do projeto.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { LuminixCms } from '@luminix/mui-cms';
|
|
9
|
+
|
|
10
|
+
<LuminixCms
|
|
11
|
+
theme={themeOptions} // ThemeOptions (MUI) — opcional
|
|
12
|
+
themeArgs={[extraTheme]} // object[] — argumentos adicionais para createTheme
|
|
13
|
+
providers={[MyProvider]} // ServiceProvider[] — providers adicionais
|
|
14
|
+
/>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Internamente, o `LuminixCms`:
|
|
18
|
+
1. Cria o tema MUI com suporte automático a modo escuro.
|
|
19
|
+
2. Registra `CmsServiceProvider` e `i18NextServiceProvider`.
|
|
20
|
+
3. Delega a renderização ao `LuminixProvider` de `@luminix/react`, que inicializa o contêiner de aplicação e o roteador.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Link
|
|
25
|
+
|
|
26
|
+
Componente de navegação interna. Equivale ao `Link` do `react-router-dom`, mas integrado ao sistema de layout da biblioteca.
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { Link } from '@luminix/mui-cms';
|
|
30
|
+
|
|
31
|
+
<Link to="/posts">Ver posts</Link>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Providers de contexto
|
|
37
|
+
|
|
38
|
+
Os providers a seguir são usados internamente pelas views e componentes da biblioteca. Em cenários avançados, você pode usá-los para acessar os contextos em componentes customizados.
|
|
39
|
+
|
|
40
|
+
### DialogProvider
|
|
41
|
+
|
|
42
|
+
Fornece o contexto de diálogos modais. Necessário para que `useDialog` funcione.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { DialogProvider } from '@luminix/mui-cms';
|
|
46
|
+
|
|
47
|
+
<DialogProvider>
|
|
48
|
+
{/* seus componentes */}
|
|
49
|
+
</DialogProvider>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### NotificationProvider
|
|
53
|
+
|
|
54
|
+
Fornece o contexto de notificações toast. Necessário para `useNotify`.
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import { NotificationProvider } from '@luminix/mui-cms';
|
|
58
|
+
|
|
59
|
+
<NotificationProvider
|
|
60
|
+
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} // SnackbarProps
|
|
61
|
+
variant="filled" // 'filled' | 'outlined' | 'standard'
|
|
62
|
+
>
|
|
63
|
+
{/* seus componentes */}
|
|
64
|
+
</NotificationProvider>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### LayoutProvider
|
|
68
|
+
|
|
69
|
+
Gerencia o estado do layout (drawer aberto/fechado, breakpoint, título da página).
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { LayoutProvider } from '@luminix/mui-cms';
|
|
73
|
+
|
|
74
|
+
<LayoutProvider>
|
|
75
|
+
{/* seus componentes */}
|
|
76
|
+
</LayoutProvider>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### ModelProvider
|
|
80
|
+
|
|
81
|
+
Disponibiliza a classe de modelo atual para os componentes filhos (ex.: dentro de uma tela de listagem).
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { ModelProvider } from '@luminix/mui-cms';
|
|
85
|
+
|
|
86
|
+
<ModelProvider Model={PostModel}>
|
|
87
|
+
{/* seus componentes */}
|
|
88
|
+
</ModelProvider>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### TableProvider
|
|
92
|
+
|
|
93
|
+
Fornece o estado da tabela (seleção, ordenação, paginação) para os componentes de `ModelIndex`.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import { TableProvider } from '@luminix/mui-cms';
|
|
97
|
+
|
|
98
|
+
<TableProvider>
|
|
99
|
+
{/* seus componentes */}
|
|
100
|
+
</TableProvider>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Componentes internos (registrados via redutor)
|
|
106
|
+
|
|
107
|
+
O `CmsServiceProvider` registra um mapa de componentes acessível via `Cms.getComponent(name)`. Esses componentes podem ser substituídos por customizados usando o redutor `componentMap`.
|
|
108
|
+
|
|
109
|
+
| Chave | Componente padrão |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `Layout` | Layout raiz da aplicação |
|
|
112
|
+
| `Dashboard` | Tela inicial |
|
|
113
|
+
| `ModelIndex` | Tela de listagem de modelos |
|
|
114
|
+
| `ModelItem` | Tela de criação/edição |
|
|
115
|
+
| `Error` | Tela de erro |
|
|
116
|
+
| `Layout.AppBar` | Barra superior |
|
|
117
|
+
| `Layout.AppLogo` | Logo no drawer |
|
|
118
|
+
| `Layout.Drawer` | Menu lateral |
|
|
119
|
+
| `Layout.SearchBar` | Campo de busca |
|
|
120
|
+
| `Layout.BackButton` | Botão voltar |
|
|
121
|
+
| `ModelIndex.Filter` | Painel de filtros avançados |
|
|
122
|
+
| `ModelIndex.Table` | Tabela de dados |
|
|
123
|
+
| `ModelIndex.Pagination` | Paginação |
|
|
124
|
+
| `ModelIndex.MassActions` | Ações em massa |
|
|
125
|
+
| `ModelIndex.InstanceActions` | Ações por linha |
|
|
126
|
+
| `ModelIndex.StaticActions` | Ações globais (ex.: "Criar") |
|
|
127
|
+
| `ModelIndex.Tabs` | Abas de filtro (ex.: lixeira) |
|
|
128
|
+
|
|
129
|
+
Para substituir um componente:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { Cms } from '@luminix/mui-cms';
|
|
133
|
+
import MeuDashboard from './MeuDashboard';
|
|
134
|
+
|
|
135
|
+
Cms.reducer('componentMap', (map) => ({
|
|
136
|
+
...map,
|
|
137
|
+
Dashboard: MeuDashboard,
|
|
138
|
+
}));
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Próximos passos
|
|
144
|
+
|
|
145
|
+
- [Facades](facades.md) — como usar `Cms`, `Filter` e `Icon`
|
|
146
|
+
- [Hooks](hooks.md) — hooks disponíveis para uso em componentes customizados
|
|
147
|
+
- [Volta ao índice](index.md)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Configuração
|
|
2
|
+
|
|
3
|
+
## Tema MUI
|
|
4
|
+
|
|
5
|
+
O `LuminixCms` aceita uma prop `theme` do tipo `ThemeOptions` (Material-UI). O tema padrão é:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
{
|
|
9
|
+
palette: {
|
|
10
|
+
primary: { main: '#1d9798' },
|
|
11
|
+
secondary: { main: '#fa510c' },
|
|
12
|
+
},
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Para sobrescrever, passe seu próprio objeto:
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
<LuminixCms
|
|
20
|
+
theme={{
|
|
21
|
+
palette: {
|
|
22
|
+
primary: { main: '#3f51b5' },
|
|
23
|
+
secondary: { main: '#f50057' },
|
|
24
|
+
},
|
|
25
|
+
typography: {
|
|
26
|
+
fontFamily: 'Inter, sans-serif',
|
|
27
|
+
},
|
|
28
|
+
}}
|
|
29
|
+
/>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
O modo escuro (`dark`) é ativado automaticamente quando o sistema operacional do usuário preferir `prefers-color-scheme: dark`.
|
|
33
|
+
|
|
34
|
+
### themeArgs
|
|
35
|
+
|
|
36
|
+
Para argumentos adicionais do `createTheme` (ex.: variáveis de componentes):
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
<LuminixCms
|
|
40
|
+
theme={{ palette: { primary: { main: '#1d9798' } } }}
|
|
41
|
+
themeArgs={[{ components: { MuiButton: { defaultProps: { disableElevation: true } } } }]}
|
|
42
|
+
/>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Layout
|
|
48
|
+
|
|
49
|
+
O layout é configurado via chave `luminix.admin.layout` na configuração da aplicação (injetada pelo `luminix/frontend`). As opções disponíveis são definidas pelo tipo `CmsConfig`:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
type CmsConfig = {
|
|
53
|
+
layout?: {
|
|
54
|
+
breakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'; // padrão: 'md'
|
|
55
|
+
drawer?: {
|
|
56
|
+
width?: number; // largura do Drawer em px
|
|
57
|
+
};
|
|
58
|
+
appBar?: {
|
|
59
|
+
height?: number; // altura da AppBar em px
|
|
60
|
+
color?: string; // cor de fundo da AppBar
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
No Laravel, publique e edite o arquivo de configuração do `luminix/admin` para definir esses valores.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## URL base do painel
|
|
71
|
+
|
|
72
|
+
Por padrão, o painel é montado em `/admin`. Para alterar, configure `luminix.admin.url` no backend:
|
|
73
|
+
|
|
74
|
+
```php
|
|
75
|
+
// config/luminix.php
|
|
76
|
+
'admin' => [
|
|
77
|
+
'url' => '/painel',
|
|
78
|
+
],
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
O `CmsServiceProvider` lê esse valor e configura o `basename` do `react-router-dom` automaticamente.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Operadores de filtro disponíveis
|
|
86
|
+
|
|
87
|
+
Os operadores usados nos filtros da tabela também são configuráveis via `luminix.admin.filter.operators`. O conjunto padrão inclui:
|
|
88
|
+
|
|
89
|
+
`equals`, `notEquals`, `contains`, `startsWith`, `endsWith`, `greaterThan`, `greaterThanOrEquals`, `lessThan`, `lessThanOrEquals`, `between`, `notBetween`, `null`, `notNull`, `relation`
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Providers customizados
|
|
94
|
+
|
|
95
|
+
Para registrar providers adicionais na inicialização da aplicação, use a prop `providers` do `LuminixCms`:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import { LuminixCms } from '@luminix/mui-cms';
|
|
99
|
+
import { ServiceProvider } from '@luminix/support';
|
|
100
|
+
|
|
101
|
+
class MyProvider extends ServiceProvider {
|
|
102
|
+
register() { /* ... */ }
|
|
103
|
+
boot() { /* ... */ }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
<LuminixCms providers={[MyProvider]} />
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Os providers `CmsServiceProvider` e `i18NextServiceProvider` são sempre incluídos automaticamente.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Próximos passos
|
|
114
|
+
|
|
115
|
+
- [Componentes](componentes.md) — `LuminixCms`, `Link` e providers de contexto
|
|
116
|
+
- [Extensibilidade](extensibilidade.md) — customizações via redutores
|
|
117
|
+
- [Volta ao índice](index.md)
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Extensibilidade
|
|
2
|
+
|
|
3
|
+
O `@luminix/mui-cms` foi projetado para ser profundamente customizável sem exigir fork ou modificação do código-fonte. O mecanismo central é o padrão **Reducible** de `@luminix/support`.
|
|
4
|
+
|
|
5
|
+
## O padrão Reducible
|
|
6
|
+
|
|
7
|
+
Um serviço `Reducible` expõe "pontos de extensão" chamados **redutores**. Cada redutor é uma cadeia de funções que transforma um valor. O resultado final é a composição de todas as funções registradas, aplicadas em ordem de prioridade.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// assinatura geral
|
|
11
|
+
ServiceFacade.reducer(
|
|
12
|
+
'nomeDoReducer', // string — nome do ponto de extensão
|
|
13
|
+
(valorAtual, ...args) => novoValor, // função transformadora
|
|
14
|
+
prioridade // number — menor número roda primeiro (padrão: 10)
|
|
15
|
+
);
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Os redutores internos do `CmsServiceProvider` usam prioridade `0`. Registre os seus com prioridade maior para rodar depois (comportamento aditivo) ou menor para rodar antes (comportamento de pré-processamento).
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Onde registrar redutores
|
|
23
|
+
|
|
24
|
+
Os redutores devem ser registrados **antes** da aplicação inicializar. O lugar ideal é dentro de um `ServiceProvider` customizado:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// src/providers/AppServiceProvider.ts
|
|
28
|
+
import { ServiceProvider } from '@luminix/support';
|
|
29
|
+
import { Cms, Icon, Filter } from '@luminix/mui-cms';
|
|
30
|
+
import { Star } from '@mui/icons-material';
|
|
31
|
+
|
|
32
|
+
class AppServiceProvider extends ServiceProvider {
|
|
33
|
+
register() {
|
|
34
|
+
// registre ícones aqui
|
|
35
|
+
Icon.registerIcon('Star', Star);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
boot() {
|
|
39
|
+
// registre redutores aqui
|
|
40
|
+
Cms.reducer('menuItems', (items) => [
|
|
41
|
+
...items,
|
|
42
|
+
{
|
|
43
|
+
key: 'relatorios',
|
|
44
|
+
text: 'Relatórios',
|
|
45
|
+
to: '/relatorios',
|
|
46
|
+
icon: Icon.render('Star'),
|
|
47
|
+
},
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default AppServiceProvider;
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
E passe o provider para o `LuminixCms`:
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { LuminixCms } from '@luminix/mui-cms';
|
|
59
|
+
import AppServiceProvider from './providers/AppServiceProvider';
|
|
60
|
+
|
|
61
|
+
<LuminixCms providers={[AppServiceProvider]} />
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Redutores do CmsService
|
|
67
|
+
|
|
68
|
+
### componentMap
|
|
69
|
+
|
|
70
|
+
Substitui componentes internos do painel:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import MeuLayout from './components/MeuLayout';
|
|
74
|
+
|
|
75
|
+
Cms.reducer('componentMap', (map) => ({
|
|
76
|
+
...map,
|
|
77
|
+
Layout: MeuLayout,
|
|
78
|
+
}));
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### menuItems
|
|
82
|
+
|
|
83
|
+
Personaliza o menu lateral:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
Cms.reducer('menuItems', (items, models) => {
|
|
87
|
+
// remove modelos do menu
|
|
88
|
+
return items.filter(item => item.key !== 'user');
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### cmsRoutes
|
|
93
|
+
|
|
94
|
+
Adiciona rotas customizadas ao painel. A estrutura de rotas é um array com **um único elemento raiz** que envolve o `Layout` e os providers. Todas as páginas são filhas desse elemento raiz via `children`. Para que o layout (AppBar, Drawer, Notification, Dialog) seja aplicado na nova página, a rota deve ser adicionada em `routes[0].children`:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import Relatorios from './views/Relatorios';
|
|
98
|
+
|
|
99
|
+
Cms.reducer('cmsRoutes', (routes, components) => {
|
|
100
|
+
const [root, ...rest] = routes;
|
|
101
|
+
return [
|
|
102
|
+
{
|
|
103
|
+
...root,
|
|
104
|
+
children: [
|
|
105
|
+
...(root.children ?? []),
|
|
106
|
+
{
|
|
107
|
+
path: '/relatorios',
|
|
108
|
+
element: <Relatorios />,
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
...rest,
|
|
113
|
+
];
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
> Adicionar a rota fora de `routes[0].children` (ex.: `[...routes, { path: '...' }]`) faz a página renderizar sem o Layout do painel.
|
|
118
|
+
|
|
119
|
+
### wireModelFormProps
|
|
120
|
+
|
|
121
|
+
Personaliza o formulário de modelo:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { Cms } from '@luminix/mui-cms';
|
|
125
|
+
|
|
126
|
+
Cms.reducer('wireModelFormProps', (props, item) => {
|
|
127
|
+
if (item?.getType() === 'post') {
|
|
128
|
+
return {
|
|
129
|
+
...props,
|
|
130
|
+
// adicione campos confirmados, campos ocultos, etc.
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return props;
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### model{Name}Columns
|
|
138
|
+
|
|
139
|
+
Define as colunas da tabela para um modelo específico:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
Cms.reducer('modelPostColumns', () => [
|
|
143
|
+
{ key: 'title', label: 'Título', scope: 'row', component: 'th' },
|
|
144
|
+
{ key: 'author', label: 'Autor', align: 'right' },
|
|
145
|
+
{ key: 'created_at', label: 'Criado em', align: 'right', size: 'small' },
|
|
146
|
+
]);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
> A convenção de nome é `model` + nome do modelo em StudlyCase + `Columns`.
|
|
150
|
+
> Ex.: `modelBlogPostColumns` para o modelo `blog_post`.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Redutores do FilterService
|
|
155
|
+
|
|
156
|
+
### filterableColumns
|
|
157
|
+
|
|
158
|
+
Adiciona ou remove colunas do painel de filtros:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import { Filter } from '@luminix/mui-cms';
|
|
162
|
+
|
|
163
|
+
Filter.reducer('filterableColumns', (columns, ModelClass) => {
|
|
164
|
+
if (ModelClass.getSchemaName() === 'post') {
|
|
165
|
+
return [
|
|
166
|
+
...columns,
|
|
167
|
+
{
|
|
168
|
+
key: 'category_id',
|
|
169
|
+
label: 'Categoria',
|
|
170
|
+
type: 'autocomplete',
|
|
171
|
+
nullable: true,
|
|
172
|
+
is_relation: true,
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
return columns;
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Redutores do Model (@luminix/core)
|
|
183
|
+
|
|
184
|
+
O `@luminix/core` expõe o redutor `model` (e `model{Name}`) para customizar a classe de modelo:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import { Model } from '@luminix/core';
|
|
188
|
+
|
|
189
|
+
Model.reducer('modelPost', (Base) => {
|
|
190
|
+
return class extends Base {
|
|
191
|
+
static plural() { return 'Posts do Blog'; }
|
|
192
|
+
static icon() { return Icon.render('Article'); }
|
|
193
|
+
};
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Consulte a documentação do `@luminix/core` para a lista completa de redutores de modelo.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Prioridades
|
|
202
|
+
|
|
203
|
+
| Prioridade | Quando usar |
|
|
204
|
+
|---|---|
|
|
205
|
+
| `0` | Valores padrão da biblioteca (já usados internamente) |
|
|
206
|
+
| `1`–`9` | Extensões do pacote `luminix/admin` ou integrações |
|
|
207
|
+
| `10` (padrão) | Customizações da aplicação |
|
|
208
|
+
| `> 10` | Overrides que precisam sobrescrever customizações anteriores |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Próximos passos
|
|
213
|
+
|
|
214
|
+
- [Ações](acoes.md) — exemplos práticos de redutores de ações
|
|
215
|
+
- [Facades](facades.md) — referência completa dos redutores disponíveis por serviço
|
|
216
|
+
- [Volta ao índice](index.md)
|