@questpie/admin 3.4.1 → 3.5.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 (101) hide show
  1. package/dist/client/blocks/block-renderer.d.mts +2 -2
  2. package/dist/client/builder/types/action-types.d.mts +2 -2
  3. package/dist/client/components/actions/action-dialog.mjs +7 -7
  4. package/dist/client/components/blocks/block-canvas.mjs +1 -1
  5. package/dist/client/components/blocks/block-editor-layout.mjs +2 -2
  6. package/dist/client/components/blocks/block-insert-button.mjs +3 -3
  7. package/dist/client/components/blocks/block-item-menu.mjs +9 -9
  8. package/dist/client/components/blocks/block-item.mjs +5 -5
  9. package/dist/client/components/blocks/block-library-sidebar.mjs +3 -3
  10. package/dist/client/components/fields/array-field.mjs +2 -2
  11. package/dist/client/components/fields/date-field.mjs +6 -5
  12. package/dist/client/components/fields/datetime-field.mjs +6 -1
  13. package/dist/client/components/fields/object-array-field.mjs +2 -2
  14. package/dist/client/components/fields/relation/displays/cards-display.mjs +1 -1
  15. package/dist/client/components/fields/relation/displays/grid-display.mjs +1 -1
  16. package/dist/client/components/fields/relation/displays/list-display.mjs +3 -3
  17. package/dist/client/components/fields/relation/displays/table-display.mjs +1 -1
  18. package/dist/client/components/fields/relation-picker.mjs +3 -3
  19. package/dist/client/components/fields/relation-select.mjs +2 -2
  20. package/dist/client/components/filter-builder/filter-builder-sheet.mjs +16 -16
  21. package/dist/client/components/history-sidebar.mjs +12 -4
  22. package/dist/client/components/layout/field-layout-renderer.mjs +8 -3
  23. package/dist/client/components/media/media-grid.mjs +2 -2
  24. package/dist/client/components/preview/live-preview-mode.mjs +4 -4
  25. package/dist/client/components/preview/preview-pane.mjs +4 -4
  26. package/dist/client/components/primitives/asset-preview.mjs +5 -5
  27. package/dist/client/components/primitives/dropzone.mjs +1 -1
  28. package/dist/client/components/ui/kbd.mjs +1 -1
  29. package/dist/client/components/ui/scroll-fade.mjs +4 -4
  30. package/dist/client/components/ui/sidebar.mjs +1 -1
  31. package/dist/client/components/ui/skeleton.mjs +1 -1
  32. package/dist/client/components/ui/table.mjs +1 -1
  33. package/dist/client/components/widgets/quick-actions-widget.mjs +6 -6
  34. package/dist/client/components/widgets/timeline-widget.mjs +3 -3
  35. package/dist/client/components/widgets/value-widget.mjs +1 -1
  36. package/dist/client/components/widgets/widget-skeletons.mjs +2 -2
  37. package/dist/client/hooks/typed-hooks.mjs +66 -21
  38. package/dist/client/hooks/use-collection.mjs +48 -7
  39. package/dist/client/hooks/use-server-actions.mjs +1 -0
  40. package/dist/client/i18n/date-locale.mjs +0 -14
  41. package/dist/client/preview/diff.mjs +4 -1
  42. package/dist/client/preview/patch.mjs +1 -1
  43. package/dist/client/preview/paths.mjs +85 -0
  44. package/dist/client/runtime/translations-provider.mjs +1 -1
  45. package/dist/client/scope/picker.d.mts +2 -2
  46. package/dist/client/scope/provider.d.mts +2 -2
  47. package/dist/client/styles/base.css +51 -1
  48. package/dist/client/views/auth/accept-invite-form.d.mts +2 -2
  49. package/dist/client/views/auth/auth-layout.d.mts +3 -3
  50. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  51. package/dist/client/views/auth/setup-form.d.mts +2 -2
  52. package/dist/client/views/collection/auto-form-fields.mjs +1 -1
  53. package/dist/client/views/collection/cells/primitive-cells.mjs +2 -2
  54. package/dist/client/views/collection/cells/upload-cells.mjs +2 -2
  55. package/dist/client/views/collection/form-view.mjs +45 -26
  56. package/dist/client/views/collection/table-view.mjs +33 -20
  57. package/dist/client/views/collection/view-skeletons.mjs +37 -38
  58. package/dist/client/views/common/global-search.mjs +3 -3
  59. package/dist/client/views/dashboard/widget-card.mjs +7 -7
  60. package/dist/client/views/layout/admin-router.mjs +84 -37
  61. package/dist/client/views/layout/admin-sidebar.mjs +22 -21
  62. package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
  63. package/dist/client/views/pages/dashboard-page.d.mts +2 -2
  64. package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
  65. package/dist/client/views/pages/invite-page.d.mts +2 -2
  66. package/dist/client/views/pages/login-page.d.mts +2 -2
  67. package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
  68. package/dist/factories.d.mts +0 -2
  69. package/dist/server/adapters/nextjs.d.mts +0 -1
  70. package/dist/server/augmentation/actions.d.mts +2 -0
  71. package/dist/server/i18n/messages/cs.mjs +2 -0
  72. package/dist/server/i18n/messages/de.mjs +2 -0
  73. package/dist/server/i18n/messages/en.mjs +2 -0
  74. package/dist/server/i18n/messages/es.mjs +2 -0
  75. package/dist/server/i18n/messages/fr.mjs +2 -0
  76. package/dist/server/i18n/messages/pl.mjs +2 -0
  77. package/dist/server/i18n/messages/pt.mjs +2 -0
  78. package/dist/server/i18n/messages/sk.mjs +2 -0
  79. package/dist/server/modules/admin/collections/account.d.mts +50 -50
  80. package/dist/server/modules/admin/collections/admin-locks.d.mts +49 -49
  81. package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
  82. package/dist/server/modules/admin/collections/admin-saved-views.d.mts +36 -36
  83. package/dist/server/modules/admin/collections/apikey.d.mts +68 -68
  84. package/dist/server/modules/admin/collections/assets.d.mts +34 -34
  85. package/dist/server/modules/admin/collections/session.d.mts +42 -42
  86. package/dist/server/modules/admin/collections/user.d.mts +14 -14
  87. package/dist/server/modules/admin/collections/user.mjs +9 -9
  88. package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
  89. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  90. package/dist/server/modules/admin/routes/execute-action.mjs +3 -2
  91. package/dist/server/modules/admin/routes/preview.d.mts +11 -11
  92. package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
  93. package/dist/server/modules/admin/routes/setup.d.mts +7 -7
  94. package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
  95. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +23 -23
  96. package/dist/server/modules/audit/.generated/module.d.mts +6 -6
  97. package/dist/server/modules/audit/collections/audit-log.d.mts +37 -37
  98. package/dist/server.d.mts +0 -2
  99. package/package.json +3 -3
  100. package/dist/server/adapters/index.d.mts +0 -2
  101. package/dist/server/auth-helpers.d.mts +0 -1
