@questpie/admin 3.5.2 → 3.5.4

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 (195) hide show
  1. package/README.md +8 -0
  2. package/dist/client/blocks/block-renderer.d.mts +2 -2
  3. package/dist/client/builder/index.d.mts +1 -1
  4. package/dist/client/builder/types/collection-types.d.mts +89 -5
  5. package/dist/client/builder/types/common.d.mts +5 -0
  6. package/dist/client/builder/types/field-types.d.mts +41 -1
  7. package/dist/client/builder/view/view.d.mts +3 -2
  8. package/dist/client/components/actions/action-dialog.mjs +5 -0
  9. package/dist/client/components/admin-link.d.mts +2 -2
  10. package/dist/client/components/fields/boolean-field.mjs +2 -1
  11. package/dist/client/components/fields/date-field.mjs +2 -1
  12. package/dist/client/components/fields/datetime-field.mjs +2 -1
  13. package/dist/client/components/fields/email-field.mjs +2 -1
  14. package/dist/client/components/fields/field-utils.d.mts +11 -0
  15. package/dist/client/components/fields/field-utils.mjs +3 -1
  16. package/dist/client/components/fields/field-wrapper.mjs +3 -3
  17. package/dist/client/components/fields/number-field.mjs +2 -1
  18. package/dist/client/components/fields/object-field.mjs +2 -1
  19. package/dist/client/components/fields/relation/displays/types.mjs +3 -3
  20. package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +7 -0
  21. package/dist/client/components/fields/rich-text-editor/extensions.mjs +19 -2
  22. package/dist/client/components/fields/rich-text-editor/image-popover.mjs +6 -2
  23. package/dist/client/components/fields/rich-text-editor/image-upload.mjs +2 -1
  24. package/dist/client/components/fields/rich-text-editor/index.d.mts +5 -3
  25. package/dist/client/components/fields/rich-text-editor/index.mjs +38 -76
  26. package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +30 -7
  27. package/dist/client/components/fields/rich-text-editor/toolbar.mjs +1 -312
  28. package/dist/client/components/fields/rich-text-editor/types.d.mts +4 -0
  29. package/dist/client/components/fields/rich-text-editor/types.mjs +1 -1
  30. package/dist/client/components/fields/rich-text-editor/utils.mjs +6 -12
  31. package/dist/client/components/fields/select-field.mjs +2 -1
  32. package/dist/client/components/fields/text-field.mjs +2 -1
  33. package/dist/client/components/fields/textarea-field.mjs +2 -1
  34. package/dist/client/components/fields/time-field.mjs +2 -1
  35. package/dist/client/components/filter-builder/filter-builder-sheet.mjs +75 -22
  36. package/dist/client/components/layout/field-layout-renderer.mjs +4 -4
  37. package/dist/client/components/media/media-grid.mjs +2 -1
  38. package/dist/client/components/primitives/asset-preview.mjs +4 -2
  39. package/dist/client/components/primitives/dropzone.d.mts +100 -0
  40. package/dist/client/components/primitives/field-select-control.mjs +2 -1
  41. package/dist/client/components/ui/button.d.mts +23 -0
  42. package/dist/client/components/ui/button.mjs +2 -2
  43. package/dist/client/components/ui/dropdown-menu.d.mts +49 -0
  44. package/dist/client/components/ui/dropdown-menu.mjs +7 -19
  45. package/dist/client/components/ui/popover.mjs +1 -1
  46. package/dist/client/components/ui/search-input.d.mts +56 -0
  47. package/dist/client/components/ui/select.mjs +2 -2
  48. package/dist/client/components/ui/sheet.d.mts +40 -0
  49. package/dist/client/components/ui/table.d.mts +49 -0
  50. package/dist/client/components/ui/table.mjs +15 -1
  51. package/dist/client/components/ui/tooltip.d.mts +21 -0
  52. package/dist/client/contexts/focus-context.d.mts +2 -2
  53. package/dist/client/hooks/query-access.d.mts +9 -0
  54. package/dist/client/hooks/query-access.mjs +20 -0
  55. package/dist/client/hooks/typed-hooks.d.mts +4 -2
  56. package/dist/client/hooks/typed-hooks.mjs +30 -29
  57. package/dist/client/hooks/use-admin-config.mjs +20 -1
  58. package/dist/client/hooks/use-autosave.mjs +91 -0
  59. package/dist/client/hooks/use-collection.mjs +65 -23
  60. package/dist/client/hooks/use-reactive-fields.d.mts +1 -0
  61. package/dist/client/hooks/use-reactive-fields.mjs +16 -1
  62. package/dist/client/hooks/use-server-actions.mjs +12 -1
  63. package/dist/client/hooks/use-upload.d.mts +40 -0
  64. package/dist/client/hooks/use-upload.mjs +4 -2
  65. package/dist/client/hooks/use-view-state.mjs +15 -7
  66. package/dist/client/i18n/hooks.d.mts +20 -0
  67. package/dist/client/lib/utils.d.mts +6 -0
  68. package/dist/client/lib/view-filter-utils.mjs +30 -0
  69. package/dist/client/preview/block-scope-context.d.mts +2 -2
  70. package/dist/client/preview/preview-banner.d.mts +2 -2
  71. package/dist/client/preview/preview-field.d.mts +4 -4
  72. package/dist/client/runtime/provider.mjs +22 -3
  73. package/dist/client/scope/picker.d.mts +2 -2
  74. package/dist/client/scope/provider.d.mts +2 -2
  75. package/dist/client/styles/base.css +75 -79
  76. package/dist/client/utils/asset-url.mjs +27 -0
  77. package/dist/client/utils/build-field-definitions-from-schema.mjs +1 -0
  78. package/dist/client/views/auth/accept-invite-form.d.mts +2 -2
  79. package/dist/client/views/auth/auth-layout.d.mts +3 -3
  80. package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
  81. package/dist/client/views/auth/login-form.d.mts +2 -2
  82. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  83. package/dist/client/views/auth/setup-form.d.mts +2 -2
  84. package/dist/client/views/collection/auto-form-fields.mjs +7 -6
  85. package/dist/client/views/collection/cells/primitive-cells.mjs +9 -6
  86. package/dist/client/views/collection/cells/shared/asset-thumbnail.d.mts +7 -0
  87. package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +3 -2
  88. package/dist/client/views/collection/cells/shared/cell-helpers.mjs +3 -2
  89. package/dist/client/views/collection/cells/upload-cells.mjs +2 -1
  90. package/dist/client/views/collection/columns/build-columns.mjs +3 -1
  91. package/dist/client/views/collection/document-view.d.mts +30 -0
  92. package/dist/client/views/collection/document-view.mjs +377 -0
  93. package/dist/client/views/collection/field-context.mjs +3 -2
  94. package/dist/client/views/collection/field-renderer.mjs +13 -5
  95. package/dist/client/views/collection/form-view.mjs +221 -282
  96. package/dist/client/views/collection/list-view.mjs +592 -190
  97. package/dist/client/views/collection/outline.mjs +44 -19
  98. package/dist/client/views/collection/quick-filter-bar.mjs +45 -0
  99. package/dist/client/views/collection/table-view.mjs +61 -17
  100. package/dist/client/views/globals/global-form-view.mjs +12 -9
  101. package/dist/client/views/layout/admin-layout-provider.mjs +4 -3
  102. package/dist/client/views/layout/admin-layout.mjs +108 -21
  103. package/dist/client/views/layout/admin-router.mjs +19 -3
  104. package/dist/client/views/layout/admin-sidebar.mjs +70 -20
  105. package/dist/client/views/layout/admin-theme.mjs +5 -4
  106. package/dist/client/views/layout/admin-view-layout.d.mts +36 -0
  107. package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
  108. package/dist/client/views/pages/dashboard-page.d.mts +2 -2
  109. package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
  110. package/dist/client/views/pages/invite-page.d.mts +2 -2
  111. package/dist/client/views/pages/login-page.d.mts +2 -2
  112. package/dist/client/views/pages/reset-password-page.d.mts +2 -2
  113. package/dist/client/views/pages/setup-page.d.mts +2 -2
  114. package/dist/client.d.mts +17 -2
  115. package/dist/client.mjs +17 -2
  116. package/dist/components/rich-text/rich-text-renderer.d.mts +5 -5
  117. package/dist/components/rich-text/rich-text-renderer.mjs +5 -2
  118. package/dist/factories.d.mts +4 -2
  119. package/dist/factories.mjs +2 -2
  120. package/dist/index.d.mts +17 -3
  121. package/dist/index.mjs +17 -2
  122. package/dist/modules/admin.d.mts +1 -1
  123. package/dist/server/adapters/index.d.mts +2 -0
  124. package/dist/server/adapters/nextjs.d.mts +1 -0
  125. package/dist/server/augmentation/actions.d.mts +9 -3
  126. package/dist/server/augmentation/dashboard.d.mts +11 -11
  127. package/dist/server/augmentation/form-layout.d.mts +16 -6
  128. package/dist/server/augmentation/index.d.mts +7 -0
  129. package/dist/server/augmentation/sidebar.d.mts +8 -8
  130. package/dist/server/augmentation/views.d.mts +4 -1
  131. package/dist/server/auth-helpers.d.mts +1 -0
  132. package/dist/server/codegen/admin-client-template.mjs +7 -6
  133. package/dist/server/fields/blocks.mjs +4 -1
  134. package/dist/server/fields/index.d.mts +1 -1
  135. package/dist/server/fields/reactive-runtime.mjs +3 -0
  136. package/dist/server/fields/rich-text.d.mts +16 -17
  137. package/dist/server/fields/rich-text.mjs +18 -7
  138. package/dist/server/i18n/messages/cs.mjs +2 -0
  139. package/dist/server/i18n/messages/de.mjs +2 -0
  140. package/dist/server/i18n/messages/en.mjs +4 -0
  141. package/dist/server/i18n/messages/es.mjs +2 -0
  142. package/dist/server/i18n/messages/fr.mjs +2 -0
  143. package/dist/server/i18n/messages/pl.mjs +2 -0
  144. package/dist/server/i18n/messages/pt.mjs +2 -0
  145. package/dist/server/i18n/messages/sk.mjs +2 -0
  146. package/dist/server/modules/admin/.generated/module.d.mts +1 -1
  147. package/dist/server/modules/admin/auth-helpers.mjs +7 -1
  148. package/dist/server/modules/admin/block/block-builder.d.mts +0 -8
  149. package/dist/server/modules/admin/block/introspection.d.mts +2 -2
  150. package/dist/server/modules/admin/block/introspection.mjs +28 -4
  151. package/dist/server/modules/admin/block/prefetch.d.mts +11 -0
  152. package/dist/server/modules/admin/block/prefetch.mjs +108 -27
  153. package/dist/server/modules/admin/client/.generated/module.d.mts +68 -67
  154. package/dist/server/modules/admin/client/.generated/module.mjs +2 -0
  155. package/dist/server/modules/admin/client/views/collection-document.d.mts +6 -0
  156. package/dist/server/modules/admin/client/views/collection-document.mjs +10 -0
  157. package/dist/server/modules/admin/collections/account.d.mts +53 -52
  158. package/dist/server/modules/admin/collections/admin-locks.d.mts +57 -56
  159. package/dist/server/modules/admin/collections/admin-preferences.d.mts +38 -37
  160. package/dist/server/modules/admin/collections/admin-saved-views.d.mts +50 -49
  161. package/dist/server/modules/admin/collections/apikey.d.mts +76 -67
  162. package/dist/server/modules/admin/collections/assets.d.mts +37 -36
  163. package/dist/server/modules/admin/collections/session.d.mts +42 -41
  164. package/dist/server/modules/admin/collections/user.d.mts +57 -56
  165. package/dist/server/modules/admin/collections/verification.d.mts +34 -33
  166. package/dist/server/modules/admin/dto/admin-config.dto.mjs +34 -4
  167. package/dist/server/modules/admin/factories.mjs +4 -34
  168. package/dist/server/modules/admin/index.d.mts +3 -3
  169. package/dist/server/modules/admin/routes/admin-config.d.mts +4 -2
  170. package/dist/server/modules/admin/routes/admin-config.mjs +56 -24
  171. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  172. package/dist/server/modules/admin/routes/execute-action.mjs +35 -9
  173. package/dist/server/modules/admin/routes/locales.mjs +1 -1
  174. package/dist/server/modules/admin/routes/preview.d.mts +11 -11
  175. package/dist/server/modules/admin/routes/preview.mjs +6 -5
  176. package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
  177. package/dist/server/modules/admin/routes/reactive.mjs +2 -2
  178. package/dist/server/modules/admin/routes/route-helpers.d.mts +11 -7
  179. package/dist/server/modules/admin/routes/route-helpers.mjs +1 -1
  180. package/dist/server/modules/admin/routes/setup.d.mts +7 -7
  181. package/dist/server/modules/admin/routes/translations.d.mts +4 -4
  182. package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
  183. package/dist/server/modules/admin/routes/widget-data.mjs +12 -4
  184. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +45 -45
  185. package/dist/server/modules/audit/.generated/module.d.mts +6 -6
  186. package/dist/server/modules/audit/collections/audit-log.d.mts +81 -80
  187. package/dist/server/modules/audit/jobs/audit-cleanup.d.mts +2 -2
  188. package/dist/server/plugin.mjs +10 -5
  189. package/dist/server/proxy-factories.d.mts +8 -1
  190. package/dist/server/proxy-factories.mjs +33 -1
  191. package/dist/server.d.mts +3 -1
  192. package/dist/shared/types/index.d.mts +1 -0
  193. package/dist/shared/types/saved-views.types.d.mts +14 -7
  194. package/dist/shared.d.mts +3 -2
  195. package/package.json +5 -4
