@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.
- package/README.md +8 -0
- package/dist/client/blocks/block-renderer.d.mts +2 -2
- package/dist/client/builder/index.d.mts +1 -1
- package/dist/client/builder/types/collection-types.d.mts +89 -5
- package/dist/client/builder/types/common.d.mts +5 -0
- package/dist/client/builder/types/field-types.d.mts +41 -1
- package/dist/client/builder/view/view.d.mts +3 -2
- package/dist/client/components/actions/action-dialog.mjs +5 -0
- package/dist/client/components/admin-link.d.mts +2 -2
- package/dist/client/components/fields/boolean-field.mjs +2 -1
- package/dist/client/components/fields/date-field.mjs +2 -1
- package/dist/client/components/fields/datetime-field.mjs +2 -1
- package/dist/client/components/fields/email-field.mjs +2 -1
- package/dist/client/components/fields/field-utils.d.mts +11 -0
- package/dist/client/components/fields/field-utils.mjs +3 -1
- package/dist/client/components/fields/field-wrapper.mjs +3 -3
- package/dist/client/components/fields/number-field.mjs +2 -1
- package/dist/client/components/fields/object-field.mjs +2 -1
- package/dist/client/components/fields/relation/displays/types.mjs +3 -3
- package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +7 -0
- package/dist/client/components/fields/rich-text-editor/extensions.mjs +19 -2
- package/dist/client/components/fields/rich-text-editor/image-popover.mjs +6 -2
- package/dist/client/components/fields/rich-text-editor/image-upload.mjs +2 -1
- package/dist/client/components/fields/rich-text-editor/index.d.mts +5 -3
- package/dist/client/components/fields/rich-text-editor/index.mjs +38 -76
- package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +30 -7
- package/dist/client/components/fields/rich-text-editor/toolbar.mjs +1 -312
- package/dist/client/components/fields/rich-text-editor/types.d.mts +4 -0
- package/dist/client/components/fields/rich-text-editor/types.mjs +1 -1
- package/dist/client/components/fields/rich-text-editor/utils.mjs +6 -12
- package/dist/client/components/fields/select-field.mjs +2 -1
- package/dist/client/components/fields/text-field.mjs +2 -1
- package/dist/client/components/fields/textarea-field.mjs +2 -1
- package/dist/client/components/fields/time-field.mjs +2 -1
- package/dist/client/components/filter-builder/filter-builder-sheet.mjs +75 -22
- package/dist/client/components/layout/field-layout-renderer.mjs +4 -4
- package/dist/client/components/media/media-grid.mjs +2 -1
- package/dist/client/components/primitives/asset-preview.mjs +4 -2
- package/dist/client/components/primitives/dropzone.d.mts +100 -0
- package/dist/client/components/primitives/field-select-control.mjs +2 -1
- package/dist/client/components/ui/button.d.mts +23 -0
- package/dist/client/components/ui/button.mjs +2 -2
- package/dist/client/components/ui/dropdown-menu.d.mts +49 -0
- package/dist/client/components/ui/dropdown-menu.mjs +7 -19
- package/dist/client/components/ui/popover.mjs +1 -1
- package/dist/client/components/ui/search-input.d.mts +56 -0
- package/dist/client/components/ui/select.mjs +2 -2
- package/dist/client/components/ui/sheet.d.mts +40 -0
- package/dist/client/components/ui/table.d.mts +49 -0
- package/dist/client/components/ui/table.mjs +15 -1
- package/dist/client/components/ui/tooltip.d.mts +21 -0
- package/dist/client/contexts/focus-context.d.mts +2 -2
- package/dist/client/hooks/query-access.d.mts +9 -0
- package/dist/client/hooks/query-access.mjs +20 -0
- package/dist/client/hooks/typed-hooks.d.mts +4 -2
- package/dist/client/hooks/typed-hooks.mjs +30 -29
- package/dist/client/hooks/use-admin-config.mjs +20 -1
- package/dist/client/hooks/use-autosave.mjs +91 -0
- package/dist/client/hooks/use-collection.mjs +65 -23
- package/dist/client/hooks/use-reactive-fields.d.mts +1 -0
- package/dist/client/hooks/use-reactive-fields.mjs +16 -1
- package/dist/client/hooks/use-server-actions.mjs +12 -1
- package/dist/client/hooks/use-upload.d.mts +40 -0
- package/dist/client/hooks/use-upload.mjs +4 -2
- package/dist/client/hooks/use-view-state.mjs +15 -7
- package/dist/client/i18n/hooks.d.mts +20 -0
- package/dist/client/lib/utils.d.mts +6 -0
- package/dist/client/lib/view-filter-utils.mjs +30 -0
- package/dist/client/preview/block-scope-context.d.mts +2 -2
- package/dist/client/preview/preview-banner.d.mts +2 -2
- package/dist/client/preview/preview-field.d.mts +4 -4
- package/dist/client/runtime/provider.mjs +22 -3
- package/dist/client/scope/picker.d.mts +2 -2
- package/dist/client/scope/provider.d.mts +2 -2
- package/dist/client/styles/base.css +75 -79
- package/dist/client/utils/asset-url.mjs +27 -0
- package/dist/client/utils/build-field-definitions-from-schema.mjs +1 -0
- package/dist/client/views/auth/accept-invite-form.d.mts +2 -2
- package/dist/client/views/auth/auth-layout.d.mts +3 -3
- package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
- package/dist/client/views/auth/login-form.d.mts +2 -2
- package/dist/client/views/auth/reset-password-form.d.mts +2 -2
- package/dist/client/views/auth/setup-form.d.mts +2 -2
- package/dist/client/views/collection/auto-form-fields.mjs +7 -6
- package/dist/client/views/collection/cells/primitive-cells.mjs +9 -6
- package/dist/client/views/collection/cells/shared/asset-thumbnail.d.mts +7 -0
- package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +3 -2
- package/dist/client/views/collection/cells/shared/cell-helpers.mjs +3 -2
- package/dist/client/views/collection/cells/upload-cells.mjs +2 -1
- package/dist/client/views/collection/columns/build-columns.mjs +3 -1
- package/dist/client/views/collection/document-view.d.mts +30 -0
- package/dist/client/views/collection/document-view.mjs +377 -0
- package/dist/client/views/collection/field-context.mjs +3 -2
- package/dist/client/views/collection/field-renderer.mjs +13 -5
- package/dist/client/views/collection/form-view.mjs +221 -282
- package/dist/client/views/collection/list-view.mjs +592 -190
- package/dist/client/views/collection/outline.mjs +44 -19
- package/dist/client/views/collection/quick-filter-bar.mjs +45 -0
- package/dist/client/views/collection/table-view.mjs +61 -17
- package/dist/client/views/globals/global-form-view.mjs +12 -9
- package/dist/client/views/layout/admin-layout-provider.mjs +4 -3
- package/dist/client/views/layout/admin-layout.mjs +108 -21
- package/dist/client/views/layout/admin-router.mjs +19 -3
- package/dist/client/views/layout/admin-sidebar.mjs +70 -20
- package/dist/client/views/layout/admin-theme.mjs +5 -4
- package/dist/client/views/layout/admin-view-layout.d.mts +36 -0
- package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
- package/dist/client/views/pages/dashboard-page.d.mts +2 -2
- package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
- package/dist/client/views/pages/invite-page.d.mts +2 -2
- package/dist/client/views/pages/login-page.d.mts +2 -2
- package/dist/client/views/pages/reset-password-page.d.mts +2 -2
- package/dist/client/views/pages/setup-page.d.mts +2 -2
- package/dist/client.d.mts +17 -2
- package/dist/client.mjs +17 -2
- package/dist/components/rich-text/rich-text-renderer.d.mts +5 -5
- package/dist/components/rich-text/rich-text-renderer.mjs +5 -2
- package/dist/factories.d.mts +4 -2
- package/dist/factories.mjs +2 -2
- package/dist/index.d.mts +17 -3
- package/dist/index.mjs +17 -2
- package/dist/modules/admin.d.mts +1 -1
- package/dist/server/adapters/index.d.mts +2 -0
- package/dist/server/adapters/nextjs.d.mts +1 -0
- package/dist/server/augmentation/actions.d.mts +9 -3
- package/dist/server/augmentation/dashboard.d.mts +11 -11
- package/dist/server/augmentation/form-layout.d.mts +16 -6
- package/dist/server/augmentation/index.d.mts +7 -0
- package/dist/server/augmentation/sidebar.d.mts +8 -8
- package/dist/server/augmentation/views.d.mts +4 -1
- package/dist/server/auth-helpers.d.mts +1 -0
- package/dist/server/codegen/admin-client-template.mjs +7 -6
- package/dist/server/fields/blocks.mjs +4 -1
- package/dist/server/fields/index.d.mts +1 -1
- package/dist/server/fields/reactive-runtime.mjs +3 -0
- package/dist/server/fields/rich-text.d.mts +16 -17
- package/dist/server/fields/rich-text.mjs +18 -7
- package/dist/server/i18n/messages/cs.mjs +2 -0
- package/dist/server/i18n/messages/de.mjs +2 -0
- package/dist/server/i18n/messages/en.mjs +4 -0
- package/dist/server/i18n/messages/es.mjs +2 -0
- package/dist/server/i18n/messages/fr.mjs +2 -0
- package/dist/server/i18n/messages/pl.mjs +2 -0
- package/dist/server/i18n/messages/pt.mjs +2 -0
- package/dist/server/i18n/messages/sk.mjs +2 -0
- package/dist/server/modules/admin/.generated/module.d.mts +1 -1
- package/dist/server/modules/admin/auth-helpers.mjs +7 -1
- package/dist/server/modules/admin/block/block-builder.d.mts +0 -8
- package/dist/server/modules/admin/block/introspection.d.mts +2 -2
- package/dist/server/modules/admin/block/introspection.mjs +28 -4
- package/dist/server/modules/admin/block/prefetch.d.mts +11 -0
- package/dist/server/modules/admin/block/prefetch.mjs +108 -27
- package/dist/server/modules/admin/client/.generated/module.d.mts +68 -67
- package/dist/server/modules/admin/client/.generated/module.mjs +2 -0
- package/dist/server/modules/admin/client/views/collection-document.d.mts +6 -0
- package/dist/server/modules/admin/client/views/collection-document.mjs +10 -0
- package/dist/server/modules/admin/collections/account.d.mts +53 -52
- package/dist/server/modules/admin/collections/admin-locks.d.mts +57 -56
- package/dist/server/modules/admin/collections/admin-preferences.d.mts +38 -37
- package/dist/server/modules/admin/collections/admin-saved-views.d.mts +50 -49
- package/dist/server/modules/admin/collections/apikey.d.mts +76 -67
- package/dist/server/modules/admin/collections/assets.d.mts +37 -36
- package/dist/server/modules/admin/collections/session.d.mts +42 -41
- package/dist/server/modules/admin/collections/user.d.mts +57 -56
- package/dist/server/modules/admin/collections/verification.d.mts +34 -33
- package/dist/server/modules/admin/dto/admin-config.dto.mjs +34 -4
- package/dist/server/modules/admin/factories.mjs +4 -34
- package/dist/server/modules/admin/index.d.mts +3 -3
- package/dist/server/modules/admin/routes/admin-config.d.mts +4 -2
- package/dist/server/modules/admin/routes/admin-config.mjs +56 -24
- package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
- package/dist/server/modules/admin/routes/execute-action.mjs +35 -9
- package/dist/server/modules/admin/routes/locales.mjs +1 -1
- package/dist/server/modules/admin/routes/preview.d.mts +11 -11
- package/dist/server/modules/admin/routes/preview.mjs +6 -5
- package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
- package/dist/server/modules/admin/routes/reactive.mjs +2 -2
- package/dist/server/modules/admin/routes/route-helpers.d.mts +11 -7
- package/dist/server/modules/admin/routes/route-helpers.mjs +1 -1
- package/dist/server/modules/admin/routes/setup.d.mts +7 -7
- package/dist/server/modules/admin/routes/translations.d.mts +4 -4
- package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
- package/dist/server/modules/admin/routes/widget-data.mjs +12 -4
- package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +45 -45
- package/dist/server/modules/audit/.generated/module.d.mts +6 -6
- package/dist/server/modules/audit/collections/audit-log.d.mts +81 -80
- package/dist/server/modules/audit/jobs/audit-cleanup.d.mts +2 -2
- package/dist/server/plugin.mjs +10 -5
- package/dist/server/proxy-factories.d.mts +8 -1
- package/dist/server/proxy-factories.mjs +33 -1
- package/dist/server.d.mts +3 -1
- package/dist/shared/types/index.d.mts +1 -0
- package/dist/shared/types/saved-views.types.d.mts +14 -7
- package/dist/shared.d.mts +3 -2
- 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-
|
|
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
|
|
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):
|
|
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> =
|
|
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
|
|
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 {
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
})
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
})
|
|
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 =
|
|
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
|
|
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 };
|