@arqel-dev/ui 0.15.0 → 0.15.1

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.
Files changed (95) hide show
  1. package/README.md +1 -1
  2. package/dist/{AreaChart-NMQ2RQGA.js → AreaChart-JAZ6LUYG.js} +8 -4
  3. package/dist/AreaChart-JAZ6LUYG.js.map +1 -0
  4. package/dist/ArqelCreatePage-UZAHV4DK.js +8 -0
  5. package/dist/{ArqelCreatePage-MV4JN2MO.js.map → ArqelCreatePage-UZAHV4DK.js.map} +1 -1
  6. package/dist/ArqelDashboardPage-Z5R4XSH4.js +6 -0
  7. package/dist/{ArqelDashboardPage-QK3BYVK3.js.map → ArqelDashboardPage-Z5R4XSH4.js.map} +1 -1
  8. package/dist/ArqelEditPage-RRYFYOTC.js +8 -0
  9. package/dist/{ArqelShowPage-5WWUSYC7.js.map → ArqelEditPage-RRYFYOTC.js.map} +1 -1
  10. package/dist/ArqelIndexPage-RGZWKKAX.js +12 -0
  11. package/dist/{ArqelIndexPage-R6JL5KOH.js.map → ArqelIndexPage-RGZWKKAX.js.map} +1 -1
  12. package/dist/ArqelShowPage-TVCJAV2F.js +6 -0
  13. package/dist/{ArqelEditPage-7J3IS2BR.js.map → ArqelShowPage-TVCJAV2F.js.map} +1 -1
  14. package/dist/{BarChart-KLHKTLO2.js → BarChart-E52NJSJE.js} +8 -4
  15. package/dist/BarChart-E52NJSJE.js.map +1 -0
  16. package/dist/{DonutChart-L56R4QF2.js → DonutChart-IGSF4LEB.js} +3 -3
  17. package/dist/{DonutChart-L56R4QF2.js.map → DonutChart-IGSF4LEB.js.map} +1 -1
  18. package/dist/{FormRenderer-BJBRIkfH.d.ts → FormRenderer-By8fZp4t.d.ts} +2 -0
  19. package/dist/{LineChart-GHMPHFZZ.js → LineChart-RRPGAZON.js} +8 -4
  20. package/dist/LineChart-RRPGAZON.js.map +1 -0
  21. package/dist/PieChart-SGN7V5LQ.js +4 -0
  22. package/dist/{PieChart-T2VQOFPP.js.map → PieChart-SGN7V5LQ.js.map} +1 -1
  23. package/dist/{RadarChart-CSWR5AO7.js → RadarChart-3AOM736J.js} +8 -4
  24. package/dist/RadarChart-3AOM736J.js.map +1 -0
  25. package/dist/action.js +2 -2
  26. package/dist/{chunk-FP5R6WED.js → chunk-2JUWLJ3K.js} +21 -13
  27. package/dist/chunk-2JUWLJ3K.js.map +1 -0
  28. package/dist/{chunk-BJER6TOI.js → chunk-3VSDQCFO.js} +3 -3
  29. package/dist/{chunk-BJER6TOI.js.map → chunk-3VSDQCFO.js.map} +1 -1
  30. package/dist/{chunk-N5U2BB6T.js → chunk-4VWNBMMA.js} +8 -6
  31. package/dist/chunk-4VWNBMMA.js.map +1 -0
  32. package/dist/{chunk-ZAM5TUPP.js → chunk-CMNZLA32.js} +60 -25
  33. package/dist/chunk-CMNZLA32.js.map +1 -0
  34. package/dist/{chunk-CVAMCRLL.js → chunk-EG2DASKR.js} +8 -4
  35. package/dist/chunk-EG2DASKR.js.map +1 -0
  36. package/dist/{chunk-DSULVRB6.js → chunk-GJ2FKAOM.js} +5 -3
  37. package/dist/chunk-GJ2FKAOM.js.map +1 -0
  38. package/dist/{chunk-FV7RESKL.js → chunk-HNUUZEOL.js} +28 -16
  39. package/dist/chunk-HNUUZEOL.js.map +1 -0
  40. package/dist/{chunk-37FLEB4N.js → chunk-IO6RMVUF.js} +8 -4
  41. package/dist/chunk-IO6RMVUF.js.map +1 -0
  42. package/dist/{chunk-4I5S6MH3.js → chunk-LLANMODS.js} +4 -4
  43. package/dist/{chunk-4I5S6MH3.js.map → chunk-LLANMODS.js.map} +1 -1
  44. package/dist/{chunk-N6WLCHQE.js → chunk-Q7WGPKUN.js} +6 -4
  45. package/dist/chunk-Q7WGPKUN.js.map +1 -0
  46. package/dist/{chunk-AZICSFBA.js → chunk-S5UNPCMQ.js} +112 -38
  47. package/dist/chunk-S5UNPCMQ.js.map +1 -0
  48. package/dist/{chunk-MTNFFSVA.js → chunk-SK6H7ARE.js} +5 -3
  49. package/dist/chunk-SK6H7ARE.js.map +1 -0
  50. package/dist/{chunk-PSPJA5U6.js → chunk-WMOBLT3Z.js} +10 -5
  51. package/dist/chunk-WMOBLT3Z.js.map +1 -0
  52. package/dist/{chunk-C5H44NSP.js → chunk-WZRPGPLH.js} +10 -5
  53. package/dist/chunk-WZRPGPLH.js.map +1 -0
  54. package/dist/{chunk-UXN67E5L.js → chunk-YQ6KXR3U.js} +8 -10
  55. package/dist/chunk-YQ6KXR3U.js.map +1 -0
  56. package/dist/{chunk-HSDZM4AM.js → chunk-YYQ45W25.js} +37 -24
  57. package/dist/chunk-YYQ45W25.js.map +1 -0
  58. package/dist/flash.js +1 -1
  59. package/dist/form.d.ts +3 -1
  60. package/dist/form.js +1 -1
  61. package/dist/index.d.ts +1 -1
  62. package/dist/index.js +9 -9
  63. package/dist/pages.js +16 -16
  64. package/dist/palette.js +1 -1
  65. package/dist/resource.js +2 -2
  66. package/dist/shell.js +8 -4
  67. package/dist/shell.js.map +1 -1
  68. package/dist/table.js +1 -1
  69. package/dist/utility.js +1 -1
  70. package/dist/widgets.js +2 -2
  71. package/package.json +6 -6
  72. package/dist/AreaChart-NMQ2RQGA.js.map +0 -1
  73. package/dist/ArqelCreatePage-MV4JN2MO.js +0 -8
  74. package/dist/ArqelDashboardPage-QK3BYVK3.js +0 -6
  75. package/dist/ArqelEditPage-7J3IS2BR.js +0 -8
  76. package/dist/ArqelIndexPage-R6JL5KOH.js +0 -12
  77. package/dist/ArqelShowPage-5WWUSYC7.js +0 -6
  78. package/dist/BarChart-KLHKTLO2.js.map +0 -1
  79. package/dist/LineChart-GHMPHFZZ.js.map +0 -1
  80. package/dist/PieChart-T2VQOFPP.js +0 -4
  81. package/dist/RadarChart-CSWR5AO7.js.map +0 -1
  82. package/dist/chunk-37FLEB4N.js.map +0 -1
  83. package/dist/chunk-AZICSFBA.js.map +0 -1
  84. package/dist/chunk-C5H44NSP.js.map +0 -1
  85. package/dist/chunk-CVAMCRLL.js.map +0 -1
  86. package/dist/chunk-DSULVRB6.js.map +0 -1
  87. package/dist/chunk-FP5R6WED.js.map +0 -1
  88. package/dist/chunk-FV7RESKL.js.map +0 -1
  89. package/dist/chunk-HSDZM4AM.js.map +0 -1
  90. package/dist/chunk-MTNFFSVA.js.map +0 -1
  91. package/dist/chunk-N5U2BB6T.js.map +0 -1
  92. package/dist/chunk-N6WLCHQE.js.map +0 -1
  93. package/dist/chunk-PSPJA5U6.js.map +0 -1
  94. package/dist/chunk-UXN67E5L.js.map +0 -1
  95. package/dist/chunk-ZAM5TUPP.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/flash/FlashToast.tsx","../src/flash/FlashContainer.tsx"],"names":["jsx"],"mappings":"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","file":"chunk-GJ2FKAOM.js","sourcesContent":["/**\n * `<FlashToast>` — single auto-dismissing toast.\n *\n * Self-rendered (no `sonner` dep) so apps with strict bundle budgets\n * stay lean. Replaceable via FlashContainer's `renderToast` prop when\n * a richer library is preferred.\n */\n\nimport { useArqelTranslations } from '@arqel-dev/react/utils';\nimport { useEffect } from 'react';\nimport { cn } from '../utils/cn.js';\n\nexport type FlashKind = 'success' | 'error' | 'info' | 'warning';\n\nexport interface FlashToastProps {\n kind: FlashKind;\n message: string;\n onDismiss: () => void;\n durationMs?: number;\n className?: string;\n}\n\nconst KIND_CLASSES: Record<FlashKind, string> = {\n success: 'border-[var(--chart-2)]/60 bg-[var(--chart-2)]/15 text-foreground',\n error: 'border-destructive/60 bg-destructive/15 text-foreground',\n warning: 'border-[var(--chart-4)]/60 bg-[var(--chart-4)]/15 text-foreground',\n info: 'border-border bg-muted text-foreground',\n};\n\nconst KIND_GLYPH: Record<FlashKind, string> = {\n success: '✓',\n error: '✗',\n warning: '!',\n info: 'i',\n};\n\nexport function FlashToast({\n kind,\n message,\n onDismiss,\n durationMs = 5000,\n className,\n}: FlashToastProps) {\n const t = useArqelTranslations();\n useEffect(() => {\n if (durationMs <= 0) return undefined;\n const id = window.setTimeout(onDismiss, durationMs);\n return () => window.clearTimeout(id);\n }, [durationMs, onDismiss]);\n\n return (\n <div\n role={kind === 'error' ? 'alert' : 'status'}\n aria-live={kind === 'error' ? 'assertive' : 'polite'}\n className={cn(\n 'pointer-events-auto flex items-start gap-3 rounded-md border px-4 py-3 shadow-md',\n 'min-w-[18rem] max-w-md text-sm',\n KIND_CLASSES[kind],\n className,\n )}\n >\n <span aria-hidden=\"true\" className=\"font-bold leading-5\">\n {KIND_GLYPH[kind]}\n </span>\n <span className=\"flex-1\">{message}</span>\n <button\n type=\"button\"\n aria-label={t('arqel.aria.flash_dismiss', 'Dismiss')}\n onClick={onDismiss}\n className=\"text-muted-foreground hover:text-foreground\"\n >\n ✕\n </button>\n </div>\n );\n}\n","/**\n * `<FlashContainer>` — bridges `useFlash()` to a stack of toasts.\n *\n * Subscribes to Inertia shared `flash` and pushes a toast each time a\n * new message of any kind arrives. Toast key is the (kind, message)\n * pair; identical repeats inside the same shared-props snapshot don't\n * duplicate. Defaults to fixed-positioning at top-right; pass `position`\n * to relocate.\n */\n\nimport { type FlashKind, useFlash } from '@arqel-dev/hooks';\nimport { useCallback, useState } from 'react';\nimport { cn } from '../utils/cn.js';\nimport { FlashToast } from './FlashToast.js';\n\ninterface ToastEntry {\n id: number;\n kind: FlashKind;\n message: string;\n}\n\nexport type FlashPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';\n\nexport interface FlashContainerProps {\n position?: FlashPosition;\n durationMs?: number;\n className?: string;\n}\n\nconst POSITION_CLASSES: Record<FlashPosition, string> = {\n 'top-right': 'top-4 right-4 items-end',\n 'top-left': 'top-4 left-4 items-start',\n 'bottom-right': 'bottom-4 right-4 items-end',\n 'bottom-left': 'bottom-4 left-4 items-start',\n};\n\nlet nextId = 0;\n\nexport function FlashContainer({\n position = 'top-right',\n durationMs = 5000,\n className,\n}: FlashContainerProps) {\n const [toasts, setToasts] = useState<ToastEntry[]>([]);\n\n const handleMessage = useCallback((kind: FlashKind, message: string) => {\n setToasts((prev) => [...prev, { id: ++nextId, kind, message }]);\n }, []);\n\n useFlash({ onMessage: handleMessage });\n\n const dismiss = (id: number) => setToasts((prev) => prev.filter((t) => t.id !== id));\n\n return (\n <div\n data-arqel-flash=\"\"\n className={cn(\n 'pointer-events-none fixed z-50 flex flex-col gap-2',\n POSITION_CLASSES[position],\n className,\n )}\n >\n {toasts.map((toast) => (\n <FlashToast\n key={toast.id}\n kind={toast.kind}\n message={toast.message}\n durationMs={durationMs}\n onDismiss={() => dismiss(toast.id)}\n />\n ))}\n </div>\n );\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { useArqelTranslations } from '@arqel-dev/react/utils';
1
2
  import { useRef, useState, useId, useEffect, useCallback } from 'react';
2
3
  import { jsx, jsxs } from 'react/jsx-runtime';
3
4
 
@@ -49,11 +50,13 @@ function recordUsage(command) {
49
50
  function topRecents() {
50
51
  return readRecents().slice().sort((a, b) => b.count === a.count ? b.lastUsed - a.lastUsed : b.count - a.count).slice(0, RECENT_LIMIT).map((e) => e.command);
51
52
  }
53
+ var GENERAL_CATEGORY = "__general";
54
+ var RECENT_CATEGORY = "__recent";
52
55
  function groupByCategory(commands) {
53
56
  const order = [];
54
57
  const buckets = /* @__PURE__ */ new Map();
55
58
  for (const cmd of commands) {
56
- const key = cmd.category ?? "General";
59
+ const key = cmd.category ?? GENERAL_CATEGORY;
57
60
  if (!buckets.has(key)) {
58
61
  buckets.set(key, []);
59
62
  order.push(key);
@@ -75,6 +78,7 @@ var dialogStyle = {
75
78
  color: "var(--foreground, #111)"
76
79
  };
77
80
  function CommandPalette({ endpoint = "/admin/commands" }) {
81
+ const t = useArqelTranslations();
78
82
  const dialogRef = useRef(null);
79
83
  const inputRef = useRef(null);
80
84
  const debounceTimer = useRef(null);
@@ -88,7 +92,16 @@ function CommandPalette({ endpoint = "/admin/commands" }) {
88
92
  const listId = useId();
89
93
  const optBaseId = useId();
90
94
  const visibleCommands = query.trim().length === 0 ? recents : results;
91
- const groups = query.trim().length === 0 && recents.length > 0 ? [{ category: "Recent", commands: recents }] : groupByCategory(visibleCommands);
95
+ const groups = query.trim().length === 0 && recents.length > 0 ? [{ category: RECENT_CATEGORY, commands: recents }] : groupByCategory(visibleCommands);
96
+ const categoryLabel = (category) => {
97
+ if (category === GENERAL_CATEGORY) {
98
+ return t("arqel.command_palette.category_general", "General");
99
+ }
100
+ if (category === RECENT_CATEGORY) {
101
+ return t("arqel.command_palette.category_recent", "Recent");
102
+ }
103
+ return category;
104
+ };
92
105
  const flat = flattenGroups(groups);
93
106
  useEffect(() => {
94
107
  function onKey(event) {
@@ -191,7 +204,7 @@ function CommandPalette({ endpoint = "/admin/commands" }) {
191
204
  className: "backdrop:bg-black/40",
192
205
  "data-arqel-cmdpal": "",
193
206
  children: /* @__PURE__ */ jsxs("div", { onKeyDown, className: "flex flex-col", children: [
194
- /* @__PURE__ */ jsx("h2", { id: titleId, className: "sr-only", children: "Command palette" }),
207
+ /* @__PURE__ */ jsx("h2", { id: titleId, className: "sr-only", children: t("arqel.aria.palette_title", "Command palette") }),
195
208
  /* @__PURE__ */ jsx(
196
209
  "input",
197
210
  {
@@ -202,25 +215,24 @@ function CommandPalette({ endpoint = "/admin/commands" }) {
202
215
  "aria-controls": listId,
203
216
  "aria-autocomplete": "list",
204
217
  ...activeOptionId ? { "aria-activedescendant": activeOptionId } : {},
205
- placeholder: "Type a command\u2026",
218
+ placeholder: t("palette.placeholder", "Type a command\u2026"),
206
219
  value: query,
207
220
  onChange: (e) => setQuery(e.target.value),
208
221
  className: "w-full border-b border-[var(--border,#e5e7eb)] bg-transparent px-4 py-3 text-base outline-none"
209
222
  }
210
223
  ),
211
- /* @__PURE__ */ jsxs("div", { role: "status", "aria-live": "polite", className: "sr-only", children: [
212
- flat.length,
213
- " commands"
214
- ] }),
224
+ /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", className: "sr-only", children: t("arqel.aria.palette_results", "{one} :count command|{other} :count commands", {
225
+ count: flat.length
226
+ }) }),
215
227
  /* @__PURE__ */ jsxs(
216
228
  "ul",
217
229
  {
218
230
  id: listId,
219
231
  role: "listbox",
220
- "aria-label": "Commands",
232
+ "aria-label": t("arqel.aria.palette_list", "Commands"),
221
233
  className: "max-h-[50vh] overflow-y-auto py-2",
222
234
  children: [
223
- groups.length === 0 && /* @__PURE__ */ jsx("li", { role: "presentation", className: "px-4 py-3 text-sm opacity-60", children: "No commands found" }),
235
+ groups.length === 0 && /* @__PURE__ */ jsx("li", { role: "presentation", className: "px-4 py-3 text-sm opacity-60", children: t("arqel.palette.no_results", "No commands found") }),
224
236
  groups.map((group) => {
225
237
  const startIdx = flat.indexOf(group.commands[0] ?? {});
226
238
  return /* @__PURE__ */ jsxs("li", { role: "presentation", children: [
@@ -229,7 +241,7 @@ function CommandPalette({ endpoint = "/admin/commands" }) {
229
241
  {
230
242
  role: "presentation",
231
243
  className: "px-4 pt-2 pb-1 text-xs font-semibold uppercase tracking-wide opacity-60",
232
- children: group.category
244
+ children: categoryLabel(group.category)
233
245
  }
234
246
  ),
235
247
  /* @__PURE__ */ jsx("ul", { role: "presentation", className: "m-0 list-none p-0", children: group.commands.map((cmd, j) => {
@@ -268,9 +280,9 @@ function CommandPalette({ endpoint = "/admin/commands" }) {
268
280
  id: hintId,
269
281
  className: "flex items-center gap-3 border-t border-[var(--border,#e5e7eb)] px-4 py-2 text-xs opacity-70",
270
282
  children: [
271
- /* @__PURE__ */ jsx("span", { children: "\u2191\u2193 navigate" }),
272
- /* @__PURE__ */ jsx("span", { children: "\u21B5 select" }),
273
- /* @__PURE__ */ jsx("span", { children: "esc close" })
283
+ /* @__PURE__ */ jsx("span", { children: t("arqel.palette.hint_navigate", "\u2191\u2193 navigate") }),
284
+ /* @__PURE__ */ jsx("span", { children: t("arqel.palette.hint_select", "\u21B5 select") }),
285
+ /* @__PURE__ */ jsx("span", { children: t("arqel.palette.hint_close", "esc close") })
274
286
  ]
275
287
  }
276
288
  )
@@ -281,5 +293,5 @@ function CommandPalette({ endpoint = "/admin/commands" }) {
281
293
  }
282
294
 
283
295
  export { CommandPalette };
284
- //# sourceMappingURL=chunk-FV7RESKL.js.map
285
- //# sourceMappingURL=chunk-FV7RESKL.js.map
296
+ //# sourceMappingURL=chunk-HNUUZEOL.js.map
297
+ //# sourceMappingURL=chunk-HNUUZEOL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/palette/CommandPalette.tsx"],"names":[],"mappings":"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","file":"chunk-HNUUZEOL.js","sourcesContent":["/**\n * `<CommandPalette>` — global Cmd+K admin command palette.\n *\n * Wraps the `/admin/commands` endpoint shipped by `arqel-dev/core` (CMDPAL-002)\n * with a native `<dialog>`-based modal. No external dialog/combobox library\n * is used: the surface area is small enough that the platform primitives\n * (HTML dialog + ARIA combobox/listbox roles) cover every requirement.\n *\n * Usage: render once at the top of `<AppShell>` — the global Cmd+K /\n * Ctrl+K listener is mounted on `window` while the component is alive.\n */\n\nimport { useArqelTranslations } from '@arqel-dev/react/utils';\nimport { type CSSProperties, useCallback, useEffect, useId, useRef, useState } from 'react';\n\nexport interface PaletteCommand {\n id: string;\n label: string;\n url: string;\n description?: string | null;\n category?: string | null;\n icon?: string | null;\n}\n\nexport interface CommandPaletteProps {\n /** Endpoint that returns `{ commands: PaletteCommand[] }`. */\n endpoint?: string;\n}\n\ninterface RecentEntry {\n id: string;\n count: number;\n lastUsed: number;\n command: PaletteCommand;\n}\n\nconst RECENT_KEY = 'arqel:cmdpal:recent';\nconst RECENT_WINDOW_MS = 30 * 24 * 60 * 60 * 1000; // 30 days\nconst RECENT_LIMIT = 5;\nconst DEBOUNCE_MS = 150;\n\nfunction readRecents(): RecentEntry[] {\n try {\n const raw = globalThis.localStorage?.getItem(RECENT_KEY);\n if (!raw) return [];\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const now = Date.now();\n return parsed.filter(\n (e): e is RecentEntry =>\n typeof e === 'object' &&\n e !== null &&\n typeof (e as RecentEntry).id === 'string' &&\n typeof (e as RecentEntry).count === 'number' &&\n typeof (e as RecentEntry).lastUsed === 'number' &&\n now - (e as RecentEntry).lastUsed <= RECENT_WINDOW_MS &&\n typeof (e as RecentEntry).command === 'object',\n );\n } catch {\n return [];\n }\n}\n\nfunction writeRecents(entries: RecentEntry[]): void {\n try {\n globalThis.localStorage?.setItem(RECENT_KEY, JSON.stringify(entries));\n } catch {\n // Ignore quota/serialization failures — recents are best-effort.\n }\n}\n\nfunction recordUsage(command: PaletteCommand): void {\n const entries = readRecents();\n const now = Date.now();\n const idx = entries.findIndex((e) => e.id === command.id);\n if (idx >= 0) {\n const existing = entries[idx];\n if (existing) {\n entries[idx] = {\n ...existing,\n count: existing.count + 1,\n lastUsed: now,\n command,\n };\n }\n } else {\n entries.push({ id: command.id, count: 1, lastUsed: now, command });\n }\n // Prune anything older than the recency window.\n const fresh = entries.filter((e) => now - e.lastUsed <= RECENT_WINDOW_MS);\n writeRecents(fresh);\n}\n\nfunction topRecents(): PaletteCommand[] {\n return readRecents()\n .slice()\n .sort((a, b) => (b.count === a.count ? b.lastUsed - a.lastUsed : b.count - a.count))\n .slice(0, RECENT_LIMIT)\n .map((e) => e.command);\n}\n\ninterface Group {\n /** Stable bucket identity (React key). For uncategorized commands this is\n * the sentinel `__general` so the visible heading can be localized at\n * render without colliding with a real category literally named \"General\". */\n category: string;\n commands: PaletteCommand[];\n}\n\n/** Sentinel bucket ids whose visible heading is resolved via i18n at render. */\nconst GENERAL_CATEGORY = '__general';\nconst RECENT_CATEGORY = '__recent';\n\nfunction groupByCategory(commands: PaletteCommand[]): Group[] {\n const order: string[] = [];\n const buckets = new Map<string, PaletteCommand[]>();\n for (const cmd of commands) {\n const key = cmd.category ?? GENERAL_CATEGORY;\n if (!buckets.has(key)) {\n buckets.set(key, []);\n order.push(key);\n }\n buckets.get(key)?.push(cmd);\n }\n return order.map((category) => ({ category, commands: buckets.get(category) ?? [] }));\n}\n\nfunction flattenGroups(groups: Group[]): PaletteCommand[] {\n return groups.flatMap((g) => g.commands);\n}\n\nconst dialogStyle: CSSProperties = {\n border: 'none',\n borderRadius: '0.75rem',\n padding: 0,\n width: 'min(640px, 92vw)',\n maxHeight: '70vh',\n background: 'var(--background, #fff)',\n color: 'var(--foreground, #111)',\n};\n\nexport function CommandPalette({ endpoint = '/admin/commands' }: CommandPaletteProps) {\n const t = useArqelTranslations();\n const dialogRef = useRef<HTMLDialogElement | null>(null);\n const inputRef = useRef<HTMLInputElement | null>(null);\n const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [results, setResults] = useState<PaletteCommand[]>([]);\n const [recents, setRecents] = useState<PaletteCommand[]>([]);\n const [highlight, setHighlight] = useState(0);\n\n const titleId = useId();\n const hintId = useId();\n const listId = useId();\n const optBaseId = useId();\n\n const visibleCommands = query.trim().length === 0 ? recents : results;\n const groups =\n query.trim().length === 0 && recents.length > 0\n ? [{ category: RECENT_CATEGORY, commands: recents }]\n : groupByCategory(visibleCommands);\n\n // Resolve the visible heading for a group, localizing the synthetic\n // \"General\"/\"Recent\" buckets while passing real categories through verbatim.\n const categoryLabel = (category: string): string => {\n if (category === GENERAL_CATEGORY) {\n return t('arqel.command_palette.category_general', 'General');\n }\n if (category === RECENT_CATEGORY) {\n return t('arqel.command_palette.category_recent', 'Recent');\n }\n return category;\n };\n const flat = flattenGroups(groups);\n\n // Cmd+K / Ctrl+K global toggle.\n useEffect(() => {\n function onKey(event: KeyboardEvent) {\n const isToggle = (event.key === 'k' || event.key === 'K') && (event.metaKey || event.ctrlKey);\n if (!isToggle) return;\n event.preventDefault();\n setOpen((prev) => !prev);\n }\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, []);\n\n // Sync `open` state with the native <dialog>.\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (open && !dialog.open) {\n try {\n dialog.showModal();\n } catch {\n // jsdom or already-open: ignore.\n }\n setRecents(topRecents());\n setQuery('');\n setResults([]);\n setHighlight(0);\n // Defer focus after the dialog is on-screen.\n queueMicrotask(() => inputRef.current?.focus());\n } else if (!open && dialog.open) {\n dialog.close();\n }\n }, [open]);\n\n // Debounced fetch.\n useEffect(() => {\n if (!open) return;\n if (query.trim().length === 0) {\n setResults([]);\n return;\n }\n if (debounceTimer.current) clearTimeout(debounceTimer.current);\n debounceTimer.current = setTimeout(() => {\n const url = `${endpoint}?q=${encodeURIComponent(query)}`;\n fetch(url, { headers: { Accept: 'application/json' } })\n .then((res) => (res.ok ? res.json() : { commands: [] }))\n .then((data: { commands?: PaletteCommand[] }) => {\n setResults(Array.isArray(data?.commands) ? data.commands : []);\n setHighlight(0);\n })\n .catch(() => {\n setResults([]);\n });\n }, DEBOUNCE_MS);\n return () => {\n if (debounceTimer.current) clearTimeout(debounceTimer.current);\n };\n }, [query, open, endpoint]);\n\n const close = useCallback(() => setOpen(false), []);\n\n const execute = useCallback((command: PaletteCommand) => {\n recordUsage(command);\n setOpen(false);\n window.location.assign(command.url);\n }, []);\n\n const onKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n close();\n return;\n }\n if (flat.length === 0) return;\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n setHighlight((h) => (h + 1) % flat.length);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n setHighlight((h) => (h - 1 + flat.length) % flat.length);\n } else if (event.key === 'Enter') {\n event.preventDefault();\n const target = flat[highlight];\n if (target) execute(target);\n }\n },\n [flat, highlight, close, execute],\n );\n\n // Close on backdrop click — dialog click hits the dialog itself, not children.\n const onDialogClick = useCallback(\n (event: React.MouseEvent<HTMLDialogElement>) => {\n if (event.target === dialogRef.current) close();\n },\n [close],\n );\n\n const optionId = (idx: number) => `${optBaseId}-opt-${idx}`;\n const activeOptionId = flat.length > 0 ? optionId(highlight) : undefined;\n\n return (\n // biome-ignore lint/a11y/useKeyWithClickEvents: dialog backdrop click closes; Escape (onCancel) handles keyboard close\n <dialog\n ref={dialogRef}\n aria-labelledby={titleId}\n aria-describedby={hintId}\n onClick={onDialogClick}\n onClose={() => setOpen(false)}\n onCancel={(event) => {\n event.preventDefault();\n close();\n }}\n style={dialogStyle}\n className=\"backdrop:bg-black/40\"\n data-arqel-cmdpal=\"\"\n >\n {/* biome-ignore lint/a11y/noStaticElementInteractions: this wrapper only delegates ArrowUp/Down/Enter/Escape from the combobox input below */}\n <div onKeyDown={onKeyDown} className=\"flex flex-col\">\n <h2 id={titleId} className=\"sr-only\">\n {t('arqel.aria.palette_title', 'Command palette')}\n </h2>\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n aria-expanded={open}\n aria-controls={listId}\n aria-autocomplete=\"list\"\n {...(activeOptionId ? { 'aria-activedescendant': activeOptionId } : {})}\n placeholder={t('palette.placeholder', 'Type a command…')}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n className=\"w-full border-b border-[var(--border,#e5e7eb)] bg-transparent px-4 py-3 text-base outline-none\"\n />\n <div role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {t('arqel.aria.palette_results', '{one} :count command|{other} :count commands', {\n count: flat.length,\n })}\n </div>\n <ul\n id={listId}\n // biome-ignore lint/a11y/noNoninteractiveElementToInteractiveRole: WAI-ARIA combobox/listbox pattern requires <ul role=\"listbox\">\n role=\"listbox\"\n aria-label={t('arqel.aria.palette_list', 'Commands')}\n className=\"max-h-[50vh] overflow-y-auto py-2\"\n >\n {groups.length === 0 && (\n <li role=\"presentation\" className=\"px-4 py-3 text-sm opacity-60\">\n {t('arqel.palette.no_results', 'No commands found')}\n </li>\n )}\n {groups.map((group) => {\n const startIdx = flat.indexOf(group.commands[0] ?? ({} as PaletteCommand));\n return (\n <li key={group.category} role=\"presentation\">\n <div\n role=\"presentation\"\n className=\"px-4 pt-2 pb-1 text-xs font-semibold uppercase tracking-wide opacity-60\"\n >\n {categoryLabel(group.category)}\n </div>\n <ul role=\"presentation\" className=\"m-0 list-none p-0\">\n {group.commands.map((cmd, j) => {\n const idx = startIdx + j;\n const isActive = idx === highlight;\n return (\n // biome-ignore lint/a11y/useFocusableInteractive: focus stays on combobox; selection via aria-activedescendant\n // biome-ignore lint/a11y/useKeyWithClickEvents: keyboard nav handled by combobox input ArrowUp/Down/Enter handler\n <li\n key={cmd.id}\n id={optionId(idx)}\n // biome-ignore lint/a11y/noNoninteractiveElementToInteractiveRole: WAI-ARIA combobox/listbox pattern requires <li role=\"option\">\n role=\"option\"\n aria-selected={isActive}\n data-active={isActive ? '' : undefined}\n onMouseEnter={() => setHighlight(idx)}\n onClick={() => execute(cmd)}\n className={\n 'flex cursor-pointer items-center gap-3 px-4 py-2 text-sm ' +\n (isActive ? 'bg-[var(--accent,#f1f5f9)]' : '')\n }\n >\n <span className=\"flex-1\">{cmd.label}</span>\n {cmd.description ? (\n <span className=\"text-xs opacity-60\">{cmd.description}</span>\n ) : null}\n </li>\n );\n })}\n </ul>\n </li>\n );\n })}\n </ul>\n <footer\n id={hintId}\n className=\"flex items-center gap-3 border-t border-[var(--border,#e5e7eb)] px-4 py-2 text-xs opacity-70\"\n >\n <span>{t('arqel.palette.hint_navigate', '↑↓ navigate')}</span>\n <span>{t('arqel.palette.hint_select', '↵ select')}</span>\n <span>{t('arqel.palette.hint_close', 'esc close')}</span>\n </footer>\n </div>\n </dialog>\n );\n}\n"]}
@@ -1,7 +1,8 @@
1
1
  import { PageHeader } from './chunk-MXUXMHOK.js';
2
2
  import { FormActions } from './chunk-MZMYV43C.js';
3
- import { FormRenderer } from './chunk-ZAM5TUPP.js';
3
+ import { FormRenderer } from './chunk-CMNZLA32.js';
4
4
  import { useArqelForm } from '@arqel-dev/hooks';
5
+ import { useArqelTranslations } from '@arqel-dev/react/utils';
5
6
  import { usePage, router } from '@inertiajs/react';
6
7
  import { jsxs, jsx } from 'react/jsx-runtime';
7
8
 
@@ -14,6 +15,7 @@ var FALLBACK_SCHEMA = {
14
15
  };
15
16
  function ArqelCreatePage() {
16
17
  const page = usePage();
18
+ const t = useArqelTranslations();
17
19
  const props = page.props;
18
20
  const fields = props.fields ?? [];
19
21
  const schema = props.form ?? FALLBACK_SCHEMA;
@@ -26,8 +28,10 @@ function ArqelCreatePage() {
26
28
  preserveScroll: true
27
29
  });
28
30
  };
31
+ const label = props.resource?.label ?? t("arqel.pages.fallback", "record");
32
+ const createTitle = t("arqel.pages.create", `Create ${label}`, { label });
29
33
  return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
30
- /* @__PURE__ */ jsx(PageHeader, { title: `Create ${props.resource?.label ?? "record"}`, description: null }),
34
+ /* @__PURE__ */ jsx(PageHeader, { title: createTitle, description: null }),
31
35
  /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-6", children: [
32
36
  /* @__PURE__ */ jsx(
33
37
  FormRenderer,
@@ -45,5 +49,5 @@ function ArqelCreatePage() {
45
49
  }
46
50
 
47
51
  export { ArqelCreatePage };
48
- //# sourceMappingURL=chunk-37FLEB4N.js.map
49
- //# sourceMappingURL=chunk-37FLEB4N.js.map
52
+ //# sourceMappingURL=chunk-IO6RMVUF.js.map
53
+ //# sourceMappingURL=chunk-IO6RMVUF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/ArqelCreatePage.tsx"],"names":[],"mappings":";;;;;;;;AAoBA,IAAM,eAAA,GAA8B;AAAA,EAClC,QAAQ,EAAC;AAAA,EACT,OAAA,EAAS,CAAA;AAAA,EACT,KAAA,EAAO,IAAA;AAAA,EACP,MAAA,EAAQ,KAAA;AAAA,EACR,QAAA,EAAU;AACZ,CAAA;AASe,SAAR,eAAA,GAAgD;AACrD,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,IAAI,oBAAA,EAAqB;AAC/B,EAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AACnB,EAAA,MAAM,MAAA,GAAU,KAAA,CAAM,MAAA,IAAU,EAAC;AACjC,EAAA,MAAM,MAAA,GAAU,MAA2C,IAAA,IAAQ,eAAA;AAEnE,EAAA,MAAM,IAAA,GAAO,YAAA,CAAa,EAAE,MAAA,EAAQ,CAAA;AAEpC,EAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAuB;AACrC,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,QAAA,EAAU,IAAA,IAAQ,EAAA;AACrC,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,QAAA,EAAU,SAAA,IAAa,QAAA;AAC9C,IAAA,MAAA,CAAO,KAAK,CAAA,EAAG,QAAQ,IAAI,IAAI,CAAA,CAAA,EAAI,KAAK,IAAA,EAA+B;AAAA,MACrE,cAAA,EAAgB;AAAA,KACjB,CAAA;AAAA,EACH,CAAA;AAKA,EAAA,MAAM,QAAQ,KAAA,CAAM,QAAA,EAAU,KAAA,IAAS,CAAA,CAAE,wBAAwB,QAAQ,CAAA;AACzE,EAAA,MAAM,WAAA,GAAc,EAAE,oBAAA,EAAsB,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA,EAAI,EAAE,OAAO,CAAA;AAExE,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAO,WAAA,EAAa,WAAA,EAAa,IAAA,EAAM,CAAA;AAAA,oBACnD,IAAA,CAAC,MAAA,EAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,WAAU,WAAA,EAChC,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,YAAA;AAAA,QAAA;AAAA,UACC,MAAA;AAAA,UACA,MAAA;AAAA,UACA,QAAQ,IAAA,CAAK,IAAA;AAAA,UACb,UAAU,CAAC,IAAA,EAAM,UAAU,IAAA,CAAK,OAAA,CAAQ,MAAM,KAAK,CAAA;AAAA,UACnD,QAAQ,IAAA,CAAK;AAAA;AAAA,OACf;AAAA,sBACA,GAAA,CAAC,WAAA,EAAA,EAAY,UAAA,EAAY,IAAA,CAAK,UAAA,EAAY,UAAU,MAAM,MAAA,CAAO,OAAA,CAAQ,IAAA,EAAK,EAAG;AAAA,KAAA,EACnF;AAAA,GAAA,EACF,CAAA;AAEJ","file":"chunk-IO6RMVUF.js","sourcesContent":["/**\n * Default Inertia page for `arqel::create`.\n *\n * Renders a `<FormRenderer>` over the schema/fields the server\n * emits (with `record: null`). Submission goes through Inertia's\n * `useForm` via `useArqelForm` from `@arqel-dev/hooks` — this page is\n * just the layout shell.\n */\n\nimport { useArqelForm } from '@arqel-dev/hooks';\nimport { useArqelTranslations } from '@arqel-dev/react/utils';\nimport type { FieldSchema } from '@arqel-dev/types/fields';\nimport type { FormSchema } from '@arqel-dev/types/forms';\nimport type { ResourceCreateProps } from '@arqel-dev/types/resources';\nimport { router, usePage } from '@inertiajs/react';\nimport type { FormEvent, JSX } from 'react';\nimport { FormActions } from '../form/FormActions.js';\nimport { FormRenderer } from '../form/FormRenderer.js';\nimport { PageHeader } from '../utility/PageHeader.js';\n\nconst FALLBACK_SCHEMA: FormSchema = {\n schema: [],\n columns: 1,\n model: null,\n inline: false,\n disabled: false,\n};\n\ninterface ArqelFormShape {\n data: Record<string, unknown>;\n setData: (name: string, value: unknown) => void;\n errors: Record<string, string[]>;\n processing: boolean;\n}\n\nexport default function ArqelCreatePage(): JSX.Element {\n const page = usePage();\n const t = useArqelTranslations();\n const props = page.props as unknown as ResourceCreateProps;\n const fields = (props.fields ?? []) as FieldSchema[];\n const schema = (props as unknown as { form?: FormSchema }).form ?? FALLBACK_SCHEMA;\n\n const form = useArqelForm({ fields }) as unknown as ArqelFormShape;\n\n const submit = (e: FormEvent): void => {\n e.preventDefault();\n const slug = props.resource?.slug ?? '';\n const basePath = props.resource?.panelPath ?? '/admin';\n router.post(`${basePath}/${slug}`, form.data as Record<string, never>, {\n preserveScroll: true,\n });\n };\n\n // Pre-interpolate the label into the English fallback so the title stays\n // correct even when the `arqel.pages.create` key is absent from the shared\n // dictionary (the hook does not re-interpolate a raw fallback).\n const label = props.resource?.label ?? t('arqel.pages.fallback', 'record');\n const createTitle = t('arqel.pages.create', `Create ${label}`, { label });\n\n return (\n <div className=\"space-y-6\">\n <PageHeader title={createTitle} description={null} />\n <form onSubmit={submit} className=\"space-y-6\">\n <FormRenderer\n schema={schema}\n fields={fields}\n values={form.data}\n onChange={(name, value) => form.setData(name, value)}\n errors={form.errors}\n />\n <FormActions processing={form.processing} onCancel={() => window.history.back()} />\n </form>\n </div>\n );\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { ResourceIndex } from './chunk-CVAMCRLL.js';
2
- import { ActionButton, ActionMenu } from './chunk-FP5R6WED.js';
1
+ import { ResourceIndex } from './chunk-EG2DASKR.js';
2
+ import { ActionButton, ActionMenu } from './chunk-2JUWLJ3K.js';
3
3
  import { usePage, router } from '@inertiajs/react';
4
4
  import { useMemo, useState, useRef, useEffect } from 'react';
5
5
  import { jsx } from 'react/jsx-runtime';
@@ -201,5 +201,5 @@ function ArqelIndexPage() {
201
201
  }
202
202
 
203
203
  export { ArqelIndexPage };
204
- //# sourceMappingURL=chunk-4I5S6MH3.js.map
205
- //# sourceMappingURL=chunk-4I5S6MH3.js.map
204
+ //# sourceMappingURL=chunk-LLANMODS.js.map
205
+ //# sourceMappingURL=chunk-LLANMODS.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/pages/ArqelIndexPage.tsx"],"names":[],"mappings":"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","file":"chunk-4I5S6MH3.js","sourcesContent":["/**\n * Default Inertia page for `arqel::index`.\n *\n * Pulls every prop the server emits via `InertiaDataBuilder::\n * buildIndexData` / `buildTableIndexData` and forwards them to\n * `<ResourceIndex>`. Apps can override per-resource by registering\n * their own page component at `Pages/Arqel/{Slug}/Index.tsx` (the\n * lookup falls through to user pages first inside `createArqelApp`).\n *\n * Wires the standard table interactions — search / filter / sort /\n * pagination — into Inertia partial `router.get` visits so the\n * server can re-run TableQueryBuilder with the new query string.\n *\n * Query-string contract (matches `Arqel\\Table\\TableQueryBuilder`):\n * - `?search=foo` global search\n * - `?sort=column&direction=asc|desc`\n * - `?page=N&per_page=M`\n * - `?filter[name]=value` one entry per filter\n *\n * `search` is debounced (300ms) so typing doesn't hammer the\n * backend; the rest fire immediately.\n */\n\nimport type { ActionSchema } from '@arqel-dev/types/actions';\nimport type { RecordType, ResourceIndexProps } from '@arqel-dev/types/resources';\nimport type { SortDirection } from '@arqel-dev/types/tables';\nimport { router, usePage } from '@inertiajs/react';\nimport { type JSX, useEffect, useMemo, useRef, useState } from 'react';\nimport { ActionButton } from '../action/ActionButton.js';\nimport { ActionMenu } from '../action/ActionMenu.js';\nimport { ResourceIndex } from '../resource/ResourceIndex.js';\n\ntype FilterValue = unknown;\n\nfunction pruneEmptyFilters(values: Record<string, FilterValue>): Record<string, FilterValue> {\n const out: Record<string, FilterValue> = {};\n for (const [k, v] of Object.entries(values)) {\n if (v === undefined || v === null || v === '') continue;\n if (Array.isArray(v) && v.length === 0) continue;\n out[k] = v;\n }\n return out;\n}\n\ninterface VisitParams {\n filters: Record<string, FilterValue>;\n search: string;\n sort?: { column: string | null; direction: string | null } | null;\n page?: number | undefined;\n perPage?: number | undefined;\n}\n\nfunction invokeAction(\n action: ActionSchema,\n record: { id: string | number } | null,\n formValues?: Record<string, unknown>,\n): void {\n const recordId = record?.id;\n // Every dispatchable action ships a server-emitted `url` (stock verbs,\n // bulk, and custom callback actions all resolve through core's authorised\n // routes — see `Action::resolveStockUrl()`, #48/#231). An absent `url`\n // signals a misconfiguration; we must NOT fall back to the dead\n // `/arqel-dev/actions/{name}` route removed in #174. Surface it clearly\n // instead of masking it as a 404.\n if (!action.url) {\n throw new Error(\n `Arqel: action \"${action.name}\" has no url to dispatch to. Declare it on ` +\n `the Resource's actions()/headerActions()/toolbarActions() so the server ` +\n `emits its endpoint URL, or give it an explicit ->url().`,\n );\n }\n const url = action.url.replace('{id}', String(recordId ?? ''));\n const method = action.method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete';\n const data: Record<string, unknown> = { ...(formValues ?? {}) };\n if (recordId !== undefined) data['record_id'] = recordId;\n\n router.visit(url, {\n method: method as never,\n data: data as never,\n preserveScroll: true,\n });\n}\n\n/**\n * Resolve the row-action list for a single record (#140).\n *\n * Row actions are defined once at table level (label / icon / color /\n * confirmation / form), but `url(Closure)` and `disabled(Closure)`\n * actions depend on the row. The server emits those resolved values\n * per record under `record.arqel.actionOverrides`; here we merge them\n * onto the shared definitions so each row links to its own URL and\n * carries its own disabled state.\n *\n * When the server also emits `record.arqel.actions` (the visible +\n * executable action names) we filter the list against it so per-row\n * authorization/visibility is honoured.\n */\nfunction resolveRecordActions(\n tableActions: ActionSchema[],\n record: {\n arqel?: {\n actions?: string[];\n actionOverrides?: Record<string, { url?: string; disabled?: true }>;\n };\n },\n): ActionSchema[] {\n const visibleNames = record.arqel?.actions;\n const overrides = record.arqel?.actionOverrides ?? {};\n\n return tableActions\n .filter((action) => (visibleNames ? visibleNames.includes(action.name) : true))\n .map((action) => {\n const override = overrides[action.name];\n if (override === undefined) return action;\n return {\n ...action,\n ...(override.url !== undefined ? { url: override.url } : {}),\n ...(override.disabled === true ? { disabled: true as const } : {}),\n };\n });\n}\n\nfunction buildQuery(params: VisitParams): Record<string, unknown> {\n const data: Record<string, unknown> = {};\n const filters = pruneEmptyFilters(params.filters);\n if (Object.keys(filters).length > 0) data['filter'] = filters;\n if (params.search !== undefined) data['search'] = params.search;\n if (params.sort?.column) {\n data['sort'] = params.sort.column;\n if (params.sort.direction) data['direction'] = params.sort.direction;\n }\n if (params.page && params.page > 1) data['page'] = params.page;\n if (params.perPage) data['per_page'] = params.perPage;\n return data;\n}\n\nexport default function ArqelIndexPage<TRecord extends RecordType = RecordType>(): JSX.Element {\n const page = usePage();\n const props = page.props as unknown as ResourceIndexProps<TRecord>;\n\n const initialFilters = useMemo(() => {\n if (typeof window === 'undefined') return {};\n const sp = new URLSearchParams(window.location.search);\n const fromUrl: Record<string, FilterValue> = {};\n for (const [key, value] of sp.entries()) {\n const m = key.match(/^filter\\[([^\\]]+)\\]$/);\n if (m?.[1]) fromUrl[m[1]] = value;\n }\n return fromUrl;\n }, []);\n\n const [filterValues, setFilterValues] = useState<Record<string, FilterValue>>(initialFilters);\n const [searchValue, setSearchValue] = useState<string>(props.search ?? '');\n const [perPage, setPerPage] = useState<number | undefined>(props.pagination?.perPage);\n const [selectedIds, setSelectedIds] = useState<ReadonlyArray<string | number>>([]);\n const searchDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const visit = (data: Record<string, unknown>): void => {\n const url = typeof window !== 'undefined' ? window.location.pathname : page.url.split('?')[0];\n router.get(url ?? '/', data as Record<string, string | number | boolean | undefined>, {\n preserveState: true,\n preserveScroll: true,\n replace: true,\n });\n };\n\n const currentSort = props.sort ?? null;\n\n const handleFilterChange = (name: string, value: FilterValue): void => {\n const nextFilters = { ...filterValues };\n if (value === undefined || value === null || value === '') {\n delete nextFilters[name];\n } else {\n nextFilters[name] = value;\n }\n setFilterValues(nextFilters);\n visit(buildQuery({ filters: nextFilters, search: searchValue, sort: currentSort, perPage }));\n };\n\n const handleClearFilters = (): void => {\n setFilterValues({});\n visit(buildQuery({ filters: {}, search: searchValue, sort: currentSort, perPage }));\n };\n\n const handleSearchChange = (value: string): void => {\n setSearchValue(value);\n if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);\n searchDebounceRef.current = setTimeout(() => {\n visit(buildQuery({ filters: filterValues, search: value, sort: currentSort, perPage }));\n }, 300);\n };\n\n useEffect(\n () => () => {\n if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);\n },\n [],\n );\n\n const handleSortChange = (column: string, direction: SortDirection): void => {\n visit(\n buildQuery({\n filters: filterValues,\n search: searchValue,\n sort: { column, direction },\n perPage,\n }),\n );\n };\n\n const handlePageChange = (pageNum: number): void => {\n visit(\n buildQuery({\n filters: filterValues,\n search: searchValue,\n sort: currentSort,\n page: pageNum,\n perPage,\n }),\n );\n };\n\n const handlePerPageChange = (newPerPage: number): void => {\n setPerPage(newPerPage);\n visit(\n buildQuery({\n filters: filterValues,\n search: searchValue,\n sort: currentSort,\n perPage: newPerPage,\n }),\n );\n };\n\n const dispatchBulkAction = (action: ActionSchema): void => {\n // Every bulk action carries a stock url (core resolves\n // /admin/{slug}/bulk/{name} for any bulk action without an\n // explicit url), so there is no client-side fallback route.\n const url = action.url;\n if (url === undefined) {\n return;\n }\n const method = action.method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete';\n router.visit(url, {\n method: method as never,\n data: { record_ids: selectedIds as readonly (string | number)[] } as never,\n preserveScroll: true,\n onSuccess: () => setSelectedIds([]),\n });\n };\n\n const bulkActionsList = props.actions?.bulk ?? [];\n const bulkActions =\n bulkActionsList.length > 0 && selectedIds.length > 0 ? (\n <div className=\"flex items-center gap-2\">\n {bulkActionsList.map((action) => (\n // Route through ActionButton so destructive bulk actions that set\n // requiresConfirmation open the ConfirmDialog before dispatching,\n // matching row-action behaviour. Non-confirming actions fire\n // immediately. The visit payload is unchanged.\n <ActionButton\n key={action.name}\n action={action}\n onInvoke={() => dispatchBulkAction(action)}\n size=\"sm\"\n // 44px touch target on mobile (WCAG 2.5.5); dense 32px on >=md.\n className=\"h-11 md:h-8\"\n />\n ))}\n </div>\n ) : undefined;\n\n const rowActionsList = props.actions?.row ?? [];\n const rowActions =\n rowActionsList.length > 0\n ? (record: TRecord) => (\n <ActionMenu\n // Resolve actions against this row so closure-URL /\n // closure-disabled actions get their per-record values\n // (#140) instead of the table-level placeholder.\n actions={resolveRecordActions(rowActionsList, record)}\n onInvoke={(action, formValues) =>\n invokeAction(action, record as { id: string | number }, formValues)\n }\n />\n )\n : undefined;\n\n return (\n <ResourceIndex<TRecord>\n {...props}\n filterValues={filterValues}\n onFilterChange={handleFilterChange}\n onClearFilters={handleClearFilters}\n onSearchChange={handleSearchChange}\n onSortChange={handleSortChange}\n onPageChange={handlePageChange}\n onPerPageChange={handlePerPageChange}\n search={searchValue}\n selectedIds={selectedIds}\n onSelectionChange={(ids) => setSelectedIds(ids)}\n {...(rowActions ? { rowActions } : {})}\n {...(bulkActions ? { bulkActions } : {})}\n />\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/pages/ArqelIndexPage.tsx"],"names":[],"mappings":"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","file":"chunk-LLANMODS.js","sourcesContent":["/**\n * Default Inertia page for `arqel::index`.\n *\n * Pulls every prop the server emits via `InertiaDataBuilder::\n * buildIndexData` / `buildTableIndexData` and forwards them to\n * `<ResourceIndex>`. Apps can override per-resource by registering\n * their own page component at `Pages/Arqel/{Slug}/Index.tsx` (the\n * lookup falls through to user pages first inside `createArqelApp`).\n *\n * Wires the standard table interactions — search / filter / sort /\n * pagination — into Inertia partial `router.get` visits so the\n * server can re-run TableQueryBuilder with the new query string.\n *\n * Query-string contract (matches `Arqel\\Table\\TableQueryBuilder`):\n * - `?search=foo` global search\n * - `?sort=column&direction=asc|desc`\n * - `?page=N&per_page=M`\n * - `?filter[name]=value` one entry per filter\n *\n * `search` is debounced (300ms) so typing doesn't hammer the\n * backend; the rest fire immediately.\n */\n\nimport type { ActionSchema } from '@arqel-dev/types/actions';\nimport type { RecordType, ResourceIndexProps } from '@arqel-dev/types/resources';\nimport type { SortDirection } from '@arqel-dev/types/tables';\nimport { router, usePage } from '@inertiajs/react';\nimport { type JSX, useEffect, useMemo, useRef, useState } from 'react';\nimport { ActionButton } from '../action/ActionButton.js';\nimport { ActionMenu } from '../action/ActionMenu.js';\nimport { ResourceIndex } from '../resource/ResourceIndex.js';\n\ntype FilterValue = unknown;\n\nfunction pruneEmptyFilters(values: Record<string, FilterValue>): Record<string, FilterValue> {\n const out: Record<string, FilterValue> = {};\n for (const [k, v] of Object.entries(values)) {\n if (v === undefined || v === null || v === '') continue;\n if (Array.isArray(v) && v.length === 0) continue;\n out[k] = v;\n }\n return out;\n}\n\ninterface VisitParams {\n filters: Record<string, FilterValue>;\n search: string;\n sort?: { column: string | null; direction: string | null } | null;\n page?: number | undefined;\n perPage?: number | undefined;\n}\n\nfunction invokeAction(\n action: ActionSchema,\n record: { id: string | number } | null,\n formValues?: Record<string, unknown>,\n): void {\n const recordId = record?.id;\n // Every dispatchable action ships a server-emitted `url` (stock verbs,\n // bulk, and custom callback actions all resolve through core's authorised\n // routes — see `Action::resolveStockUrl()`, #48/#231). An absent `url`\n // signals a misconfiguration; we must NOT fall back to the dead\n // `/arqel-dev/actions/{name}` route removed in #174. Surface it clearly\n // instead of masking it as a 404.\n if (!action.url) {\n throw new Error(\n `Arqel: action \"${action.name}\" has no url to dispatch to. Declare it on ` +\n `the Resource's actions()/headerActions()/toolbarActions() so the server ` +\n `emits its endpoint URL, or give it an explicit ->url().`,\n );\n }\n const url = action.url.replace('{id}', String(recordId ?? ''));\n const method = action.method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete';\n const data: Record<string, unknown> = { ...(formValues ?? {}) };\n if (recordId !== undefined) data['record_id'] = recordId;\n\n router.visit(url, {\n method: method as never,\n data: data as never,\n preserveScroll: true,\n });\n}\n\n/**\n * Resolve the row-action list for a single record (#140).\n *\n * Row actions are defined once at table level (label / icon / color /\n * confirmation / form), but `url(Closure)` and `disabled(Closure)`\n * actions depend on the row. The server emits those resolved values\n * per record under `record.arqel.actionOverrides`; here we merge them\n * onto the shared definitions so each row links to its own URL and\n * carries its own disabled state.\n *\n * When the server also emits `record.arqel.actions` (the visible +\n * executable action names) we filter the list against it so per-row\n * authorization/visibility is honoured.\n */\nfunction resolveRecordActions(\n tableActions: ActionSchema[],\n record: {\n arqel?: {\n actions?: string[];\n actionOverrides?: Record<string, { url?: string; disabled?: true }>;\n };\n },\n): ActionSchema[] {\n const visibleNames = record.arqel?.actions;\n const overrides = record.arqel?.actionOverrides ?? {};\n\n return tableActions\n .filter((action) => (visibleNames ? visibleNames.includes(action.name) : true))\n .map((action) => {\n const override = overrides[action.name];\n if (override === undefined) return action;\n return {\n ...action,\n ...(override.url !== undefined ? { url: override.url } : {}),\n ...(override.disabled === true ? { disabled: true as const } : {}),\n };\n });\n}\n\nfunction buildQuery(params: VisitParams): Record<string, unknown> {\n const data: Record<string, unknown> = {};\n const filters = pruneEmptyFilters(params.filters);\n if (Object.keys(filters).length > 0) data['filter'] = filters;\n if (params.search !== undefined) data['search'] = params.search;\n if (params.sort?.column) {\n data['sort'] = params.sort.column;\n if (params.sort.direction) data['direction'] = params.sort.direction;\n }\n if (params.page && params.page > 1) data['page'] = params.page;\n if (params.perPage) data['per_page'] = params.perPage;\n return data;\n}\n\nexport default function ArqelIndexPage<TRecord extends RecordType = RecordType>(): JSX.Element {\n const page = usePage();\n const props = page.props as unknown as ResourceIndexProps<TRecord>;\n\n const initialFilters = useMemo(() => {\n if (typeof window === 'undefined') return {};\n const sp = new URLSearchParams(window.location.search);\n const fromUrl: Record<string, FilterValue> = {};\n for (const [key, value] of sp.entries()) {\n const m = key.match(/^filter\\[([^\\]]+)\\]$/);\n if (m?.[1]) fromUrl[m[1]] = value;\n }\n return fromUrl;\n }, []);\n\n const [filterValues, setFilterValues] = useState<Record<string, FilterValue>>(initialFilters);\n const [searchValue, setSearchValue] = useState<string>(props.search ?? '');\n const [perPage, setPerPage] = useState<number | undefined>(props.pagination?.perPage);\n const [selectedIds, setSelectedIds] = useState<ReadonlyArray<string | number>>([]);\n const searchDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const visit = (data: Record<string, unknown>): void => {\n const url = typeof window !== 'undefined' ? window.location.pathname : page.url.split('?')[0];\n router.get(url ?? '/', data as Record<string, string | number | boolean | undefined>, {\n preserveState: true,\n preserveScroll: true,\n replace: true,\n });\n };\n\n const currentSort = props.sort ?? null;\n\n const handleFilterChange = (name: string, value: FilterValue): void => {\n const nextFilters = { ...filterValues };\n if (value === undefined || value === null || value === '') {\n delete nextFilters[name];\n } else {\n nextFilters[name] = value;\n }\n setFilterValues(nextFilters);\n visit(buildQuery({ filters: nextFilters, search: searchValue, sort: currentSort, perPage }));\n };\n\n const handleClearFilters = (): void => {\n setFilterValues({});\n visit(buildQuery({ filters: {}, search: searchValue, sort: currentSort, perPage }));\n };\n\n const handleSearchChange = (value: string): void => {\n setSearchValue(value);\n if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);\n searchDebounceRef.current = setTimeout(() => {\n visit(buildQuery({ filters: filterValues, search: value, sort: currentSort, perPage }));\n }, 300);\n };\n\n useEffect(\n () => () => {\n if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);\n },\n [],\n );\n\n const handleSortChange = (column: string, direction: SortDirection): void => {\n visit(\n buildQuery({\n filters: filterValues,\n search: searchValue,\n sort: { column, direction },\n perPage,\n }),\n );\n };\n\n const handlePageChange = (pageNum: number): void => {\n visit(\n buildQuery({\n filters: filterValues,\n search: searchValue,\n sort: currentSort,\n page: pageNum,\n perPage,\n }),\n );\n };\n\n const handlePerPageChange = (newPerPage: number): void => {\n setPerPage(newPerPage);\n visit(\n buildQuery({\n filters: filterValues,\n search: searchValue,\n sort: currentSort,\n perPage: newPerPage,\n }),\n );\n };\n\n const dispatchBulkAction = (action: ActionSchema): void => {\n // Every bulk action carries a stock url (core resolves\n // /admin/{slug}/bulk/{name} for any bulk action without an\n // explicit url), so there is no client-side fallback route.\n const url = action.url;\n if (url === undefined) {\n return;\n }\n const method = action.method.toLowerCase() as 'get' | 'post' | 'put' | 'patch' | 'delete';\n router.visit(url, {\n method: method as never,\n data: { record_ids: selectedIds as readonly (string | number)[] } as never,\n preserveScroll: true,\n onSuccess: () => setSelectedIds([]),\n });\n };\n\n const bulkActionsList = props.actions?.bulk ?? [];\n const bulkActions =\n bulkActionsList.length > 0 && selectedIds.length > 0 ? (\n <div className=\"flex items-center gap-2\">\n {bulkActionsList.map((action) => (\n // Route through ActionButton so destructive bulk actions that set\n // requiresConfirmation open the ConfirmDialog before dispatching,\n // matching row-action behaviour. Non-confirming actions fire\n // immediately. The visit payload is unchanged.\n <ActionButton\n key={action.name}\n action={action}\n onInvoke={() => dispatchBulkAction(action)}\n size=\"sm\"\n // 44px touch target on mobile (WCAG 2.5.5); dense 32px on >=md.\n className=\"h-11 md:h-8\"\n />\n ))}\n </div>\n ) : undefined;\n\n const rowActionsList = props.actions?.row ?? [];\n const rowActions =\n rowActionsList.length > 0\n ? (record: TRecord) => (\n <ActionMenu\n // Resolve actions against this row so closure-URL /\n // closure-disabled actions get their per-record values\n // (#140) instead of the table-level placeholder.\n actions={resolveRecordActions(rowActionsList, record)}\n onInvoke={(action, formValues) =>\n invokeAction(action, record as { id: string | number }, formValues)\n }\n />\n )\n : undefined;\n\n return (\n <ResourceIndex<TRecord>\n {...props}\n filterValues={filterValues}\n onFilterChange={handleFilterChange}\n onClearFilters={handleClearFilters}\n onSearchChange={handleSearchChange}\n onSortChange={handleSortChange}\n onPageChange={handlePageChange}\n onPerPageChange={handlePerPageChange}\n search={searchValue}\n selectedIds={selectedIds}\n onSelectionChange={(ids) => setSelectedIds(ids)}\n {...(rowActions ? { rowActions } : {})}\n {...(bulkActions ? { bulkActions } : {})}\n />\n );\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { PageHeader } from './chunk-MXUXMHOK.js';
2
- import { FormRenderer } from './chunk-ZAM5TUPP.js';
2
+ import { FormRenderer } from './chunk-CMNZLA32.js';
3
+ import { useArqelTranslations } from '@arqel-dev/react/utils';
3
4
  import { usePage } from '@inertiajs/react';
4
5
  import { jsxs, jsx } from 'react/jsx-runtime';
5
6
 
@@ -12,6 +13,7 @@ var FALLBACK_SCHEMA = {
12
13
  };
13
14
  function ArqelShowPage() {
14
15
  const page = usePage();
16
+ const t = useArqelTranslations();
15
17
  const props = page.props;
16
18
  const fields = props.fields ?? [];
17
19
  const values = {};
@@ -27,7 +29,7 @@ function ArqelShowPage() {
27
29
  /* @__PURE__ */ jsx(
28
30
  PageHeader,
29
31
  {
30
- title: props.recordTitle ?? props.resource?.label ?? "Record",
32
+ title: props.recordTitle ?? props.resource?.label ?? t("arqel.pages.record", "Record"),
31
33
  description: props.recordSubtitle ?? null
32
34
  }
33
35
  ),
@@ -46,5 +48,5 @@ function ArqelShowPage() {
46
48
  }
47
49
 
48
50
  export { ArqelShowPage };
49
- //# sourceMappingURL=chunk-N6WLCHQE.js.map
50
- //# sourceMappingURL=chunk-N6WLCHQE.js.map
51
+ //# sourceMappingURL=chunk-Q7WGPKUN.js.map
52
+ //# sourceMappingURL=chunk-Q7WGPKUN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/ArqelShowPage.tsx"],"names":[],"mappings":";;;;;;AAiBA,IAAM,eAAA,GAA8B;AAAA,EAClC,QAAQ,EAAC;AAAA,EACT,OAAA,EAAS,CAAA;AAAA,EACT,KAAA,EAAO,IAAA;AAAA,EACP,MAAA,EAAQ,KAAA;AAAA,EACR,QAAA,EAAU;AACZ,CAAA;AAEe,SAAR,aAAA,GAAuF;AAC5F,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,IAAI,oBAAA,EAAqB;AAC/B,EAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AACnB,EAAA,MAAM,MAAA,GAAU,KAAA,CAAM,MAAA,IAAU,EAAC;AAIjC,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,IAAA,IAAI,OAAO,SAAS,QAAA,IAAY,KAAA,CAAM,WAAW,IAAA,IAAQ,OAAO,KAAA,CAAM,MAAA,KAAW,QAAA,EAAU;AACzF,MAAA,MAAA,CAAO,IAAI,CAAA,GAAK,KAAA,CAAM,MAAA,CAAmC,IAAI,CAAA;AAAA,IAC/D;AAAA,EACF;AAEA,EAAA,MAAM,eAAgB,KAAA,CAA2C,IAAA;AACjE,EAAA,MAAM,SAAqB,YAAA,GAAe,EAAE,GAAG,YAAA,EAAc,QAAA,EAAU,MAAK,GAAI,eAAA;AAEhF,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,MAAM,WAAA,IAAe,KAAA,CAAM,UAAU,KAAA,IAAS,CAAA,CAAE,sBAAsB,QAAQ,CAAA;AAAA,QACrF,WAAA,EAAa,MAAM,cAAA,IAAkB;AAAA;AAAA,KACvC;AAAA,oBACA,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,MAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,UAAU,MAAM;AAAA,QAEhB,CAAA;AAAA,QACA,QAAQ;AAAC;AAAA;AACX,GAAA,EACF,CAAA;AAEJ","file":"chunk-Q7WGPKUN.js","sourcesContent":["/**\n * Default Inertia page for `arqel::show`.\n *\n * Read-only render of the record. Re-uses `<FormRenderer>` with\n * every field forced to disabled — keeps a single rendering path\n * for create/edit/show without a parallel \"DetailRenderer\" stack.\n */\n\nimport { useArqelTranslations } from '@arqel-dev/react/utils';\nimport type { FieldSchema } from '@arqel-dev/types/fields';\nimport type { FormSchema } from '@arqel-dev/types/forms';\nimport type { RecordType, ResourceDetailProps } from '@arqel-dev/types/resources';\nimport { usePage } from '@inertiajs/react';\nimport type { JSX } from 'react';\nimport { FormRenderer } from '../form/FormRenderer.js';\nimport { PageHeader } from '../utility/PageHeader.js';\n\nconst FALLBACK_SCHEMA: FormSchema = {\n schema: [],\n columns: 1,\n model: null,\n inline: false,\n disabled: true,\n};\n\nexport default function ArqelShowPage<TRecord extends RecordType = RecordType>(): JSX.Element {\n const page = usePage();\n const t = useArqelTranslations();\n const props = page.props as unknown as ResourceDetailProps<TRecord>;\n const fields = (props.fields ?? []) as FieldSchema[];\n\n // Seed values from the record so FormRenderer has something to\n // display. Detail mode disables every field.\n const values: Record<string, unknown> = {};\n for (const field of fields) {\n const name = field.name;\n if (typeof name === 'string' && props.record !== null && typeof props.record === 'object') {\n values[name] = (props.record as Record<string, unknown>)[name];\n }\n }\n\n const declaredForm = (props as unknown as { form?: FormSchema }).form;\n const schema: FormSchema = declaredForm ? { ...declaredForm, disabled: true } : FALLBACK_SCHEMA;\n\n return (\n <div className=\"space-y-6\">\n <PageHeader\n title={props.recordTitle ?? props.resource?.label ?? t('arqel.pages.record', 'Record')}\n description={props.recordSubtitle ?? null}\n />\n <FormRenderer\n schema={schema}\n fields={fields}\n values={values}\n onChange={() => {\n // No-op — show pages are read-only.\n }}\n errors={{}}\n />\n </div>\n );\n}\n"]}