@@ -0,0 +1,56 @@
1
+ import * as React from "react";
2
+
3
+ //#region src/client/components/ui/search-input.d.ts
4
+ interface SearchInputProps extends Omit<React.ComponentProps<"input">, "type"> {
5
+ /**
6
+ * Keyboard shortcut to display (e.g., "⌘K")
7
+ */
8
+ shortcut?: string;
9
+ /**
10
+ * Callback when clear button is clicked
11
+ */
12
+ onClear?: () => void;
13
+ /**
14
+ * Show loading spinner instead of search icon
15
+ */
16
+ isLoading?: boolean;
17
+ /**
18
+ * Additional className for the container
19
+ */
20
+ containerClassName?: string;
21
+ }
22
+ /**
23
+ * SearchInput - Consistent search input with icon, loading state, clear button, and keyboard shortcut
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * // Basic usage
28
+ * <SearchInput
29
+ * value={searchTerm}
30
+ * onChange={(e) => setSearchTerm(e.target.value)}
31
+ * onClear={() => setSearchTerm("")}
32
+ * placeholder="Search..."
33
+ * />
34
+ *
35
+ * // With keyboard shortcut
36
+ * <SearchInput
37
+ * shortcut="⌘K"
38
+ * onClick={openSearchDialog}
39
+ * readOnly
40
+ * />
41
+ *
42
+ * // Loading state
43
+ * <SearchInput isLoading={isSearching} ... />
44
+ * ```
45
+ */
46
+ declare function SearchInput({
47
+ shortcut,
48
+ onClear,
49
+ isLoading,
50
+ containerClassName,
51
+ className,
52
+ value,
53
+ ...props
54
+ }: SearchInputProps): React.ReactElement;
55
+ //#endregion
56
+ export { SearchInput };
@@ -10,7 +10,7 @@ const Select$1 = Select.Root;
10
10
  function SelectGroup({ className, ...props }) {
11
11
  return /* @__PURE__ */ jsx(Select.Group, {
12
12
  "data-slot": "select-group",
13
- className: cn("qa-select__group scroll-my-1 p-1", className),
13
+ className: cn("qa-select__group scroll-my-1 p-0", className),
14
14
  ...props
15
15
  });
16
16
  }