@@ -195,7 +195,7 @@ function LivePreviewContent({ open, children, previewUrl, previewRef, onFieldVal
195
195
  className: "flex items-center gap-2",
196
196
  children: [/* @__PURE__ */ jsx(Icon, {
197
197
  icon: "ph:eye",
198
- className: "text-muted-foreground h-4 w-4"
198
+ className: "text-muted-foreground size-4"
199
199
  }), /* @__PURE__ */ jsx("span", {
200
200
  className: "font-medium",
201
201
  children: t("preview.livePreview")
@@ -228,7 +228,7 @@ function LivePreviewContent({ open, children, previewUrl, previewRef, onFieldVal
228
228
  title: t("preview.exitTooltip"),
229
229
  children: [/* @__PURE__ */ jsx(Icon, {
230
230
  icon: "ph:sign-out",
231
- className: "h-4 w-4"
231
+ className: "size-4"
232
232
  }), /* @__PURE__ */ jsx("span", {
233
233
  className: "hidden sm:inline",
234
234
  children: t("preview.exitPreview")
@@ -261,7 +261,7 @@ function LivePreviewContent({ open, children, previewUrl, previewRef, onFieldVal
261
261
  className: "flex h-full items-center justify-center",
262
262
  children: [/* @__PURE__ */ jsx(Icon, {
263
263
  icon: "ph:spinner",
264
- className: "text-muted-foreground h-6 w-6 animate-spin"
264
+ className: "text-muted-foreground size-6 animate-spin"
265
265
  }), /* @__PURE__ */ jsx("span", {
266
266
  className: "text-muted-foreground ml-2 text-sm",
267
267
  children: t("preview.loadingPreview")
@@ -290,7 +290,7 @@ function LivePreviewContent({ open, children, previewUrl, previewRef, onFieldVal
290
290
  className: "flex h-full items-center justify-center",
291
291
  children: [/* @__PURE__ */ jsx(Icon, {
292
292
  icon: "ph:spinner",
293
- className: "text-muted-foreground h-6 w-6 animate-spin"
293
+ className: "text-muted-foreground size-6 animate-spin"
294
294
  }), /* @__PURE__ */ jsx("span", {
295
295
  className: "text-muted-foreground ml-2 text-sm",
296
296
  children: t("preview.loadingPreview")
@@ -294,13 +294,13 @@ const PreviewPane = React.forwardRef(({ url, selectedBlockId, onFieldClick, onBl
294
294
  }, 3e3);
295
295
  }, []);
296
296
  return /* @__PURE__ */ jsxs("div", {
297
- className: cn("relative h-full w-full", className),
297
+ className: cn("relative size-full", className),
298
298
  children: [
299
299
  isLoading && /* @__PURE__ */ jsxs("div", {
300
300
  className: "bg-muted absolute inset-0 z-10 flex items-center justify-center",
301
301
  children: [/* @__PURE__ */ jsx(Icon, {
302
302
  icon: "ph:spinner",
303
- className: "text-muted-foreground h-6 w-6 animate-spin"
303
+ className: "text-muted-foreground size-6 animate-spin"
304
304
  }), /* @__PURE__ */ jsx("span", {
305
305
  className: "text-muted-foreground ml-2 text-sm",
306
306
  children: t("preview.loadingPreview")
@@ -320,7 +320,7 @@ const PreviewPane = React.forwardRef(({ url, selectedBlockId, onFieldClick, onBl
320
320
  className: "bg-background absolute top-4 right-4 z-10 flex items-center gap-2 border px-3 py-2 shadow-md",
321
321
  children: [/* @__PURE__ */ jsx(Icon, {
322
322
  icon: "ph:spinner",
323
- className: "text-muted-foreground h-4 w-4 animate-spin"
323
+ className: "text-muted-foreground size-4 animate-spin"
324
324
  }), /* @__PURE__ */ jsx("span", {
325
325
  className: "text-muted-foreground text-sm",
326
326
  children: t("preview.refreshing")
@@ -329,7 +329,7 @@ const PreviewPane = React.forwardRef(({ url, selectedBlockId, onFieldClick, onBl
329
329
  previewUrlResolved && /* @__PURE__ */ jsx("iframe", {
330
330
  ref: iframeRef,
331
331
  src: previewUrlResolved,
332
- className: "h-full w-full border-0",
332
+ className: "size-full border-0",
333
333
  title: t("common.preview"),
334
334
  onLoad: handleLoad,
335
335
  sandbox: "allow-scripts allow-same-origin allow-forms"
@@ -110,10 +110,10 @@ function AssetPreview({ asset, pendingFile, onRemove, onEdit, loading = false, p
110
110
  thumbnailUrl && !imageError ? /* @__PURE__ */ jsx("img", {
111
111
  src: thumbnailUrl,
112
112
  alt: asset.alt || filename,
113
- className: "image-outline h-full w-full object-cover",
113
+ className: "image-outline size-full object-cover",
114
114
  onError: () => setImageError(true)
115
115
  }) : /* @__PURE__ */ jsx("div", {
116
- className: "flex h-full w-full items-center justify-center",
116
+ className: "flex size-full items-center justify-center",
117
117
  children: /* @__PURE__ */ jsx(Icon, {
118
118
  icon: fileIconName,
119
119
  className: "text-muted-foreground size-8"
@@ -221,7 +221,7 @@ function AssetPreview({ asset, pendingFile, onRemove, onEdit, loading = false, p
221
221
  children: thumbnailUrl && !imageError ? /* @__PURE__ */ jsx("img", {
222
222
  src: thumbnailUrl,
223
223
  alt: asset.alt || filename,
224
- className: "image-outline h-full w-full object-cover",
224
+ className: "image-outline size-full object-cover",
225
225
  onError: () => setImageError(true)
226
226
  }) : /* @__PURE__ */ jsx(Icon, {
227
227
  icon: fileIconName,
@@ -325,10 +325,10 @@ function AssetPreview({ asset, pendingFile, onRemove, onEdit, loading = false, p
325
325
  thumbnailUrl && !imageError ? /* @__PURE__ */ jsx("img", {
326
326
  src: thumbnailUrl,
327
327
  alt: asset.alt || filename,
328
- className: "image-outline h-full w-full object-contain",
328
+ className: "image-outline size-full object-contain",
329
329
  onError: () => setImageError(true)
330
330
  }) : /* @__PURE__ */ jsxs("div", {
331
- className: "flex h-full w-full flex-col items-center justify-center gap-2",
331
+ className: "flex size-full flex-col items-center justify-center gap-2",
332
332
  children: [/* @__PURE__ */ jsx(Icon, {
333
333
  icon: fileIconName,
334
334
  className: "text-muted-foreground size-12"
@@ -189,7 +189,7 @@ function Dropzone({ onDrop, accept, maxSize, multiple = false, disabled = false,
189
189
  onDragLeave: handleDragLeave,
190
190
  onDragOver: handleDragOver,
191
191
  onDrop: handleDrop,
192
- className: cn("qa-dropzone control-surface relative flex cursor-pointer hover:bg-muted/40 rounded-lg border transition-colors", isCompact ? "min-h-16 flex-row items-center justify-start gap-3 border border-dashed p-3 text-left" : "min-h-[120px] flex-col items-center justify-center gap-2 border-2 p-6 text-center", isDragging && "border-border-strong bg-surface-high", error && "border-destructive/50 bg-destructive/5", (disabled || loading) && "pointer-events-none opacity-60", className),
192
+ className: cn("qa-dropzone control-surface hover:bg-muted/40 relative flex cursor-pointer rounded-lg border transition-colors", isCompact ? "min-h-16 flex-row items-center justify-start gap-3 border border-dashed p-3 text-left" : "min-h-[120px] flex-col items-center justify-center gap-2 border-2 p-6 text-center", isDragging && "border-border-strong bg-surface-high", error && "border-destructive/50 bg-destructive/5", (disabled || loading) && "pointer-events-none opacity-60", className),
193
193
  "aria-disabled": disabled || loading,
194
194
  "data-dragging": isDragging || void 0,
195
195
  children: [
@@ -13,7 +13,7 @@ import { jsx } from "react/jsx-runtime";
13
13
  */
14
14
  function Kbd({ className, children, ...props }) {
15
15
  return /* @__PURE__ */ jsx("kbd", {
16
- className: cn("qa-kbd rounded-xs bg-muted text-muted-foreground pointer-events-none inline-flex h-5 items-center gap-1 border px-1.5 font-mono text-[10px] font-medium select-none", className),
16
+ className: cn("qa-kbd bg-muted text-muted-foreground pointer-events-none inline-flex h-5 items-center gap-1 rounded-xs border px-1.5 font-mono text-[10px] font-medium select-none", className),
17
17
  ...props,
18
18
  children
19
19
  });
@@ -45,7 +45,7 @@ function ScrollFade({ orientation = "horizontal", fadeSize = 20, leftInset = 0,
45
45
  children: [
46
46
  children,
47
47
  h && /* @__PURE__ */ jsx("div", {
48
- className: cn(fade, "inset-y-0 bg-gradient-to-r from-background to-transparent", overflow.left ? "opacity-100" : "opacity-0"),
48
+ className: cn(fade, "from-background inset-y-0 bg-gradient-to-r to-transparent", overflow.left ? "opacity-100" : "opacity-0"),
49
49
  style: {
50
50
  left: leftInset,
51
51
  width: fadeSize
@@ -53,17 +53,17 @@ function ScrollFade({ orientation = "horizontal", fadeSize = 20, leftInset = 0,
53
53
  "aria-hidden": true
54
54
  }),
55
55
  h && /* @__PURE__ */ jsx("div", {
56
- className: cn(fade, "inset-y-0 right-0 bg-gradient-to-l from-background to-transparent", overflow.right ? "opacity-100" : "opacity-0"),
56
+ className: cn(fade, "from-background inset-y-0 right-0 bg-gradient-to-l to-transparent", overflow.right ? "opacity-100" : "opacity-0"),
57
57
  style: { width: fadeSize },
58
58
  "aria-hidden": true
59
59
  }),
60
60
  v && /* @__PURE__ */ jsx("div", {
61
- className: cn(fade, "inset-x-0 top-0 bg-gradient-to-b from-background to-transparent", overflow.top ? "opacity-100" : "opacity-0"),
61
+ className: cn(fade, "from-background inset-x-0 top-0 bg-gradient-to-b to-transparent", overflow.top ? "opacity-100" : "opacity-0"),
62
62
  style: { height: fadeSize },
63
63
  "aria-hidden": true
64
64
  }),
65
65
  v && /* @__PURE__ */ jsx("div", {
66
- className: cn(fade, "inset-x-0 bottom-0 bg-gradient-to-t from-background to-transparent", overflow.bottom ? "opacity-100" : "opacity-0"),
66
+ className: cn(fade, "from-background inset-x-0 bottom-0 bg-gradient-to-t to-transparent", overflow.bottom ? "opacity-100" : "opacity-0"),
67
67
  style: { height: fadeSize },
68
68
  "aria-hidden": true
69
69
  })
@@ -105,7 +105,7 @@ function Sidebar({ side = "left", variant = "sidebar", collapsible = "offExample
105
105
  className: "sr-only",
106
106
  children: [/* @__PURE__ */ jsx(SheetTitle, { children: "Sidebar" }), /* @__PURE__ */ jsx(SheetDescription, { children: "Displays the mobile sidebar." })]
107
107
  }), /* @__PURE__ */ jsx("div", {
108
- className: "bg-sidebar border-sidebar-border flex h-full w-full flex-col overflow-hidden rounded-xl border shadow-lg",
108
+ className: "bg-sidebar border-sidebar-border flex size-full flex-col overflow-hidden rounded-xl border shadow-lg",
109
109
  children
110
110
  })]
111
111
  })
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
3
3
  import { cva } from "class-variance-authority";
4
4
 
5
5
  //#region src/client/components/ui/skeleton.tsx
6
- const skeletonVariants = cva("qa-skeleton bg-muted animate-pulse", {
6
+ const skeletonVariants = cva("qa-skeleton bg-muted", {
7
7
  variants: { variant: {
8
8
  default: "rounded-sm",
9
9
  text: "rounded-xs",
@@ -6,7 +6,7 @@ import { jsx } from "react/jsx-runtime";
6
6
  function Table({ className, ...props }) {
7
7
  return /* @__PURE__ */ jsx("div", {
8
8
  "data-slot": "table-container",
9
- className: "qa-table-container scrollbar-thin relative w-full min-w-0 overflow-x-auto",
9
+ className: "qa-table-container relative w-full min-w-0 scrollbar-thin overflow-x-auto",
10
10
  children: /* @__PURE__ */ jsx("table", {
11
11
  "data-slot": "table",
12
12
  className: cn("qa-table w-full caption-bottom border-separate border-spacing-0 text-sm", className),
@@ -89,13 +89,13 @@ function QuickActionsWidget({ config, basePath = "/admin", navigate }) {
89
89
  children: /* @__PURE__ */ jsx("div", {
90
90
  className: "grid h-full grid-cols-2 gap-3",
91
91
  children: parsedActions.map((action) => {
92
- const iconElement = resolveIconElement(action.icon, { className: "h-4 w-4" });
92
+ const iconElement = resolveIconElement(action.icon, { className: "size-4" });
93
93
  return /* @__PURE__ */ jsxs("button", {
94
94
  type: "button",
95
95
  onClick: () => handleClick(action),
96
96
  className: cn("flex min-h-24 flex-col items-center justify-center gap-2 rounded-md border p-3 text-center", "transition-[background-color,border-color,transform] active:scale-[0.96]", variantStyles[action.variant]),
97
97
  children: [iconElement && /* @__PURE__ */ jsx("div", {
98
- className: cn("flex h-9 w-9 items-center justify-center rounded-md", iconVariantStyles[action.variant]),
98
+ className: cn("flex size-9 items-center justify-center rounded-md", iconVariantStyles[action.variant]),
99
99
  children: iconElement
100
100
  }), /* @__PURE__ */ jsx("span", {
101
101
  className: "text-xs leading-tight font-medium text-balance",
@@ -113,14 +113,14 @@ function QuickActionsWidget({ config, basePath = "/admin", navigate }) {
113
113
  children: /* @__PURE__ */ jsx("div", {
114
114
  className: "-mx-1 space-y-1",
115
115
  children: parsedActions.map((action) => {
116
- const iconElement = resolveIconElement(action.icon, { className: "h-4 w-4" });
116
+ const iconElement = resolveIconElement(action.icon, { className: "size-4" });
117
117
  return /* @__PURE__ */ jsxs("button", {
118
118
  type: "button",
119
119
  onClick: () => handleClick(action),
120
- className: cn("group flex min-h-10 w-full items-center gap-3 rounded-md px-2 py-2 text-left transition-[background-color,transform] active:scale-[0.96]", variantStyles[action.variant]),
120
+ className: cn("group flex min-h-10 w-full items-center gap-3 rounded-md p-2 text-left transition-[background-color,transform] active:scale-[0.96]", variantStyles[action.variant]),
121
121
  children: [
122
122
  iconElement && /* @__PURE__ */ jsx("div", {
123
- className: cn("flex h-8 w-8 shrink-0 items-center justify-center rounded-md", iconVariantStyles[action.variant]),
123
+ className: cn("flex size-8 shrink-0 items-center justify-center rounded-md", iconVariantStyles[action.variant]),
124
124
  children: iconElement
125
125
  }),
126
126
  /* @__PURE__ */ jsx("span", {
@@ -129,7 +129,7 @@ function QuickActionsWidget({ config, basePath = "/admin", navigate }) {
129
129
  }),
130
130
  /* @__PURE__ */ jsx(Icon, {
131
131
  icon: "ph:arrow-right",
132
- className: "text-muted-foreground h-4 w-4 opacity-0 transition-opacity group-hover:opacity-100"
132
+ className: "text-muted-foreground size-4 opacity-0 transition-opacity group-hover:opacity-100"
133
133
  })
134
134
  ]
135
135
  }, action.id);
@@ -114,17 +114,17 @@ function TimelineWidget({ config, navigate }) {
114
114
  const timelineContent = items.length === 0 ? emptyContent : /* @__PURE__ */ jsx("div", {
115
115
  className: "space-y-0",
116
116
  children: items.map((item, index) => {
117
- const iconElement = resolveIconElement(item.icon, { className: "h-3 w-3 text-white" });
117
+ const iconElement = resolveIconElement(item.icon, { className: "size-3 text-white" });
118
118
  const variant = item.variant || "default";
119
119
  const isLast = index === items.length - 1;
120
120
  const isClickable = !!(item.href && navigate);
121
121
  const itemContent = /* @__PURE__ */ jsxs(Fragment, { children: [
122
122
  !isLast && /* @__PURE__ */ jsx("div", { className: "bg-border absolute top-6 bottom-0 left-[11px] w-px" }),
123
123
  /* @__PURE__ */ jsx("div", {
124
- className: cn("relative z-10 flex h-6 w-6 shrink-0 items-center justify-center rounded-full", variantStyles[variant]),
124
+ className: cn("relative z-10 flex size-6 shrink-0 items-center justify-center rounded-full", variantStyles[variant]),
125
125
  children: iconElement ?? /* @__PURE__ */ jsx(Icon, {
126
126
  icon: "ph:circle-bold",
127
- className: "h-3 w-3 text-white"
127
+ className: "size-3 text-white"
128
128
  })
129
129
  }),
130
130
  /* @__PURE__ */ jsxs("div", {
@@ -115,7 +115,7 @@ function ValueWidget({ config }) {
115
115
  }),
116
116
  data.trend && /* @__PURE__ */ jsxs("div", {
117
117
  className: cn("flex items-center gap-1 text-sm", cls.trend),
118
- children: [resolveIconElement(TrendIcon, { className: cn("h-3 w-3", cls.trendIcon) }), /* @__PURE__ */ jsx("span", { children: data.trend.value })]
118
+ children: [resolveIconElement(TrendIcon, { className: cn("size-3", cls.trendIcon) }), /* @__PURE__ */ jsx("span", { children: data.trend.value })]
119
119
  }),
120
120
  subtitle && /* @__PURE__ */ jsx("p", {
121
121
  className: cn("text-muted-foreground text-xs", cls.subtitle),
@@ -123,7 +123,7 @@ function TimelineSkeletonItem({ last = false }) {
123
123
  className: "flex flex-col items-center",
124
124
  children: [/* @__PURE__ */ jsx(Skeleton, {
125
125
  variant: "avatar",
126
- className: "h-3 w-3"
126
+ className: "size-3"
127
127
  }), !last && /* @__PURE__ */ jsx(Skeleton, { className: "mt-1 w-0.5 flex-1" })]
128
128
  }), /* @__PURE__ */ jsxs("div", {
129
129
  className: "flex-1 space-y-1 pb-4",
@@ -165,7 +165,7 @@ function ValueWidgetSkeleton({ featured = false }) {
165
165
  className: "space-y-3",
166
166
  children: [/* @__PURE__ */ jsxs("div", {
167
167
  className: "flex items-start gap-3",
168
- children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-10 shrink-0" }), /* @__PURE__ */ jsxs("div", {
168
+ children: [/* @__PURE__ */ jsx(Skeleton, { className: "size-10 shrink-0" }), /* @__PURE__ */ jsxs("div", {
169
169
  className: "flex-1 space-y-2",
170
170
  children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-24" }), /* @__PURE__ */ jsx(Skeleton, { className: cn("h-8", featured ? "w-40" : "w-24") })]
171
171
  })]
@@ -59,43 +59,76 @@ function createTypedHooks() {
59
59
  function useCollectionList(collection, options, queryOptions) {
60
60
  const client = useAdminStore(selectClient);
61
61
  const { locale: contentLocale } = useScopedLocale();
62
+ const queryOpts = createQuestpieQueryOptions(client, {
63
+ keyPrefix: ["questpie", "collections"],
64
+ locale: contentLocale
65
+ });
62
66
  return useQuery({
63
- ...createQuestpieQueryOptions(client, {
64
- keyPrefix: ["questpie", "collections"],
65
- locale: contentLocale
66
- }).collections[collection].find({
67
+ ...collection ? queryOpts.collections[collection].find({
67
68
  ...options,
68
69
  locale: contentLocale
69
- }),
70
+ }) : {
71
+ queryKey: [
72
+ "questpie",
73
+ "collections",
74
+ "__none__",
75
+ "find"
76
+ ],
77
+ queryFn: () => ({
78
+ docs: [],
79
+ totalDocs: 0
80
+ })
81
+ },
82
+ enabled: !!collection && (queryOptions?.enabled ?? true),
70
83
  ...queryOptions
71
84
  });
72
85
  }
73
86
  function useCollectionCount(collection, options, queryOptions) {
74
87
  const client = useAdminStore(selectClient);
75
88
  const { locale: contentLocale } = useScopedLocale();
89
+ const queryOpts = createQuestpieQueryOptions(client, {
90
+ keyPrefix: ["questpie", "collections"],
91
+ locale: contentLocale
92
+ });
76
93
  return useQuery({
77
- ...createQuestpieQueryOptions(client, {
78
- keyPrefix: ["questpie", "collections"],
79
- locale: contentLocale
80
- }).collections[collection].count({
94
+ ...collection ? queryOpts.collections[collection].count({
81
95
  ...options,
82
96
  locale: contentLocale
83
- }),
97
+ }) : {
98
+ queryKey: [
99
+ "questpie",
100
+ "collections",
101
+ "__none__",
102
+ "count"
103
+ ],
104
+ queryFn: () => 0
105
+ },
106
+ enabled: !!collection && (queryOptions?.enabled ?? true),
84
107
  ...queryOptions
85
108
  });
86
109
  }
87
110
  function useCollectionItem(collection, id, options, queryOptions) {
88
111
  const client = useAdminStore(selectClient);
89
112
  const { locale: contentLocale } = useScopedLocale();
113
+ const queryOpts = createQuestpieQueryOptions(client, {
114
+ keyPrefix: ["questpie", "collections"],
115
+ locale: contentLocale
116
+ });
90
117
  return useQuery({
91
- ...createQuestpieQueryOptions(client, {
92
- keyPrefix: ["questpie", "collections"],
93
- locale: contentLocale
94
- }).collections[collection].findOne({
118
+ ...collection ? queryOpts.collections[collection].findOne({
95
119
  where: { id },
96
120
  locale: contentLocale,
97
121
  ...options
98
- }),
122
+ }) : {
123
+ queryKey: [
124
+ "questpie",
125
+ "collections",
126
+ "__none__",
127
+ "findOne"
128
+ ],
129
+ queryFn: () => null
130
+ },
131
+ enabled: !!collection && (queryOptions?.enabled ?? true),
99
132
  ...queryOptions
100
133
  });
101
134
  }
@@ -259,16 +292,28 @@ function createTypedHooks() {
259
292
  function useCollectionVersions(collection, id, options, queryOptions) {
260
293
  const client = useAdminStore(selectClient);
261
294
  const { locale: contentLocale } = useScopedLocale();
295
+ const queryOpts = createQuestpieQueryOptions(client, {
296
+ keyPrefix: ["questpie", "collections"],
297
+ locale: contentLocale
298
+ });
262
299
  return useQuery({
263
- ...createQuestpieQueryOptions(client, {
264
- keyPrefix: ["questpie", "collections"],
265
- locale: contentLocale
266
- }).collections[collection].findVersions({
300
+ ...collection ? queryOpts.collections[collection].findVersions({
267
301
  id,
268
302
  ...options?.limit !== void 0 ? { limit: options.limit } : {},
269
303
  ...options?.offset !== void 0 ? { offset: options.offset } : {}
270
- }),
271
- enabled: !!id && (queryOptions?.enabled ?? true),
304
+ }) : {
305
+ queryKey: [
306
+ "questpie",
307
+ "collections",
308
+ "__none__",
309
+ "findVersions"
310
+ ],
311
+ queryFn: () => ({
312
+ docs: [],
313
+ totalDocs: 0
314
+ })
315
+ },
316
+ enabled: !!collection && !!id && (queryOptions?.enabled ?? true),
272
317
  ...queryOptions
273
318
  });
274
319
  }
@@ -20,7 +20,19 @@ function useCollectionList(collection, options, queryOptions, realtimeOptions) {
20
20
  locale
21
21
  };
22
22
  return useQuery({
23
- ...queryOpts.collections[collection].find(findOptions, { realtime: realtimeOptions?.realtime }),
23
+ ...collection ? queryOpts.collections[collection].find(findOptions, { realtime: realtimeOptions?.realtime }) : {
24
+ queryKey: [
25
+ "questpie",
26
+ "collections",
27
+ "__none__",
28
+ "find"
29
+ ],
30
+ queryFn: () => ({
31
+ docs: [],
32
+ totalDocs: 0
33
+ })
34
+ },
35
+ enabled: !!collection && (queryOptions?.enabled ?? true),
24
36
  ...queryOptions
25
37
  });
26
38
  }
@@ -48,7 +60,16 @@ function useCollectionCount(collection, options, queryOptions, realtimeOptions)
48
60
  locale
49
61
  };
50
62
  return useQuery({
51
- ...queryOpts.collections[collection].count(countOptions, { realtime: realtimeOptions?.realtime }),
63
+ ...collection ? queryOpts.collections[collection].count(countOptions, { realtime: realtimeOptions?.realtime }) : {
64
+ queryKey: [
65
+ "questpie",
66
+ "collections",
67
+ "__none__",
68
+ "count"
69
+ ],
70
+ queryFn: () => 0
71
+ },
72
+ enabled: !!collection && (queryOptions?.enabled ?? true),
52
73
  ...queryOptions
53
74
  });
54
75
  }
@@ -66,11 +87,20 @@ function useCollectionCount(collection, options, queryOptions, realtimeOptions)
66
87
  function useCollectionItem(collection, id, options, queryOptions) {
67
88
  const { queryOpts, locale } = useQuestpieQueryOptions();
68
89
  return useQuery({
69
- ...queryOpts.collections[collection].findOne({
90
+ ...collection ? queryOpts.collections[collection].findOne({
70
91
  where: { id },
71
92
  locale,
72
93
  ...options
73
- }),
94
+ }) : {
95
+ queryKey: [
96
+ "questpie",
97
+ "collections",
98
+ "__none__",
99
+ "findOne"
100
+ ],
101
+ queryFn: () => null
102
+ },
103
+ enabled: !!collection && (queryOptions?.enabled ?? true),
74
104
  ...queryOptions
75
105
  });
76
106
  }
@@ -289,12 +319,23 @@ function useCollectionRestore(collection, mutationOptions) {
289
319
  function useCollectionVersions(collection, id, options, queryOptions) {
290
320
  const { queryOpts } = useQuestpieQueryOptions();
291
321
  return useQuery({
292
- ...queryOpts.collections[collection].findVersions({
322
+ ...collection ? queryOpts.collections[collection].findVersions({
293
323
  id,
294
324
  ...options?.limit !== void 0 ? { limit: options.limit } : {},
295
325
  ...options?.offset !== void 0 ? { offset: options.offset } : {}
296
- }),
297
- enabled: !!id && (queryOptions?.enabled ?? true),
326
+ }) : {
327
+ queryKey: [
328
+ "questpie",
329
+ "collections",
330
+ "__none__",
331
+ "findVersions"
332
+ ],
333
+ queryFn: () => ({
334
+ docs: [],
335
+ totalDocs: 0
336
+ })
337
+ },
338
+ enabled: !!collection && !!id && (queryOptions?.enabled ?? true),
298
339
  ...queryOptions
299
340
  });
300
341
  }
@@ -108,6 +108,7 @@ function mapServerAction(serverAction, collection, fieldRegistry, client, locale
108
108
  });
109
109
  if (!response.success || response.result?.type === "error") throw new Error(getActionErrorMessage(response, t));
110
110
  await applyServerActionEffects(response.result, ctx);
111
+ return response.result?.toast?.message;
111
112
  }
112
113
  }
113
114
  };
@@ -1,20 +1,6 @@
1
1
  import { enUS } from "date-fns/locale/en-US";
2
2
 
3
3
  //#region src/client/i18n/date-locale.ts
4
- /**
5
- * date-fns locale resolver for DayPicker and date formatting.
6
- *
7
- * Only `enUS` is included by default to keep bundle size small.
8
- * Register additional locales at admin setup time:
9
- *
10
- * @example
11
- * ```ts
12
- * import { sk } from "date-fns/locale/sk";
13
- * import { registerDateFnsLocale } from "@questpie/admin/client-module";
14
- *
15
- * registerDateFnsLocale("sk", sk);
16
- * ```
17
- */
18
4
  const localeRegistry = new Map([["en", enUS], ["en-US", enUS]]);
19
5
  /**
20
6
  * Resolve a date-fns Locale from a BCP-47 locale code (e.g. "sk", "en-US").
@@ -44,7 +44,7 @@ function diffSnapshotAtPath(previous, next, path) {
44
44
  op: "remove",
45
45
  path
46
46
  }] : [];
47
- if (previousValue.exists && isDeepEqual(previousValue.value, nextValue.value)) return [];
47
+ if (previousValue.exists && isPatchValueEqual(previousValue.value, nextValue.value)) return [];
48
48
  return [{
49
49
  op: "set",
50
50
  path,
@@ -75,6 +75,9 @@ function isDeepEqual(left, right) {
75
75
  }
76
76
  return false;
77
77
  }
78
+ function isPatchValueEqual(left, right) {
79
+ return Object.is(left, right);
80
+ }
78
81
  function isArrayIndex(segment) {
79
82
  return /^(0|[1-9]\d*)$/.test(segment);
80
83
  }
@@ -1,7 +1,7 @@
1
1
  //#region src/client/preview/patch.ts
2
2
  function cloneSnapshot(value) {
3
+ if (value === null || typeof value !== "object") return value;
3
4
  if (typeof globalThis.structuredClone === "function") return globalThis.structuredClone(value);
4
- if (value === void 0) return value;
5
5
  return JSON.parse(JSON.stringify(value));
6
6
  }
7
7
  function shouldApplyPatchBatch(lastAppliedSeq, nextSeq) {
@@ -0,0 +1,85 @@
1
+ //#region src/client/preview/paths.ts
2
+ function resolveKnownPreviewPath(path, { schema, blocks, values, previousValues }) {
3
+ if (!schema?.fields || !isSafePreviewPath(path)) return;
4
+ const [fieldName, ...rest] = path.split(".");
5
+ if (!fieldName) return void 0;
6
+ const field = schema.fields[fieldName];
7
+ if (!field) return void 0;
8
+ if (rest.length === 0) return fieldName;
9
+ if (resolveFieldPath({
10
+ field,
11
+ fieldName,
12
+ segments: rest,
13
+ blocks,
14
+ values,
15
+ previousValues
16
+ })) return path;
17
+ }
18
+ function isSafePreviewPath(path) {
19
+ if (!path || path.length > 512) return false;
20
+ return path.split(".").every((segment) => segment.length > 0 && segment !== "__proto__" && segment !== "prototype" && segment !== "constructor");
21
+ }
22
+ function resolveFieldPath({ field, fieldName, segments, blocks, values, previousValues }) {
23
+ const metadata = field.metadata;
24
+ if (!metadata) return false;
25
+ if (metadata.type === "blocks") return resolveBlocksPath({
26
+ fieldName,
27
+ segments,
28
+ blocks,
29
+ values,
30
+ previousValues
31
+ });
32
+ return resolveMetadataPath(metadata, segments);
33
+ }
34
+ function resolveMetadataPath(metadata, segments) {
35
+ if (segments.length === 0) return true;
36
+ if (metadata.type === "richText" || metadata.type === "json") return true;
37
+ if (metadata.type === "object") {
38
+ const [fieldName, ...rest] = segments;
39
+ const nested = fieldName ? metadata.nestedFields?.[fieldName] : void 0;
40
+ return nested ? resolveMetadataPath(nested, rest) : false;
41
+ }
42
+ if (metadata.type === "array") {
43
+ const [first, ...rest] = segments;
44
+ const itemSegments = first && isArrayIndex(first) ? rest : segments;
45
+ if (itemSegments.length === 0) return true;
46
+ const [fieldName, ...fieldRest] = itemSegments;
47
+ const nested = fieldName ? metadata.nestedFields?.[fieldName] : void 0;
48
+ return nested ? resolveMetadataPath(nested, fieldRest) : false;
49
+ }
50
+ return false;
51
+ }
52
+ function resolveBlocksPath({ fieldName, segments, blocks, values, previousValues }) {
53
+ const [section, blockId, blockFieldName, ...rest] = segments;
54
+ if (section === "_tree") return true;
55
+ if (section !== "_values" || !blockId || !blockFieldName) return false;
56
+ const blockType = findBlockTypeById(readPath(values, `${fieldName}._tree`), blockId) ?? findBlockTypeById(readPath(previousValues, `${fieldName}._tree`), blockId);
57
+ if (!blockType) return false;
58
+ const blockField = blocks?.[blockType]?.fields?.[blockFieldName];
59
+ if (!blockField) return false;
60
+ return resolveMetadataPath(blockField.metadata, rest);
61
+ }
62
+ function findBlockTypeById(tree, blockId) {
63
+ if (!Array.isArray(tree)) return;
64
+ for (const node of tree) {
65
+ if (!node || typeof node !== "object") continue;
66
+ const record = node;
67
+ if (record.id === blockId && typeof record.type === "string") return record.type;
68
+ const childType = findBlockTypeById(record.children, blockId);
69
+ if (childType) return childType;
70
+ }
71
+ }
72
+ function readPath(value, path) {
73
+ let current = value;
74
+ for (const segment of path.split(".")) {
75
+ if (!current || typeof current !== "object") return;
76
+ current = current[segment];
77
+ }
78
+ return current;
79
+ }
80
+ function isArrayIndex(segment) {
81
+ return /^(0|[1-9]\d*)$/.test(segment);
82
+ }
83
+
84
+ //#endregion
85
+ export { resolveKnownPreviewPath };
@@ -139,7 +139,7 @@ function LoadingFallback() {
139
139
  className: "qp-flex qp-flex-col qp-items-center qp-gap-4",
140
140
  children: [/* @__PURE__ */ jsx("div", { className: "qp-h-8 qp-w-8 qp-animate-spin qp-rounded-full qp-border-4 qp-border-foreground qp-border-t-transparent" }), /* @__PURE__ */ jsx("span", {
141
141
  className: "qp-text-sm qp-text-muted-foreground",
142
- children: "Loading..."
142
+ children: "Loading"
143
143
  })]
144
144
  })
145
145
  });