@marktiderman/genesis-ui 2.16.0 → 2.17.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/SKILL.md +2 -1
- package/dist/{AppShell-C88Uj7kT.d.ts → AppShell-DDyVqNmJ.d.ts} +4 -2
- package/dist/{chunk-46TZGMFW.js → chunk-24NUW3QN.js} +22 -22
- package/dist/chunk-24NUW3QN.js.map +1 -0
- package/dist/{chunk-C2IPSMNE.js → chunk-3FKF2SN4.js} +18 -4
- package/dist/chunk-3FKF2SN4.js.map +1 -0
- package/dist/{chunk-25XEXYGC.js → chunk-OT6KKSD2.js} +20 -20
- package/dist/chunk-OT6KKSD2.js.map +1 -0
- package/dist/{chunk-STZVZUYO.js → chunk-TQ7OJDSU.js} +8 -6
- package/dist/chunk-TQ7OJDSU.js.map +1 -0
- package/dist/chunk-YCQAYWMX.js +192 -0
- package/dist/chunk-YCQAYWMX.js.map +1 -0
- package/dist/components/data/index.d.ts +6 -6
- package/dist/components/data/index.js +170 -123
- package/dist/components/data/index.js.map +1 -1
- package/dist/components/layout/detail-page.d.ts +1 -1
- package/dist/components/layout/index.d.ts +2 -2
- package/dist/components/layout/index.js +4 -2
- package/dist/components/layout/index.js.map +1 -1
- package/dist/components/layout/settings-page.d.ts +1 -1
- package/dist/components/patterns/index.js +3 -2
- package/dist/components/patterns/sortable-list.js +2 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/use-resource-page.d.ts +1 -1
- package/dist/index.d.ts +176 -2
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/{split-Dk9f4Mi0.d.ts → split-D-uYckQ_.d.ts} +1 -1
- package/dist/{use-resource-page-DaJzuq3M.d.ts → use-resource-page-BA1P7xea.d.ts} +1 -1
- package/dist/{use-resource-table-easmRDQI.d.ts → use-resource-table-WDqz7oQ-.d.ts} +17 -3
- package/package.json +1 -1
- package/dist/chunk-25XEXYGC.js.map +0 -1
- package/dist/chunk-46TZGMFW.js.map +0 -1
- package/dist/chunk-C2IPSMNE.js.map +0 -1
- package/dist/chunk-STZVZUYO.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/patterns/sortable-list.tsx"],"names":[],"mappings":"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","file":"chunk-OT6KKSD2.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { GripVertical, MoreVertical } from \"lucide-react\";\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from \"../ui/dropdown-menu\";\nimport { cn } from \"../../utils\";\nimport { useAnnouncer } from \"./use-announcer\";\nimport { fillMessage, useUiMessages } from \"../../messages\";\n\nexport interface SortableListItemContext {\n /** The item's position as shown, from 0. */\n index: number;\n /**\n * The drag handle: drag it with a pointer, or focus it and press Space or\n * Enter to pick the item up, the arrow keys to move it and Space or Enter\n * again to drop it. Render it somewhere in the row.\n */\n handle: React.ReactNode;\n /** True while this item is being dragged with a pointer. */\n isDragging: boolean;\n /** True while this item is picked up from the keyboard. */\n isGrabbed: boolean;\n /** Move this item without dragging, for a row menu of your own. */\n moveUp: () => void;\n moveDown: () => void;\n moveTo: (index: number) => void;\n}\n\nexport interface SortableListReorder {\n /** Key of the item that moved. */\n key: string;\n}\n\nexport interface SortableListProps<T> {\n items: readonly T[];\n /** A stable key per item. Required: dragging finds the item again by key. */\n getKey: (item: T) => string;\n /** A name for an item, for the handle's label and announcements (\"Week 1\"). */\n getItemLabel: (item: T) => string;\n renderItem: (item: T, context: SortableListItemContext) => React.ReactNode;\n /**\n * Move the item at `from` to `to` (both from 0, `to` counted after the item\n * is taken out). Each finished move calls this once: a keyboard pick-up\n * that wanders and comes back calls nothing.\n *\n * The list shows the new order straight away and keeps showing it until the\n * returned promise settles; by then `items` must be in the new order. A\n * synchronous handler must update `items` in the same tick. A rejected\n * promise puts the old order back and announces that the move failed. Other\n * moves wait until this one settles.\n */\n onReorder: (from: number, to: number, move: SortableListReorder) => void | Promise<void>;\n /** Accessible name of the list (\"Course steps\"). */\n label: string;\n /** Turns off dragging and every kind of move. */\n disabled?: boolean | undefined;\n /**\n * A \"Move\" menu on each row (up, down, to top, to bottom), on by default so\n * touch and screen-reader users always have a way to move an item. Turn it\n * off only when the row offers `moveUp` / `moveDown` / `moveTo` itself.\n */\n moveMenu?: boolean | undefined;\n className?: string | undefined;\n itemClassName?: string | undefined;\n}\n\ntype DropAt = { key: string; edge: \"before\" | \"after\" };\n\nconst DRAG_TYPE = \"application/x-genesis-sortable-item\";\n\n// useLayoutEffect warns during server rendering; nothing needs refocusing there.\nconst useIsomorphicLayoutEffect = typeof window === \"undefined\" ? React.useEffect : React.useLayoutEffect;\n\nfunction moved(keys: readonly string[], from: number, to: number) {\n const next = keys.slice();\n const [key] = next.splice(from, 1);\n next.splice(to, 0, key!);\n return next;\n}\n\n/**\n * A vertical list the user can rearrange: course steps, lesson blocks, form\n * fields.\n *\n * Every way to move an item is equivalent, so dragging is never the only one\n * (the same stance as KanbanBoard's \"Move to…\" menu):\n * - drag the handle with a pointer;\n * - focus the handle, Space or Enter to pick up, ↑/↓ and Home/End to move,\n * Space or Enter to drop, Escape to put it back (tabbing away also puts it\n * back); Alt+↑/↓ moves one step without picking up;\n * - the row's \"Move\" menu, or `moveUp` / `moveDown` / `moveTo` from the render\n * context.\n *\n * Moves are announced in a polite live region once they succeed. Native drag\n * and drop needs no dependency and Radix has none to offer (docs/FRAMEWORK.md\n * rule 3).\n *\n * @stability Beta\n */\nexport function SortableList<T>({\n items,\n getKey,\n getItemLabel,\n renderItem,\n onReorder,\n label,\n disabled,\n moveMenu = true,\n className,\n itemClassName,\n}: SortableListProps<T>) {\n const [armed, setArmed] = React.useState<string | null>(null);\n const [dragging, setDragging] = React.useState<string | null>(null);\n const [dropAt, setDropAt] = React.useState<DropAt | null>(null);\n // While a key is grabbed, `preview` is the order on screen; nothing is\n // written until the drop.\n const [grabbed, setGrabbed] = React.useState<{ key: string; from: number } | null>(null);\n // The order to show instead of `items`: during a keyboard pick-up, and from\n // a committed move until its promise settles.\n const [preview, setPreview] = React.useState<string[] | null>(null);\n const [pending, setPending] = React.useState(false);\n // The same, readable within one tick: two moves fired back to back must\n // not both start from the old order.\n const pendingRef = React.useRef(false);\n const t = useUiMessages().sortable;\n const { message: announcement, announce } = useAnnouncer();\n const handles = React.useRef(new Map<string, HTMLButtonElement>());\n // The element that had focus when a move started, to put focus back on if\n // the DOM move drops it to the body. Cleared after every commit.\n const restoreFocus = React.useRef<HTMLElement | null>(null);\n const instructionsId = React.useId();\n\n const byKey = new Map(items.map((item) => [getKey(item), item] as const));\n const itemKeys = items.map(getKey);\n const keys = preview && preview.length === itemKeys.length && preview.every((k) => byKey.has(k)) ? preview : itemKeys;\n const total = keys.length;\n const nameOf = (key: string) => {\n const item = byKey.get(key);\n return item === undefined ? t.item : getItemLabel(item);\n };\n\n // Moving a focused element in the DOM drops focus to the body in real\n // browsers. Remember what had focus, the handle or a row's own button, and\n // put it back after the commit.\n const keepFocus = () => {\n const active = typeof document === \"undefined\" ? null : document.activeElement;\n restoreFocus.current = active instanceof HTMLElement && active !== document.body ? active : null;\n };\n useIsomorphicLayoutEffect(() => {\n const element = restoreFocus.current;\n restoreFocus.current = null;\n if (!element || !element.isConnected) return;\n const active = document.activeElement;\n if (active !== element && (active === null || active === document.body)) element.focus();\n });\n\n // An item that disappears mid-gesture, or the list turning disabled, ends\n // the gesture.\n React.useEffect(() => {\n if (disabled && (grabbed || armed || dragging)) {\n setGrabbed(null);\n setArmed(null);\n setDragging(null);\n setDropAt(null);\n if (!pendingRef.current) setPreview(null);\n return;\n }\n if (dragging && !byKey.has(dragging)) {\n setDragging(null);\n setDropAt(null);\n setArmed(null);\n }\n if (grabbed && !byKey.has(grabbed.key)) {\n setGrabbed(null);\n setPreview(null);\n }\n });\n\n const commit = (key: string, from: number, to: number, message: string) => {\n if (from === to) return;\n pendingRef.current = true;\n setPending(true);\n setPreview(moved(itemKeys, from, to));\n // Called synchronously, so a synchronous handler updates `items` in the\n // same tick as the preview.\n let result: void | Promise<void>;\n try {\n result = onReorder(from, to, { key });\n } catch (error) {\n result = Promise.reject(error);\n }\n Promise.resolve(result)\n .then(\n () => announce(message),\n () => announce(fillMessage(t.moveFailed, { name: nameOf(key) })),\n )\n .finally(() => {\n // A rejected move reverts the order, which moves rows again.\n keepFocus();\n pendingRef.current = false;\n setPending(false);\n setPreview(null);\n });\n };\n\n const move = (key: string, to: number) => {\n if (disabled || pendingRef.current || grabbed) return;\n if (!Number.isFinite(to)) return;\n const from = itemKeys.indexOf(key);\n const target = Math.max(0, Math.min(total - 1, Math.round(to)));\n if (from < 0 || target === from) return;\n keepFocus();\n commit(key, from, target, fillMessage(t.moved, { name: nameOf(key), n: target + 1, total }));\n };\n\n const pickUp = (key: string) => {\n if (disabled || pendingRef.current) return;\n const from = itemKeys.indexOf(key);\n if (from < 0) return;\n setGrabbed({ key, from });\n setPreview(itemKeys);\n announce(fillMessage(t.pickedUp, { name: nameOf(key), n: from + 1, total }));\n };\n\n const drop = (key: string) => {\n if (!grabbed) return;\n const to = keys.indexOf(key);\n const from = grabbed.from;\n setGrabbed(null);\n if (to === from) {\n setPreview(null);\n announce(fillMessage(t.dropped, { name: nameOf(key), n: to + 1, total }));\n return;\n }\n keepFocus();\n commit(key, from, to, fillMessage(t.dropped, { name: nameOf(key), n: to + 1, total }));\n };\n\n const cancel = (key: string) => {\n if (!grabbed) return;\n const from = grabbed.from;\n keepFocus();\n setGrabbed(null);\n setPreview(null);\n announce(fillMessage(t.cancelled, { name: nameOf(key), n: from + 1, total }));\n };\n\n const step = (key: string, to: number) => {\n const index = keys.indexOf(key);\n const target = Math.max(0, Math.min(total - 1, to));\n if (index < 0 || target === index) return;\n keepFocus();\n setPreview(moved(keys, index, target));\n announce(fillMessage(t.moved, { name: nameOf(key), n: target + 1, total }));\n };\n\n // Escape while an item is picked up must not also close a surrounding\n // Dialog or Sheet, which listen before the handle does.\n React.useEffect(() => {\n if (!grabbed) return;\n const onKey = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n event.stopPropagation();\n cancel(grabbed.key);\n };\n window.addEventListener(\"keydown\", onKey, true);\n return () => window.removeEventListener(\"keydown\", onKey, true);\n });\n\n // A press on the handle arms its row for native dragging; any release or\n // cancel, wherever it lands, disarms it.\n React.useEffect(() => {\n if (!armed || dragging) return;\n const disarm = () => setArmed(null);\n // A context menu or a release outside the window never sends pointerup.\n const events = [\"pointerup\", \"pointercancel\", \"contextmenu\", \"blur\"] as const;\n for (const type of events) window.addEventListener(type, disarm, { once: true });\n return () => {\n for (const type of events) window.removeEventListener(type, disarm);\n };\n }, [armed, dragging]);\n\n const onHandleKeyDown = (event: React.KeyboardEvent, key: string) => {\n if (disabled) return;\n const isGrabbed = grabbed?.key === key;\n const index = keys.indexOf(key);\n const delta = event.key === \"ArrowUp\" ? -1 : event.key === \"ArrowDown\" ? 1 : 0;\n if (isGrabbed) {\n if (delta) {\n event.preventDefault();\n step(key, index + delta);\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n step(key, event.key === \"Home\" ? 0 : total - 1);\n }\n return;\n }\n if (delta && event.altKey) {\n event.preventDefault();\n move(key, index + delta);\n }\n };\n\n // Space and Enter reach the handle as a click with `detail === 0`, as do\n // screen readers' activations; a pointer click is a press for dragging.\n const onHandleClick = (event: React.MouseEvent, key: string) => {\n if (disabled || event.detail !== 0) return;\n if (grabbed?.key === key) drop(key);\n else if (!grabbed) pickUp(key);\n };\n\n const onDragOver = (event: React.DragEvent<HTMLLIElement>, key: string) => {\n if (!dragging) return;\n event.preventDefault();\n event.dataTransfer.dropEffect = \"move\";\n const rect = event.currentTarget.getBoundingClientRect();\n const edge = event.clientY < rect.top + rect.height / 2 ? \"before\" : \"after\";\n if (dropAt?.key !== key || dropAt.edge !== edge) setDropAt({ key, edge });\n };\n\n const endDrag = () => {\n setDragging(null);\n setDropAt(null);\n setArmed(null);\n };\n\n const onDrop = (event: React.DragEvent) => {\n event.preventDefault();\n const key = event.dataTransfer.getData(DRAG_TYPE) || dragging;\n const target = dropAt;\n endDrag();\n if (!key || !target || pendingRef.current || grabbed) return;\n const from = itemKeys.indexOf(key);\n const over = itemKeys.indexOf(target.key);\n if (from < 0 || over < 0) return;\n // `to` counts positions after the dragged item is taken out.\n let to = target.edge === \"before\" ? over : over + 1;\n if (from < to) to -= 1;\n commit(key, from, to, fillMessage(t.dropped, { name: nameOf(key), n: to + 1, total }));\n };\n\n return (\n <>\n <ul aria-label={label} aria-busy={pending || undefined} className={cn(\"flex flex-col gap-1\", className)}>\n {keys.map((key, index) => {\n const item = byKey.get(key)!;\n const itemLabel = getItemLabel(item);\n const isGrabbed = grabbed?.key === key;\n const isDragging = dragging === key;\n const handle = disabled ? null : (\n <button\n type=\"button\"\n ref={(node) => {\n if (node) handles.current.set(key, node);\n else handles.current.delete(key);\n }}\n aria-label={fillMessage(t.reorder, { name: itemLabel })}\n aria-describedby={instructionsId}\n data-grabbed={isGrabbed || undefined}\n className={cn(\n \"inline-flex h-7 w-5 shrink-0 cursor-grab items-center justify-center rounded text-muted-foreground\",\n \"hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n isGrabbed && \"bg-accent text-foreground\",\n )}\n onPointerDown={() => {\n if (!pendingRef.current && !grabbed) setArmed(key);\n }}\n onPointerCancel={() => setArmed(null)}\n onClick={(event) => onHandleClick(event, key)}\n onKeyDown={(event) => onHandleKeyDown(event, key)}\n onBlur={() => {\n // A DOM move during the pick-up blurs the handle for a moment;\n // that is not the user leaving.\n if (isGrabbed && restoreFocus.current !== handles.current.get(key)) cancel(key);\n }}\n >\n <GripVertical className=\"h-4 w-4\" aria-hidden />\n </button>\n );\n return (\n <li\n key={key}\n data-sortable-key={key}\n draggable={(!disabled && armed === key) || undefined}\n className={cn(\n \"relative rounded-md\",\n moveMenu && !disabled && \"pr-8\",\n isDragging && \"opacity-50\",\n isGrabbed && \"ring-2 ring-primary/50\",\n itemClassName,\n )}\n onDragStart={(event) => {\n if (disabled || armed !== key) return;\n event.dataTransfer.setData(DRAG_TYPE, key);\n event.dataTransfer.effectAllowed = \"move\";\n setDragging(key);\n }}\n onDragEnd={endDrag}\n onDragOver={(event) => onDragOver(event, key)}\n onDrop={onDrop}\n >\n {dropAt?.key === key && dragging !== key && (\n <span\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-x-0 h-0.5 rounded bg-primary\",\n dropAt.edge === \"before\" ? \"-top-0.5\" : \"-bottom-0.5\",\n )}\n />\n )}\n {renderItem(item, {\n index,\n handle,\n isDragging,\n isGrabbed,\n moveUp: () => move(key, index - 1),\n moveDown: () => move(key, index + 1),\n moveTo: (to) => move(key, to),\n })}\n {moveMenu && !disabled && total > 1 && (\n <DropdownMenu>\n <DropdownMenuTrigger\n aria-label={fillMessage(t.move, { name: itemLabel })}\n className=\"absolute right-1 top-1 rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <MoreVertical className=\"h-4 w-4\" aria-hidden />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem disabled={index === 0} onSelect={() => move(key, index - 1)}>\n {t.moveUp}\n </DropdownMenuItem>\n <DropdownMenuItem disabled={index === total - 1} onSelect={() => move(key, index + 1)}>\n {t.moveDown}\n </DropdownMenuItem>\n <DropdownMenuItem disabled={index === 0} onSelect={() => move(key, 0)}>\n {t.moveToTop}\n </DropdownMenuItem>\n <DropdownMenuItem disabled={index === total - 1} onSelect={() => move(key, total - 1)}>\n {t.moveToBottom}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </li>\n );\n })}\n </ul>\n <p id={instructionsId} hidden>\n {t.instructions}\n </p>\n <div aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </div>\n </>\n );\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import { useResourcePage } from './chunk-RKPS7ERS.js';
|
|
|
3
3
|
import { useResourceUrlState } from './chunk-DIV4BYXX.js';
|
|
4
4
|
import { useViewSettings } from './chunk-OZ7ZAYCS.js';
|
|
5
5
|
import { toast } from './chunk-4RAZJ6LL.js';
|
|
6
|
+
import { useUiMessages } from './chunk-YCQAYWMX.js';
|
|
6
7
|
import { defaultNavigate } from './chunk-J45FHL7D.js';
|
|
7
8
|
import { useKeyboardNavigation } from './chunk-YJ6MPS6U.js';
|
|
8
9
|
import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
|
|
@@ -113,7 +114,7 @@ function useResourceTableModel(props) {
|
|
|
113
114
|
openOnCardClick = false,
|
|
114
115
|
renderTable: renderTableProp,
|
|
115
116
|
gridCols: gridColsProp,
|
|
116
|
-
keyboardNavigation =
|
|
117
|
+
keyboardNavigation = props.variant !== "embedded",
|
|
117
118
|
capabilities,
|
|
118
119
|
toolbar,
|
|
119
120
|
emptyState,
|
|
@@ -131,6 +132,7 @@ function useResourceTableModel(props) {
|
|
|
131
132
|
slotProps,
|
|
132
133
|
className
|
|
133
134
|
} = props;
|
|
135
|
+
const messages = useUiMessages();
|
|
134
136
|
const isClientMode = !!resourceName;
|
|
135
137
|
const resourceServerPaging = isClientMode && pagination === "server";
|
|
136
138
|
const resourceCursorPaging = isClientMode && pagination === "cursor";
|
|
@@ -416,7 +418,7 @@ function useResourceTableModel(props) {
|
|
|
416
418
|
} : useBuiltInDelete ? (item) => {
|
|
417
419
|
performDelete(item).catch((err) => {
|
|
418
420
|
if (!resourceOptions?.onError) {
|
|
419
|
-
toast.error(err instanceof Error ? err.message :
|
|
421
|
+
toast.error(err instanceof Error ? err.message : messages.page.deleteFailed);
|
|
420
422
|
}
|
|
421
423
|
});
|
|
422
424
|
} : (
|
|
@@ -432,7 +434,7 @@ function useResourceTableModel(props) {
|
|
|
432
434
|
} catch {
|
|
433
435
|
}
|
|
434
436
|
}
|
|
435
|
-
toast.error(error.message ||
|
|
437
|
+
toast.error(error.message || messages.page.deleteFailed);
|
|
436
438
|
};
|
|
437
439
|
try {
|
|
438
440
|
Promise.resolve(onDelete?.(item)).catch(report);
|
|
@@ -768,7 +770,7 @@ function useResourceTable(props) {
|
|
|
768
770
|
openRow: m.handleRowClick,
|
|
769
771
|
closeDetail: m.closeDetail,
|
|
770
772
|
openItemMissing: m.linkMissing,
|
|
771
|
-
create: m.useBuiltInCreate || props.onCreate ? m.handleCreate : void 0,
|
|
773
|
+
create: (m.useBuiltInCreate || props.onCreate) && m.allows("create") ? m.handleCreate : void 0,
|
|
772
774
|
edit: m.handleEdit,
|
|
773
775
|
form: {
|
|
774
776
|
open: m.formOpen,
|
|
@@ -789,5 +791,5 @@ function useResourceTable(props) {
|
|
|
789
791
|
}
|
|
790
792
|
|
|
791
793
|
export { showUndoToast, showWriteErrorToast, useResourceTable, useResourceTableModel };
|
|
792
|
-
//# sourceMappingURL=chunk-
|
|
793
|
-
//# sourceMappingURL=chunk-
|
|
794
|
+
//# sourceMappingURL=chunk-TQ7OJDSU.js.map
|
|
795
|
+
//# sourceMappingURL=chunk-TQ7OJDSU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/data/undo-toast.ts","../src/components/data/use-resource-table.ts"],"names":[],"mappings":"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","file":"chunk-TQ7OJDSU.js","sourcesContent":["import type { MutationMode, UndoableWrite } from \"@marktiderman/genesis-core/hooks\";\nimport { toast } from \"../ui/sonner\";\n\nconst DONE: Record<UndoableWrite[\"kind\"], string> = {\n create: \"Created.\",\n update: \"Saved.\",\n delete: \"Deleted.\",\n};\n\n/**\n * The undo toast for an `undoable` write (core's `onUndoable`): a sonner\n * toast with an Undo button, shown for as long as the undo is offered.\n * Needs a mounted `<Toaster />`.\n */\nexport function showUndoToast(write: UndoableWrite): void {\n toast(DONE[write.kind], {\n duration: write.delayMs,\n action: {\n label: \"Undo\",\n onClick: () => {\n void write.undo().then((undone) => {\n // Sonner pauses on hover, so the button can outlive the window.\n if (!undone && write.strategy === \"delay\") {\n toast(\"Already saved. It can no longer be undone.\");\n }\n });\n },\n },\n });\n}\n\n/** The default error report for writes that fail after the form has closed. */\nexport function showWriteErrorToast(error: Error): void {\n toast.error(error.message || \"The change could not be saved.\");\n}\n\n/**\n * ResourcePage's write-mode options for its `useResource`: the page's\n * `mutationMode` unless `resourceOptions` sets one, the undo toast, and an\n * error toast for a write that fails after it was shown as done.\n */\nexport function writeModeOptions(\n resourceOptions: { mutationMode?: MutationMode; onUndoable?: (write: UndoableWrite) => void; onError?: (error: Error) => void } | undefined,\n mutationMode: MutationMode | undefined,\n): { mutationMode: MutationMode; onUndoable: (write: UndoableWrite) => void; onError?: (error: Error) => void } {\n const mode = resourceOptions?.mutationMode ?? mutationMode ?? \"pessimistic\";\n return {\n mutationMode: mode,\n onUndoable: resourceOptions?.onUndoable ?? showUndoToast,\n onError: resourceOptions?.onError ?? (mode === \"pessimistic\" ? undefined : showWriteErrorToast),\n };\n}\n","\"use client\";\n\n/**\n * `useResourceTable`: ResourcePage's behaviour without its markup. Lives\n * apart from ResourcePage.tsx so importing the hook (e.g. from `/hooks`)\n * does not pull in the page's components and icons.\n */\nimport { useMemo, useState, useCallback, useEffect, useRef } from \"react\";\nimport type { DataTableColumn, DataTableSort } from \"./DataTable\";\nimport type {\n ResourceAction,\n ResourceDeleteConfirmCopy,\n ResourcePageProps,\n} from \"./ResourcePage\";\nimport { useViewSettings } from \"../../hooks/use-view-settings\";\nimport { useKeyboardNavigation } from \"../../hooks/use-keyboard-navigation\";\nimport { useResourceUrlState } from \"../../hooks/use-resource-url-state\";\nimport {\n useResourcePage,\n type ResourceActions,\n} from \"../../hooks/use-resource-page\";\nimport {\n useCapabilities,\n useInfiniteResource,\n useOne,\n useResource,\n} from \"@marktiderman/genesis-core/hooks\";\nimport type {\n BaseRecord,\n Identifier,\n} from \"@marktiderman/genesis-core/provider\";\nimport { writeModeOptions } from \"./undo-toast\";\nimport { toast } from \"../ui/sonner\";\nimport { useUiMessages } from \"../../messages\";\nimport { defaultNavigate } from \"../../navigation\";\n\n/**\n * Everything ResourcePage's markup reads. Internal: its names may change in\n * any release. Apps use {@link useResourceTable}.\n *\n * @internal\n */\nexport function useResourceTableModel<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(props: ResourcePageProps<T>) {\n const {\n resource: resourceName,\n data: dataProp,\n total: totalProp,\n pagination = \"client\",\n clientRowLimit = 1000,\n title,\n subtitle,\n icon,\n columns: columnsProp,\n getKey: getKeyProp,\n detail = \"panel\",\n detailWidth = \"md\",\n titleField: titleFieldProp,\n subtitleField: subtitleFieldProp,\n getTitle,\n getSubtitle,\n renderDetail: renderDetailProp,\n detailFields,\n statusFilter,\n searchFields,\n searchPlaceholder,\n initialFilters,\n onFiltersChange,\n filters: filtersProp,\n page: pageProp,\n perPage: perPageProp,\n onPageChange,\n onPerPageChange,\n onSortChange,\n onSearchChange,\n loading: loadingProp,\n error: errorProp,\n errorMessage,\n onRetry: onRetryProp,\n savedViews,\n onLoadView,\n onSaveView,\n onDeleteView,\n canSaveViews,\n columnVisibility,\n columnVisibilityKey,\n resizableColumns,\n resizeKey,\n stickyHeader,\n stickyFirstColumn,\n pageSizeOptions,\n onCreate,\n onEdit,\n onDelete,\n can,\n canEditItem,\n createLabel = \"New\",\n canEdit,\n canDelete,\n allowDelete,\n confirmDelete,\n onDeleted,\n secondaryActions,\n allowCreate,\n allowEdit,\n formFields,\n renderForm: renderFormProp,\n formMode,\n formSteps,\n formLayout: formLayoutProp,\n mutationMode: mutationModeProp,\n bulkActions,\n renderCard: renderCardProp,\n openOnCardClick = false,\n renderTable: renderTableProp,\n gridCols: gridColsProp,\n keyboardNavigation = props.variant !== \"embedded\",\n capabilities,\n toolbar,\n emptyState,\n emptyIcon,\n emptyMessage,\n emptyDescription,\n header: headerMode = \"page\",\n resourceOptions,\n live,\n urlState: urlStateProp,\n defaultView = \"table\",\n onNavigate = defaultNavigate,\n viewSettingsKey: viewSettingsKeyProp,\n slots,\n slotProps,\n className,\n } = props;\n const messages = useUiMessages();\n\n // ── Determine mode ──\n const isClientMode = !!resourceName;\n\n /**\n * Server-controlled mode is entered by supplying ANY of the controlled\n * props — presence is the switch, so a caller that only pages (no server\n * search) still gets its `data` left alone.\n */\n // `resource` mode paging through the provider: ResourcePage owns both the\n // fetch and the page state, and reuses the server-controlled path below\n // (no client-side transform, the pager under the list) with useResource's\n // setters standing in for the caller's callbacks.\n const resourceServerPaging = isClientMode && pagination === \"server\";\n // `pagination=\"cursor\"`: pages load by cursor and append (\"Load more\").\n const resourceCursorPaging = isClientMode && pagination === \"cursor\";\n\n // ── URL state (`urlState`): the open record, search, sort and page ──\n // An adapter has `setSearchParams`; the options object wraps one.\n const url = useResourceUrlState(\n urlStateProp\n ? \"setSearchParams\" in urlStateProp\n ? { searchParams: urlStateProp }\n : urlStateProp\n : undefined,\n );\n // Read once: the URL seeds the list when it mounts, then follows it.\n const [urlSeed] = useState(() => {\n if (!url) return null;\n // A URL sort only counts when it names a sortable column: a hand-edited\n // or stale link must not send an arbitrary field to the provider.\n const sortable =\n !url.sort || !columnsProp\n ? true\n : columnsProp.some((col) =>\n typeof col === \"string\"\n ? col === url.sort!.field\n : col.key === url.sort!.field && col.sortable !== false,\n );\n return { q: url.q, sort: sortable ? url.sort : null, page: url.page };\n });\n // The URL names the open record only where there is a peek to open.\n const urlPeek = detail === \"panel\" || detail === \"modal\" ? url : undefined;\n const urlSortKey = urlSeed?.sort\n ? `${urlSeed.sort.field}:${urlSeed.sort.order}`\n : \"\";\n\n const isServerControlled =\n resourceServerPaging ||\n pageProp !== undefined ||\n perPageProp !== undefined ||\n onPageChange !== undefined ||\n onPerPageChange !== undefined ||\n onSortChange !== undefined ||\n onSearchChange !== undefined;\n\n const viewSettingsKey =\n viewSettingsKeyProp ??\n resourceName ??\n title.toLowerCase().replace(/\\s+/g, \"-\");\n const { settings, updateSetting } = useViewSettings(viewSettingsKey);\n\n // Server search needs the columns to match. Without them the provider\n // would get a query it ignores, so the search box hides instead of lying.\n const serverSearchFields = resourceOptions?.searchFields ?? searchFields;\n\n // ── Client-side mode: call useResource (hook is always called for rules-of-hooks) ──\n // Core's useResource constrains its row type to BaseRecord (rows carry an\n // `id`), which is stricter than ResourcePage's public `T extends\n // Record<string, unknown>`. Intersect at the call site so the public\n // ResourcePageProps<T> generic stays unchanged while satisfying the hook.\n const resourceHook = useResource<T & BaseRecord>(\n resourceName ?? \"__noop__\",\n isClientMode\n ? {\n ...resourceOptions,\n // Client paging fetches everything it can in one request; server\n // paging starts at the user's stored page size. An explicit\n // `defaultPerPage` wins over both.\n defaultPerPage:\n resourceOptions?.defaultPerPage ??\n (resourceServerPaging\n ? (perPageProp ?? settings.pageSize)\n : clientRowLimit),\n searchFields: resourceServerPaging\n ? serverSearchFields\n : resourceOptions?.searchFields,\n // Paging, searching and sorting change the query key; keep the\n // current page on screen while the next one loads.\n keepPreviousData:\n resourceOptions?.keepPreviousData ?? resourceServerPaging,\n // Start where the URL says, so restoring a link doesn't push a\n // search or sort that resets the page to 1.\n ...(resourceServerPaging && urlSeed\n ? {\n defaultSearch: urlSeed.q,\n ...(urlSeed.page ? { defaultPage: urlSeed.page } : {}),\n ...(urlSeed.sort ? { defaultSort: urlSeed.sort } : {}),\n }\n : {}),\n ...writeModeOptions(resourceOptions, mutationModeProp),\n // Cursor paging reads through useInfiniteResource below; this hook\n // only writes.\n ...(resourceCursorPaging ? { enabled: false } : {}),\n live: resourceOptions?.live ?? live,\n }\n : { enabled: false },\n );\n const infinite = useInfiniteResource<T & BaseRecord>(resourceName ?? \"__noop__\", {\n enabled: resourceCursorPaging && (resourceOptions?.enabled ?? true),\n perPage: resourceOptions?.defaultPerPage ?? perPageProp ?? settings.pageSize,\n defaultSort: resourceOptions?.defaultSort,\n defaultFilters: resourceOptions?.defaultFilters,\n select: resourceOptions?.select,\n live: resourceOptions?.live ?? live,\n });\n\n /** Explicit prop beats the per-user stored preference. */\n const effectivePageSize = resourceServerPaging\n ? (resourceHook.params.pagination?.perPage ?? settings.pageSize)\n : (perPageProp ?? settings.pageSize);\n\n // ── Resolve display data ──\n const displayData: T[] = resourceCursorPaging\n ? infinite.rows\n : isClientMode\n ? (resourceHook.list.data?.data ?? [])\n : (dataProp ?? []);\n const displayTotal: number = resourceCursorPaging\n ? (infinite.total ?? infinite.rows.length)\n : isClientMode\n ? (resourceHook.list.data?.total ?? 0)\n : (totalProp ?? 0);\n // Client-side mode reads the hook it owns; server-data mode reads the\n // caller's `loading` / `error` props, defaulting to false so a page that\n // supplies neither renders exactly as it did before they existed.\n const isLoading = resourceCursorPaging\n ? infinite.query.isLoading\n : isClientMode\n ? resourceHook.list.isLoading\n : (loadingProp ?? false);\n const hasError = resourceCursorPaging\n ? infinite.query.isError\n : isClientMode\n ? resourceHook.list.isError\n : (errorProp ?? false);\n\n // ── Call useResourcePage ──\n const page = useResourcePage<T>({\n resource: resourceName,\n data: displayData,\n total: displayTotal,\n columns: columnsProp,\n statusFilter,\n searchFields,\n initialFilters:\n initialFilters ??\n (urlSeed && (urlSeed.q || urlSeed.sort)\n ? [\n ...(urlSeed.q\n ? [{ field: \"__search__\", operator: \"contains\" as const, value: urlSeed.q }]\n : []),\n ...(urlSeed.sort\n ? [{ field: \"__sort__\", operator: \"eq\" as const, value: urlSortKey }]\n : []),\n ]\n : undefined),\n onFiltersChange,\n defaultView,\n // Each page remembers its own table/cards choice, under the same key as\n // its density and page size — not one key shared by every data page.\n viewKey: viewSettingsKey,\n detail,\n titleField: titleFieldProp,\n subtitleField: subtitleFieldProp,\n controlled: isServerControlled,\n });\n\n // ── `pagination=\"server\"`: push the filter row's state into useResource ──\n // Effects rather than the change handlers, so `initialFilters` and \"Clear\n // all\" reach the provider by the same path as a keystroke. Each push is\n // skipped while its value still equals what the hook already has, so the\n // first render does not reset `defaultSort` or refetch for nothing.\n const {\n setSearch: setResourceSearch,\n setSort: setResourceSort,\n setFilters: setResourceFilters,\n } = resourceHook;\n // Seeded from the URL, which useResource already starts on (see above).\n const pushedSearchRef = useRef(resourceServerPaging ? (urlSeed?.q ?? \"\") : \"\");\n const searchEffectRanRef = useRef(false);\n useEffect(() => {\n if (!resourceServerPaging) return;\n const firstRun = !searchEffectRanRef.current;\n searchEffectRanRef.current = true;\n if (page.search === pushedSearchRef.current) return;\n const push = () => {\n pushedSearchRef.current = page.search;\n setResourceSearch(page.search);\n };\n // One request per pause in typing, not per keystroke — but an\n // `initialFilters` search (first run) or a cleared box (\"Clear all\")\n // goes out at once, landing with the sort / status pushes instead of\n // 300ms behind them.\n if (firstRun || page.search === \"\") {\n push();\n return;\n }\n const timer = setTimeout(push, 300);\n return () => clearTimeout(timer);\n }, [resourceServerPaging, page.search, setResourceSearch]);\n\n const defaultSort = resourceOptions?.defaultSort;\n const pushedSortRef = useRef<string>(resourceServerPaging ? urlSortKey : \"\");\n useEffect(() => {\n if (!resourceServerPaging) return;\n const key = page.sort ? `${page.sort.field}:${page.sort.order}` : \"\";\n if (key === pushedSortRef.current) return;\n pushedSortRef.current = key;\n // Clearing the sort returns to the resource's default order, not to\n // whatever order the provider happens to use.\n setResourceSort(page.sort ?? defaultSort);\n }, [resourceServerPaging, page.sort, defaultSort, setResourceSort]);\n\n const statusField = statusFilter\n ? typeof statusFilter === \"string\"\n ? statusFilter\n : statusFilter.field\n : undefined;\n const defaultFilters = resourceOptions?.defaultFilters;\n const pushedStatusRef = useRef<string>(\"\");\n useEffect(() => {\n if (!resourceServerPaging || !statusField) return;\n // `defaultFilters` is part of the key: useResource re-syncs its filters\n // to a changed `defaultFilters` (dropping the status filter), so a\n // change there must re-push even when the chips did not move.\n const key = JSON.stringify([page.statusValue, defaultFilters ?? null]);\n if (key === pushedStatusRef.current) return;\n pushedStatusRef.current = key;\n setResourceFilters([\n ...(defaultFilters ?? []),\n ...(page.statusValue.length > 0\n ? [{ field: statusField, operator: \"in\" as const, value: page.statusValue }]\n : []),\n ]);\n }, [\n resourceServerPaging,\n statusField,\n page.statusValue,\n defaultFilters,\n setResourceFilters,\n ]);\n\n // ── `pagination=\"client\"`: say so when the resource outgrew the fetch ──\n const clientTruncated =\n isClientMode &&\n !resourceServerPaging &&\n !resourceCursorPaging &&\n !isLoading &&\n !hasError &&\n displayTotal > displayData.length;\n const warnedTruncatedRef = useRef(false);\n useEffect(() => {\n if (!clientTruncated || warnedTruncatedRef.current) return;\n warnedTruncatedRef.current = true;\n console.warn(\n `ResourcePage: \"${resourceName}\" has ${displayTotal} rows but only ${displayData.length} were fetched. ` +\n `Pass \\`pagination=\"server\"\\` to page through all of them, or raise \\`clientRowLimit\\` ` +\n `(no higher than the provider's \\`maxPerPage\\`, which refuses a larger page).`,\n );\n }, [clientTruncated, resourceName, displayTotal, displayData.length]);\n // ── Build ResourceActions for column render functions ──\n // `refetch` is stable; the query results around it are new each render.\n const refetchList = resourceHook.list.refetch;\n const refetchInfinite = infinite.query.refetch;\n const actions: ResourceActions<T> = useMemo(() => {\n if (isClientMode) {\n return {\n update: resourceHook.update as ResourceActions<T>[\"update\"],\n remove: resourceHook.remove,\n refetch: () => (resourceCursorPaging ? refetchInfinite() : refetchList()),\n };\n }\n return {\n update: async () => {\n throw new Error(\n \"ResourceActions.update not available in server-data mode\",\n );\n },\n remove: async () => {\n throw new Error(\n \"ResourceActions.remove not available in server-data mode\",\n );\n },\n refetch: () => {\n /* no-op in server-data mode */\n },\n };\n }, [\n isClientMode,\n resourceHook.update,\n resourceHook.remove,\n refetchList,\n resourceCursorPaging,\n refetchInfinite,\n ]);\n\n // ── Row identity ──\n const keyOf = useCallback(\n (item: T): string =>\n getKeyProp ? getKeyProp(item) : String((item as Record<string, unknown>).id ?? \"\"),\n [getKeyProp],\n );\n\n // ── The peek's row, kept live ──\n // `page.selectedItem` is a snapshot taken at click time. Re-resolving it by\n // key against the current rows means a save (which refetches) shows its\n // new values in the open peek instead of the pre-edit copy. A row missing\n // from the current rows keeps the snapshot: paging, sorting, search and\n // filters all drop rows that still exist. A confirmed delete closes the\n // peek itself (`performDelete`).\n // An empty key (rows with no `id` and no `getKey`) identifies nothing, so\n // it keeps the snapshot rather than matching the first keyless row.\n // With `urlState` the URL names the open record (`?id=`): a link opens it,\n // and Back closes it. The click-time snapshot still covers a record that\n // isn't in the current rows.\n const snapshotKey = page.selectedItem ? keyOf(page.selectedItem) : null;\n const selectedKey = urlPeek ? urlPeek.detailId : snapshotKey;\n const snapshot =\n page.selectedItem && snapshotKey === selectedKey ? page.selectedItem : null;\n const rowOrSnapshot: T | null = !selectedKey\n ? snapshot\n : (displayData.find((row) => keyOf(row) === selectedKey) ?? snapshot);\n // A linked record that isn't in the loaded rows (another page, outside the\n // search) is fetched on its own; one that can't be read shows as missing.\n const linkedId = urlPeek && selectedKey && !rowOrSnapshot ? selectedKey : null;\n const linked = useOne<T & BaseRecord>(resourceName ?? \"__noop__\", linkedId, {\n enabled: isClientMode && !!linkedId,\n });\n const selectedItem: T | null =\n rowOrSnapshot ?? (linkedId && linked.data ? (linked.data as T) : null);\n // Missing only when that is known: the fetch failed (resource mode), or\n // `data` is the whole set (data mode without server paging). A record\n // absent from one server-controlled page may be on another.\n const linkMissing =\n !!linkedId &&\n !selectedItem &&\n !isLoading &&\n (isClientMode ? linked.isError : !isServerControlled);\n const detailOpen = urlPeek ? selectedItem !== null || linkMissing : page.detailOpen;\n\n // ── Bulk selection ──\n const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());\n\n const handleToggleSelect = useCallback((id: string) => {\n setSelectedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }, []);\n\n const handleToggleAll = useCallback(() => {\n setSelectedIds((prev) => {\n if (prev.size === page.data.length) return new Set();\n return new Set(page.data.map(keyOf));\n });\n }, [page.data, keyOf]);\n\n const handleClearSelection = useCallback(() => {\n setSelectedIds(new Set());\n }, []);\n\n // ── Built-in form state ──\n const [formOpen, setFormOpen] = useState(false);\n const [formAction, setFormAction] = useState<\"create\" | \"edit\">(\"create\");\n const [formItem, setFormItem] = useState<T | null>(null);\n\n // Determine if built-in form should handle create/edit\n const useBuiltInCreate = allowCreate && !onCreate && isClientMode;\n const useBuiltInEdit = allowEdit && !onEdit && isClientMode;\n\n const handleCreate = useCallback(() => {\n if (useBuiltInCreate) {\n setFormAction(\"create\");\n setFormItem(null);\n setFormOpen(true);\n } else if (onCreate) {\n onCreate();\n }\n }, [useBuiltInCreate, onCreate]);\n\n // One permission check: `can`, then the deprecated per-row predicates.\n const allows = useCallback(\n (action: ResourceAction, item?: T): boolean => {\n if (can && !can(action, item)) return false;\n if (!item) return true;\n if (canEditItem && !canEditItem(item)) return false;\n if (action === \"edit\" && canEdit && !canEdit(item)) return false;\n if (action === \"delete\" && canDelete && !canDelete(item)) return false;\n return true;\n },\n [can, canEditItem, canEdit, canDelete],\n );\n\n const handleEdit = useCallback(\n (item: T) => {\n if (!allows(\"edit\", item)) return;\n if (useBuiltInEdit) {\n setFormAction(\"edit\");\n setFormItem(item);\n setFormOpen(true);\n } else if (onEdit) {\n onEdit(item);\n }\n },\n [useBuiltInEdit, onEdit, allows],\n );\n\n const closeDetail = useCallback(() => {\n page.setDetailOpen(false);\n page.setSelectedItem(null);\n urlPeek?.setDetailId(null);\n }, [page, urlPeek]);\n\n // ── Delete: built-in, confirmed, or the caller's as-is ──\n const useBuiltInDelete = !!allowDelete && !onDelete && isClientMode;\n const deleteConfirmed =\n confirmDelete === undefined ? useBuiltInDelete : !!confirmDelete;\n const deleteCopy =\n typeof confirmDelete === \"object\" ? confirmDelete : undefined;\n // The row being confirmed, kept after the dialog closes so its copy does\n // not flip to the defaults during the exit animation; `deleteOpen` is what\n // actually opens and closes it.\n const [pendingDelete, setPendingDelete] = useState<T | null>(null);\n const [deleteOpen, setDeleteOpen] = useState(false);\n const { remove: removeRecord } = resourceHook;\n // A recycle-bin resource says so in the confirm step instead of \"can't be undone\".\n const { data: providerCaps } = useCapabilities(resourceName, {\n enabled: useBuiltInDelete && deleteConfirmed,\n });\n const deleteKind: \"recycle\" | \"permanent\" = providerCaps?.softDelete ? \"recycle\" : \"permanent\";\n\n const performDelete = useCallback(\n async (item: T) => {\n if (useBuiltInDelete) {\n // A caller-supplied `getKey` (e.g. `encodeRecordKey` for a composite\n // key) is the row's identity to the provider too; otherwise `id`.\n await removeRecord(\n (getKeyProp\n ? keyOf(item)\n : (item as Record<string, unknown>).id) as Identifier,\n );\n } else if (onDelete) {\n await onDelete(item);\n }\n closeDetail();\n onDeleted?.(item);\n },\n [\n useBuiltInDelete,\n removeRecord,\n getKeyProp,\n keyOf,\n onDelete,\n closeDetail,\n onDeleted,\n ],\n );\n\n const deleteHandler: ((item: T) => void) | undefined = !(\n useBuiltInDelete || onDelete\n )\n ? undefined\n : deleteConfirmed\n ? (item: T) => {\n setPendingDelete(item);\n setDeleteOpen(true);\n }\n : useBuiltInDelete\n ? (item: T) => {\n performDelete(item).catch((err: unknown) => {\n // useResource has already handed the failure to\n // `resourceOptions.onError`; without one, the user is told.\n if (!resourceOptions?.onError) {\n toast.error(err instanceof Error ? err.message : messages.page.deleteFailed);\n }\n });\n }\n : // Unconfirmed `onDelete` keeps its original contract exactly:\n // called straight from the peek, nothing closed for it.\n (item: T) => {\n // A throw or a rejected promise is reported, never left unhandled,\n // even when `onError` itself throws (the toast is the fallback).\n const report = (err: unknown) => {\n const error = err instanceof Error ? err : new Error(String(err));\n if (resourceOptions?.onError) {\n try {\n resourceOptions.onError(error);\n return;\n } catch {\n // fall through to the toast\n }\n }\n toast.error(error.message || messages.page.deleteFailed);\n };\n // Called right away, as before; a throw or a rejection is reported.\n try {\n Promise.resolve(onDelete?.(item)).catch(report);\n } catch (err) {\n report(err);\n }\n };\n\n // Per-row rights, evaluated against the row the peek is showing.\n const selectedEditable = !!selectedItem && allows(\"edit\", selectedItem);\n const selectedDeletable = !!selectedItem && allows(\"delete\", selectedItem);\n\n // ── Patch tableColumns to use real actions (client-side mode) ──\n const tableColumns = useMemo(() => {\n const base = isClientMode\n ? page.columns.map((col) => ({\n key: col.key,\n header: col.header ?? col.key,\n sortable: col.sortable ?? true,\n hideBelow: col.hideBelow,\n width: col.width,\n minWidth: col.minWidth,\n defaultVisible: col.defaultVisible,\n editable: col.editable,\n accessor: col.accessor,\n render: col.render\n ? (item: T, value: unknown) => col.render!(item, value, actions)\n : undefined,\n }))\n : page.tableColumns;\n if (!isServerControlled) return base;\n // The server owns the ordering. DataTable's header sort is client-side\n // and would only reorder the rows of the current page — a visibly wrong\n // answer presented as a sort — so the affordance is withdrawn rather\n // than left to lie. The DataFilters sort control drives `onSortChange`.\n return base.map((col) => ({ ...col, sortable: false }));\n }, [\n isClientMode,\n isServerControlled,\n page.columns,\n page.tableColumns,\n actions,\n ]);\n\n // ── Client mode: DataTable's header sort is `page.sort` ──\n // The primary header sort is the page's sort (and so the URL's); Shift-\n // click tie-breakers are kept here while that primary still matches, and\n // dropped when the sort changes elsewhere (the sort select, the URL).\n const [tableTieBreaks, setTableTieBreaks] = useState<{\n primary: string;\n rest: DataTableSort[];\n } | null>(null);\n const pageSort = page.sort;\n const setPageSort = page.setSort;\n const tableSort = useMemo<DataTableSort[]>(() => {\n if (!pageSort) return [];\n const primary: DataTableSort = { key: pageSort.field, dir: pageSort.order };\n const rest =\n tableTieBreaks && tableTieBreaks.primary === `${primary.key}:${primary.dir}`\n ? tableTieBreaks.rest\n : [];\n // Only the table's own columns: a sort-select option or a URL sort on a\n // field the table doesn't show still orders the rows (page.sort), but is\n // not a header sort.\n return [primary, ...rest].filter((s) => tableColumns.some((c) => c.key === s.key));\n }, [pageSort, tableTieBreaks, tableColumns]);\n const handleTableSort = useCallback(\n (next: DataTableSort[]) => {\n const [primary, ...rest] = next;\n setTableTieBreaks(primary ? { primary: `${primary.key}:${primary.dir}`, rest } : null);\n setPageSort(primary ? { field: primary.key, order: primary.dir } : null);\n },\n [setPageSort],\n );\n\n // ── Server-driven pager state, needed above for handleSearchChange's\n // already-on-page-1 check. ──\n // The pager's inputs: the caller's controlled props, or — for\n // `pagination=\"server\"` — useResource's own page state.\n const pagerPage = resourceServerPaging\n ? (resourceHook.params.pagination?.page ?? 1)\n : pageProp;\n const pagerPerPage = resourceServerPaging\n ? resourceHook.params.pagination?.perPage\n : perPageProp;\n const pagerTotal = resourceServerPaging ? displayTotal : totalProp;\n const pagerOnPageChange = resourceServerPaging\n ? resourceHook.setPage\n : onPageChange;\n const currentPage = pagerPage ?? 1;\n\n // ── `urlState`: write search, sort and (server paging) page back ──\n // Replace-only, so Back steps through opened records rather than every\n // keystroke; an unchanged URL is not rewritten.\n const writeUrl = url?.write;\n useEffect(() => {\n writeUrl?.({\n q: page.search,\n sort: page.sort,\n ...(resourceServerPaging ? { page: currentPage } : {}),\n });\n }, [writeUrl, page.search, page.sort, currentPage, resourceServerPaging]);\n\n // ── Filter changes: keep the controlled UI state, and tell the server ──\n // In client-side mode these are exactly the hook's own setters; in\n // server-controlled mode they additionally notify the caller and reset to\n // page 1, since the previous page number is meaningless against a new\n // query. The reset is skipped when already on page 1 — nothing changed,\n // so there is nothing for the caller to do.\n const handleSearchChange = useCallback(\n (value: string) => {\n page.filterConfig.onSearchChange(value);\n if (!isServerControlled) return;\n onSearchChange?.(value);\n // `pagination=\"server\"`: useResource's setSearch resets the page\n // itself once the debounce settles; resetting here too would fetch\n // page 1 of the OLD query first.\n if (currentPage !== 1 && !resourceServerPaging) onPageChange?.(1);\n },\n [\n page.filterConfig,\n isServerControlled,\n onSearchChange,\n onPageChange,\n resourceServerPaging,\n currentPage,\n ],\n );\n\n const handleSortSelect = useCallback(\n (value: string) => {\n page.filterConfig.onSortChange(value);\n if (!isServerControlled) return;\n const [field, order] = value.split(\":\");\n onSortChange?.(\n field && (order === \"asc\" || order === \"desc\")\n ? { field, order }\n : null,\n );\n // See handleSearchChange: useResource's setSort resets the page.\n if (!resourceServerPaging) onPageChange?.(1);\n },\n [\n page.filterConfig,\n isServerControlled,\n onSortChange,\n onPageChange,\n resourceServerPaging,\n ],\n );\n\n const handleClearFilters = useCallback(() => {\n page.clearFilters();\n if (!isServerControlled) return;\n // Clearing has to reach the server too — otherwise \"Clear all\" empties\n // the controls and leaves the same rows on screen.\n onSearchChange?.(\"\");\n onSortChange?.(null);\n if (!resourceServerPaging) onPageChange?.(1);\n }, [\n page,\n isServerControlled,\n onSearchChange,\n onSortChange,\n onPageChange,\n resourceServerPaging,\n ]);\n\n // ── Status-chip changes: same page-1 reset as search/sort ──\n // In server-controlled mode `useResourcePage` skips client-side status\n // filtering, so a status change only reaches the caller through\n // `onFiltersChange`. Nothing else calls `onPageChange(1)` for it, so\n // selecting a more restrictive status while on page 3 could otherwise\n // fetch page 3 of the new result set and render an empty page while the\n // matching rows sit on page 1. Guarded the same way as\n // `handleSearchChange`, and not reachable from `handleClearFilters`\n // (which already does its own single reset).\n const handleStatusChange = useCallback(\n (values: string[]) => {\n page.filterConfig.statusChips?.onChange(values);\n if (!isServerControlled) return;\n if (currentPage !== 1 && !resourceServerPaging) onPageChange?.(1);\n },\n [\n page.filterConfig,\n isServerControlled,\n onPageChange,\n resourceServerPaging,\n currentPage,\n ],\n );\n\n const statusChipsConfig = useMemo(() => {\n const base = page.filterConfig.statusChips;\n if (!base) return undefined;\n return { ...base, onChange: handleStatusChange };\n }, [page.filterConfig.statusChips, handleStatusChange]);\n\n const handlePageSizeChange = useCallback(\n (size: number) => {\n updateSetting(\"pageSize\", size);\n onPerPageChange?.(size);\n // useResource's setPerPage resets to page 1 itself.\n if (resourceServerPaging) resourceHook.setPerPage(size);\n else if (isServerControlled) onPageChange?.(1);\n },\n [\n updateSetting,\n onPerPageChange,\n resourceServerPaging,\n resourceHook.setPerPage,\n isServerControlled,\n onPageChange,\n ],\n );\n\n // ── Pagination-config error ──\n // `perPage` AND `total` are both required whenever `onPageChange` is\n // supplied. Neither can be derived from the other, and neither can be\n // derived from the rows:\n // - `perPage`: see the prop doc on `perPage`. A short final page has\n // fewer rows than the page size, so the row count of a page cannot\n // stand in for the page size.\n // - `total`: `displayTotal` falls back to `0` (Line 453). With `total`\n // omitted the range span reads \"No records\" and `Next` stays\n // disabled, while `page.data` renders rows directly below it. A\n // surface that says \"no records\" above visible records is a lie, not\n // a degraded view.\n // Rather than silently guess either one, the pager below refuses to\n // render and shows the error instead. Logged once per mount (not on\n // every render) so it's visible in a console without spamming it.\n const missingPerPage =\n isServerControlled && !!pagerOnPageChange && pagerPerPage === undefined;\n const missingTotal =\n isServerControlled && !!pagerOnPageChange && pagerTotal === undefined;\n const pagerMisconfigured = missingPerPage || missingTotal;\n const missingPagerProps = [\n ...(missingPerPage ? [\"perPage\"] : []),\n ...(missingTotal ? [\"total\"] : []),\n ];\n const loggedMissingPerPageRef = useRef(false);\n useEffect(() => {\n if (!pagerMisconfigured) return;\n if (loggedMissingPerPageRef.current) return;\n loggedMissingPerPageRef.current = true;\n console.error(\n `ResourcePage: ${missingPagerProps\n .map((name) => `\\`${name}\\``)\n .join(\" and \")} ${\n missingPagerProps.length > 1 ? \"are\" : \"is\"\n } required when \\`onPageChange\\` is supplied.`,\n );\n // `missingPagerProps` is derived from `pagerMisconfigured`'s own inputs\n // and the ref makes this run at most once, so it is not a dependency.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pagerMisconfigured]);\n\n // ── Server-driven pager math ──\n // By the time the pager renders, `pagerMisconfigured` has already gated\n // it off, so `perPageProp` and `totalProp` are both present here.\n const pagerPageSize = pagerPerPage ?? effectivePageSize;\n const totalPages = Math.max(\n 1,\n Math.ceil(displayTotal / Math.max(1, pagerPageSize)),\n );\n const rangeFrom =\n page.data.length === 0 ? 0 : (currentPage - 1) * pagerPageSize + 1;\n const rangeTo = rangeFrom === 0 ? 0 : rangeFrom + page.data.length - 1;\n\n // ── `pagination=\"server\"`: never strand the user past the last page ──\n // Deleting the last row of the last page (or any shrink in `total`) would\n // otherwise leave `page` beyond the end: the list comes back empty, the\n // shell swaps in its empty state — pager included — and there is no way\n // back. Step back to the real last page instead.\n const { setPage: setResourcePage } = resourceHook;\n const settledPage =\n !isLoading && !hasError && !resourceHook.list.isPlaceholderData;\n useEffect(() => {\n if (!resourceServerPaging || !settledPage) return;\n if (currentPage > totalPages) setResourcePage(totalPages);\n }, [resourceServerPaging, settledPage, currentPage, totalPages, setResourcePage]);\n\n // ── Detail title/subtitle values ──\n const titleOf = (item: T): string =>\n getTitle\n ? getTitle(item)\n : String((item as Record<string, unknown>)[page.titleField] ?? \"\");\n const detailTitle = selectedItem ? titleOf(selectedItem) : \"\";\n const detailSubtitle = !selectedItem\n ? undefined\n : getSubtitle\n ? getSubtitle(selectedItem)\n : page.subtitleField\n ? String(\n (selectedItem as Record<string, unknown>)[page.subtitleField] ?? \"\",\n )\n : undefined;\n\n // ── Row click handler (route mode navigates) ──\n const handleRowClick = (item: T) => {\n if (detail === \"route\") {\n // Navigate to /{resource}/{id}\n const id = (item as Record<string, unknown>).id;\n if (resourceName && id) {\n onNavigate(`/${resourceName}/${id}`);\n }\n return;\n }\n page.handleRowClick(item);\n urlPeek?.setDetailId(keyOf(item));\n };\n\n // ── Keyboard navigation (j/k, Enter, Backspace, x) ──\n // Only engaged for grid/list views: table view runs its own independent\n // client-side sort + pagination (DataTable), so a flat index into\n // `page.data` can't reliably be mapped back onto its currently-visible,\n // possibly differently-ordered rows.\n const hasBulkSelect = !!bulkActions && bulkActions.length > 0;\n // A detail panel/modal or the built-in form is covering the list. Cursor\n // keys suspend (they'd otherwise drive the list behind the overlay, and\n // Enter would re-open the row instead of activating the focused control);\n // ⌫ stays live so it can dismiss the overlay.\n const overlayOpen = detailOpen || formOpen || deleteOpen;\n const keyboardNav = useKeyboardNavigation({\n itemCount: page.data.length,\n enabled: keyboardNavigation && page.viewMode !== \"table\",\n overlayOpen,\n onOpen: (index) => {\n const item = page.data[index];\n if (item) handleRowClick(item);\n },\n onToggleSelect: hasBulkSelect\n ? (index) => {\n const item = page.data[index];\n if (item) {\n handleToggleSelect(keyOf(item));\n }\n }\n : undefined,\n // Supplied only while there is an open detail to close — the hook\n // suppresses Backspace's default whenever this is present, so leaving it\n // wired up permanently would swallow the browser/app's Backspace on\n // every grid/list page (including detail=\"none\" and detail=\"route\",\n // which never open one). `detailOpen` is only ever true for the panel\n // and modal modes, so it is the precise precondition here.\n onBack: detailOpen ? closeDetail : undefined,\n });\n\n // `pagination=\"cursor\"`: the \"Load more\" footer's state.\n const infinitePages = infinite.query.data?.pages;\n const loadMore = resourceCursorPaging\n ? {\n hasMore: infinite.hasNextPage,\n loading: infinite.isFetchingNextPage,\n load: infinite.fetchNextPage,\n loaded: infinite.rows.length,\n // Rows the latest \"Load more\" added; 0 before the first one.\n lastLoaded:\n infinitePages && infinitePages.length > 1\n ? infinitePages[infinitePages.length - 1]!.data.length\n : 0,\n }\n : undefined;\n\n // ── Create button ──\n\n return {\n actions,\n allows,\n clientTruncated,\n loadMore,\n closeDetail,\n currentPage,\n deleteConfirmed,\n deleteCopy,\n deleteHandler,\n deleteKind,\n deleteOpen,\n detailOpen,\n detailSubtitle,\n detailTitle,\n displayData,\n displayTotal,\n effectivePageSize,\n formAction,\n formItem,\n formOpen,\n handleClearFilters,\n handleClearSelection,\n handleCreate,\n handleEdit,\n handlePageSizeChange,\n handleRowClick,\n handleSearchChange,\n handleSortSelect,\n handleTableSort,\n handleToggleAll,\n handleToggleSelect,\n hasError,\n isClientMode,\n isLoading,\n isServerControlled,\n keyOf,\n keyboardNav,\n linkMissing,\n linked,\n missingPagerProps,\n page,\n pagerMisconfigured,\n pagerOnPageChange,\n pendingDelete,\n performDelete,\n rangeFrom,\n rangeTo,\n resourceHook,\n resourceServerPaging,\n selectedDeletable,\n selectedEditable,\n selectedIds,\n selectedItem,\n serverSearchFields,\n setDeleteOpen,\n setFormOpen,\n settings,\n statusChipsConfig,\n tableColumns,\n tableSort,\n titleOf,\n totalPages,\n updateSetting,\n useBuiltInCreate,\n useBuiltInDelete,\n useBuiltInEdit,\n };\n}\n\n/**\n * What {@link useResourceTable} returns: the list's rows and the handlers a\n * custom layout wires to its controls.\n *\n * @stability Beta\n */\nexport interface ResourceTableState<\n T extends Record<string, unknown> = Record<string, unknown>,\n> {\n // ── Rows ──\n /**\n * The rows to show: filtered and sorted. With `pagination=\"client\"` this\n * is every matching row (page it yourself); with server paging it is the\n * current page.\n */\n rows: T[];\n /**\n * How many rows match, across all pages. With `pagination=\"cursor\"` it is\n * the server's count while no search or status filter is active; with one,\n * only loaded rows are filtered, so it counts the loaded rows that match.\n */\n total: number;\n loading: boolean;\n /** The read failed. */\n error: boolean;\n /** True when more than `clientRowLimit` rows exist and only that many were loaded. */\n truncated: boolean;\n /**\n * `pagination=\"cursor\"`: whether more rows can be loaded, whether a page\n * is loading, and `load()` to append the next page. Undefined otherwise.\n */\n loadMore?: {\n hasMore: boolean;\n loading: boolean;\n load: () => void;\n /** Rows loaded so far. */\n loaded: number;\n /** Rows the latest load added (0 before the first \"Load more\"). */\n lastLoaded: number;\n };\n /** The columns, resolved to DataTable's format. */\n columns: DataTableColumn<T>[];\n /** Write actions for cell renderers (update, remove, …). */\n actions: ResourceActions<T>;\n /** A row's identity: `getKey`, else its `id`. */\n getKey: (item: T) => string;\n /** A row's title: `getTitle`, else its title field. */\n getTitle: (item: T) => string;\n /** The page's permission check (`can`, then the deprecated per-row predicates). */\n can: (action: ResourceAction, item?: T) => boolean;\n\n // ── Search, sort and filters ──\n search: string;\n setSearch: (value: string) => void;\n /** Sort keys, primary first. */\n sort: DataTableSort[];\n setSort: (sort: DataTableSort[]) => void;\n /** The status filter's choices, its selected values and its setter, when the list has one. */\n statusFilter:\n | { options: string[]; selected: string[]; onChange: (values: string[]) => void }\n | undefined;\n hasActiveFilters: boolean;\n clearFilters: () => void;\n\n // ── Paging (server or caller-controlled paging) ──\n /** The current page, from 1. */\n page: number;\n pageCount: number;\n pageSize: number;\n setPageSize: (size: number) => void;\n /** Go to a page; undefined when the page is not controlled (client paging). */\n setPage: ((page: number) => void) | undefined;\n /** The 1-based range of the rows shown, for \"21–40 of 95\"; 0 when empty. */\n rangeFrom: number;\n rangeTo: number;\n\n // ── Selection ──\n selectedIds: Set<string>;\n toggleSelected: (id: string) => void;\n toggleAll: () => void;\n clearSelection: () => void;\n\n // ── The open record ──\n /** The open row, kept current as the data changes. */\n openItem: T | null;\n detailOpen: boolean;\n /** What clicking a row does: opens the peek, modal or route. */\n openRow: (item: T) => void;\n closeDetail: () => void;\n /** A record linked by URL that does not exist (or was deleted). */\n openItemMissing: boolean;\n\n // ── Create and edit ──\n /** Undefined when the page cannot create. */\n create: (() => void) | undefined;\n edit: (item: T) => void;\n /** The built-in form's state, for rendering your own form. */\n form: {\n open: boolean;\n setOpen: (open: boolean) => void;\n action: \"create\" | \"edit\";\n /** The row being edited; null when creating. */\n item: T | null;\n };\n\n // ── Delete ──\n /** Delete a row: asks first when the delete is confirmed. Undefined when the page cannot delete. */\n remove: ((item: T) => void) | undefined;\n /** The confirm step's state, when `remove` asks first. */\n deleteConfirm: {\n open: boolean;\n setOpen: (open: boolean) => void;\n /** The row being confirmed (kept through the close animation). */\n item: T | null;\n /** Run the delete; rejects with the failure. */\n confirm: () => Promise<void>;\n /** \"recycle\" when the provider soft-deletes, so the copy can say it can be restored. */\n kind: \"recycle\" | \"permanent\";\n copy: ResourceDeleteConfirmCopy<T> | undefined;\n };\n}\n\n/**\n * The list behind {@link ResourcePage}, without any markup: where the rows\n * come from (a `resource` through the data provider, or `data` you pass),\n * search, sort, status filter and paging, selection, the open record (and\n * its URL state), the built-in create/edit form and confirmed delete, and\n * the row handlers. Takes the same options as `ResourcePage`.\n *\n * Use it to build a different layout over the same behaviour; `ResourcePage`\n * itself is this behaviour plus Genesis's markup.\n *\n * @stability Beta\n */\nexport function useResourceTable<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(props: ResourcePageProps<T>): ResourceTableState<T> {\n const m = useResourceTableModel<T>(props);\n const { pendingDelete, performDelete } = m;\n const confirm = useCallback(\n () => (pendingDelete ? performDelete(pendingDelete) : Promise.resolve()),\n [pendingDelete, performDelete],\n );\n return {\n rows: m.page.data,\n total:\n m.loadMore && m.page.search === \"\" && m.page.statusValue.length === 0\n ? m.displayTotal\n : m.page.total,\n loading: m.isLoading,\n error: m.hasError,\n truncated: m.clientTruncated,\n // Present only with `pagination=\"cursor\"`.\n ...(m.loadMore ? { loadMore: m.loadMore } : {}),\n columns: m.tableColumns,\n actions: m.actions,\n getKey: m.keyOf,\n getTitle: m.titleOf,\n can: m.allows,\n search: m.page.search,\n setSearch: m.handleSearchChange,\n sort: m.tableSort,\n setSort: m.handleTableSort,\n statusFilter: m.statusChipsConfig,\n hasActiveFilters: m.page.hasActiveFilters,\n clearFilters: m.handleClearFilters,\n page: m.currentPage,\n pageCount: m.totalPages,\n pageSize: m.effectivePageSize,\n setPageSize: m.handlePageSizeChange,\n setPage: m.pagerOnPageChange,\n rangeFrom: m.rangeFrom,\n rangeTo: m.rangeTo,\n selectedIds: m.selectedIds,\n toggleSelected: m.handleToggleSelect,\n toggleAll: m.handleToggleAll,\n clearSelection: m.handleClearSelection,\n openItem: m.selectedItem,\n detailOpen: m.detailOpen,\n openRow: m.handleRowClick,\n closeDetail: m.closeDetail,\n openItemMissing: m.linkMissing,\n create:\n (m.useBuiltInCreate || props.onCreate) && m.allows(\"create\") ? m.handleCreate : undefined,\n edit: m.handleEdit,\n form: {\n open: m.formOpen,\n setOpen: m.setFormOpen,\n action: m.formAction,\n item: m.formItem,\n },\n remove: m.deleteHandler,\n deleteConfirm: {\n open: m.deleteOpen,\n setOpen: m.setDeleteOpen,\n item: pendingDelete,\n confirm,\n kind: m.deleteKind,\n copy: m.deleteCopy,\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/messages-en.ts
|
|
6
|
+
var uiMessages = {
|
|
7
|
+
common: {
|
|
8
|
+
/** Shown for an empty value in a cell, card or peek. */
|
|
9
|
+
empty: "\u2014",
|
|
10
|
+
yes: "Yes",
|
|
11
|
+
no: "No",
|
|
12
|
+
cancel: "Cancel",
|
|
13
|
+
save: "Save",
|
|
14
|
+
close: "Close",
|
|
15
|
+
edit: "Edit",
|
|
16
|
+
delete: "Delete",
|
|
17
|
+
clear: "Clear",
|
|
18
|
+
open: "Open",
|
|
19
|
+
/** `{name}`: the record's title. */
|
|
20
|
+
openItem: "Open {name}",
|
|
21
|
+
loading: "Loading\u2026",
|
|
22
|
+
saving: "Saving"
|
|
23
|
+
},
|
|
24
|
+
page: {
|
|
25
|
+
errorTitle: "Something went wrong",
|
|
26
|
+
/** `{entity}`: the page's record name, e.g. "task". */
|
|
27
|
+
errorBody: "Failed to load {entity}s. Please try again.",
|
|
28
|
+
retry: "Retry",
|
|
29
|
+
create: "New",
|
|
30
|
+
loadMore: "Load more",
|
|
31
|
+
/** `{loaded}`: rows loaded so far. */
|
|
32
|
+
allLoaded: "All {loaded} loaded",
|
|
33
|
+
/** Announced after Load more. `{added}`: rows the last load added; `{loaded}`: rows shown. */
|
|
34
|
+
loadedMore: "Loaded {added} more. {loaded} shown.",
|
|
35
|
+
/** `{shown}`, `{total}`: rows loaded and rows that exist. */
|
|
36
|
+
truncated: "Showing the first {shown} of {total} records.",
|
|
37
|
+
pagination: "Pagination",
|
|
38
|
+
noRecords: "No records",
|
|
39
|
+
/** `{from}`–`{to}`: the rows on this page; `{total}`: all rows. */
|
|
40
|
+
range: "Showing {from}-{to} of {total}",
|
|
41
|
+
previous: "Previous",
|
|
42
|
+
next: "Next",
|
|
43
|
+
/** `{page}` of `{pages}`. */
|
|
44
|
+
pageOf: "Page {page} of {pages}",
|
|
45
|
+
notFoundTitle: "Record not found",
|
|
46
|
+
notFoundBody: "This record doesn't exist, or you don't have access to it.",
|
|
47
|
+
deleteFailed: "The delete failed."
|
|
48
|
+
},
|
|
49
|
+
table: {
|
|
50
|
+
noRecords: "No records found",
|
|
51
|
+
/** `{name}`: the row's label. */
|
|
52
|
+
selectRow: "Select {name}",
|
|
53
|
+
selectAll: "Select all rows",
|
|
54
|
+
columns: "Columns",
|
|
55
|
+
resetColumns: "Reset to defaults",
|
|
56
|
+
ascending: "ascending",
|
|
57
|
+
descending: "descending",
|
|
58
|
+
/** A secondary sort's header label. `{header}`, `{direction}` (ascending/descending), `{n}`: its place in the sort. */
|
|
59
|
+
sortedBy: "{header}, sorted {direction}, sort {n}",
|
|
60
|
+
rows: "Rows:",
|
|
61
|
+
noRows: "No records",
|
|
62
|
+
/** `{from}`–`{to}` of `{total}`: the rows on this page. */
|
|
63
|
+
range: "Showing {from}\u2013{to} of {total}",
|
|
64
|
+
/** `{page}` / `{pages}`. */
|
|
65
|
+
pageOf: "{page} / {pages}"
|
|
66
|
+
},
|
|
67
|
+
confirmDelete: {
|
|
68
|
+
title: "Delete this record?",
|
|
69
|
+
recycle: "It moves to the recycle bin, where it can be restored.",
|
|
70
|
+
permanent: "This can't be undone."
|
|
71
|
+
},
|
|
72
|
+
detail: {
|
|
73
|
+
/** The panel's name for screen readers when it has no title. */
|
|
74
|
+
fallbackTitle: "Detail panel"
|
|
75
|
+
},
|
|
76
|
+
filters: {
|
|
77
|
+
search: "Search...",
|
|
78
|
+
status: "Status",
|
|
79
|
+
sortBy: "Sort by...",
|
|
80
|
+
views: "Views",
|
|
81
|
+
/** `{count}`: saved views. */
|
|
82
|
+
viewCount: "({count})",
|
|
83
|
+
noViews: "No saved views yet",
|
|
84
|
+
saveCurrent: "Save current view",
|
|
85
|
+
clearAll: "Clear all",
|
|
86
|
+
saveViewTitle: "Save Current View",
|
|
87
|
+
viewNamePlaceholder: "View name (e.g. 'Active Sessions')"
|
|
88
|
+
},
|
|
89
|
+
bulk: {
|
|
90
|
+
/** `{count}`: selected rows. */
|
|
91
|
+
selected: "{count} selected"
|
|
92
|
+
},
|
|
93
|
+
view: {
|
|
94
|
+
mode: "View mode",
|
|
95
|
+
grid: "Grid view",
|
|
96
|
+
table: "Table view",
|
|
97
|
+
list: "List view",
|
|
98
|
+
settings: "View settings",
|
|
99
|
+
settingsTitle: "Display Settings",
|
|
100
|
+
pageSize: "Page size",
|
|
101
|
+
/** `{n}`: a page size. */
|
|
102
|
+
pageSizeOption: "{n} items",
|
|
103
|
+
density: "Density",
|
|
104
|
+
compact: "Compact",
|
|
105
|
+
comfortable: "Comfortable",
|
|
106
|
+
spacious: "Spacious"
|
|
107
|
+
},
|
|
108
|
+
kanban: {
|
|
109
|
+
noItems: "No items",
|
|
110
|
+
/** The name used when a card has no label. */
|
|
111
|
+
card: "Card",
|
|
112
|
+
/** The same, inside a control's label ("Pick up card"). */
|
|
113
|
+
cardInLabel: "card",
|
|
114
|
+
/** `{name}`: the card. */
|
|
115
|
+
pickUp: "Pick up {name}",
|
|
116
|
+
move: "Move {name}",
|
|
117
|
+
moveTo: "Move to",
|
|
118
|
+
/** `{name}`, `{column}`: where it landed. */
|
|
119
|
+
moved: "{name} moved to {column}.",
|
|
120
|
+
moveFailed: "Couldn\u2019t move {name}.",
|
|
121
|
+
/** Keyboard pick-up. `{column}`: where it is now. */
|
|
122
|
+
pickedUp: "{name} picked up in {column}. Use the left and right arrow keys to choose a column, Space to drop, Escape to cancel.",
|
|
123
|
+
/** Touch pick-up. */
|
|
124
|
+
pickedUpTouch: "{name} picked up in {column}.",
|
|
125
|
+
/** `{n}` of `{count}` columns. */
|
|
126
|
+
over: "Over {column}, column {n} of {count}.",
|
|
127
|
+
droppedBack: "{name} dropped back in {column}.",
|
|
128
|
+
cancelled: "Move cancelled. {name} stays in {column}.",
|
|
129
|
+
instructions: "Space or Enter picks the card up. Left and right arrows, Home and End choose a column. Space or Enter drops it, Escape puts it back. Alt with an arrow moves it one column."
|
|
130
|
+
},
|
|
131
|
+
sortable: {
|
|
132
|
+
item: "Item",
|
|
133
|
+
/** `{name}`: the item. */
|
|
134
|
+
reorder: "Reorder {name}",
|
|
135
|
+
move: "Move {name}",
|
|
136
|
+
moveUp: "Move up",
|
|
137
|
+
moveDown: "Move down",
|
|
138
|
+
moveToTop: "Move to top",
|
|
139
|
+
moveToBottom: "Move to bottom",
|
|
140
|
+
/** `{n}` of `{total}`: the position. */
|
|
141
|
+
moved: "{name} moved to position {n} of {total}.",
|
|
142
|
+
moveFailed: "Couldn\u2019t move {name}.",
|
|
143
|
+
pickedUp: "{name} picked up, position {n} of {total}. Use the up and down arrow keys to move, Space to drop, Escape to cancel.",
|
|
144
|
+
dropped: "{name} dropped at position {n} of {total}.",
|
|
145
|
+
cancelled: "Move cancelled. {name} is back at position {n} of {total}.",
|
|
146
|
+
instructions: "Space or Enter picks the item up. Up and down arrows, Home and End move it. Space or Enter drops it, Escape puts it back. Alt with an arrow moves it one step."
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
function merge(base, over) {
|
|
150
|
+
if (!over) return base;
|
|
151
|
+
const out = { ...base };
|
|
152
|
+
for (const [key, value] of Object.entries(over)) {
|
|
153
|
+
if (value === void 0) continue;
|
|
154
|
+
const current = base[key];
|
|
155
|
+
out[key] = current && typeof current === "object" && value && typeof value === "object" ? merge(current, value) : value;
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
function resolveUiMessages(overrides) {
|
|
160
|
+
return merge(
|
|
161
|
+
uiMessages,
|
|
162
|
+
overrides
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
function fillMessage(template, values) {
|
|
166
|
+
return template.replace(
|
|
167
|
+
/\{(\w+)\}/g,
|
|
168
|
+
(token, name) => values[name] !== void 0 ? String(values[name]) : token
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
var MessagesContext = createContext(uiMessages);
|
|
172
|
+
function UiMessagesProvider({
|
|
173
|
+
messages,
|
|
174
|
+
children
|
|
175
|
+
}) {
|
|
176
|
+
const parent = useContext(MessagesContext);
|
|
177
|
+
const value = useMemo(
|
|
178
|
+
() => merge(
|
|
179
|
+
parent,
|
|
180
|
+
messages
|
|
181
|
+
),
|
|
182
|
+
[parent, messages]
|
|
183
|
+
);
|
|
184
|
+
return /* @__PURE__ */ jsx(MessagesContext.Provider, { value, children });
|
|
185
|
+
}
|
|
186
|
+
function useUiMessages() {
|
|
187
|
+
return useContext(MessagesContext);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export { UiMessagesProvider, fillMessage, resolveUiMessages, uiMessages, useUiMessages };
|
|
191
|
+
//# sourceMappingURL=chunk-YCQAYWMX.js.map
|
|
192
|
+
//# sourceMappingURL=chunk-YCQAYWMX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/messages-en.ts","../src/messages.tsx"],"names":[],"mappings":"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","file":"chunk-YCQAYWMX.js","sourcesContent":["/**\n * Every word Genesis UI's data components show or announce, in English.\n * `{name}` marks a value filled in at run time; keep it in a translation.\n * Override any part through `UiMessagesProvider` (see `messages.tsx`).\n */\nexport const uiMessages = {\n common: {\n /** Shown for an empty value in a cell, card or peek. */\n empty: \"—\",\n yes: \"Yes\",\n no: \"No\",\n cancel: \"Cancel\",\n save: \"Save\",\n close: \"Close\",\n edit: \"Edit\",\n delete: \"Delete\",\n clear: \"Clear\",\n open: \"Open\",\n /** `{name}`: the record's title. */\n openItem: \"Open {name}\",\n loading: \"Loading…\",\n saving: \"Saving\",\n },\n page: {\n errorTitle: \"Something went wrong\",\n /** `{entity}`: the page's record name, e.g. \"task\". */\n errorBody: \"Failed to load {entity}s. Please try again.\",\n retry: \"Retry\",\n create: \"New\",\n loadMore: \"Load more\",\n /** `{loaded}`: rows loaded so far. */\n allLoaded: \"All {loaded} loaded\",\n /** Announced after Load more. `{added}`: rows the last load added; `{loaded}`: rows shown. */\n loadedMore: \"Loaded {added} more. {loaded} shown.\",\n /** `{shown}`, `{total}`: rows loaded and rows that exist. */\n truncated: \"Showing the first {shown} of {total} records.\",\n pagination: \"Pagination\",\n noRecords: \"No records\",\n /** `{from}`–`{to}`: the rows on this page; `{total}`: all rows. */\n range: \"Showing {from}-{to} of {total}\",\n previous: \"Previous\",\n next: \"Next\",\n /** `{page}` of `{pages}`. */\n pageOf: \"Page {page} of {pages}\",\n notFoundTitle: \"Record not found\",\n notFoundBody: \"This record doesn't exist, or you don't have access to it.\",\n deleteFailed: \"The delete failed.\",\n },\n table: {\n noRecords: \"No records found\",\n /** `{name}`: the row's label. */\n selectRow: \"Select {name}\",\n selectAll: \"Select all rows\",\n columns: \"Columns\",\n resetColumns: \"Reset to defaults\",\n ascending: \"ascending\",\n descending: \"descending\",\n /** A secondary sort's header label. `{header}`, `{direction}` (ascending/descending), `{n}`: its place in the sort. */\n sortedBy: \"{header}, sorted {direction}, sort {n}\",\n rows: \"Rows:\",\n noRows: \"No records\",\n /** `{from}`–`{to}` of `{total}`: the rows on this page. */\n range: \"Showing {from}–{to} of {total}\",\n /** `{page}` / `{pages}`. */\n pageOf: \"{page} / {pages}\",\n },\n confirmDelete: {\n title: \"Delete this record?\",\n recycle: \"It moves to the recycle bin, where it can be restored.\",\n permanent: \"This can't be undone.\",\n },\n detail: {\n /** The panel's name for screen readers when it has no title. */\n fallbackTitle: \"Detail panel\",\n },\n filters: {\n search: \"Search...\",\n status: \"Status\",\n sortBy: \"Sort by...\",\n views: \"Views\",\n /** `{count}`: saved views. */\n viewCount: \"({count})\",\n noViews: \"No saved views yet\",\n saveCurrent: \"Save current view\",\n clearAll: \"Clear all\",\n saveViewTitle: \"Save Current View\",\n viewNamePlaceholder: \"View name (e.g. 'Active Sessions')\",\n },\n bulk: {\n /** `{count}`: selected rows. */\n selected: \"{count} selected\",\n },\n view: {\n mode: \"View mode\",\n grid: \"Grid view\",\n table: \"Table view\",\n list: \"List view\",\n settings: \"View settings\",\n settingsTitle: \"Display Settings\",\n pageSize: \"Page size\",\n /** `{n}`: a page size. */\n pageSizeOption: \"{n} items\",\n density: \"Density\",\n compact: \"Compact\",\n comfortable: \"Comfortable\",\n spacious: \"Spacious\",\n },\n kanban: {\n noItems: \"No items\",\n /** The name used when a card has no label. */\n card: \"Card\",\n /** The same, inside a control's label (\"Pick up card\"). */\n cardInLabel: \"card\",\n /** `{name}`: the card. */\n pickUp: \"Pick up {name}\",\n move: \"Move {name}\",\n moveTo: \"Move to\",\n /** `{name}`, `{column}`: where it landed. */\n moved: \"{name} moved to {column}.\",\n moveFailed: \"Couldn’t move {name}.\",\n /** Keyboard pick-up. `{column}`: where it is now. */\n pickedUp:\n \"{name} picked up in {column}. Use the left and right arrow keys to choose a column, Space to drop, Escape to cancel.\",\n /** Touch pick-up. */\n pickedUpTouch: \"{name} picked up in {column}.\",\n /** `{n}` of `{count}` columns. */\n over: \"Over {column}, column {n} of {count}.\",\n droppedBack: \"{name} dropped back in {column}.\",\n cancelled: \"Move cancelled. {name} stays in {column}.\",\n instructions:\n \"Space or Enter picks the card up. Left and right arrows, Home and End choose a column. Space or Enter drops it, Escape puts it back. Alt with an arrow moves it one column.\",\n },\n sortable: {\n item: \"Item\",\n /** `{name}`: the item. */\n reorder: \"Reorder {name}\",\n move: \"Move {name}\",\n moveUp: \"Move up\",\n moveDown: \"Move down\",\n moveToTop: \"Move to top\",\n moveToBottom: \"Move to bottom\",\n /** `{n}` of `{total}`: the position. */\n moved: \"{name} moved to position {n} of {total}.\",\n moveFailed: \"Couldn’t move {name}.\",\n pickedUp:\n \"{name} picked up, position {n} of {total}. Use the up and down arrow keys to move, Space to drop, Escape to cancel.\",\n dropped: \"{name} dropped at position {n} of {total}.\",\n cancelled: \"Move cancelled. {name} is back at position {n} of {total}.\",\n instructions:\n \"Space or Enter picks the item up. Up and down arrows, Home and End move it. Space or Enter drops it, Escape puts it back. Alt with an arrow moves it one step.\",\n },\n};\n\n/** The shape a translation fills. */\nexport type UiMessages = typeof uiMessages;\n","\"use client\";\n\n/**\n * The words Genesis UI's own components show and announce, in one place, so\n * an app can reword or translate them. The same shape as the support and\n * chat packages' copy: an English catalogue, overrides that replace any part\n * of it (what you leave out stays English), and `{name}` placeholders.\n *\n * ```tsx\n * <UiMessagesProvider messages={{ data: { loadMore: \"Mehr laden\" } }}>\n * <App />\n * </UiMessagesProvider>\n * ```\n *\n * Props that already name a piece of copy (`createLabel`, `emptyMessage`,\n * `confirmDelete.title`, …) still win over the catalogue.\n */\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport { uiMessages, type UiMessages } from \"./messages-en\";\n\nexport { uiMessages, type UiMessages };\n\ntype DeepPartial<T> = { [K in keyof T]?: T[K] extends string ? string : DeepPartial<T[K]> };\n\n/** Any part of the catalogue. */\nexport type UiMessagesOverrides = DeepPartial<UiMessages>;\n\nfunction merge(base: Record<string, unknown>, over: Record<string, unknown> | undefined): Record<string, unknown> {\n if (!over) return base;\n const out: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(over)) {\n if (value === undefined) continue;\n const current = base[key];\n out[key] =\n current && typeof current === \"object\" && value && typeof value === \"object\"\n ? merge(current as Record<string, unknown>, value as Record<string, unknown>)\n : value;\n }\n return out;\n}\n\n/** The catalogue with overrides merged over the English. */\nexport function resolveUiMessages(overrides?: UiMessagesOverrides): UiMessages {\n return merge(\n uiMessages as unknown as Record<string, unknown>,\n overrides as Record<string, unknown> | undefined,\n ) as unknown as UiMessages;\n}\n\n/** Fills `{name}` placeholders; an unknown placeholder is left as written. */\nexport function fillMessage(template: string, values: Readonly<Record<string, string | number>>): string {\n return template.replace(/\\{(\\w+)\\}/g, (token, name: string) =>\n values[name] !== undefined ? String(values[name]) : token,\n );\n}\n\nconst MessagesContext = createContext<UiMessages>(uiMessages);\n\n/**\n * Rewords or translates Genesis UI's components below it. Nested providers\n * build on the one above, so a section can change a few words.\n */\nexport function UiMessagesProvider({\n messages,\n children,\n}: {\n messages: UiMessagesOverrides;\n children: ReactNode;\n}) {\n const parent = useContext(MessagesContext);\n const value = useMemo(\n () =>\n merge(\n parent as unknown as Record<string, unknown>,\n messages as Record<string, unknown>,\n ) as unknown as UiMessages,\n [parent, messages],\n );\n return <MessagesContext.Provider value={value}>{children}</MessagesContext.Provider>;\n}\n\n/** The catalogue in effect: English unless a `UiMessagesProvider` says otherwise. */\nexport function useUiMessages(): UiMessages {\n return useContext(MessagesContext);\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { B as BulkAction, C as ConfirmDeleteDialog, a as ConfirmDeleteDialogProps, D as DataBulkBar, b as DataFilterConfig, c as DataFilters, d as DataGrid, e as DataPageShell, f as DataPageShellProps, g as DetailPanel, h as DetailPanelProps, F as FilterCombobox, i as FilterOption, j as ResourceAction, k as ResourceCardActions, l as ResourceDeleteConfirmCopy, m as ResourceForm, n as ResourceFormProps, o as ResourcePage, p as ResourcePageProps, q as ResourcePageSlotMap, r as ResourcePageSlotProps, s as ResourcePageSlots, R as ResourceTableState, S as SavedViewItem, t as StatusChipOption, v as StatusChipsVariant, u as useResourceTable } from '../../use-resource-table-
|
|
2
|
-
export { D as DataTable, c as DataTableColumn, e as DataTableProps, d as DataTableSort, L as LinkCell, R as ResourceActions, a as ResourceColumnDef, T as ThumbnailCell } from '../../use-resource-page-
|
|
1
|
+
export { B as BulkAction, C as ConfirmDeleteDialog, a as ConfirmDeleteDialogProps, D as DataBulkBar, b as DataFilterConfig, c as DataFilters, d as DataGrid, e as DataPageShell, f as DataPageShellProps, g as DetailPanel, h as DetailPanelProps, F as FilterCombobox, i as FilterOption, j as ResourceAction, k as ResourceCardActions, l as ResourceDeleteConfirmCopy, m as ResourceForm, n as ResourceFormProps, o as ResourcePage, p as ResourcePageProps, q as ResourcePageSlotMap, r as ResourcePageSlotProps, s as ResourcePageSlots, R as ResourceTableState, S as SavedViewItem, t as StatusChipOption, v as StatusChipsVariant, u as useResourceTable } from '../../use-resource-table-WDqz7oQ-.js';
|
|
2
|
+
export { D as DataTable, c as DataTableColumn, e as DataTableProps, d as DataTableSort, L as LinkCell, R as ResourceActions, a as ResourceColumnDef, T as ThumbnailCell } from '../../use-resource-page-BA1P7xea.js';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { ReactNode } from 'react';
|
|
5
5
|
export { EmptyState } from '../patterns/empty-state.js';
|
|
@@ -15,8 +15,8 @@ import { UndoableWrite, WizardStep } from '@marktiderman/genesis-core/hooks';
|
|
|
15
15
|
import { ResourceFormFieldDef } from '@marktiderman/genesis-core';
|
|
16
16
|
export { FieldType, ResourceFormFieldDef, SelectOption } from '@marktiderman/genesis-core';
|
|
17
17
|
import { Control, UseFormReturn, FieldErrors } from 'react-hook-form';
|
|
18
|
-
import { A as AppShell$1 } from '../../AppShell-
|
|
19
|
-
export { a as AppShellOptions, c as AppShellProps, N as NavItem, P as ParentNavigation } from '../../AppShell-
|
|
18
|
+
import { A as AppShell$1 } from '../../AppShell-DDyVqNmJ.js';
|
|
19
|
+
export { a as AppShellOptions, c as AppShellProps, N as NavItem, P as ParentNavigation } from '../../AppShell-DDyVqNmJ.js';
|
|
20
20
|
import { P as PageHeader$1 } from '../../PageHeader-V9lVkZtF.js';
|
|
21
21
|
export { a as PageHeaderOptions, b as PageHeaderProps } from '../../PageHeader-V9lVkZtF.js';
|
|
22
22
|
export { Density } from '../../hooks/use-view-settings.js';
|
|
@@ -44,7 +44,7 @@ declare function CurrencyCell(currency?: string, locale?: string): (_item: unkno
|
|
|
44
44
|
/**
|
|
45
45
|
* BadgeCell -- status badge with configurable color map.
|
|
46
46
|
*/
|
|
47
|
-
declare function BadgeCell(colorMap?: Record<string, "default" | "secondary" | "destructive" | "outline" | "success" | "warning" | "info" | "muted">): (_item: unknown, value: unknown) => React.JSX.Element
|
|
47
|
+
declare function BadgeCell(colorMap?: Record<string, "default" | "secondary" | "destructive" | "outline" | "success" | "warning" | "info" | "muted">): (_item: unknown, value: unknown) => "—" | React.JSX.Element;
|
|
48
48
|
|
|
49
49
|
type StatCardColor = "primary" | "success" | "warning" | "info" | "destructive" | "muted";
|
|
50
50
|
interface StatCardProps {
|
|
@@ -114,7 +114,7 @@ interface KanbanBoardProps<T> {
|
|
|
114
114
|
* can't be done from a keyboard or a touch screen (docs/FRAMEWORK.md rule 3),
|
|
115
115
|
* so dragging is never the only way to move a card.
|
|
116
116
|
*/
|
|
117
|
-
declare function KanbanBoard<T>({ columns, renderCard, emptyMessage, className, getKey, onMoveItem, getItemLabel, renderColumnFooter, }: KanbanBoardProps<T>): React.JSX.Element;
|
|
117
|
+
declare function KanbanBoard<T>({ columns, renderCard, emptyMessage: emptyMessageProp, className, getKey, onMoveItem, getItemLabel, renderColumnFooter, }: KanbanBoardProps<T>): React.JSX.Element;
|
|
118
118
|
|
|
119
119
|
interface DataListProps<T> {
|
|
120
120
|
items: T[];
|