@@ -44,7 +44,7 @@ function SelectContent({ className, children, side = "bottom", sideOffset = 4, a
44
44
  className: "isolate z-50",
45
45
  children: /* @__PURE__ */ jsxs(Select.Popup, {
46
46
  "data-slot": "select-content",
47
- className: cn("qa-select__content floating-surface motion-floating text-popover-foreground relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto data-ending-style:scale-[var(--motion-scale-enter)] data-ending-style:opacity-0 data-starting-style:scale-[var(--motion-scale-enter)] data-starting-style:opacity-0", className),
47
+ className: cn("qa-select__content floating-surface motion-floating text-popover-foreground relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto p-1 data-ending-style:scale-[var(--motion-scale-enter)] data-ending-style:opacity-0 data-starting-style:scale-[var(--motion-scale-enter)] data-starting-style:opacity-0", className),
48
48
  ...props,
49
49
  children: [
50
50
  /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
@@ -0,0 +1,40 @@
1
+ import * as React from "react";
2
+ import * as react_jsx_runtime27 from "react/jsx-runtime";
3
+ import { Dialog } from "@base-ui/react/dialog";
4
+
5
+ //#region src/client/components/ui/sheet.d.ts
6
+ declare function Sheet({
7
+ ...props
8
+ }: Dialog.Root.Props): react_jsx_runtime27.JSX.Element;
9
+ declare function SheetContent({
10
+ className,
11
+ children,
12
+ side,
13
+ showCloseButton,
14
+ animated,
15
+ showOverlay,
16
+ ...props
17
+ }: Dialog.Popup.Props & {
18
+ side?: "top" | "right" | "bottom" | "left";
19
+ showCloseButton?: boolean;
20
+ animated?: boolean;
21
+ showOverlay?: boolean;
22
+ }): react_jsx_runtime27.JSX.Element;
23
+ declare function SheetHeader({
24
+ className,
25
+ ...props
26
+ }: React.ComponentProps<"div">): react_jsx_runtime27.JSX.Element;
27
+ declare function SheetFooter({
28
+ className,
29
+ ...props
30
+ }: React.ComponentProps<"div">): react_jsx_runtime27.JSX.Element;
31
+ declare function SheetTitle({
32
+ className,
33
+ ...props
34
+ }: Dialog.Title.Props): react_jsx_runtime27.JSX.Element;
35
+ declare function SheetDescription({
36
+ className,
37
+ ...props
38
+ }: Dialog.Description.Props): react_jsx_runtime27.JSX.Element;
39
+ //#endregion
40
+ export { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle };
@@ -0,0 +1,49 @@
1
+ import * as React from "react";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
+
4
+ //#region src/client/components/ui/table.d.ts
5
+ declare function Table({
6
+ className,
7
+ ...props
8
+ }: React.ComponentProps<"table">): react_jsx_runtime0.JSX.Element;
9
+ declare function TableHeader({
10
+ className,
11
+ ...props
12
+ }: React.ComponentProps<"thead">): react_jsx_runtime0.JSX.Element;
13
+ declare function TableBody({
14
+ className,
15
+ ...props
16
+ }: React.ComponentProps<"tbody">): react_jsx_runtime0.JSX.Element;
17
+ declare function TableFooter({
18
+ className,
19
+ ...props
20
+ }: React.ComponentProps<"tfoot">): react_jsx_runtime0.JSX.Element;
21
+ declare const TableRow: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLTableRowElement>, HTMLTableRowElement>, "ref"> & React.RefAttributes<HTMLTableRowElement>>;
22
+ interface TableHeadProps extends React.ComponentProps<"th"> {
23
+ stickyLeft?: number;
24
+ showStickyBorder?: boolean;
25
+ }
26
+ declare function TableHead({
27
+ className,
28
+ stickyLeft,
29
+ showStickyBorder,
30
+ style,
31
+ ...props
32
+ }: TableHeadProps): react_jsx_runtime0.JSX.Element;
33
+ interface TableCellProps extends React.ComponentProps<"td"> {
34
+ stickyLeft?: number;
35
+ showStickyBorder?: boolean;
36
+ }
37
+ declare function TableCell({
38
+ className,
39
+ stickyLeft,
40
+ showStickyBorder,
41
+ style,
42
+ ...props
43
+ }: TableCellProps): react_jsx_runtime0.JSX.Element;
44
+ declare function TableCaption({
45
+ className,
46
+ ...props
47
+ }: React.ComponentProps<"caption">): react_jsx_runtime0.JSX.Element;
48
+ //#endregion
49
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
@@ -28,6 +28,13 @@ function TableBody({ className, ...props }) {
28
28
  ...props
29
29
  });
30
30
  }
31
+ function TableFooter({ className, ...props }) {
32
+ return /* @__PURE__ */ jsx("tfoot", {
33
+ "data-slot": "table-footer",
34
+ className: cn("qa-table__footer bg-background font-medium", className),
35
+ ...props
36
+ });
37
+ }
31
38
  const TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tr", {
32
39
  ref,
33
40
  "data-slot": "table-row",
@@ -61,6 +68,13 @@ function TableCell({ className, stickyLeft, showStickyBorder, style, ...props })
61
68
  ...props
62
69
  });
63
70
  }
