@arqel-dev/ui 0.8.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/LICENSE +21 -0
- package/README.md +62 -0
- package/SKILL.md +116 -0
- package/dist/FormRenderer-BJBRIkfH.d.ts +70 -0
- package/dist/TableToolbar-POLdlSgC.d.ts +54 -0
- package/dist/WidgetWrapper-DUQy381N.d.ts +54 -0
- package/dist/action.d.ts +73 -0
- package/dist/action.js +1092 -0
- package/dist/action.js.map +1 -0
- package/dist/auth.d.ts +12 -0
- package/dist/auth.js +12 -0
- package/dist/auth.js.map +1 -0
- package/dist/flash.d.ts +37 -0
- package/dist/flash.js +106 -0
- package/dist/flash.js.map +1 -0
- package/dist/form.d.ts +61 -0
- package/dist/form.js +675 -0
- package/dist/form.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +3708 -0
- package/dist/index.js.map +1 -0
- package/dist/pages.d.ts +73 -0
- package/dist/pages.js +1648 -0
- package/dist/pages.js.map +1 -0
- package/dist/palette.d.ts +28 -0
- package/dist/palette.js +285 -0
- package/dist/palette.js.map +1 -0
- package/dist/primitives.d.ts +76 -0
- package/dist/primitives.js +660 -0
- package/dist/primitives.js.map +1 -0
- package/dist/resource.d.ts +27 -0
- package/dist/resource.js +722 -0
- package/dist/resource.js.map +1 -0
- package/dist/shell.d.ts +50 -0
- package/dist/shell.js +1048 -0
- package/dist/shell.js.map +1 -0
- package/dist/table.d.ts +13 -0
- package/dist/table.js +620 -0
- package/dist/table.js.map +1 -0
- package/dist/utility.d.ts +62 -0
- package/dist/utility.js +106 -0
- package/dist/utility.js.map +1 -0
- package/dist/utils.d.ts +12 -0
- package/dist/utils.js +11 -0
- package/dist/utils.js.map +1 -0
- package/dist/widgets.d.ts +163 -0
- package/dist/widgets.js +677 -0
- package/dist/widgets.js.map +1 -0
- package/package.json +145 -0
- package/src/styles/globals.css +137 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arqel Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# @arqel-dev/ui
|
|
2
|
+
|
|
3
|
+
[](../../LICENSE)
|
|
4
|
+
[](https://react.dev)
|
|
5
|
+
[](#)
|
|
6
|
+
|
|
7
|
+
Structural React components for [Arqel](https://arqel.dev) admin panels.
|
|
8
|
+
|
|
9
|
+
## Status
|
|
10
|
+
|
|
11
|
+
🚧 **Pre-alpha** — UI-001..006 entregues (shell, table, form, action, flash, utility).
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add @arqel-dev/ui @arqel-dev/react @arqel-dev/hooks @arqel-dev/types
|
|
17
|
+
pnpm add @inertiajs/react react react-dom @base-ui-components/react @tanstack/react-table lucide-react
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import '@arqel-dev/ui/styles.css';
|
|
24
|
+
import {
|
|
25
|
+
AppShell, Sidebar, Topbar, MainContent,
|
|
26
|
+
ResourceIndex, FormRenderer, ActionButton, FlashContainer,
|
|
27
|
+
} from '@arqel-dev/ui';
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## What's inside
|
|
31
|
+
|
|
32
|
+
| Subpath | Components |
|
|
33
|
+
|-------------------|--------------------------------------------------------------------------------|
|
|
34
|
+
| `@arqel-dev/ui/shell` | `AppShell`, `Sidebar`, `Topbar`, `MainContent`, `Footer` |
|
|
35
|
+
| `@arqel-dev/ui/table` | `DataTable`, `TableCell`, `TableFilters`, `TablePagination`, `TableToolbar` |
|
|
36
|
+
| `@arqel-dev/ui/resource` | `ResourceIndex` |
|
|
37
|
+
| `@arqel-dev/ui/form` | `FormRenderer`, `FieldRenderer`, `FormSection`, `FormFieldset`, `FormGrid`, `FormTabs`, `FormActions`, `registerField` |
|
|
38
|
+
| `@arqel-dev/ui/action` | `Button`, `ActionButton`, `ActionMenu`, `ConfirmDialog`, `ActionFormModal` |
|
|
39
|
+
| `@arqel-dev/ui/auth` | `CanAccess` |
|
|
40
|
+
| `@arqel-dev/ui/flash` | `FlashContainer`, `FlashToast` |
|
|
41
|
+
| `@arqel-dev/ui/utility` | `Breadcrumbs`, `PageHeader`, `EmptyState`, `ErrorState`, `LoadingSkeleton` |
|
|
42
|
+
| `@arqel-dev/ui/utils` | `cn` |
|
|
43
|
+
|
|
44
|
+
## Design tokens
|
|
45
|
+
|
|
46
|
+
Tokens são CSS vars em `oklch`, honram light/dark via `.dark` class flip aplicada pelo `<ThemeProvider>`:
|
|
47
|
+
|
|
48
|
+
```css
|
|
49
|
+
--color-arqel-bg / -fg
|
|
50
|
+
--color-arqel-primary / -fg
|
|
51
|
+
--color-arqel-secondary / -fg
|
|
52
|
+
--color-arqel-destructive / -fg
|
|
53
|
+
--color-arqel-success / -warning
|
|
54
|
+
--color-arqel-muted / -fg
|
|
55
|
+
--color-arqel-border / -input / -ring
|
|
56
|
+
--radius-arqel / -sm / -lg
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Links
|
|
60
|
+
|
|
61
|
+
- [Documentação](https://arqel.dev/docs/ui) — em construção
|
|
62
|
+
- [PLANNING](../../PLANNING/08-fase-1-mvp.md) — tickets `UI-*`
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# SKILL.md — @arqel-dev/ui
|
|
2
|
+
|
|
3
|
+
> Contexto canónico para AI agents.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
`@arqel-dev/ui` é a "casca" estrutural do admin panel Arqel: shell (AppShell + Sidebar + Topbar), página de listagem (ResourceIndex + DataTable), formulário polimórfico (FormRenderer + FieldRenderer), botões e modais de Action, flash toasts, blocos de auth e utilitários (Breadcrumbs, PageHeader, EmptyState, ErrorState, LoadingSkeleton).
|
|
8
|
+
|
|
9
|
+
A partir da migração para shadcn, o pacote é construído sobre **shadcn (style `new-york`) + Radix UI**, integrado via `shadcn@4.6` CLI. Todas as primitivas oficiais vivem em `src/shadcn/` (gerado pela CLI; **read-only**) e são re-exportadas via `src/primitives/index.ts` + barrel top-level `src/index.ts`. Componentes custom (shell, table, form renderer, etc.) consomem essas primitivas; estado vive nos hooks/Inertia.
|
|
10
|
+
|
|
11
|
+
## Status
|
|
12
|
+
|
|
13
|
+
**Stack base:**
|
|
14
|
+
|
|
15
|
+
- shadcn CLI v4.6, registry default `new-york`
|
|
16
|
+
- Radix UI (`radix-ui`) — substitui Base UI (`@base-ui-components/react`) em Dialog, DropdownMenu, Sheet, Tooltip, Select, Checkbox, Separator, Label
|
|
17
|
+
- `class-variance-authority` (cva) + `tailwind-merge` + `clsx` (via `cn()`)
|
|
18
|
+
- Tailwind v4 (`@import 'tailwindcss';`) + `tw-animate-css`
|
|
19
|
+
- `globals.css` agora usa **shadcn CSS vars** (`--background`, `--foreground`, `--primary`, `--secondary`, `--muted`, `--accent`, `--destructive`, `--border`, `--input`, `--ring`, `--card`, `--popover`, `--sidebar*`, `--radius`, `--chart-*`) com `@theme inline` bridge para mapear vars → tokens Tailwind. `.dark` override aplicado por `<ThemeProvider>` de `@arqel-dev/react`.
|
|
20
|
+
|
|
21
|
+
**Primitivas re-exportadas** (de `@arqel-dev/ui`):
|
|
22
|
+
|
|
23
|
+
- `Button` (cva) — variants `default | destructive | outline | secondary | ghost | link`; sizes `default | xs | sm | lg | icon | icon-xs | icon-sm | icon-lg`
|
|
24
|
+
- `Input`, `Textarea`, `Label`, `Checkbox`, `Separator`, `Skeleton`
|
|
25
|
+
- `Card` + `CardHeader`, `CardTitle`, `CardDescription`, `CardContent`, `CardFooter`, `CardAction`
|
|
26
|
+
- `Alert` + `AlertTitle`, `AlertDescription`
|
|
27
|
+
- `Badge` (cva) — variants `default | secondary | destructive | outline` (success/warning foram removidas)
|
|
28
|
+
- `Select` + `SelectTrigger`, `SelectContent`, `SelectItem`, `SelectValue`, `SelectGroup`, `SelectLabel`, `SelectSeparator`
|
|
29
|
+
- `Field` + `FieldGroup`, `FieldLabel`, `FieldError`, `FieldDescription`, `FieldSeparator`
|
|
30
|
+
- `Dialog`, `DropdownMenu`, `Sheet`, `Tooltip` (Radix-based)
|
|
31
|
+
|
|
32
|
+
**Blocks shadcn integrados:**
|
|
33
|
+
|
|
34
|
+
- `sidebar-07` — base do `<Sidebar>` / `<AppShell>` (com `<SidebarProvider>`, `<SidebarTrigger>`, `<SidebarInset>`, colapsável para ícone, persistência via cookie)
|
|
35
|
+
- `login-04` — split-screen card + hero illustration; usado por `LoginPage` em `@arqel-dev/auth`
|
|
36
|
+
- `signup-04` — análogo para `RegisterPage`
|
|
37
|
+
|
|
38
|
+
**Custom components (sobre as primitivas):**
|
|
39
|
+
|
|
40
|
+
- `<AppShell variant>`: 4 variants (`sidebar-left | sidebar-right | topbar-only | full-width`) com `SidebarProvider` interno
|
|
41
|
+
- `<Sidebar>` (block `sidebar-07` + collapsible icon + items via `useNavigation()` ou prop `items`, groups, badges, `aria-current="page"`)
|
|
42
|
+
- `<Topbar>`: brand + theme toggle + `SidebarTrigger` mobile + slots search/userMenu/tenantSwitcher
|
|
43
|
+
- `<MainContent>` (`SidebarInset` wrapper) com padding responsivo + `maxWidth` (`md..7xl | none`)
|
|
44
|
+
- `<DataTable>` (TanStack Table v8) — 9 cell renderers, seleção controlada, sticky header, `aria-sort`
|
|
45
|
+
- `<TableFilters>` / `<TablePagination>` / `<TableToolbar>` / `<ResourceIndex>`
|
|
46
|
+
- `<FormRenderer>` + `<FieldRenderer>` + `FieldRegistry` + `<FormSection>` / `<FormFieldset>` / `<FormGrid>` / `<FormTabs>` / `<FormActions>`
|
|
47
|
+
- `<ActionButton>` / `<ActionMenu>` (Radix DropdownMenu) / `<ConfirmDialog>` (Radix Dialog) / `<ActionFormModal>` (Radix Dialog hospedando `<FormRenderer>`)
|
|
48
|
+
- `<FlashContainer>` + `<FlashToast>` (4 posições, `role=alert/status`)
|
|
49
|
+
- `<Breadcrumbs>`, `<PageHeader>`, `<EmptyState>`, `<ErrorState>`, `<LoadingSkeleton>`
|
|
50
|
+
- `<CanAccess>` wrapper sobre `useCanAccess`
|
|
51
|
+
|
|
52
|
+
## Key Contracts
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import '@arqel-dev/ui/styles.css';
|
|
56
|
+
import {
|
|
57
|
+
AppShell, Sidebar, Topbar, MainContent, FlashContainer,
|
|
58
|
+
ResourceIndex, FormRenderer, ActionButton, CanAccess,
|
|
59
|
+
Breadcrumbs, PageHeader,
|
|
60
|
+
Button, Card, CardHeader, CardContent, Field, FieldLabel, Input,
|
|
61
|
+
} from '@arqel-dev/ui';
|
|
62
|
+
|
|
63
|
+
export default function UsersIndex(props: ResourceIndexProps<User>) {
|
|
64
|
+
return (
|
|
65
|
+
<AppShell sidebar={<Sidebar />} topbar={<Topbar />}>
|
|
66
|
+
<MainContent breadcrumbs={<Breadcrumbs />}>
|
|
67
|
+
<ResourceIndex
|
|
68
|
+
{...props}
|
|
69
|
+
rowActions={(record) => (
|
|
70
|
+
<ActionButton
|
|
71
|
+
action={editAction}
|
|
72
|
+
onInvoke={() => router.visit(`/admin/users/${record.id}/edit`)}
|
|
73
|
+
/>
|
|
74
|
+
)}
|
|
75
|
+
/>
|
|
76
|
+
</MainContent>
|
|
77
|
+
<FlashContainer />
|
|
78
|
+
</AppShell>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Conventions
|
|
84
|
+
|
|
85
|
+
- **Subpath imports** preferidos para tree-shaking (`@arqel-dev/ui/shell`, `/table`, `/form`, `/action`, `/auth`, `/flash`, `/utility`, `/utils`, `/primitives`)
|
|
86
|
+
- CSS exposto como `@arqel-dev/ui/styles.css` — apps importam uma vez
|
|
87
|
+
- Design tokens via **shadcn CSS vars** (`--background`, `--primary`, `--sidebar`, `--radius`, etc.) — mapeados em `@theme inline`. Honorar tema = nunca hardcodar cor.
|
|
88
|
+
- `.dark` class flip aplicada por `<ThemeProvider>` de `@arqel-dev/react`
|
|
89
|
+
- Componentes presentational — callbacks lifted (sem fetch interno)
|
|
90
|
+
- `peerDependencies`: `radix-ui`, `@tanstack/react-table`, `lucide-react`, `@arqel-dev/{react,hooks}`
|
|
91
|
+
- Props com `undefined` explícito quando opcionais (`exactOptionalPropertyTypes: true`)
|
|
92
|
+
|
|
93
|
+
## Anti-patterns
|
|
94
|
+
|
|
95
|
+
- ❌ **Editar `src/shadcn/*`** — gerado/atualizado pela `shadcn` CLI, ignorado pelo Biome lint. Para customizar uma primitiva: faz fork do componente shadcn para `src/<feature>/<Component>.tsx` próprio e re-exporta dali, mantendo `src/shadcn/` pristine.
|
|
96
|
+
- ❌ **Importar `@base-ui-components/react`** — substituído por `radix-ui`. Code legacy deve migrar.
|
|
97
|
+
- ❌ **Hardcode de cor** — usa CSS vars shadcn (`bg-primary`, `text-foreground`, etc.) para honrar tema
|
|
98
|
+
- ❌ **Bundle Tailwind no dist** — apps trazem o próprio Tailwind; expomos só os tokens via `globals.css`
|
|
99
|
+
- ❌ **Importar de `dist/`** — usa exports declarados (`@arqel-dev/ui` ou subpaths)
|
|
100
|
+
- ❌ **Estado local em ResourceIndex/DataTable** — sempre lifted via callbacks
|
|
101
|
+
- ❌ **Duplicar `useFlash({ onMessage })`** — um único `<FlashContainer>` no AppShell
|
|
102
|
+
- ❌ **Recriar variants `success`/`warning` no `Badge`** — foram removidas; usa `default`/`secondary`/`outline` ou compõe com `className`
|
|
103
|
+
|
|
104
|
+
## Testing
|
|
105
|
+
|
|
106
|
+
- 70+ testes Vitest passando (jsdom + @testing-library/react + @testing-library/user-event)
|
|
107
|
+
- `pnpm test` watch, `pnpm exec vitest run --coverage` para relatório
|
|
108
|
+
- Coverage atual: ~67% global (barrels e overlays mobile do Sidebar baixam o número)
|
|
109
|
+
|
|
110
|
+
## Related
|
|
111
|
+
|
|
112
|
+
- Tickets: [`PLANNING/08-fase-1-mvp.md`](../../PLANNING/08-fase-1-mvp.md) §UI-001..007
|
|
113
|
+
- API: [`PLANNING/06-api-react.md`](../../PLANNING/06-api-react.md) §8, §12
|
|
114
|
+
- shadcn registry: `components.json` na raiz do pacote
|
|
115
|
+
- Source: [`packages-js/ui/src/`](src/) — `shadcn/` (gerado), `primitives/` (barrel), `shell/`, `table/`, `form/`, `action/`, `auth/`, `flash/`, `utility/`
|
|
116
|
+
- Tests: [`packages-js/ui/tests/`](tests/)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ReactNode, ComponentType } from 'react';
|
|
2
|
+
import { FieldSchema } from '@arqel-dev/types/fields';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import { FormSchema } from '@arqel-dev/types/forms';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `<FieldRenderer>` — renders a single field.
|
|
8
|
+
*
|
|
9
|
+
* Resolution order:
|
|
10
|
+
* 1. Component registered via `registerField(field.component)` (rich
|
|
11
|
+
* inputs from `@arqel-dev/fields`)
|
|
12
|
+
* 2. Native fallback dispatched by `field.type` (text/number/boolean/...)
|
|
13
|
+
*
|
|
14
|
+
* Errors come from `errors[name]` (Inertia or client). The component
|
|
15
|
+
* also honours `disabled` / `readonly` / `required` from the schema.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
interface FieldRendererProps {
|
|
19
|
+
field: FieldSchema;
|
|
20
|
+
value: unknown;
|
|
21
|
+
onChange: (value: unknown) => void;
|
|
22
|
+
errors?: string[] | undefined;
|
|
23
|
+
disabled?: boolean | undefined;
|
|
24
|
+
className?: string | undefined;
|
|
25
|
+
inputId?: string | undefined;
|
|
26
|
+
describedBy?: string | undefined;
|
|
27
|
+
}
|
|
28
|
+
declare function FieldRenderer(props: FieldRendererProps): ReactNode;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* `FieldRegistry` — name → React component mapping for FieldRenderer.
|
|
32
|
+
*
|
|
33
|
+
* `@arqel-dev/fields` (FIELDS-JS-*) calls `registerField` at module init to
|
|
34
|
+
* plug rich inputs in; until then FieldRenderer falls back to the
|
|
35
|
+
* native HTML primitives in `nativeFields.tsx`. Registration is global
|
|
36
|
+
* by design — apps can override Arqel defaults by re-registering with
|
|
37
|
+
* the same name.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
type FieldComponent = ComponentType<FieldRendererProps>;
|
|
41
|
+
declare function registerField(name: string, component: FieldComponent): void;
|
|
42
|
+
declare function getFieldComponent(name: string): FieldComponent | undefined;
|
|
43
|
+
declare function unregisterField(name: string): void;
|
|
44
|
+
declare function getRegisteredFields(): string[];
|
|
45
|
+
/** Test-only helper. */
|
|
46
|
+
declare function clearFieldRegistry(): void;
|
|
47
|
+
|
|
48
|
+
interface FormActionsProps {
|
|
49
|
+
submitLabel?: string;
|
|
50
|
+
cancelLabel?: string;
|
|
51
|
+
onCancel?: () => void;
|
|
52
|
+
processing?: boolean;
|
|
53
|
+
disabled?: boolean;
|
|
54
|
+
extra?: ReactNode;
|
|
55
|
+
className?: string;
|
|
56
|
+
}
|
|
57
|
+
declare function FormActions({ submitLabel, cancelLabel, onCancel, processing, disabled, extra, className, }: FormActionsProps): react_jsx_runtime.JSX.Element;
|
|
58
|
+
|
|
59
|
+
interface FormRendererProps {
|
|
60
|
+
schema: FormSchema;
|
|
61
|
+
fields: FieldSchema[];
|
|
62
|
+
values: Record<string, unknown>;
|
|
63
|
+
errors?: Record<string, string[]>;
|
|
64
|
+
onChange: (name: string, value: unknown) => void;
|
|
65
|
+
disabled?: boolean;
|
|
66
|
+
className?: string;
|
|
67
|
+
}
|
|
68
|
+
declare function FormRenderer({ schema, fields, values, errors, onChange, disabled, className, }: FormRendererProps): react_jsx_runtime.JSX.Element;
|
|
69
|
+
|
|
70
|
+
export { type FieldComponent as F, FieldRenderer as a, type FieldRendererProps as b, FormActions as c, type FormActionsProps as d, FormRenderer as e, type FormRendererProps as f, clearFieldRegistry as g, getFieldComponent as h, getRegisteredFields as i, registerField as r, unregisterField as u };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ColumnSchema, TableSort, SortDirection, FilterSchema } from '@arqel-dev/types/tables';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
import { PaginationMeta } from '@arqel-dev/types/resources';
|
|
5
|
+
|
|
6
|
+
type RowId = string | number;
|
|
7
|
+
interface DataTableRecord {
|
|
8
|
+
id: RowId;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
interface DataTableProps<TRecord extends DataTableRecord> {
|
|
12
|
+
columns: ColumnSchema[];
|
|
13
|
+
records: TRecord[];
|
|
14
|
+
enableSelection?: boolean;
|
|
15
|
+
selectedIds?: ReadonlyArray<RowId>;
|
|
16
|
+
onSelectionChange?: ((ids: RowId[]) => void) | undefined;
|
|
17
|
+
sort?: TableSort | null;
|
|
18
|
+
onSortChange?: ((column: string, direction: SortDirection) => void) | undefined;
|
|
19
|
+
rowActions?: ((record: TRecord) => ReactNode) | undefined;
|
|
20
|
+
loading?: boolean;
|
|
21
|
+
emptyState?: ReactNode;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
declare function DataTable<TRecord extends DataTableRecord>({ columns, records, enableSelection, selectedIds, onSelectionChange, sort, onSortChange, rowActions, loading, emptyState, className, }: DataTableProps<TRecord>): react_jsx_runtime.JSX.Element;
|
|
25
|
+
|
|
26
|
+
interface TableFiltersProps {
|
|
27
|
+
filters: FilterSchema[];
|
|
28
|
+
values: Record<string, unknown>;
|
|
29
|
+
onChange: (name: string, value: unknown) => void;
|
|
30
|
+
onClearAll?: (() => void) | undefined;
|
|
31
|
+
className?: string | undefined;
|
|
32
|
+
}
|
|
33
|
+
declare function TableFilters({ filters, values, onChange, onClearAll, className, }: TableFiltersProps): react_jsx_runtime.JSX.Element | null;
|
|
34
|
+
|
|
35
|
+
interface TablePaginationProps {
|
|
36
|
+
meta: PaginationMeta;
|
|
37
|
+
onPageChange: (page: number) => void;
|
|
38
|
+
onPerPageChange?: ((perPage: number) => void) | undefined;
|
|
39
|
+
perPageOptions?: number[];
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
declare function TablePagination({ meta, onPageChange, onPerPageChange, perPageOptions, className, }: TablePaginationProps): react_jsx_runtime.JSX.Element;
|
|
43
|
+
|
|
44
|
+
interface TableToolbarProps {
|
|
45
|
+
search?: ReactNode;
|
|
46
|
+
filters?: ReactNode;
|
|
47
|
+
selectedCount?: number;
|
|
48
|
+
bulkActions?: ReactNode;
|
|
49
|
+
onClearSelection?: (() => void) | undefined;
|
|
50
|
+
className?: string;
|
|
51
|
+
}
|
|
52
|
+
declare function TableToolbar({ search, filters, selectedCount, bulkActions, onClearSelection, className, }: TableToolbarProps): react_jsx_runtime.JSX.Element;
|
|
53
|
+
|
|
54
|
+
export { DataTable as D, TableFilters as T, type DataTableProps as a, type DataTableRecord as b, type TableFiltersProps as c, TablePagination as d, type TablePaginationProps as e, TableToolbar as f, type TableToolbarProps as g };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `<StatCard>` — KPI / "big number" widget.
|
|
6
|
+
*
|
|
7
|
+
* Renders the payload produced by `Arqel\Widgets\StatWidget::data()`:
|
|
8
|
+
*
|
|
9
|
+
* {
|
|
10
|
+
* name, type: 'stat', heading?, description?,
|
|
11
|
+
* value, statDescription?, descriptionIcon?,
|
|
12
|
+
* color, icon?, chart?: number[], url?
|
|
13
|
+
* }
|
|
14
|
+
*
|
|
15
|
+
* Includes a tiny inline-SVG sparkline (no Recharts dep) when `chart`
|
|
16
|
+
* is set. ChartCard / TableCard (Recharts-based) ship in a separate
|
|
17
|
+
* cluster; this component is intentionally Recharts-free so the
|
|
18
|
+
* common "big number" case stays bundle-cheap.
|
|
19
|
+
*/
|
|
20
|
+
type StatCardColor = 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info';
|
|
21
|
+
interface StatCardWidget {
|
|
22
|
+
name: string;
|
|
23
|
+
type: 'stat';
|
|
24
|
+
heading?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
value: string | number | null;
|
|
27
|
+
statDescription?: string | null;
|
|
28
|
+
descriptionIcon?: string | null;
|
|
29
|
+
color: StatCardColor;
|
|
30
|
+
icon?: string | null;
|
|
31
|
+
chart?: number[] | null;
|
|
32
|
+
url?: string | null;
|
|
33
|
+
}
|
|
34
|
+
interface StatCardProps {
|
|
35
|
+
widget: StatCardWidget;
|
|
36
|
+
className?: string | undefined;
|
|
37
|
+
columnSpan?: number | string | undefined;
|
|
38
|
+
}
|
|
39
|
+
declare function StatCard({ widget, className, columnSpan }: StatCardProps): react_jsx_runtime.JSX.Element;
|
|
40
|
+
|
|
41
|
+
interface WidgetWrapperProps {
|
|
42
|
+
heading?: string | undefined;
|
|
43
|
+
description?: string | undefined;
|
|
44
|
+
loading?: boolean | undefined;
|
|
45
|
+
error?: Error | null | undefined;
|
|
46
|
+
onRetry?: (() => void) | undefined;
|
|
47
|
+
/** Tailwind grid column span (number → `col-span-{n}`, or raw class). */
|
|
48
|
+
columnSpan?: number | string | undefined;
|
|
49
|
+
className?: string | undefined;
|
|
50
|
+
children: ReactNode;
|
|
51
|
+
}
|
|
52
|
+
declare function WidgetWrapper({ heading, description, loading, error, onRetry, columnSpan, className, children, }: WidgetWrapperProps): react_jsx_runtime.JSX.Element;
|
|
53
|
+
|
|
54
|
+
export { StatCard as S, WidgetWrapper as W, type StatCardColor as a, type StatCardProps as b, type StatCardWidget as c, type WidgetWrapperProps as d };
|
package/dist/action.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ActionSchema, ConfirmationConfig } from '@arqel-dev/types/actions';
|
|
3
|
+
import { FieldSchema } from '@arqel-dev/types/fields';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
6
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
7
|
+
import { VariantProps } from 'class-variance-authority';
|
|
8
|
+
|
|
9
|
+
declare const buttonVariants: (props?: ({
|
|
10
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
|
|
11
|
+
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
12
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
13
|
+
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
|
14
|
+
asChild?: boolean;
|
|
15
|
+
}): react_jsx_runtime.JSX.Element;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Re-export shadcn (new-york) Button so existing consumers continue to
|
|
19
|
+
* import `Button` and `buttonVariants` from `@arqel-dev/ui/action`
|
|
20
|
+
* while the actual implementation lives in `src/shadcn/ui/button.tsx`.
|
|
21
|
+
*
|
|
22
|
+
* Variants exposed (shadcn): `default | destructive | outline |
|
|
23
|
+
* secondary | ghost | link`. Sizes: `default | xs | sm | lg | icon |
|
|
24
|
+
* icon-xs | icon-sm | icon-lg`.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
type ButtonProps = ComponentProps<typeof Button>;
|
|
28
|
+
|
|
29
|
+
interface ActionButtonProps {
|
|
30
|
+
action: ActionSchema;
|
|
31
|
+
/** Field schemas for any form modal (resolved server-side from Action::form). */
|
|
32
|
+
formFields?: FieldSchema[];
|
|
33
|
+
onInvoke: (formValues?: Record<string, unknown>) => void;
|
|
34
|
+
processing?: boolean;
|
|
35
|
+
errors?: Record<string, string[]>;
|
|
36
|
+
size?: ButtonProps['size'];
|
|
37
|
+
className?: string;
|
|
38
|
+
}
|
|
39
|
+
declare function ActionButton({ action, formFields, onInvoke, processing, errors, size, className, }: ActionButtonProps): react_jsx_runtime.JSX.Element;
|
|
40
|
+
|
|
41
|
+
interface ActionFormModalProps {
|
|
42
|
+
open: boolean;
|
|
43
|
+
onOpenChange: (open: boolean) => void;
|
|
44
|
+
action: ActionSchema;
|
|
45
|
+
fields: FieldSchema[];
|
|
46
|
+
onSubmit: (values: Record<string, unknown>) => void;
|
|
47
|
+
processing?: boolean;
|
|
48
|
+
errors?: Record<string, string[]> | undefined;
|
|
49
|
+
initialValues?: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
declare function ActionFormModal({ open, onOpenChange, action, fields, onSubmit, processing, errors, initialValues, }: ActionFormModalProps): react_jsx_runtime.JSX.Element;
|
|
52
|
+
|
|
53
|
+
interface ActionMenuProps {
|
|
54
|
+
actions: ActionSchema[];
|
|
55
|
+
formFieldsByAction?: Record<string, FieldSchema[]>;
|
|
56
|
+
onInvoke: (action: ActionSchema, formValues?: Record<string, unknown>) => void;
|
|
57
|
+
inlineThreshold?: number;
|
|
58
|
+
processing?: boolean;
|
|
59
|
+
trigger?: ReactNode;
|
|
60
|
+
className?: string;
|
|
61
|
+
}
|
|
62
|
+
declare function ActionMenu({ actions, formFieldsByAction, onInvoke, inlineThreshold, processing, trigger, className, }: ActionMenuProps): react_jsx_runtime.JSX.Element | null;
|
|
63
|
+
|
|
64
|
+
interface ConfirmDialogProps {
|
|
65
|
+
open: boolean;
|
|
66
|
+
onOpenChange: (open: boolean) => void;
|
|
67
|
+
config?: ConfirmationConfig | undefined;
|
|
68
|
+
onConfirm: () => void;
|
|
69
|
+
processing?: boolean;
|
|
70
|
+
}
|
|
71
|
+
declare function ConfirmDialog({ open, onOpenChange, config, onConfirm, processing, }: ConfirmDialogProps): react_jsx_runtime.JSX.Element;
|
|
72
|
+
|
|
73
|
+
export { ActionButton, type ActionButtonProps, ActionFormModal, type ActionFormModalProps, ActionMenu, type ActionMenuProps, Button, type ButtonProps, ConfirmDialog, type ConfirmDialogProps, buttonVariants };
|