@cfast/ui 0.1.0 → 0.2.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 +23 -23
- package/dist/chunk-PWBG6CGF.js +1400 -0
- package/dist/{permission-gate-DVmY42oz.d.ts → client-CIx8_tmv.d.ts} +617 -2
- package/dist/client.d.ts +4 -617
- package/dist/client.js +6 -8
- package/dist/index.d.ts +52 -5
- package/dist/index.js +17 -13
- package/llms.txt +6 -6
- package/package.json +5 -29
- package/dist/chunk-JEGEIQ3R.js +0 -925
- package/dist/chunk-RDTUEOLK.js +0 -486
- package/dist/joy.d.ts +0 -199
- package/dist/joy.js +0 -1150
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
2
3
|
import { ReactNode, ComponentType } from 'react';
|
|
3
4
|
import { ActionHookResult, ClientDescriptor } from '@cfast/actions/client';
|
|
4
5
|
|
|
@@ -52,7 +53,7 @@ type UIPluginComponents = {
|
|
|
52
53
|
* A UI plugin providing styled component implementations for plugin slots.
|
|
53
54
|
*
|
|
54
55
|
* Created via `createUIPlugin()`. Slots not provided fall back to the headless
|
|
55
|
-
* defaults (unstyled HTML elements). The Joy UI plugin (`@cfast/
|
|
56
|
+
* defaults (unstyled HTML elements). The Joy UI plugin (`@cfast/joy`) is the
|
|
56
57
|
* built-in implementation; third-party plugins can target shadcn, Mantine, or
|
|
57
58
|
* any other component library.
|
|
58
59
|
*
|
|
@@ -1245,6 +1246,219 @@ type NavigationProgressProps = {
|
|
|
1245
1246
|
color?: string;
|
|
1246
1247
|
};
|
|
1247
1248
|
|
|
1249
|
+
/**
|
|
1250
|
+
* Creates a {@link UIPlugin} that maps component slots to styled implementations.
|
|
1251
|
+
*
|
|
1252
|
+
* Slots not provided in the `components` map fall back to the unstyled HTML
|
|
1253
|
+
* defaults from the headless layer. This allows incremental adoption -- implement
|
|
1254
|
+
* only the slots your design system covers.
|
|
1255
|
+
*
|
|
1256
|
+
* @param config - Plugin configuration object.
|
|
1257
|
+
* @param config.components - Partial map of slot names to styled component implementations.
|
|
1258
|
+
* See {@link UIPluginComponents} for available slots.
|
|
1259
|
+
* @returns A {@link UIPlugin} instance to pass to {@link UIPluginProvider}.
|
|
1260
|
+
*
|
|
1261
|
+
* @example
|
|
1262
|
+
* ```ts
|
|
1263
|
+
* import { createUIPlugin } from "@cfast/ui";
|
|
1264
|
+
*
|
|
1265
|
+
* const joyPlugin = createUIPlugin({
|
|
1266
|
+
* components: {
|
|
1267
|
+
* button: JoyButton,
|
|
1268
|
+
* table: JoyTable,
|
|
1269
|
+
* chip: JoyChip,
|
|
1270
|
+
* },
|
|
1271
|
+
* });
|
|
1272
|
+
* ```
|
|
1273
|
+
*/
|
|
1274
|
+
declare function createUIPlugin(config: {
|
|
1275
|
+
components: Partial<UIPluginComponents>;
|
|
1276
|
+
}): UIPlugin;
|
|
1277
|
+
/**
|
|
1278
|
+
* React context provider that makes a {@link UIPlugin} available to all `@cfast/ui` components.
|
|
1279
|
+
*
|
|
1280
|
+
* Place this near the root of your component tree (typically in the root layout).
|
|
1281
|
+
* All headless components use {@link useComponent} internally to resolve their
|
|
1282
|
+
* styled implementations from this context.
|
|
1283
|
+
*
|
|
1284
|
+
* @param props - Component props.
|
|
1285
|
+
* @param props.plugin - The UI plugin created by {@link createUIPlugin}.
|
|
1286
|
+
* @param props.children - Child elements that can access the plugin via
|
|
1287
|
+
* {@link useUIPlugin} or {@link useComponent}.
|
|
1288
|
+
* @returns A React element wrapping children with the UI plugin context.
|
|
1289
|
+
*
|
|
1290
|
+
* @example
|
|
1291
|
+
* ```tsx
|
|
1292
|
+
* import { UIPluginProvider, createUIPlugin } from "@cfast/ui";
|
|
1293
|
+
*
|
|
1294
|
+
* const plugin = createUIPlugin({ components: { button: MyButton } });
|
|
1295
|
+
*
|
|
1296
|
+
* function Root() {
|
|
1297
|
+
* return (
|
|
1298
|
+
* <UIPluginProvider plugin={plugin}>
|
|
1299
|
+
* <App />
|
|
1300
|
+
* </UIPluginProvider>
|
|
1301
|
+
* );
|
|
1302
|
+
* }
|
|
1303
|
+
* ```
|
|
1304
|
+
*/
|
|
1305
|
+
declare function UIPluginProvider({ plugin, children, }: {
|
|
1306
|
+
plugin: UIPlugin;
|
|
1307
|
+
children: React.ReactNode;
|
|
1308
|
+
}): react_jsx_runtime.JSX.Element;
|
|
1309
|
+
/**
|
|
1310
|
+
* Returns the current {@link UIPlugin} from React context.
|
|
1311
|
+
*
|
|
1312
|
+
* Returns `null` if no {@link UIPluginProvider} is present in the component tree.
|
|
1313
|
+
* Most consumers should use {@link useComponent} instead, which handles the
|
|
1314
|
+
* fallback to headless defaults automatically.
|
|
1315
|
+
*
|
|
1316
|
+
* @returns The active {@link UIPlugin}, or `null` if no provider is mounted.
|
|
1317
|
+
*
|
|
1318
|
+
* @example
|
|
1319
|
+
* ```ts
|
|
1320
|
+
* const plugin = useUIPlugin();
|
|
1321
|
+
* if (plugin?.components.button) {
|
|
1322
|
+
* // A custom button implementation is available
|
|
1323
|
+
* }
|
|
1324
|
+
* ```
|
|
1325
|
+
*/
|
|
1326
|
+
declare function useUIPlugin(): UIPlugin | null;
|
|
1327
|
+
/**
|
|
1328
|
+
* Resolves a component for a given {@link UIPluginComponents} slot.
|
|
1329
|
+
*
|
|
1330
|
+
* Looks up the slot in the current {@link UIPlugin} (via {@link useUIPlugin}).
|
|
1331
|
+
* If the plugin provides an implementation for the slot, that component is returned.
|
|
1332
|
+
* Otherwise, the headless HTML default is returned. This ensures every component
|
|
1333
|
+
* renders correctly even without a UI plugin installed.
|
|
1334
|
+
*
|
|
1335
|
+
* @typeParam K - The slot key from {@link UIPluginComponents}.
|
|
1336
|
+
* @param slot - The component slot name to resolve (e.g., `"button"`, `"table"`, `"chip"`).
|
|
1337
|
+
* @returns The component implementation for the given slot.
|
|
1338
|
+
*
|
|
1339
|
+
* @example
|
|
1340
|
+
* ```ts
|
|
1341
|
+
* function MyComponent() {
|
|
1342
|
+
* const Button = useComponent("button");
|
|
1343
|
+
* const Chip = useComponent("chip");
|
|
1344
|
+
*
|
|
1345
|
+
* return <Button onClick={handleClick}>Click me</Button>;
|
|
1346
|
+
* }
|
|
1347
|
+
* ```
|
|
1348
|
+
*/
|
|
1349
|
+
declare function useComponent<K extends keyof UIPluginComponents>(slot: K): UIPluginComponents[K];
|
|
1350
|
+
|
|
1351
|
+
/**
|
|
1352
|
+
* Function signature for the imperative confirmation dialog.
|
|
1353
|
+
*
|
|
1354
|
+
* Call with {@link ConfirmOptions} to show a dialog. Resolves to `true` if
|
|
1355
|
+
* the user confirms, or `false` if they cancel or dismiss.
|
|
1356
|
+
*/
|
|
1357
|
+
type ConfirmFn = (options: ConfirmOptions) => Promise<boolean>;
|
|
1358
|
+
/**
|
|
1359
|
+
* Returns an imperative {@link ConfirmFn} that opens a confirmation dialog
|
|
1360
|
+
* and resolves to `true` (confirmed) or `false` (cancelled/dismissed).
|
|
1361
|
+
*
|
|
1362
|
+
* Must be used within a `ConfirmProvider` -- typically supplied by the
|
|
1363
|
+
* Joy UI plugin or a custom UI plugin implementation.
|
|
1364
|
+
*
|
|
1365
|
+
* @returns A {@link ConfirmFn} that accepts {@link ConfirmOptions} and returns a `Promise<boolean>`.
|
|
1366
|
+
* @throws {Error} If called outside of a `ConfirmProvider`.
|
|
1367
|
+
*
|
|
1368
|
+
* @example
|
|
1369
|
+
* ```ts
|
|
1370
|
+
* function DangerZone() {
|
|
1371
|
+
* const confirm = useConfirm();
|
|
1372
|
+
*
|
|
1373
|
+
* async function handleDelete() {
|
|
1374
|
+
* const ok = await confirm({
|
|
1375
|
+
* title: "Delete account",
|
|
1376
|
+
* description: "This action cannot be undone.",
|
|
1377
|
+
* confirmLabel: "Delete",
|
|
1378
|
+
* variant: "danger",
|
|
1379
|
+
* });
|
|
1380
|
+
* if (ok) { /* proceed *\/ }
|
|
1381
|
+
* }
|
|
1382
|
+
*
|
|
1383
|
+
* return <button onClick={handleDelete}>Delete</button>;
|
|
1384
|
+
* }
|
|
1385
|
+
* ```
|
|
1386
|
+
*/
|
|
1387
|
+
declare function useConfirm(): ConfirmFn;
|
|
1388
|
+
|
|
1389
|
+
type ToastContextValue = {
|
|
1390
|
+
show: (options: ToastOptions) => void;
|
|
1391
|
+
};
|
|
1392
|
+
declare const ToastContext: react.Context<ToastContextValue | null>;
|
|
1393
|
+
/**
|
|
1394
|
+
* Returns an imperative {@link ToastApi} for showing toast notifications.
|
|
1395
|
+
*
|
|
1396
|
+
* Provides convenience methods (`success`, `error`, `info`, `warning`) as well
|
|
1397
|
+
* as a generic `show` method that accepts full {@link ToastOptions}.
|
|
1398
|
+
*
|
|
1399
|
+
* Must be used within a `ToastProvider` -- typically supplied by the Joy UI
|
|
1400
|
+
* plugin (backed by Sonner) or a custom UI plugin implementation.
|
|
1401
|
+
*
|
|
1402
|
+
* @returns A {@link ToastApi} object with methods for each notification type.
|
|
1403
|
+
* @throws {Error} If called outside of a `ToastProvider`.
|
|
1404
|
+
*
|
|
1405
|
+
* @example
|
|
1406
|
+
* ```ts
|
|
1407
|
+
* function PublishButton() {
|
|
1408
|
+
* const toast = useToast();
|
|
1409
|
+
*
|
|
1410
|
+
* async function handlePublish() {
|
|
1411
|
+
* try {
|
|
1412
|
+
* await publishPost();
|
|
1413
|
+
* toast.success("Post published");
|
|
1414
|
+
* } catch (err) {
|
|
1415
|
+
* toast.error("Failed to publish post");
|
|
1416
|
+
* }
|
|
1417
|
+
* }
|
|
1418
|
+
*
|
|
1419
|
+
* return <button onClick={handlePublish}>Publish</button>;
|
|
1420
|
+
* }
|
|
1421
|
+
* ```
|
|
1422
|
+
*/
|
|
1423
|
+
declare function useToast(): ToastApi;
|
|
1424
|
+
|
|
1425
|
+
/**
|
|
1426
|
+
* Maps action names to their success/error toast messages.
|
|
1427
|
+
*
|
|
1428
|
+
* Each key is an action name from a {@link ClientDescriptor}, and the value
|
|
1429
|
+
* specifies the toast messages to show when that action succeeds or fails.
|
|
1430
|
+
*/
|
|
1431
|
+
type ActionToastConfig = Record<string, {
|
|
1432
|
+
success?: string;
|
|
1433
|
+
error?: string;
|
|
1434
|
+
}>;
|
|
1435
|
+
/**
|
|
1436
|
+
* Automatically shows toast notifications when `@cfast/actions` results arrive.
|
|
1437
|
+
*
|
|
1438
|
+
* Watches all configured actions via their {@link ClientDescriptor} and triggers
|
|
1439
|
+
* success or error toasts when their result data changes. Internally uses
|
|
1440
|
+
* {@link useToast} and `useActions` from `@cfast/actions/client`.
|
|
1441
|
+
*
|
|
1442
|
+
* Must be used within both a `ToastProvider` and an actions context
|
|
1443
|
+
* (i.e., inside `app.Provider`).
|
|
1444
|
+
*
|
|
1445
|
+
* @param descriptor - Client-side action descriptor from `@cfast/actions`, typically
|
|
1446
|
+
* `composed.client` from a `createActions()` call.
|
|
1447
|
+
* @param config - Map of action names to toast messages. Only actions listed here
|
|
1448
|
+
* are watched; others are ignored.
|
|
1449
|
+
* @returns void
|
|
1450
|
+
*
|
|
1451
|
+
* @example
|
|
1452
|
+
* ```ts
|
|
1453
|
+
* // In a route component:
|
|
1454
|
+
* useActionToast(composed.client, {
|
|
1455
|
+
* deletePost: { success: "Post deleted", error: "Failed to delete" },
|
|
1456
|
+
* publishPost: { success: "Post published" },
|
|
1457
|
+
* });
|
|
1458
|
+
* ```
|
|
1459
|
+
*/
|
|
1460
|
+
declare function useActionToast(descriptor: ClientDescriptor, config: ActionToastConfig): void;
|
|
1461
|
+
|
|
1248
1462
|
/**
|
|
1249
1463
|
* Conditionally renders children based on action permission status.
|
|
1250
1464
|
*
|
|
@@ -1266,4 +1480,405 @@ type NavigationProgressProps = {
|
|
|
1266
1480
|
*/
|
|
1267
1481
|
declare function PermissionGate({ action, children, fallback, }: PermissionGateProps): react_jsx_runtime.JSX.Element | null;
|
|
1268
1482
|
|
|
1269
|
-
|
|
1483
|
+
/**
|
|
1484
|
+
* Permission-aware button that submits a `@cfast/actions` action.
|
|
1485
|
+
*
|
|
1486
|
+
* Accepts an `ActionHookResult` from `useActions()` and renders a button
|
|
1487
|
+
* via the UI plugin's `button` slot. The button's visibility and disabled
|
|
1488
|
+
* state are controlled by the action's permission status. Extra props are
|
|
1489
|
+
* forwarded to the underlying button component.
|
|
1490
|
+
*
|
|
1491
|
+
* - `whenForbidden="hide"` -- hidden when not permitted
|
|
1492
|
+
* - `whenForbidden="disable"` -- shown but disabled when not permitted (default)
|
|
1493
|
+
* - `whenForbidden="show"` -- shown and clickable regardless of permission
|
|
1494
|
+
*
|
|
1495
|
+
* @param props - See {@link ActionButtonProps}.
|
|
1496
|
+
*
|
|
1497
|
+
* @example
|
|
1498
|
+
* ```tsx
|
|
1499
|
+
* <ActionButton
|
|
1500
|
+
* action={publishPost}
|
|
1501
|
+
* whenForbidden="disable"
|
|
1502
|
+
* confirmation="Publish this post?"
|
|
1503
|
+
* >
|
|
1504
|
+
* Publish
|
|
1505
|
+
* </ActionButton>
|
|
1506
|
+
* ```
|
|
1507
|
+
*/
|
|
1508
|
+
declare function ActionButton({ action, children, whenForbidden, confirmation: _confirmation, ...buttonProps }: ActionButtonProps): react_jsx_runtime.JSX.Element | null;
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* Provides the {@link useConfirm} context and renders the confirmation dialog.
|
|
1512
|
+
*
|
|
1513
|
+
* Wrap your application (or a subtree) with `ConfirmProvider` to enable the
|
|
1514
|
+
* imperative `useConfirm()` hook. The dialog is rendered using the UI plugin's
|
|
1515
|
+
* `confirmDialog` slot, so it matches your chosen component library.
|
|
1516
|
+
*
|
|
1517
|
+
* @param props.children - The React tree that can call `useConfirm()`.
|
|
1518
|
+
*
|
|
1519
|
+
* @example
|
|
1520
|
+
* ```tsx
|
|
1521
|
+
* // In your root layout:
|
|
1522
|
+
* <ConfirmProvider>
|
|
1523
|
+
* <App />
|
|
1524
|
+
* </ConfirmProvider>
|
|
1525
|
+
*
|
|
1526
|
+
* // In any descendant component:
|
|
1527
|
+
* const confirm = useConfirm();
|
|
1528
|
+
* const ok = await confirm({ title: "Delete?", variant: "danger" });
|
|
1529
|
+
* ```
|
|
1530
|
+
*/
|
|
1531
|
+
declare function ConfirmProvider({ children }: {
|
|
1532
|
+
children: ReactNode;
|
|
1533
|
+
}): react_jsx_runtime.JSX.Element;
|
|
1534
|
+
|
|
1535
|
+
/**
|
|
1536
|
+
* Displays action result feedback (success, error, and field-level validation messages).
|
|
1537
|
+
*
|
|
1538
|
+
* Renders alerts via the UI plugin's `alert` slot. Success messages are shown
|
|
1539
|
+
* in green, errors in red, and field-level validation errors as a bulleted list.
|
|
1540
|
+
* Returns `null` when there is no feedback to display.
|
|
1541
|
+
*
|
|
1542
|
+
* @param props - See {@link FormStatusProps}.
|
|
1543
|
+
*
|
|
1544
|
+
* @example
|
|
1545
|
+
* ```tsx
|
|
1546
|
+
* function EditForm() {
|
|
1547
|
+
* const actionData = useActionData();
|
|
1548
|
+
* return (
|
|
1549
|
+
* <Form method="post">
|
|
1550
|
+
* <FormStatus data={actionData} />
|
|
1551
|
+
* ...
|
|
1552
|
+
* </Form>
|
|
1553
|
+
* );
|
|
1554
|
+
* }
|
|
1555
|
+
* ```
|
|
1556
|
+
*/
|
|
1557
|
+
declare function FormStatus({ data }: FormStatusProps): react_jsx_runtime.JSX.Element | null;
|
|
1558
|
+
|
|
1559
|
+
/**
|
|
1560
|
+
* Extracts up to two uppercase initials from a full name.
|
|
1561
|
+
*
|
|
1562
|
+
* Splits the name on spaces and takes the first character of each part.
|
|
1563
|
+
*
|
|
1564
|
+
* @param name - The full name to extract initials from.
|
|
1565
|
+
* @returns A string of 1-2 uppercase characters (e.g. `"DS"` for `"Daniel Schmidt"`).
|
|
1566
|
+
*
|
|
1567
|
+
* @example
|
|
1568
|
+
* ```ts
|
|
1569
|
+
* getInitials("Daniel Schmidt"); // "DS"
|
|
1570
|
+
* getInitials("Alice"); // "A"
|
|
1571
|
+
* ```
|
|
1572
|
+
*/
|
|
1573
|
+
declare function getInitials(name: string): string;
|
|
1574
|
+
/**
|
|
1575
|
+
* Avatar component with automatic initials fallback.
|
|
1576
|
+
*
|
|
1577
|
+
* Renders an `<img>` when a `src` URL is provided. When `src` is absent or null,
|
|
1578
|
+
* displays the user's initials (derived via {@link getInitials}) inside a circular
|
|
1579
|
+
* badge. This is the headless implementation; styled versions are provided by UI plugins.
|
|
1580
|
+
*
|
|
1581
|
+
* @param props - See {@link AvatarWithInitialsProps}.
|
|
1582
|
+
*
|
|
1583
|
+
* @example
|
|
1584
|
+
* ```tsx
|
|
1585
|
+
* <AvatarWithInitials
|
|
1586
|
+
* src={user.avatarUrl}
|
|
1587
|
+
* name={user.name}
|
|
1588
|
+
* size="sm"
|
|
1589
|
+
* />
|
|
1590
|
+
* ```
|
|
1591
|
+
*/
|
|
1592
|
+
declare function AvatarWithInitials({ src, name, size, }: AvatarWithInitialsProps): react_jsx_runtime.JSX.Element;
|
|
1593
|
+
|
|
1594
|
+
/**
|
|
1595
|
+
* Colored badge displaying a user's role name.
|
|
1596
|
+
*
|
|
1597
|
+
* Renders via the UI plugin's `chip` slot. Default color mapping:
|
|
1598
|
+
* admin = danger, editor = primary, author = success, reader = neutral.
|
|
1599
|
+
* Pass a custom `colors` map to override or extend the defaults.
|
|
1600
|
+
*
|
|
1601
|
+
* @param props - See {@link RoleBadgeProps}.
|
|
1602
|
+
*
|
|
1603
|
+
* @example
|
|
1604
|
+
* ```tsx
|
|
1605
|
+
* <RoleBadge role="admin" />
|
|
1606
|
+
* // Custom colors:
|
|
1607
|
+
* <RoleBadge role="moderator" colors={{ moderator: "warning" }} />
|
|
1608
|
+
* ```
|
|
1609
|
+
*/
|
|
1610
|
+
declare function RoleBadge({ role, colors }: RoleBadgeProps): react_jsx_runtime.JSX.Element;
|
|
1611
|
+
|
|
1612
|
+
/**
|
|
1613
|
+
* Persistent banner shown when an admin is impersonating another user.
|
|
1614
|
+
*
|
|
1615
|
+
* Reads the current user from `@cfast/auth` via `useCurrentUser()`. When the
|
|
1616
|
+
* user has `isImpersonating` set, renders a warning alert with the impersonated
|
|
1617
|
+
* user's name/email and a "Stop Impersonating" button that posts to `stopAction`.
|
|
1618
|
+
* Hidden when not impersonating.
|
|
1619
|
+
*
|
|
1620
|
+
* @param props - See {@link ImpersonationBannerProps}.
|
|
1621
|
+
*
|
|
1622
|
+
* @example
|
|
1623
|
+
* ```tsx
|
|
1624
|
+
* // In your root layout:
|
|
1625
|
+
* <ImpersonationBanner />
|
|
1626
|
+
*
|
|
1627
|
+
* // With custom stop action URL:
|
|
1628
|
+
* <ImpersonationBanner stopAction="/api/stop-impersonation" />
|
|
1629
|
+
* ```
|
|
1630
|
+
*/
|
|
1631
|
+
declare function ImpersonationBanner({ stopAction, }: ImpersonationBannerProps): react_jsx_runtime.JSX.Element | null;
|
|
1632
|
+
|
|
1633
|
+
/**
|
|
1634
|
+
* Data table with column sorting, row selection, and pluggable cell rendering.
|
|
1635
|
+
*
|
|
1636
|
+
* Renders via the UI plugin's table slots (`table`, `tableHead`, `tableBody`,
|
|
1637
|
+
* `tableRow`, `tableCell`). Accepts column definitions as strings (auto-labeled)
|
|
1638
|
+
* or full {@link ColumnDef} objects for custom labels, sorting, and renderers.
|
|
1639
|
+
*
|
|
1640
|
+
* Integrates with `@cfast/pagination` hook results for paginated data and with
|
|
1641
|
+
* `@cfast/actions` for row-level actions.
|
|
1642
|
+
*
|
|
1643
|
+
* @typeParam T - The row data type.
|
|
1644
|
+
* @param props - See {@link DataTableProps}.
|
|
1645
|
+
*
|
|
1646
|
+
* @example
|
|
1647
|
+
* ```tsx
|
|
1648
|
+
* const pagination = usePagination<Post>();
|
|
1649
|
+
*
|
|
1650
|
+
* <DataTable
|
|
1651
|
+
* data={pagination}
|
|
1652
|
+
* columns={["title", "author", { key: "createdAt", sortable: false }]}
|
|
1653
|
+
* selectable
|
|
1654
|
+
* onRowClick={(row) => navigate(`/posts/${row.id}`)}
|
|
1655
|
+
* />
|
|
1656
|
+
* ```
|
|
1657
|
+
*/
|
|
1658
|
+
declare function DataTable<T = unknown>({ data, columns: columnsProp, selectable, selectedRows: externalSelectedRows, onSelectionChange, onRowClick, getRowId, emptyMessage, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
|
|
1659
|
+
|
|
1660
|
+
/**
|
|
1661
|
+
* URL-synced filter controls for data tables and list views.
|
|
1662
|
+
*
|
|
1663
|
+
* Each filter serializes its state to URL search params (e.g., `?published=true`).
|
|
1664
|
+
* On filter change, React Router navigates with the updated params, resetting
|
|
1665
|
+
* pagination to page 1. In the loader, `@cfast/pagination`'s `parseParams()`
|
|
1666
|
+
* reads these params and applies them as Drizzle `where` clauses.
|
|
1667
|
+
*
|
|
1668
|
+
* Supports text, select, boolean, and other filter types via {@link FilterDef}.
|
|
1669
|
+
* An optional `searchable` prop adds a full-text search input across specified columns.
|
|
1670
|
+
*
|
|
1671
|
+
* @param props - See {@link FilterBarProps}.
|
|
1672
|
+
*
|
|
1673
|
+
* @example
|
|
1674
|
+
* ```tsx
|
|
1675
|
+
* <FilterBar
|
|
1676
|
+
* filters={[
|
|
1677
|
+
* { column: "published", type: "select", options: [
|
|
1678
|
+
* { label: "Published", value: "true" },
|
|
1679
|
+
* { label: "Draft", value: "false" },
|
|
1680
|
+
* ]},
|
|
1681
|
+
* { column: "createdAt", type: "dateRange" },
|
|
1682
|
+
* ]}
|
|
1683
|
+
* searchable={["title", "content"]}
|
|
1684
|
+
* />
|
|
1685
|
+
* ```
|
|
1686
|
+
*/
|
|
1687
|
+
declare function FilterBar({ filters, searchable, }: FilterBarProps): react_jsx_runtime.JSX.Element;
|
|
1688
|
+
|
|
1689
|
+
type BulkActionBarProps = {
|
|
1690
|
+
selectedCount: number;
|
|
1691
|
+
actions: BulkAction[];
|
|
1692
|
+
onAction: (action: BulkAction) => void;
|
|
1693
|
+
onClearSelection: () => void;
|
|
1694
|
+
};
|
|
1695
|
+
/**
|
|
1696
|
+
* Toolbar that appears when rows are selected in a {@link DataTable}.
|
|
1697
|
+
*
|
|
1698
|
+
* Displays the selected row count, action buttons for each {@link BulkAction},
|
|
1699
|
+
* and a "Clear" button to deselect all rows. Actions are rendered via the UI
|
|
1700
|
+
* plugin's `button` slot. Hidden automatically when `selectedCount` is zero.
|
|
1701
|
+
*
|
|
1702
|
+
* @param props - See {@link BulkActionBarProps}.
|
|
1703
|
+
*
|
|
1704
|
+
* @example
|
|
1705
|
+
* ```tsx
|
|
1706
|
+
* <BulkActionBar
|
|
1707
|
+
* selectedCount={selectedRows.length}
|
|
1708
|
+
* actions={[
|
|
1709
|
+
* { label: "Delete", icon: TrashIcon },
|
|
1710
|
+
* { label: "Publish" },
|
|
1711
|
+
* ]}
|
|
1712
|
+
* onAction={(action) => handleBulk(action, selectedRows)}
|
|
1713
|
+
* onClearSelection={() => clearSelection()}
|
|
1714
|
+
* />
|
|
1715
|
+
* ```
|
|
1716
|
+
*/
|
|
1717
|
+
declare function BulkActionBar({ selectedCount, actions, onAction, onClearSelection, }: BulkActionBarProps): react_jsx_runtime.JSX.Element | null;
|
|
1718
|
+
|
|
1719
|
+
/** A column definition extended with an inferred TypedField component. */
|
|
1720
|
+
type InferredColumn = ColumnDef & {
|
|
1721
|
+
/** The field component that renders the appropriate display for this column type. */
|
|
1722
|
+
field: ComponentType<{
|
|
1723
|
+
value: unknown;
|
|
1724
|
+
}>;
|
|
1725
|
+
};
|
|
1726
|
+
/**
|
|
1727
|
+
* Inspects a Drizzle table's columns and returns inferred {@link ColumnDef} entries
|
|
1728
|
+
* with appropriate TypedField components attached.
|
|
1729
|
+
*
|
|
1730
|
+
* Uses {@link fieldForColumn} internally to map each Drizzle column's `dataType`
|
|
1731
|
+
* to a display component (e.g., `DateField`, `BooleanField`, `TextField`).
|
|
1732
|
+
* Labels are auto-derived from camelCase column keys.
|
|
1733
|
+
*
|
|
1734
|
+
* Memoized -- only recomputes when the `table` reference or `columns` array changes.
|
|
1735
|
+
*
|
|
1736
|
+
* @param table - A Drizzle table object whose entries expose `dataType` and `name` metadata.
|
|
1737
|
+
* Pass `undefined` to return an empty array (safe for conditional rendering).
|
|
1738
|
+
* @param columns - Optional subset of column names to include. When provided,
|
|
1739
|
+
* only matching columns are returned and their order is preserved.
|
|
1740
|
+
* @returns Array of {@link InferredColumn} definitions, each containing a `field`
|
|
1741
|
+
* component ready for rendering.
|
|
1742
|
+
*
|
|
1743
|
+
* @example
|
|
1744
|
+
* ```ts
|
|
1745
|
+
* import { useColumnInference } from "@cfast/ui";
|
|
1746
|
+
* import { posts } from "~/db/schema";
|
|
1747
|
+
*
|
|
1748
|
+
* const cols = useColumnInference(posts, ["title", "createdAt", "published"]);
|
|
1749
|
+
* // cols[0].field === TextField
|
|
1750
|
+
* // cols[1].field === DateField
|
|
1751
|
+
* // cols[2].field === BooleanField
|
|
1752
|
+
* ```
|
|
1753
|
+
*/
|
|
1754
|
+
declare function useColumnInference(table: Record<string, unknown> | undefined, columns?: string[]): InferredColumn[];
|
|
1755
|
+
|
|
1756
|
+
/**
|
|
1757
|
+
* Drag-and-drop file upload area that integrates with `@cfast/storage`.
|
|
1758
|
+
*
|
|
1759
|
+
* Accepts an `upload` result from `useUpload()` (`@cfast/storage/client`).
|
|
1760
|
+
* File type restrictions and max size are inherited from the storage schema.
|
|
1761
|
+
* Renders via the UI plugin's `dropZone` slot and manages drag state,
|
|
1762
|
+
* file validation, and upload progress internally.
|
|
1763
|
+
*
|
|
1764
|
+
* @param props - See {@link DropZoneProps}.
|
|
1765
|
+
*
|
|
1766
|
+
* @example
|
|
1767
|
+
* ```tsx
|
|
1768
|
+
* const upload = useUpload("postCoverImage");
|
|
1769
|
+
*
|
|
1770
|
+
* <DropZone upload={upload} />
|
|
1771
|
+
*
|
|
1772
|
+
* // Allow multiple files:
|
|
1773
|
+
* <DropZone upload={upload} multiple />
|
|
1774
|
+
* ```
|
|
1775
|
+
*/
|
|
1776
|
+
declare function DropZone({ upload, multiple, children, }: DropZoneProps): react_jsx_runtime.JSX.Element;
|
|
1777
|
+
|
|
1778
|
+
/**
|
|
1779
|
+
* Displays an image from `@cfast/storage` or a direct URL.
|
|
1780
|
+
*
|
|
1781
|
+
* Resolves the display URL from either a direct `src`, or a `fileKey` + `getUrl`
|
|
1782
|
+
* resolver function (for signed URL generation). Shows a placeholder when no
|
|
1783
|
+
* image is available, or renders the `fallback` element if provided.
|
|
1784
|
+
*
|
|
1785
|
+
* @param props - See {@link ImagePreviewProps}.
|
|
1786
|
+
*
|
|
1787
|
+
* @example
|
|
1788
|
+
* ```tsx
|
|
1789
|
+
* <ImagePreview
|
|
1790
|
+
* fileKey={post.coverImageKey}
|
|
1791
|
+
* getUrl={(key) => storage.getSignedUrl(key)}
|
|
1792
|
+
* width={200}
|
|
1793
|
+
* height={150}
|
|
1794
|
+
* fallback={<PlaceholderImage />}
|
|
1795
|
+
* />
|
|
1796
|
+
* ```
|
|
1797
|
+
*/
|
|
1798
|
+
declare function ImagePreview({ fileKey, src, getUrl, width, height, fallback, alt, }: ImagePreviewProps): react_jsx_runtime.JSX.Element;
|
|
1799
|
+
|
|
1800
|
+
/**
|
|
1801
|
+
* Displays a list of uploaded files with metadata, formatted sizes, and download links.
|
|
1802
|
+
*
|
|
1803
|
+
* Each file is rendered as a row showing the file name, size (human-readable), and
|
|
1804
|
+
* a download link (either via `onDownload` callback or the file's direct `url`).
|
|
1805
|
+
* Returns a "No files" placeholder when the list is empty.
|
|
1806
|
+
*
|
|
1807
|
+
* @param props - See {@link FileListProps}.
|
|
1808
|
+
*
|
|
1809
|
+
* @example
|
|
1810
|
+
* ```tsx
|
|
1811
|
+
* <FileList
|
|
1812
|
+
* files={post.attachments}
|
|
1813
|
+
* onDownload={(file) => window.open(storage.getSignedUrl(file.key))}
|
|
1814
|
+
* />
|
|
1815
|
+
* ```
|
|
1816
|
+
*/
|
|
1817
|
+
declare function FileList$1({ files, onDownload, }: FileListProps): react_jsx_runtime.JSX.Element;
|
|
1818
|
+
|
|
1819
|
+
/**
|
|
1820
|
+
* Full-page list layout composing filters, data table, pagination, and empty state.
|
|
1821
|
+
*
|
|
1822
|
+
* Combines {@link PageContainer}, {@link FilterBar}, {@link DataTable},
|
|
1823
|
+
* {@link EmptyState}, {@link BulkActionBar}, and pagination controls into a
|
|
1824
|
+
* single component. This is the primary component used by `@cfast/admin` for
|
|
1825
|
+
* every table view, but it is equally useful in application code.
|
|
1826
|
+
*
|
|
1827
|
+
* Supports both offset-based pagination (page numbers) and cursor-based pagination
|
|
1828
|
+
* (load more). The `createAction` prop controls the visibility of the "Create" button
|
|
1829
|
+
* via permission checks.
|
|
1830
|
+
*
|
|
1831
|
+
* @typeParam T - The row data type.
|
|
1832
|
+
* @param props - See {@link ListViewProps}.
|
|
1833
|
+
*
|
|
1834
|
+
* @example
|
|
1835
|
+
* ```tsx
|
|
1836
|
+
* const pagination = useOffsetPagination<Post>();
|
|
1837
|
+
*
|
|
1838
|
+
* <ListView
|
|
1839
|
+
* title="Blog Posts"
|
|
1840
|
+
* data={pagination}
|
|
1841
|
+
* columns={["title", "author", "published", "createdAt"]}
|
|
1842
|
+
* filters={[{ column: "published", type: "select", options: publishedOptions }]}
|
|
1843
|
+
* searchable={["title", "content"]}
|
|
1844
|
+
* createAction={createPost.client}
|
|
1845
|
+
* selectable
|
|
1846
|
+
* bulkActions={[
|
|
1847
|
+
* { label: "Delete", handler: (rows) => bulkDelete(rows) },
|
|
1848
|
+
* ]}
|
|
1849
|
+
* />
|
|
1850
|
+
* ```
|
|
1851
|
+
*/
|
|
1852
|
+
declare function ListView<T = unknown>({ title, data, table: _table, columns, actions: _actions, filters, searchable, createAction, createLabel, selectable, bulkActions, breadcrumb, }: ListViewProps<T>): react_jsx_runtime.JSX.Element;
|
|
1853
|
+
|
|
1854
|
+
/**
|
|
1855
|
+
* Read-only detail page for a single record, rendered in a two-column grid.
|
|
1856
|
+
*
|
|
1857
|
+
* Composes {@link PageContainer} with automatic TypedField rendering. When a Drizzle
|
|
1858
|
+
* `table` is provided, field types are inferred from column metadata and rendered with
|
|
1859
|
+
* the appropriate field component (DateField, BooleanField, etc.). Fields can also be
|
|
1860
|
+
* specified manually as strings or full {@link ColumnDef} objects with custom renderers.
|
|
1861
|
+
*
|
|
1862
|
+
* If no `fields` are specified, they are inferred from the record's own keys
|
|
1863
|
+
* (minus any keys listed in `exclude`).
|
|
1864
|
+
*
|
|
1865
|
+
* @typeParam T - The record data type.
|
|
1866
|
+
* @param props - See {@link DetailViewProps}.
|
|
1867
|
+
*
|
|
1868
|
+
* @example
|
|
1869
|
+
* ```tsx
|
|
1870
|
+
* <DetailView
|
|
1871
|
+
* title={post.title}
|
|
1872
|
+
* table={posts}
|
|
1873
|
+
* record={post}
|
|
1874
|
+
* fields={["title", "content", "author", "published", "createdAt"]}
|
|
1875
|
+
* breadcrumb={[
|
|
1876
|
+
* { label: "Posts", to: "/posts" },
|
|
1877
|
+
* { label: post.title },
|
|
1878
|
+
* ]}
|
|
1879
|
+
* />
|
|
1880
|
+
* ```
|
|
1881
|
+
*/
|
|
1882
|
+
declare function DetailView<T = unknown>({ title, table, record, fields: fieldsProp, exclude, breadcrumb, }: DetailViewProps<T>): react_jsx_runtime.JSX.Element;
|
|
1883
|
+
|
|
1884
|
+
export { ImagePreview as $, type AppShellProps as A, type BooleanFieldProps as B, type ChipSlotProps as C, type DateFieldProps as D, type EmailFieldProps as E, type FileFieldProps as F, type DetailViewProps as G, DropZone as H, type ImageFieldProps as I, type JsonFieldProps as J, type DropZoneProps as K, type DropZoneSlotProps as L, FileList$1 as M, type NumberFieldProps as N, type FileListFile as O, type FileListProps as P, FilterBar as Q, type RelationFieldProps as R, type FilterBarProps as S, type TextFieldProps as T, type UrlFieldProps as U, type FilterDef as V, type FilterOption as W, type FilterType as X, FormStatus as Y, type FormStatusData as Z, type FormStatusProps as _, type FieldComponent as a, type ImagePreviewProps as a0, ImpersonationBanner as a1, type ImpersonationBannerProps as a2, ListView as a3, type ListViewProps as a4, type PageContainerSlotProps as a5, PermissionGate as a6, type PermissionGateProps as a7, RoleBadge as a8, type RoleBadgeProps as a9, type SidebarSlotProps as aa, type TableCellSlotProps as ab, type TableRowSlotProps as ac, type TableSectionSlotProps as ad, type TableSlotProps as ae, type ToastApi as af, ToastContext as ag, type ToastOptions as ah, type ToastSlotProps as ai, type ToastType as aj, type TooltipSlotProps as ak, type UIPlugin as al, type UIPluginComponents as am, UIPluginProvider as an, type UserMenuLink as ao, type WhenForbidden as ap, createUIPlugin as aq, getInitials as ar, useActionToast as as, useColumnInference as at, useComponent as au, useConfirm as av, useToast as aw, useUIPlugin as ax, type EmptyStateProps as b, type NavigationProgressProps as c, type BreadcrumbItem as d, type TabItem as e, type NavigationItem as f, type UserMenuProps as g, ActionButton as h, type ActionButtonProps as i, type AlertSlotProps as j, type AppShellSlotProps as k, AvatarWithInitials as l, type AvatarWithInitialsProps as m, type BaseFieldProps as n, type BreadcrumbSlotProps as o, type BulkAction as p, BulkActionBar as q, type ButtonSlotProps as r, type ColumnDef as s, type ColumnShorthand as t, type ConfirmDialogSlotProps as u, type ConfirmOptions as v, ConfirmProvider as w, DataTable as x, type DataTableProps as y, DetailView as z };
|