71
+ function TableCaption({ className, ...props }) {
72
+ return /* @__PURE__ */ jsx("caption", {
73
+ "data-slot": "table-caption",
74
+ className: cn("qa-table__caption text-muted-foreground mt-4 text-xs", className),
75
+ ...props
76
+ });
77
+ }
64
78
 
65
79
  //#endregion
66
- export { Table, TableBody, TableCell, TableHead, TableHeader, TableRow };
80
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
@@ -0,0 +1,21 @@
1
+ import * as react_jsx_runtime21 from "react/jsx-runtime";
2
+ import { Tooltip } from "@base-ui/react/tooltip";
3
+
4
+ //#region src/client/components/ui/tooltip.d.ts
5
+ declare function Tooltip$1({
6
+ ...props
7
+ }: Tooltip.Root.Props): react_jsx_runtime21.JSX.Element;
8
+ declare function TooltipTrigger({
9
+ ...props
10
+ }: Tooltip.Trigger.Props): react_jsx_runtime21.JSX.Element;
11
+ declare function TooltipContent({
12
+ className,
13
+ side,
14
+ sideOffset,
15
+ align,
16
+ alignOffset,
17
+ children,
18
+ ...props
19
+ }: Tooltip.Popup.Props & Pick<Tooltip.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset">): react_jsx_runtime21.JSX.Element;
20
+ //#endregion
21
+ export { Tooltip$1 as Tooltip, TooltipContent, TooltipTrigger };
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as react_jsx_runtime16 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime50 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/client/contexts/focus-context.d.ts
5
5
 
@@ -59,7 +59,7 @@ type FocusProviderProps = {
59
59
  declare function FocusProvider({
60
60
  children,
61
61
  onFocusChange
62
- }: FocusProviderProps): react_jsx_runtime16.JSX.Element;
62
+ }: FocusProviderProps): react_jsx_runtime50.JSX.Element;
63
63
  /**
64
64
  * Use the focus context
65
65
  */
