@dimaan/ui 0.0.18 → 0.0.20
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/dist/index.cjs +145 -165
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +203 -144
- package/dist/index.d.ts +203 -144
- package/dist/index.js +146 -166
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1127,32 +1127,49 @@ type FieldProps<TValues extends FieldValues = FieldValues, TName extends FieldPa
|
|
|
1127
1127
|
*/
|
|
1128
1128
|
declare function Field<TValues extends FieldValues = FieldValues, TName extends FieldPath<TValues> = FieldPath<TValues>>(props: FieldProps<TValues, TName>): ReactElement;
|
|
1129
1129
|
|
|
1130
|
+
interface FormPageLabels {
|
|
1131
|
+
/** Back button label (top-left). Direction-aware default: `"Back"` / `"رجوع"`. */
|
|
1132
|
+
back?: string;
|
|
1133
|
+
/** Cancel button label. Direction-aware default: `"Cancel"` / `"إلغاء"`. */
|
|
1134
|
+
cancel?: string;
|
|
1135
|
+
/** Save (submit) button label when idle. Direction-aware default: `"Save"` / `"حفظ"`. */
|
|
1136
|
+
save?: string;
|
|
1137
|
+
/** Save (submit) button label while `isSubmitting` is true. Direction-aware default: `"Saving…"` / `"جارٍ الحفظ…"`. */
|
|
1138
|
+
saving?: string;
|
|
1139
|
+
}
|
|
1130
1140
|
interface FormPageProps {
|
|
1131
1141
|
/** Page title (required). Rendered as an `<h1>` by `PageHeader`. */
|
|
1132
1142
|
title: ReactNode;
|
|
1133
1143
|
/** Optional secondary text under the title. */
|
|
1134
1144
|
description?: ReactNode;
|
|
1135
|
-
/** Optional back-button config — forwarded straight to `PageHeader.back`. */
|
|
1136
|
-
back?: PageHeaderBackProps;
|
|
1137
1145
|
/** Page-header bottom border separator. Defaults to `true` for form pages. */
|
|
1138
1146
|
bordered?: boolean;
|
|
1139
1147
|
/** Form-submit handler. Wire RHF via `form.handleSubmit(onSave)`. */
|
|
1140
1148
|
onSubmit: FormEventHandler<HTMLFormElement>;
|
|
1149
|
+
/** Cancel-button handler. Defaults to navigating back one history entry. */
|
|
1150
|
+
onCancel?: () => void;
|
|
1151
|
+
/**
|
|
1152
|
+
* Disables the submit button and swaps its label to `labels.saving`. When
|
|
1153
|
+
* omitted, `FormPage` reads `formState.isSubmitting` from the surrounding
|
|
1154
|
+
* `<FormProvider>` (if any). Pass an explicit boolean to override.
|
|
1155
|
+
*/
|
|
1156
|
+
isSubmitting?: boolean;
|
|
1157
|
+
/** Localized copy for the built-in Cancel / Save buttons. */
|
|
1158
|
+
labels?: FormPageLabels;
|
|
1141
1159
|
/**
|
|
1142
1160
|
* Show skeleton placeholders in the body while the initial record is being
|
|
1143
1161
|
* fetched (typical for the edit page). The action bar still renders so the
|
|
1144
|
-
*
|
|
1145
|
-
* disabling submit buttons while loading.
|
|
1162
|
+
* user can Cancel out; the Save button is disabled while loading.
|
|
1146
1163
|
*/
|
|
1147
1164
|
isLoading?: boolean;
|
|
1148
1165
|
/** Number of skeleton rows shown while loading. Defaults to `6`. */
|
|
1149
1166
|
loadingRowCount?: number;
|
|
1150
1167
|
/**
|
|
1151
|
-
*
|
|
1152
|
-
*
|
|
1153
|
-
*
|
|
1168
|
+
* Extra action buttons rendered inside the sticky bar **before** the
|
|
1169
|
+
* built-in Cancel / Save pair (e.g. "Save & continue", "Delete"). Most
|
|
1170
|
+
* forms can omit this — Cancel + Save are owned by `FormPage` itself.
|
|
1154
1171
|
*/
|
|
1155
|
-
actions
|
|
1172
|
+
actions?: ReactNode;
|
|
1156
1173
|
/** Form body. Compose `<Field>` + your chosen controls, grouped however you like. */
|
|
1157
1174
|
children: ReactNode;
|
|
1158
1175
|
/** Class applied to the outer wrapper. */
|
|
@@ -1166,36 +1183,30 @@ interface FormPageProps {
|
|
|
1166
1183
|
}
|
|
1167
1184
|
/**
|
|
1168
1185
|
* Declarative form-page template — composes `PageHeader` + a scrollable form
|
|
1169
|
-
* body + a sticky action bar
|
|
1170
|
-
*
|
|
1171
|
-
*
|
|
1186
|
+
* body + a sticky action bar (with built-in **Cancel** and **Save** buttons)
|
|
1187
|
+
* into a single component.
|
|
1188
|
+
*
|
|
1189
|
+
* **Zero-prop defaults** make the minimal call site small:
|
|
1190
|
+
* - Back & Cancel both default to `navigate(-1)`.
|
|
1191
|
+
* - `isSubmitting` is auto-detected from the surrounding `<FormProvider>`'s
|
|
1192
|
+
* `formState.isSubmitting` — no need to wire it manually.
|
|
1193
|
+
* - All button labels are direction-aware (EN / AR) and resolved from
|
|
1194
|
+
* `<html dir>` via `useDirection()`.
|
|
1195
|
+
*
|
|
1196
|
+
* Override any of these by passing the matching prop (`onCancel`,
|
|
1197
|
+
* `isSubmitting`, `labels`).
|
|
1172
1198
|
*
|
|
1173
1199
|
* The component expects its parent to provide the scroll context — in the
|
|
1174
1200
|
* default `<AppShell>` setup, that's `<DashboardContent>`. The sticky bar
|
|
1175
1201
|
* relies on `position: sticky` against that scroll container.
|
|
1176
1202
|
*
|
|
1177
|
-
* @example
|
|
1203
|
+
* @example Minimal usage inside a `<FormProvider>` (RHF + Zod)
|
|
1178
1204
|
* ```tsx
|
|
1179
1205
|
* const form = useForm<UserDraft>({ resolver: zodResolver(schema), defaultValues });
|
|
1180
1206
|
*
|
|
1181
1207
|
* return (
|
|
1182
1208
|
* <FormProvider {...form}>
|
|
1183
|
-
* <FormPage
|
|
1184
|
-
* title="New user"
|
|
1185
|
-
* description="Invite a teammate to your workspace."
|
|
1186
|
-
* back={{ to: '/users' }}
|
|
1187
|
-
* onSubmit={form.handleSubmit(onSave)}
|
|
1188
|
-
* actions={
|
|
1189
|
-
* <>
|
|
1190
|
-
* <Button type="button" variant="outline" onClick={() => navigate(-1)}>
|
|
1191
|
-
* Cancel
|
|
1192
|
-
* </Button>
|
|
1193
|
-
* <Button type="submit" disabled={form.formState.isSubmitting}>
|
|
1194
|
-
* Save
|
|
1195
|
-
* </Button>
|
|
1196
|
-
* </>
|
|
1197
|
-
* }
|
|
1198
|
-
* >
|
|
1209
|
+
* <FormPage title="New user" onSubmit={form.handleSubmit(onSave)}>
|
|
1199
1210
|
* <div className="grid gap-4 md:grid-cols-2">
|
|
1200
1211
|
* <Field name="name" label="Full name" required><Input /></Field>
|
|
1201
1212
|
* <Field name="email" label="Email" required><Input type="email" /></Field>
|
|
@@ -1205,14 +1216,26 @@ interface FormPageProps {
|
|
|
1205
1216
|
* );
|
|
1206
1217
|
* ```
|
|
1207
1218
|
*
|
|
1219
|
+
* @example Override Cancel + add an extra action button
|
|
1220
|
+
* ```tsx
|
|
1221
|
+
* <FormPage
|
|
1222
|
+
* title="مستخدم جديد"
|
|
1223
|
+
* onSubmit={form.handleSubmit(onSave)}
|
|
1224
|
+
* onCancel={() => form.reset()}
|
|
1225
|
+
* actions={<Button type="button" variant="outline" onClick={onSaveAndContinue}>Save & continue</Button>}
|
|
1226
|
+
* >
|
|
1227
|
+
* {…fields…}
|
|
1228
|
+
* </FormPage>
|
|
1229
|
+
* ```
|
|
1230
|
+
*
|
|
1208
1231
|
* @example Edit mode with `isLoading`
|
|
1209
1232
|
* ```tsx
|
|
1210
|
-
* <FormPage title="Edit user" isLoading={query.isLoading} onSubmit={…}
|
|
1233
|
+
* <FormPage title="Edit user" isLoading={query.isLoading} onSubmit={…}>
|
|
1211
1234
|
* {…fields…}
|
|
1212
1235
|
* </FormPage>
|
|
1213
1236
|
* ```
|
|
1214
1237
|
*/
|
|
1215
|
-
declare function FormPage({ title, description,
|
|
1238
|
+
declare function FormPage({ title, description, bordered, onSubmit, onCancel, isSubmitting, labels: labelsProp, isLoading, loadingRowCount, actions, children, className, formClassName, bodyClassName, actionsClassName, }: FormPageProps): react_jsx_runtime.JSX.Element;
|
|
1216
1239
|
|
|
1217
1240
|
/** Outermost wrapper of `FormPage` — vertical flex column that fills its parent. */
|
|
1218
1241
|
declare const formPageBaseClass = "flex w-full flex-col gap-6";
|
|
@@ -1443,8 +1466,21 @@ interface PaginationState {
|
|
|
1443
1466
|
}
|
|
1444
1467
|
/** Set of row ids (returned from `getRowId`) that are currently selected. */
|
|
1445
1468
|
type RowSelectionState = ReadonlySet<string>;
|
|
1446
|
-
type SortableValue = string | number | bigint | boolean | Date | null | undefined;
|
|
1447
1469
|
type ColumnAlign = 'start' | 'center' | 'end';
|
|
1470
|
+
/**
|
|
1471
|
+
* Translatable strings rendered inside Table's chrome (paginator labels +
|
|
1472
|
+
* aria-labels). All optional; English defaults are used when omitted.
|
|
1473
|
+
*/
|
|
1474
|
+
interface TableLabels {
|
|
1475
|
+
/** "Rows per page" label next to the page-size select. */
|
|
1476
|
+
rowsPerPage?: string;
|
|
1477
|
+
/** Connector word in the range readout — e.g. "of" in `1–10 of 100`. */
|
|
1478
|
+
pageRangeOf?: string;
|
|
1479
|
+
/** aria-label on the Previous-page button. */
|
|
1480
|
+
previousPage?: string;
|
|
1481
|
+
/** aria-label on the Next-page button. */
|
|
1482
|
+
nextPage?: string;
|
|
1483
|
+
}
|
|
1448
1484
|
interface Column<T> {
|
|
1449
1485
|
/** Stable column id. Used for sort state and React keys. */
|
|
1450
1486
|
id: string;
|
|
@@ -1456,35 +1492,55 @@ interface Column<T> {
|
|
|
1456
1492
|
render?: (row: T, rowIndex: number) => ReactNode;
|
|
1457
1493
|
/** Enable click-to-sort UI on the header. */
|
|
1458
1494
|
sortable?: boolean;
|
|
1459
|
-
/** Optional override for the value used to compare during sorting. */
|
|
1460
|
-
sortAccessor?: (row: T) => SortableValue;
|
|
1461
1495
|
/** Tailwind classes applied to both <th> and <td>. */
|
|
1462
1496
|
className?: string;
|
|
1463
1497
|
/** Inline alignment hint. Defaults to 'start'. */
|
|
1464
1498
|
align?: ColumnAlign;
|
|
1465
1499
|
}
|
|
1466
1500
|
interface TableProps<T> {
|
|
1467
|
-
/**
|
|
1501
|
+
/**
|
|
1502
|
+
* Current page rows. Server-driven: the consumer's data layer slices
|
|
1503
|
+
* `data` for the active sort + pagination + filter query, and Table
|
|
1504
|
+
* renders it as-is. Table never sorts or paginates `data` locally.
|
|
1505
|
+
*/
|
|
1468
1506
|
data: readonly T[];
|
|
1469
1507
|
/** Column definitions. */
|
|
1470
1508
|
columns: ReadonlyArray<Column<T>>;
|
|
1471
|
-
/** Stable id for each row. Required for selection; recommended always. */
|
|
1472
|
-
getRowId: (row: T, index: number) => string;
|
|
1473
1509
|
/**
|
|
1474
|
-
*
|
|
1475
|
-
*
|
|
1510
|
+
* Stable id for each row. **Optional with a default**: when omitted,
|
|
1511
|
+
* Table reads `row.id` (most APIs use it) and falls back to the row
|
|
1512
|
+
* index. Provide this explicitly for records that use a different
|
|
1513
|
+
* identifier (`_id`, `uuid`) or any time the list can reorder —
|
|
1514
|
+
* index-based ids break selection across reorders.
|
|
1515
|
+
*/
|
|
1516
|
+
getRowId?: (row: T, index: number) => string;
|
|
1517
|
+
/**
|
|
1518
|
+
* Total row count on the server. Pair with `pagination` +
|
|
1519
|
+
* `onPaginationChange` to drive the paginator. Falls back to
|
|
1520
|
+
* `data.length` when omitted (small lists with no paginator).
|
|
1476
1521
|
*/
|
|
1477
1522
|
totalCount?: number;
|
|
1478
|
-
|
|
1523
|
+
/** Current sort state — the consumer's data layer is the source of truth. */
|
|
1479
1524
|
sort?: SortState;
|
|
1525
|
+
/**
|
|
1526
|
+
* Fires when the user clicks a sortable column header. Pair with `sort` to
|
|
1527
|
+
* drive sorting through your data layer. Without `onSortChange`, sortable
|
|
1528
|
+
* column buttons render but do nothing.
|
|
1529
|
+
*/
|
|
1480
1530
|
onSortChange?: (next: SortState) => void;
|
|
1481
|
-
|
|
1531
|
+
/** Current page state — the consumer's data layer is the source of truth. */
|
|
1482
1532
|
pagination?: PaginationState;
|
|
1533
|
+
/** Fires when the user changes the page or page size. */
|
|
1483
1534
|
onPaginationChange?: (next: PaginationState) => void;
|
|
1484
1535
|
/** Page size dropdown options. Defaults to [10, 25, 50]. */
|
|
1485
1536
|
pageSizeOptions?: readonly number[];
|
|
1486
|
-
/** Force the paginator to render even when
|
|
1537
|
+
/** Force the paginator to render even when totalCount <= pageSize. */
|
|
1487
1538
|
showPagination?: boolean;
|
|
1539
|
+
/**
|
|
1540
|
+
* Translatable strings rendered inside Table itself (paginator labels +
|
|
1541
|
+
* aria-labels). Pass only the keys you need to override.
|
|
1542
|
+
*/
|
|
1543
|
+
labels?: TableLabels;
|
|
1488
1544
|
/** Adds the selection column + header checkbox. */
|
|
1489
1545
|
enableRowSelection?: boolean;
|
|
1490
1546
|
defaultSelectedRowIds?: ReadonlySet<string>;
|
|
@@ -1524,23 +1580,26 @@ interface TableProps<T> {
|
|
|
1524
1580
|
caption?: ReactNode;
|
|
1525
1581
|
}
|
|
1526
1582
|
|
|
1583
|
+
/**
|
|
1584
|
+
* Server-driven data table. `data` is rendered as-is — the consumer's data
|
|
1585
|
+
* layer is responsible for slicing rows for the active sort + pagination
|
|
1586
|
+
* query. Table just reports user input (sort clicks, page changes,
|
|
1587
|
+
* selection) through callbacks and lets the consumer refetch.
|
|
1588
|
+
*/
|
|
1527
1589
|
declare function Table<T>(props: TableProps<T>): react_jsx_runtime.JSX.Element;
|
|
1528
1590
|
|
|
1529
1591
|
/**
|
|
1530
|
-
* One filter dropdown definition for `<ListPage>`.
|
|
1531
|
-
*
|
|
1592
|
+
* One filter dropdown definition for `<ListPage>`. Server owns the actual
|
|
1593
|
+
* filtering — the consumer keeps `filterValues` in state and ListPage just
|
|
1594
|
+
* renders the Select + reports changes.
|
|
1532
1595
|
*/
|
|
1533
|
-
interface ListPageFilter
|
|
1534
|
-
/** Unique key
|
|
1596
|
+
interface ListPageFilter {
|
|
1597
|
+
/** Unique key — used in the `filterValues` record and as aria-label fallback. */
|
|
1535
1598
|
key: string;
|
|
1536
|
-
/**
|
|
1537
|
-
|
|
1538
|
-
/** Returns the row value to match against the filter selection. */
|
|
1539
|
-
accessor: (row: T) => string;
|
|
1599
|
+
/** Display label. Falls back to `key` for the Select's aria-label. */
|
|
1600
|
+
label?: ReactNode;
|
|
1540
1601
|
/** Options to choose from. The first option's value is treated as "no filter / show all". */
|
|
1541
1602
|
options: SelectOption[];
|
|
1542
|
-
/** Override the "no filter" default. Defaults to the first option's `value`. */
|
|
1543
|
-
defaultValue?: string;
|
|
1544
1603
|
/** Width of the Select. Defaults to `'default'` (~11rem). */
|
|
1545
1604
|
width?: 'narrow' | 'default' | 'wide';
|
|
1546
1605
|
}
|
|
@@ -1551,142 +1610,142 @@ interface ListPageEmptyState {
|
|
|
1551
1610
|
/** Override the default action button. Pass `null` to hide entirely. */
|
|
1552
1611
|
action?: ReactNode | null;
|
|
1553
1612
|
}
|
|
1554
|
-
|
|
1555
|
-
|
|
1613
|
+
/**
|
|
1614
|
+
* Translatable strings for `<ListPage>`. Extends {@link TableLabels} so the
|
|
1615
|
+
* four paginator keys (`rowsPerPage` / `pageRangeOf` / `previousPage` /
|
|
1616
|
+
* `nextPage`) flow through to the inner Table without re-declaration.
|
|
1617
|
+
*/
|
|
1618
|
+
interface ListPageLabels extends TableLabels {
|
|
1619
|
+
/** Search input placeholder. */
|
|
1556
1620
|
searchPlaceholder?: string;
|
|
1557
|
-
/**
|
|
1621
|
+
/** Search input aria-label. Falls back to the placeholder. */
|
|
1558
1622
|
searchAriaLabel?: string;
|
|
1559
|
-
/**
|
|
1623
|
+
/** "Reset filters" button label. */
|
|
1560
1624
|
reset?: string;
|
|
1561
|
-
/**
|
|
1625
|
+
/** "No results matching filters" title. */
|
|
1562
1626
|
emptyTitle?: string;
|
|
1563
|
-
/**
|
|
1627
|
+
/** "No results matching filters" description. */
|
|
1564
1628
|
emptyDescription?: string;
|
|
1565
|
-
/**
|
|
1629
|
+
/** "No data yet" title (data empty, no filters active). */
|
|
1566
1630
|
noDataTitle?: string;
|
|
1567
|
-
/**
|
|
1631
|
+
/** "No data yet" description. */
|
|
1568
1632
|
noDataDescription?: string;
|
|
1569
1633
|
}
|
|
1570
1634
|
interface ListPageProps<T> {
|
|
1571
1635
|
title: ReactNode;
|
|
1572
1636
|
description?: ReactNode;
|
|
1573
|
-
/** Page-header bordered separator. Defaults to `true
|
|
1637
|
+
/** Page-header bordered separator. Defaults to `true`. */
|
|
1574
1638
|
bordered?: boolean;
|
|
1575
1639
|
/** Header action slot — primary "Add" button, etc. */
|
|
1576
1640
|
actions?: ReactNode;
|
|
1577
|
-
data: T[];
|
|
1578
|
-
columns: Column<T
|
|
1579
|
-
|
|
1641
|
+
data: readonly T[];
|
|
1642
|
+
columns: ReadonlyArray<Column<T>>;
|
|
1643
|
+
/**
|
|
1644
|
+
* Stable id for each row. Forwarded to Table; defaults to `row.id` then
|
|
1645
|
+
* the row index. Provide explicitly for records that use a different
|
|
1646
|
+
* identifier or any time the list can reorder.
|
|
1647
|
+
*/
|
|
1648
|
+
getRowId?: (row: T, index: number) => string;
|
|
1580
1649
|
/** Show skeleton rows in the table area while data is fetching. */
|
|
1581
1650
|
isLoading?: boolean;
|
|
1582
1651
|
/** Number of skeleton rows rendered while loading. Defaults to the table page size. */
|
|
1583
1652
|
loadingRowCount?: number;
|
|
1584
|
-
/**
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1653
|
+
/** Current search query — the consumer's state. */
|
|
1654
|
+
searchValue?: string;
|
|
1655
|
+
/**
|
|
1656
|
+
* Fires on every keystroke. Providing this **renders the search input**.
|
|
1657
|
+
* Wire it to your data layer (and reset pagination to page 0 on change).
|
|
1658
|
+
*/
|
|
1659
|
+
onSearchChange?: (value: string) => void;
|
|
1589
1660
|
/**
|
|
1590
|
-
*
|
|
1591
|
-
*
|
|
1592
|
-
* the source of truth for `pageIndex` / `pageSize`.
|
|
1661
|
+
* Filter definitions. Renders one `<Select>` per entry. Pair with
|
|
1662
|
+
* `filterValues` + `onFilterChange` to drive them.
|
|
1593
1663
|
*/
|
|
1664
|
+
filters?: ListPageFilter[];
|
|
1665
|
+
/** Current filter selections, keyed by `filter.key`. */
|
|
1666
|
+
filterValues?: Record<string, string>;
|
|
1667
|
+
/** Fires when any filter Select changes. */
|
|
1668
|
+
onFilterChange?: (key: string, value: string) => void;
|
|
1669
|
+
enableRowSelection?: boolean;
|
|
1670
|
+
bulkActions?: (selected: T[]) => ReactNode;
|
|
1671
|
+
/** Current page state from the consumer's data layer. */
|
|
1594
1672
|
pagination?: PaginationState;
|
|
1595
|
-
/** Uncontrolled initial pagination state. Ignored when `pagination` is set. */
|
|
1596
|
-
defaultPagination?: PaginationState;
|
|
1597
1673
|
/** Fires when the user changes the page or page size. */
|
|
1598
1674
|
onPaginationChange?: (next: PaginationState) => void;
|
|
1599
|
-
/**
|
|
1600
|
-
* Total row count across all pages on the server. Setting this flips the
|
|
1601
|
-
* inner Table into server-side mode — it stops slicing `data` locally and
|
|
1602
|
-
* trusts `data` to be the current page already.
|
|
1603
|
-
*
|
|
1604
|
-
* In server-side mode the consumer also typically skips `searchKeys` /
|
|
1605
|
-
* `filters` (those would filter only the current page) and drives search /
|
|
1606
|
-
* filter from the data-fetching layer instead.
|
|
1607
|
-
*/
|
|
1675
|
+
/** Total row count across all pages on the server. */
|
|
1608
1676
|
totalCount?: number;
|
|
1609
1677
|
/** Page-size dropdown options. Defaults to `[10, 25, 50]`. */
|
|
1610
1678
|
pageSizeOptions?: readonly number[];
|
|
1611
1679
|
/**
|
|
1612
|
-
* Shown when
|
|
1613
|
-
* "No results
|
|
1614
|
-
* with a reset button.
|
|
1680
|
+
* Shown when search / filters are active but match zero rows. Defaults to
|
|
1681
|
+
* a "No results" prompt with a Reset button.
|
|
1615
1682
|
*/
|
|
1616
1683
|
emptyState?: ListPageEmptyState;
|
|
1617
1684
|
/**
|
|
1618
|
-
* Shown when `data` is empty AND
|
|
1619
|
-
* state).
|
|
1620
|
-
* icon. When `actions` is set, you typically want to encourage creation
|
|
1621
|
-
* via this slot's `action`.
|
|
1685
|
+
* Shown when `data` is empty AND nothing is being searched / filtered
|
|
1686
|
+
* (first-run state). Defaults to an Inbox + "No data yet" message.
|
|
1622
1687
|
*/
|
|
1623
1688
|
noDataState?: ListPageEmptyState;
|
|
1624
1689
|
labels?: ListPageLabels;
|
|
1625
1690
|
className?: string;
|
|
1626
1691
|
}
|
|
1627
1692
|
/**
|
|
1628
|
-
* Declarative list-page template — composes `PageHeader + search
|
|
1629
|
-
* filter selects + Table + EmptyState` into a single
|
|
1693
|
+
* Declarative server-driven list-page template — composes `PageHeader + search
|
|
1694
|
+
* input + filter selects + Table + EmptyState` into a single component.
|
|
1630
1695
|
*
|
|
1631
|
-
* **
|
|
1632
|
-
* `data`
|
|
1633
|
-
*
|
|
1634
|
-
*
|
|
1696
|
+
* **All data-shaping is server-side.** ListPage does not filter / search /
|
|
1697
|
+
* paginate `data` locally; it renders whatever the consumer's data layer
|
|
1698
|
+
* returned for the current `searchValue` + `filterValues` + `pagination`
|
|
1699
|
+
* query. ListPage's job is the UI: render the controls, report user input
|
|
1700
|
+
* back through callbacks, and pick the right empty state.
|
|
1635
1701
|
*
|
|
1636
1702
|
* **Three rendering branches in the table area:**
|
|
1637
|
-
* - `isLoading` → Table with skeleton rows
|
|
1638
|
-
* - `data` empty AND
|
|
1639
|
-
* - filters
|
|
1703
|
+
* - `isLoading` → Table with skeleton rows.
|
|
1704
|
+
* - `data` empty AND nothing being searched / filtered → `noDataState` (first-run).
|
|
1705
|
+
* - search / filters active but `data` empty → `emptyState` (no results) with a Reset button.
|
|
1640
1706
|
*
|
|
1641
|
-
* @example
|
|
1707
|
+
* @example Server-driven list with TanStack Query
|
|
1642
1708
|
* ```tsx
|
|
1643
|
-
*
|
|
1644
|
-
*
|
|
1645
|
-
*
|
|
1646
|
-
* actions={<Button onClick={openCreate}>Add user</Button>}
|
|
1647
|
-
* data={users}
|
|
1648
|
-
* isLoading={query.isLoading}
|
|
1649
|
-
* columns={USER_COLUMNS}
|
|
1650
|
-
* getRowId={(u) => u.id}
|
|
1651
|
-
* searchKeys={['name', 'email']}
|
|
1652
|
-
* filters={[
|
|
1653
|
-
* {
|
|
1654
|
-
* key: 'status',
|
|
1655
|
-
* ariaLabel: 'Status',
|
|
1656
|
-
* accessor: (u) => u.status,
|
|
1657
|
-
* options: [
|
|
1658
|
-
* { value: 'all', label: 'All statuses' },
|
|
1659
|
-
* { value: 'active', label: 'Active' },
|
|
1660
|
-
* { value: 'invited', label: 'Invited' },
|
|
1661
|
-
* ],
|
|
1662
|
-
* },
|
|
1663
|
-
* ]}
|
|
1664
|
-
* enableRowSelection
|
|
1665
|
-
* bulkActions={(rows) => <Button variant="destructive">Delete ({rows.length})</Button>}
|
|
1666
|
-
* noDataState={{
|
|
1667
|
-
* title: 'No users yet',
|
|
1668
|
-
* description: 'Invite your first team member to get started.',
|
|
1669
|
-
* action: <Button onClick={openCreate}>Add user</Button>,
|
|
1670
|
-
* }}
|
|
1671
|
-
* />
|
|
1672
|
-
* ```
|
|
1709
|
+
* const [search, setSearch] = useState('');
|
|
1710
|
+
* const [filters, setFilters] = useState({ status: 'all' });
|
|
1711
|
+
* const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
|
|
1673
1712
|
*
|
|
1674
|
-
*
|
|
1675
|
-
*
|
|
1676
|
-
*
|
|
1677
|
-
*
|
|
1678
|
-
*
|
|
1679
|
-
*
|
|
1680
|
-
*
|
|
1681
|
-
*
|
|
1682
|
-
*
|
|
1683
|
-
*
|
|
1684
|
-
*
|
|
1685
|
-
*
|
|
1686
|
-
*
|
|
1713
|
+
* const { data, isLoading } = useQuery({
|
|
1714
|
+
* queryKey: ['users', search, filters, pagination],
|
|
1715
|
+
* queryFn: () => fetchUsers({ search, ...filters, ...pagination }),
|
|
1716
|
+
* });
|
|
1717
|
+
*
|
|
1718
|
+
* return (
|
|
1719
|
+
* <ListPage
|
|
1720
|
+
* title="Users"
|
|
1721
|
+
* actions={<Button onClick={openCreate}>Add user</Button>}
|
|
1722
|
+
* data={data?.rows ?? []}
|
|
1723
|
+
* totalCount={data?.total ?? 0}
|
|
1724
|
+
* isLoading={isLoading}
|
|
1725
|
+
* columns={USER_COLUMNS}
|
|
1726
|
+
*
|
|
1727
|
+
* searchValue={search}
|
|
1728
|
+
* onSearchChange={(v) => {
|
|
1729
|
+
* setSearch(v);
|
|
1730
|
+
* setPagination((p) => ({ ...p, pageIndex: 0 }));
|
|
1731
|
+
* }}
|
|
1732
|
+
*
|
|
1733
|
+
* filters={[
|
|
1734
|
+
* { key: 'status', label: 'Status', options: STATUS_OPTIONS },
|
|
1735
|
+
* ]}
|
|
1736
|
+
* filterValues={filters}
|
|
1737
|
+
* onFilterChange={(key, value) => {
|
|
1738
|
+
* setFilters((prev) => ({ ...prev, [key]: value }));
|
|
1739
|
+
* setPagination((p) => ({ ...p, pageIndex: 0 }));
|
|
1740
|
+
* }}
|
|
1741
|
+
*
|
|
1742
|
+
* pagination={pagination}
|
|
1743
|
+
* onPaginationChange={setPagination}
|
|
1744
|
+
* />
|
|
1745
|
+
* );
|
|
1687
1746
|
* ```
|
|
1688
1747
|
*/
|
|
1689
|
-
declare function ListPage<T>({ title, description, bordered, actions, data, columns, getRowId, isLoading, loadingRowCount,
|
|
1748
|
+
declare function ListPage<T>({ title, description, bordered, actions, data, columns, getRowId, isLoading, loadingRowCount, searchValue, onSearchChange, filters, filterValues, onFilterChange, enableRowSelection, bulkActions, pagination, onPaginationChange, totalCount, pageSizeOptions, emptyState, noDataState, labels: labelsProp, className, }: ListPageProps<T>): react_jsx_runtime.JSX.Element;
|
|
1690
1749
|
|
|
1691
1750
|
type RadioGroupSize = 'sm' | 'md' | 'lg';
|
|
1692
1751
|
/** Outer circle (radio button itself) — sized + bordered. */
|
|
@@ -2079,4 +2138,4 @@ declare function useDirection(): Direction;
|
|
|
2079
2138
|
|
|
2080
2139
|
declare function cn(...inputs: ClassValue[]): string;
|
|
2081
2140
|
|
|
2082
|
-
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, type AlertDialogContentProps, AlertDialogDescription, type AlertDialogDescriptionProps, AlertDialogFooter, type AlertDialogFooterProps, AlertDialogHeader, type AlertDialogHeaderProps, AlertDialogOverlay, type AlertDialogOverlayProps, AlertDialogPortal, AlertDialogTitle, type AlertDialogTitleProps, AlertDialogTrigger, AppShell, type AppShellBrand, type AppShellNavGroup, type AppShellNavItem, type AppShellProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, type CheckboxSize, type Column, type ColumnAlign, type ConfirmDialogLabels, ConfirmDialogProvider, type ConfirmDialogProviderProps, type ConfirmOptions, DashboardContent, type DashboardContentProps, DashboardHeader, type DashboardHeaderProps, DashboardLayout, type DashboardLayoutContextValue, type DashboardLayoutProps, DashboardMain, type DashboardMainProps, DatePicker, type DatePickerProps, type DatePickerSize, type DatePickerVariant, DetailPage, type DetailPageLabels, type DetailPageNotFoundState, type DetailPageProps, Dialog, DialogClose, DialogContent, type DialogContentProps, DialogDescription, type DialogDescriptionProps, DialogFooter, type DialogFooterProps, DialogHeader, type DialogHeaderProps, DialogOverlay, type DialogOverlayProps, DialogPortal, DialogTitle, type DialogTitleProps, DialogTrigger, type Direction, DropdownMenu, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuItemVariant, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, DropdownMenuSeparator, type DropdownMenuSeparatorProps, DropdownMenuShortcut, type DropdownMenuShortcutProps, DropdownMenuTrigger, EmptyState, type EmptyStateProps, type EmptyStateSize, Field, type FieldOrientation, type FieldProps, type FieldRHFProps, FormPage, type FormPageProps, HeaderActions, type HeaderActionsProps, HeaderCollapseTrigger, type HeaderCollapseTriggerProps, HeaderMobileTrigger, type HeaderMobileTriggerProps, HeaderSearch, type HeaderSearchProps, HeaderTitle, type HeaderTitleProps, Input, type InputProps, type InputSize, type InputVariant, type LanguageOption, LanguageSwitcher, type LanguageSwitcherProps, ListPage, type ListPageEmptyState, type ListPageFilter, type ListPageLabels, type ListPageProps, PageHeader, type PageHeaderBackProps, type PageHeaderBackRenderProps, type PageHeaderHeadingLevel, type PageHeaderProps, type PaginationState, RadioGroup, RadioGroupItem, type RadioGroupOption, type RadioGroupOrientation, type RadioGroupProps, type RadioGroupSize, type RowSelectionState, Select, type SelectOption, type SelectProps, type SelectSize, type SelectVariant, Sidebar, SidebarFooter, type SidebarFooterProps, SidebarGroup, type SidebarGroupProps, SidebarHeader, type SidebarHeaderProps, SidebarNav, SidebarNavGroup, type SidebarNavGroupProps, SidebarNavItem, type SidebarNavItemProps, type SidebarNavItemRenderProps, type SidebarNavProps, type SidebarProps, type SortDirection, type SortState,
|
|
2141
|
+
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, type AlertDialogContentProps, AlertDialogDescription, type AlertDialogDescriptionProps, AlertDialogFooter, type AlertDialogFooterProps, AlertDialogHeader, type AlertDialogHeaderProps, AlertDialogOverlay, type AlertDialogOverlayProps, AlertDialogPortal, AlertDialogTitle, type AlertDialogTitleProps, AlertDialogTrigger, AppShell, type AppShellBrand, type AppShellNavGroup, type AppShellNavItem, type AppShellProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, type CheckboxSize, type Column, type ColumnAlign, type ConfirmDialogLabels, ConfirmDialogProvider, type ConfirmDialogProviderProps, type ConfirmOptions, DashboardContent, type DashboardContentProps, DashboardHeader, type DashboardHeaderProps, DashboardLayout, type DashboardLayoutContextValue, type DashboardLayoutProps, DashboardMain, type DashboardMainProps, DatePicker, type DatePickerProps, type DatePickerSize, type DatePickerVariant, DetailPage, type DetailPageLabels, type DetailPageNotFoundState, type DetailPageProps, Dialog, DialogClose, DialogContent, type DialogContentProps, DialogDescription, type DialogDescriptionProps, DialogFooter, type DialogFooterProps, DialogHeader, type DialogHeaderProps, DialogOverlay, type DialogOverlayProps, DialogPortal, DialogTitle, type DialogTitleProps, DialogTrigger, type Direction, DropdownMenu, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuItemVariant, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, DropdownMenuSeparator, type DropdownMenuSeparatorProps, DropdownMenuShortcut, type DropdownMenuShortcutProps, DropdownMenuTrigger, EmptyState, type EmptyStateProps, type EmptyStateSize, Field, type FieldOrientation, type FieldProps, type FieldRHFProps, FormPage, type FormPageLabels, type FormPageProps, HeaderActions, type HeaderActionsProps, HeaderCollapseTrigger, type HeaderCollapseTriggerProps, HeaderMobileTrigger, type HeaderMobileTriggerProps, HeaderSearch, type HeaderSearchProps, HeaderTitle, type HeaderTitleProps, Input, type InputProps, type InputSize, type InputVariant, type LanguageOption, LanguageSwitcher, type LanguageSwitcherProps, ListPage, type ListPageEmptyState, type ListPageFilter, type ListPageLabels, type ListPageProps, PageHeader, type PageHeaderBackProps, type PageHeaderBackRenderProps, type PageHeaderHeadingLevel, type PageHeaderProps, type PaginationState, RadioGroup, RadioGroupItem, type RadioGroupOption, type RadioGroupOrientation, type RadioGroupProps, type RadioGroupSize, type RowSelectionState, Select, type SelectOption, type SelectProps, type SelectSize, type SelectVariant, Sidebar, SidebarFooter, type SidebarFooterProps, SidebarGroup, type SidebarGroupProps, SidebarHeader, type SidebarHeaderProps, SidebarNav, SidebarNavGroup, type SidebarNavGroupProps, SidebarNavItem, type SidebarNavItemProps, type SidebarNavItemRenderProps, type SidebarNavProps, type SidebarProps, type SortDirection, type SortState, Switch, type SwitchProps, type SwitchSize, Table, type TableLabels, type TableProps, type TableSize, type TableSizeClasses, Textarea, type TextareaProps, type TextareaResize, type TextareaSize, type TextareaVariant, Toaster, type ToasterProps, Tooltip, type TooltipProps, TooltipProvider, type TooltipProviderProps, badgeBaseClass, badgeDotSizeClass, badgeSizeClass, badgeVariantClass, buttonBaseClass, buttonSizeClass, buttonVariantClass, cn, datePickerCalendarClass, datePickerCaptionClass, datePickerContentClass, datePickerDayBaseClass, datePickerDayWrapperClass, datePickerDisabledClass, datePickerMonthClass, datePickerMonthGridClass, datePickerMonthsClass, datePickerNavButtonClass, datePickerNavClass, datePickerOutsideClass, datePickerPlaceholderClass, datePickerSelectedClass, datePickerTodayClass, datePickerTriggerBaseClass, datePickerTriggerSizeClass, datePickerTriggerVariantClass, datePickerValueClass, datePickerWeekClass, datePickerWeekdayClass, datePickerWeekdaysClass, detailPageBaseClass, detailPageBodyClass, detailPageEmptyClass, detailPageSkeletonRowClass, dialogCloseButtonClass, dialogContentClass, dialogDescriptionClass, dialogFooterClass, dialogHeaderClass, dialogOverlayClass, dialogTitleClass, dropdownMenuContentClass, dropdownMenuItemBaseClass, dropdownMenuItemInsetClass, dropdownMenuItemVariantClass, dropdownMenuLabelClass, dropdownMenuSeparatorClass, dropdownMenuShortcutClass, emptyStateActionsSpacingClass, emptyStateBaseClass, emptyStateContainerSizeClass, emptyStateDescriptionSizeClass, emptyStateIconWrapperBaseClass, emptyStateIconWrapperSizeClass, emptyStateTitleSizeClass, formPageActionsBarClass, formPageBaseClass, formPageBodyClass, formPageSkeletonRowClass, inputBaseClass, inputSizeClass, inputVariantClass, pageHeaderActionsClass, pageHeaderBackClass, pageHeaderBackIconClass, pageHeaderBaseClass, pageHeaderBorderedClass, pageHeaderBreadcrumbsClass, pageHeaderDescriptionClass, pageHeaderTitleBlockClass, pageHeaderTitleClass, pageHeaderTitleRowClass, radioGroupBaseClass, radioGroupOrientationClass, radioIndicatorBaseClass, radioIndicatorDotClass, radioIndicatorSizeClass, radioItemBaseClass, radioItemSizeClass, radioLabelSizeClass, radioOptionRowClass, selectBaseClass, selectSizeClass, selectVariantClass, switchThumbBaseClass, switchThumbClass, switchTrackBaseClass, switchTrackClass, alignClass as tableAlignClass, tableBaseClass, selectedRowClass as tableSelectedRowClass, tableSizeClass, sortIconClass as tableSortIconClass, textareaBaseClass, textareaResizeClass, textareaSizeClass, textareaVariantClass, toastClassNames, tooltipArrowClass, tooltipContentClass, useConfirm, useDashboardLayout, useDirection };
|