@@ -0,0 +1,9 @@
1
+ import "../builder/registry.mjs";
2
+ import { QuestpieQueryOptionsProxy } from "@questpie/tanstack-query";
3
+ import { QuestpieApp, QuestpieClient } from "questpie/client";
4
+
5
+ //#region src/client/hooks/query-access.d.ts
6
+
7
+ type CollectionQueryKey<TApp extends QuestpieApp> = keyof QuestpieQueryOptionsProxy<TApp>["collections"] & string;
8
+ //#endregion
9
+ export { CollectionQueryKey };
@@ -0,0 +1,20 @@
1
+ import { selectClient, useAdminStore } from "../runtime/provider.mjs";
2
+
3
+ //#region src/client/hooks/query-access.ts
4
+ /** Single intentional cast site for dynamic collection names in views. */
5
+ function adminCollectionKey(name) {
6
+ return name;
7
+ }
8
+ function getCollectionQueryApi(queryOpts, collection) {
9
+ return queryOpts.collections[collection];
10
+ }
11
+ function getGlobalQueryApi(queryOpts, globalName) {
12
+ return queryOpts.globals[globalName];
13
+ }
14
+ /** Typed app client from admin store (factory hooks with explicit TApp). */
15
+ function useAppClient() {
16
+ return useAdminStore(selectClient);
17
+ }
18
+
19
+ //#endregion
20
+ export { adminCollectionKey, getCollectionQueryApi, getGlobalQueryApi, useAppClient };
@@ -1,4 +1,6 @@
1
+ import { CollectionQueryKey } from "./query-access.mjs";
1
2
  import { UseMutationOptions, UseQueryOptions } from "@tanstack/react-query";
3
+ import { QuestpieQueryOptionsProxy } from "@questpie/tanstack-query";
2
4
  import { QuestpieApp } from "questpie/client";
3
5
 
4
6
  //#region src/client/hooks/typed-hooks.d.ts
@@ -6,11 +8,11 @@ import { QuestpieApp } from "questpie/client";
6
8
  /**
7
9
  * Extract collection names from a QuestpieApp config
8
10
  */
9
- type CollectionNames<TApp extends QuestpieApp> = keyof TApp["collections"] & string;
11
+ type CollectionNames<TApp extends QuestpieApp> = CollectionQueryKey<TApp>;
10
12
  /**
11
13
  * Extract global names from a QuestpieApp config
12
14
  */
13
- type GlobalNames<TApp extends QuestpieApp> = keyof NonNullable<TApp["globals"]> & string;
15
+ type GlobalNames<TApp extends QuestpieApp> = keyof QuestpieQueryOptionsProxy<TApp>["globals"] & string;
14
16
  interface TypedHooks<TApp extends QuestpieApp> {
15
17
  /**
16
18
  * Hook to fetch collection list with filters, sorting, pagination
@@ -1,5 +1,6 @@
1
- import { selectClient, selectContentLocale, useAdminStore } from "../runtime/provider.mjs";
1
+ import { selectContentLocale, useAdminStore } from "../runtime/provider.mjs";
2
2
  import { useScopedLocale } from "../runtime/locale-scope.mjs";
3
+ import { getCollectionQueryApi, getGlobalQueryApi, useAppClient } from "./query-access.mjs";
3
4
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
4
5
  import { createQuestpieQueryOptions } from "@questpie/tanstack-query";
5
6
 
@@ -57,14 +58,14 @@ import { createQuestpieQueryOptions } from "@questpie/tanstack-query";
57
58
  */
58
59
  function createTypedHooks() {
59
60
  function useCollectionList(collection, options, queryOptions) {
60
- const client = useAdminStore(selectClient);
61
+ const client = useAppClient();
61
62
  const { locale: contentLocale } = useScopedLocale();
62
63
  const queryOpts = createQuestpieQueryOptions(client, {
63
64
  keyPrefix: ["questpie", "collections"],
64
65
  locale: contentLocale
65
66
  });
66
67
  return useQuery({
67
- ...collection ? queryOpts.collections[collection].find({
68
+ ...collection ? getCollectionQueryApi(queryOpts, collection).find({
68
69
  ...options,
69
70
  locale: contentLocale
70
71
  }) : {
@@ -84,14 +85,14 @@ function createTypedHooks() {
84
85
  });
85
86
  }
86
87
  function useCollectionCount(collection, options, queryOptions) {
87
- const client = useAdminStore(selectClient);
88
+ const client = useAppClient();
88
89
  const { locale: contentLocale } = useScopedLocale();
89
90
  const queryOpts = createQuestpieQueryOptions(client, {
90
91
  keyPrefix: ["questpie", "collections"],
91
92
  locale: contentLocale
92
93
  });
93
94
  return useQuery({
94
- ...collection ? queryOpts.collections[collection].count({
95
+ ...collection ? getCollectionQueryApi(queryOpts, collection).count({
95
96
  ...options,
96
97
  locale: contentLocale
97
98
  }) : {
@@ -108,14 +109,14 @@ function createTypedHooks() {
108
109
  });
109
110
  }
110
111
  function useCollectionItem(collection, id, options, queryOptions) {
111
- const client = useAdminStore(selectClient);
112
+ const client = useAppClient();
112
113
  const { locale: contentLocale } = useScopedLocale();
113
114
  const queryOpts = createQuestpieQueryOptions(client, {
114
115
  keyPrefix: ["questpie", "collections"],
115
116
  locale: contentLocale
116
117
  });
117
118
  return useQuery({
118
- ...collection ? queryOpts.collections[collection].findOne({
119
+ ...collection ? getCollectionQueryApi(queryOpts, collection).findOne({
119
120
  where: { id },
120
121
  locale: contentLocale,
121
122
  ...options
@@ -133,14 +134,14 @@ function createTypedHooks() {
133
134
  });
134
135
  }
135
136
  function useCollectionCreate(collection, mutationOptions) {
136
- const client = useAdminStore(selectClient);
137
+ const client = useAppClient();
137
138
  const { locale: contentLocale } = useScopedLocale();
138
139
  const queryClient = useQueryClient();
139
140
  const queryOpts = createQuestpieQueryOptions(client, {
140
141
  keyPrefix: ["questpie", "collections"],
141
142
  locale: contentLocale
142
143
  });
143
- const baseOptions = queryOpts.collections[collection].create();
144
+ const baseOptions = getCollectionQueryApi(queryOpts, collection).create();
144
145
  const listQueryKey = queryOpts.key([
145
146
  "collections",
146
147
  collection,
@@ -167,14 +168,14 @@ function createTypedHooks() {
167
168
  });
168
169
  }
169
170
  function useCollectionUpdate(collection, mutationOptions) {
170
- const client = useAdminStore(selectClient);
171
+ const client = useAppClient();
171
172
  const { locale: contentLocale } = useScopedLocale();
172
173
  const queryClient = useQueryClient();
173
174
  const queryOpts = createQuestpieQueryOptions(client, {
174
175
  keyPrefix: ["questpie", "collections"],
175
176
  locale: contentLocale
176
177
  });
177
- const baseOptions = queryOpts.collections[collection].update();
178
+ const baseOptions = getCollectionQueryApi(queryOpts, collection).update();
178
179
  const listQueryKey = queryOpts.key([
179
180
  "collections",
180
181
  collection,
@@ -208,14 +209,14 @@ function createTypedHooks() {
208
209
  });
209
210
  }
210
211
  function useCollectionDelete(collection, mutationOptions) {
211
- const client = useAdminStore(selectClient);
212
+ const client = useAppClient();
212
213
  const { locale: contentLocale } = useScopedLocale();
213
214
  const queryClient = useQueryClient();
214
215
  const queryOpts = createQuestpieQueryOptions(client, {
215
216
  keyPrefix: ["questpie", "collections"],
216
217
  locale: contentLocale
217
218
  });
218
- const baseOptions = queryOpts.collections[collection].delete();
219
+ const baseOptions = getCollectionQueryApi(queryOpts, collection).delete();
219
220
  const listQueryKey = queryOpts.key([
220
221
  "collections",
221
222
  collection,
@@ -249,14 +250,14 @@ function createTypedHooks() {
249
250
  });
250
251
  }
251
252
  function useCollectionRestore(collection, mutationOptions) {
252
- const client = useAdminStore(selectClient);
253
+ const client = useAppClient();
253
254
  const { locale: contentLocale } = useScopedLocale();
254
255
  const queryClient = useQueryClient();
255
256
  const queryOpts = createQuestpieQueryOptions(client, {
256
257
  keyPrefix: ["questpie", "collections"],
257
258
  locale: contentLocale
258
259
  });
259
- const baseOptions = queryOpts.collections[collection].restore();
260
+ const baseOptions = getCollectionQueryApi(queryOpts, collection).restore();
260
261
  const listQueryKey = queryOpts.key([
261
262
  "collections",
262
263
  collection,
@@ -290,14 +291,14 @@ function createTypedHooks() {
290
291
  });
291
292
  }
292
293
  function useCollectionVersions(collection, id, options, queryOptions) {
293
- const client = useAdminStore(selectClient);
294
+ const client = useAppClient();
294
295
  const { locale: contentLocale } = useScopedLocale();
295
296
  const queryOpts = createQuestpieQueryOptions(client, {
296
297
  keyPrefix: ["questpie", "collections"],
297
298
  locale: contentLocale
298
299
  });
299
300
  return useQuery({
300
- ...collection ? queryOpts.collections[collection].findVersions({
301
+ ...collection ? getCollectionQueryApi(queryOpts, collection).findVersions({
301
302
  id,
302
303
  ...options?.limit !== void 0 ? { limit: options.limit } : {},
303
304
  ...options?.offset !== void 0 ? { offset: options.offset } : {}
@@ -318,14 +319,14 @@ function createTypedHooks() {
318
319
  });
319
320
  }
320
321
  function useCollectionRevertVersion(collection, mutationOptions) {
321
- const client = useAdminStore(selectClient);
322
+ const client = useAppClient();
322
323
  const { locale: contentLocale } = useScopedLocale();
323
324
  const queryClient = useQueryClient();
324
325
  const queryOpts = createQuestpieQueryOptions(client, {
325
326
  keyPrefix: ["questpie", "collections"],
326
327
  locale: contentLocale
327
328
  });
328
- const baseOptions = queryOpts.collections[collection].revertToVersion();
329
+ const baseOptions = getCollectionQueryApi(queryOpts, collection).revertToVersion();
329
330
  const listQueryKey = queryOpts.key([
330
331
  "collections",
331
332
  collection,
@@ -366,13 +367,13 @@ function createTypedHooks() {
366
367
  });
367
368
  }
368
369
  function useGlobal(globalName, options, queryOptions) {
369
- const client = useAdminStore(selectClient);
370
+ const client = useAppClient();
370
371
  const contentLocale = useAdminStore(selectContentLocale);
371
372
  return useQuery({
372
- ...createQuestpieQueryOptions(client, {
373
+ ...getGlobalQueryApi(createQuestpieQueryOptions(client, {
373
374
  keyPrefix: ["questpie", "globals"],
374
375
  locale: contentLocale
375
- }).globals[globalName].get({
376
+ }), globalName).get({
376
377
  ...options,
377
378
  locale: contentLocale
378
379
  }),
@@ -380,7 +381,7 @@ function createTypedHooks() {
380
381
  });
381
382
  }
382
383
  function useGlobalUpdate(globalName, mutationOptions) {
383
- const client = useAdminStore(selectClient);
384
+ const client = useAppClient();
384
385
  const contentLocale = useAdminStore(selectContentLocale);
385
386
  const queryClient = useQueryClient();
386
387
  const queryOpts = createQuestpieQueryOptions(client, {
@@ -394,7 +395,7 @@ function createTypedHooks() {
394
395
  contentLocale
395
396
  ]);
396
397
  return useMutation({
397
- ...queryOpts.globals[globalName].update(),
398
+ ...getGlobalQueryApi(queryOpts, globalName).update(),
398
399
  onSuccess: (data, variables, context) => {
399
400
  (mutationOptions?.onSuccess)?.(data, variables, context);
400
401
  },
@@ -406,13 +407,13 @@ function createTypedHooks() {
406
407
  });
407
408
  }
408
409
  function useGlobalVersions(globalName, options, queryOptions) {
409
- const client = useAdminStore(selectClient);
410
+ const client = useAppClient();
410
411
  const contentLocale = useAdminStore(selectContentLocale);
411
412
  return useQuery({
412
- ...createQuestpieQueryOptions(client, {
413
+ ...getGlobalQueryApi(createQuestpieQueryOptions(client, {
413
414
  keyPrefix: ["questpie", "globals"],
414
415
  locale: contentLocale
415
- }).globals[globalName].findVersions({
416
+ }), globalName).findVersions({
416
417
  ...options,
417
418
  locale: contentLocale
418
419
  }),
@@ -420,7 +421,7 @@ function createTypedHooks() {
420
421
  });
421
422
  }
422
423
  function useGlobalRevertVersion(globalName, mutationOptions) {
423
- const client = useAdminStore(selectClient);
424
+ const client = useAppClient();
424
425
  const contentLocale = useAdminStore(selectContentLocale);
425
426
  const queryClient = useQueryClient();
426
427
  const queryOpts = createQuestpieQueryOptions(client, {
@@ -440,7 +441,7 @@ function createTypedHooks() {
440
441
  contentLocale
441
442
  ]);
442
443
  return useMutation({
443
- ...queryOpts.globals[globalName].revertToVersion(),
444
+ ...getGlobalQueryApi(queryOpts, globalName).revertToVersion(),
444
445
  onSuccess: (data, variables, context) => {
445
446
  (mutationOptions?.onSuccess)?.(data, variables, context);
446
447
  },
@@ -11,6 +11,11 @@ const adminConfigQueryKey = [
11
11
  "admin",
12
12
  "config"
13
13
  ];
14
+ const publicAdminConfigQueryKey = [
15
+ "questpie",
16
+ "admin",
17
+ "public-config"
18
+ ];
14
19
  /** Query options factory for admin config — can be used for prefetching in loaders */
15
20
  function getAdminConfigQueryOptions(client) {
16
21
  return {
@@ -23,6 +28,20 @@ function getAdminConfigQueryOptions(client) {
23
28
  gcTime: 1800 * 1e3
24
29
  };
25
30
  }
31
+ /** Query options for auth-page-safe public branding/bootstrap config. */
32
+ function getPublicAdminConfigQueryOptions(client) {
33
+ return {
34
+ queryKey: publicAdminConfigQueryKey,
35
+ queryFn: async () => {
36
+ if (!client || !client.routes) return {};
37
+ const routes = client.routes;
38
+ if (typeof routes.getPublicAdminConfig === "function") return routes.getPublicAdminConfig();
39
+ return {};
40
+ },
41
+ staleTime: 300 * 1e3,
42
+ gcTime: 1800 * 1e3
43
+ };
44
+ }
26
45
  /** Standard query hook - returns loading/error states */
27
46
  function useAdminConfig(queryOptions) {
28
47
  return useQuery({
@@ -36,4 +55,4 @@ function useSuspenseAdminConfig() {
36
55
  }
37
56
 
38
57
  //#endregion
39
- export { getAdminConfigQueryOptions, useAdminConfig, useSuspenseAdminConfig };
58
+ export { getAdminConfigQueryOptions, getPublicAdminConfigQueryOptions, useAdminConfig, useSuspenseAdminConfig };
@@ -0,0 +1,91 @@
1
+ import { useTranslation } from "../i18n/hooks.mjs";
2
+ import * as React from "react";
3
+ import { toast } from "sonner";
4
+
5
+ //#region src/client/hooks/use-autosave.ts
6
+ /**
7
+ * useAutosave — engine-agnostic debounced autosave for react-hook-form views.
8
+ *
9
+ * Extracted from the form view's `AutosaveManager`. The save pipeline
10
+ * (`runAutosave`) is unchanged — it guards on dirty/submitting, submits via the
11
+ * form, resets to the server result, and reports save state.
12
+ *
13
+ * The trigger is driven by `form.subscribe({ formState: { values: true } })`
14
+ * (the same value-subscription `PreviewPatchBridge` uses) rather than DOM
15
+ * `input`/`change` listeners. That makes it engine-agnostic: it catches native
16
+ * input edits AND programmatic `field.onChange` emissions (e.g. the TipTap
17
+ * rich-text field, whose contenteditable does not fire bubbling DOM events).
18
+ *
19
+ * Both the form view and the document view consume this hook so they share one
20
+ * autosave code path.
21
+ */
22
+ /**
23
+ * Wire debounced autosave onto a form. Returns the imperative `runAutosave`
24
+ * callback so callers can also flush manually if needed.
25
+ */
26
+ function useAutosave({ form, id, enabled, debounce, isDirtyRef, isSubmittingRef, updateMutation, onPreviewCommit, onPreviewRefresh, onSavingChange, onSaved }) {
27
+ const { t } = useTranslation();
28
+ const timerRef = React.useRef(null);
29
+ const runAutosave = React.useCallback(async () => {
30
+ if (!id || !isDirtyRef.current || isSubmittingRef.current) return;
31
+ try {
32
+ onSavingChange(true);
33
+ await form.handleSubmit(async (data) => {
34
+ const result = await updateMutation.mutateAsync({
35
+ id,
36
+ data
37
+ });
38
+ form.reset(result, { keepTouched: true });
39
+ onPreviewCommit?.(result);
40
+ onPreviewRefresh?.();
41
+ onSaved(/* @__PURE__ */ new Date());
42
+ onSavingChange(false);
43
+ }, () => {
44
+ onSavingChange(false);
45
+ })();
46
+ } catch (error) {
47
+ onSavingChange(false);
48
+ console.error("Autosave failed:", error);
49
+ toast.error(t("error.autosaveFailed"), { description: error instanceof Error ? error.message : void 0 });
50
+ }
51
+ }, [
52
+ form,
53
+ id,
54
+ isDirtyRef,
55
+ isSubmittingRef,
56
+ onSaved,
57
+ onSavingChange,
58
+ onPreviewCommit,
59
+ onPreviewRefresh,
60
+ t,
61
+ updateMutation
62
+ ]);
63
+ React.useEffect(() => {
64
+ if (timerRef.current) clearTimeout(timerRef.current);
65
+ if (!enabled || !id) return;
66
+ const scheduleAutosave = () => {
67
+ if (timerRef.current) clearTimeout(timerRef.current);
68
+ timerRef.current = setTimeout(() => {
69
+ runAutosave();
70
+ }, debounce);
71
+ };
72
+ const unsubscribe = form.subscribe({
73
+ formState: { values: true },
74
+ callback: scheduleAutosave
75
+ });
76
+ return () => {
77
+ unsubscribe();
78
+ if (timerRef.current) clearTimeout(timerRef.current);
79
+ };
80
+ }, [
81
+ debounce,
82
+ enabled,
83
+ form,
84
+ id,
85
+ runAutosave
86
+ ]);
87
+ return runAutosave;
88
+ }
89
+
90
+ //#endregion
91
+ export { useAutosave };