@questpie/admin 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -122
- package/dist/augmentation.d.mts +110 -11
- package/dist/client/blocks/block-renderer.d.mts +5 -12
- package/dist/client/blocks/block-renderer.mjs +89 -55
- package/dist/client/blocks/index.d.mts +2 -4
- package/dist/client/blocks/types.d.mts +3 -4
- package/dist/client/blocks/types.mjs +1 -2
- package/dist/client/builder/admin-types.d.mts +11 -44
- package/dist/client/builder/admin.d.mts +34 -45
- package/dist/client/builder/admin.mjs +35 -44
- package/dist/client/builder/field/field.d.mts +27 -205
- package/dist/client/builder/field/field.mjs +22 -68
- package/dist/client/builder/index.d.mts +23 -28
- package/dist/client/builder/page/page.d.mts +15 -27
- package/dist/client/builder/page/page.mjs +21 -17
- package/dist/client/builder/registry.d.mts +14 -34
- package/dist/client/builder/types/action-registry.mjs +148 -14
- package/dist/client/builder/types/action-types.d.mts +8 -35
- package/dist/client/builder/types/collection-types.mjs +1 -2
- package/dist/client/builder/types/common.d.mts +6 -20
- package/dist/client/builder/types/field-types.d.mts +4 -5
- package/dist/client/builder/types/field-types.mjs +1 -2
- package/dist/client/builder/types/ui-config.d.mts +3 -5
- package/dist/client/builder/types/widget-types.d.mts +19 -20
- package/dist/client/builder/validation.d.mts +33 -3
- package/dist/client/builder/validation.mjs +169 -150
- package/dist/client/builder/view/view.d.mts +26 -106
- package/dist/client/builder/view/view.mjs +14 -96
- package/dist/client/builder/widget/widget.d.mts +16 -22
- package/dist/client/builder/widget/widget.mjs +11 -16
- package/dist/client/components/actions/action-button.mjs +207 -97
- package/dist/client/components/actions/action-dialog.mjs +471 -176
- package/dist/client/components/actions/confirmation-dialog.mjs +166 -47
- package/dist/client/components/actions/header-actions.mjs +164 -71
- package/dist/client/components/admin-link.d.mts +8 -9
- package/dist/client/components/admin-link.mjs +127 -48
- package/dist/client/components/auth/auth-guard.d.mts +6 -7
- package/dist/client/components/auth/auth-guard.mjs +9 -9
- package/dist/client/components/auth/auth-loading.d.mts +3 -4
- package/dist/client/components/auth/auth-loading.mjs +38 -10
- package/dist/client/components/blocks/block-canvas.mjs +111 -42
- package/dist/client/components/blocks/block-editor-context.mjs +90 -23
- package/dist/client/components/blocks/block-editor-layout.mjs +176 -59
- package/dist/client/components/blocks/block-editor-provider.mjs +219 -139
- package/dist/client/components/blocks/block-fields-renderer.mjs +212 -42
- package/dist/client/components/blocks/block-insert-button.mjs +168 -51
- package/dist/client/components/blocks/block-item-menu.mjs +312 -110
- package/dist/client/components/blocks/block-item.mjs +372 -125
- package/dist/client/components/blocks/block-library-sidebar.mjs +209 -114
- package/dist/client/components/blocks/block-tree.mjs +73 -15
- package/dist/client/components/blocks/block-type-icon.mjs +65 -20
- package/dist/client/components/blocks/utils/tree-utils.mjs +1 -2
- package/dist/client/components/component-renderer.d.mts +11 -22
- package/dist/client/components/component-renderer.mjs +151 -38
- package/dist/client/components/error-boundary.mjs +77 -25
- package/dist/client/components/fields/array-field.mjs +474 -199
- package/dist/client/components/fields/asset-preview-field.mjs +143 -44
- package/dist/client/components/fields/blocks-field/blocks-field.mjs +143 -35
- package/dist/client/components/fields/boolean-field.mjs +62 -32
- package/dist/client/components/fields/date-field.mjs +46 -12
- package/dist/client/components/fields/datetime-field.mjs +42 -11
- package/dist/client/components/fields/email-field.mjs +57 -28
- package/dist/client/components/fields/field-utils.mjs +1 -2
- package/dist/client/components/fields/field-wrapper.mjs +107 -32
- package/dist/client/components/fields/json-field.mjs +323 -110
- package/dist/client/components/fields/locale-badge.mjs +16 -8
- package/dist/client/components/fields/number-field.mjs +63 -30
- package/dist/client/components/fields/object-array-field.mjs +666 -272
- package/dist/client/components/fields/object-field.mjs +656 -98
- package/dist/client/components/fields/relation/displays/cards-display.mjs +225 -111
- package/dist/client/components/fields/relation/displays/chips-display.mjs +150 -77
- package/dist/client/components/fields/relation/displays/grid-display.mjs +186 -91
- package/dist/client/components/fields/relation/displays/list-display.mjs +230 -111
- package/dist/client/components/fields/relation/displays/table-display.mjs +241 -66
- package/dist/client/components/fields/relation/displays/types.mjs +2 -3
- package/dist/client/components/fields/relation/relation-items-display.mjs +131 -35
- package/dist/client/components/fields/relation-field.mjs +70 -15
- package/dist/client/components/fields/relation-picker.mjs +93 -98
- package/dist/client/components/fields/relation-select.mjs +42 -29
- package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +90 -41
- package/dist/client/components/fields/rich-text-editor/extensions.mjs +33 -7
- package/dist/client/components/fields/rich-text-editor/image-popover.mjs +48 -23
- package/dist/client/components/fields/rich-text-editor/index.mjs +491 -158
- package/dist/client/components/fields/rich-text-editor/link-popover.mjs +13 -14
- package/dist/client/components/fields/rich-text-editor/presets.mjs +1 -2
- package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +96 -53
- package/dist/client/components/fields/rich-text-editor/table-controls.mjs +416 -107
- package/dist/client/components/fields/rich-text-editor/toolbar.mjs +476 -215
- package/dist/client/components/fields/rich-text-editor/types.mjs +1 -2
- package/dist/client/components/fields/rich-text-editor/utils.mjs +1 -2
- package/dist/client/components/fields/rich-text-field.mjs +55 -17
- package/dist/client/components/fields/select-field.mjs +79 -44
- package/dist/client/components/fields/text-field.mjs +62 -29
- package/dist/client/components/fields/textarea-field.mjs +61 -29
- package/dist/client/components/fields/time-field.mjs +39 -11
- package/dist/client/components/fields/upload-field.mjs +253 -129
- package/dist/client/components/filter-builder/columns-tab.mjs +287 -93
- package/dist/client/components/filter-builder/filter-builder-sheet.mjs +437 -138
- package/dist/client/components/filter-builder/filters-tab.mjs +409 -126
- package/dist/client/components/filter-builder/saved-views-tab.mjs +259 -106
- package/dist/client/components/history-sidebar.mjs +496 -0
- package/dist/client/components/layout/field-layout-renderer.mjs +301 -0
- package/dist/client/components/locale-switcher.mjs +231 -108
- package/dist/client/components/media/media-grid.mjs +259 -84
- package/dist/client/components/media/media-picker-dialog.mjs +500 -192
- package/dist/client/components/preview/live-preview-mode.mjs +416 -124
- package/dist/client/components/preview/preview-pane.mjs +353 -144
- package/dist/client/components/primitives/asset-preview.mjs +665 -257
- package/dist/client/components/primitives/checkbox-input.mjs +37 -11
- package/dist/client/components/primitives/date-input.mjs +392 -149
- package/dist/client/components/primitives/dropzone.mjs +314 -185
- package/dist/client/components/primitives/number-input.mjs +14 -10
- package/dist/client/components/primitives/select-multi.mjs +519 -185
- package/dist/client/components/primitives/select-single.mjs +416 -126
- package/dist/client/components/primitives/text-input.mjs +10 -5
- package/dist/client/components/primitives/textarea-input.mjs +10 -5
- package/dist/client/components/primitives/time-input.mjs +118 -45
- package/dist/client/components/primitives/toggle-input.mjs +31 -11
- package/dist/client/components/primitives/types.mjs +1 -2
- package/dist/client/components/sheets/resource-sheet.mjs +72 -64
- package/dist/client/components/ui/accordion.mjs +156 -37
- package/dist/client/components/ui/alert.mjs +70 -17
- package/dist/client/components/ui/badge.mjs +57 -16
- package/dist/client/components/ui/button.mjs +49 -14
- package/dist/client/components/ui/card.mjs +194 -39
- package/dist/client/components/ui/checkbox.mjs +71 -16
- package/dist/client/components/ui/command.mjs +220 -50
- package/dist/client/components/ui/dialog.mjs +265 -52
- package/dist/client/components/ui/drawer.mjs +260 -57
- package/dist/client/components/ui/dropdown-menu.mjs +293 -67
- package/dist/client/components/ui/empty-state.mjs +72 -26
- package/dist/client/components/ui/field.mjs +332 -56
- package/dist/client/components/ui/input-group.mjs +174 -41
- package/dist/client/components/ui/input.mjs +38 -9
- package/dist/client/components/ui/kbd.mjs +37 -8
- package/dist/client/components/ui/label.mjs +38 -8
- package/dist/client/components/ui/popover.mjs +162 -35
- package/dist/client/components/ui/responsive-dialog.mjs +277 -71
- package/dist/client/components/ui/search-input.mjs +101 -36
- package/dist/client/components/ui/select.mjs +297 -57
- package/dist/client/components/ui/separator.mjs +39 -9
- package/dist/client/components/ui/sheet.mjs +253 -51
- package/dist/client/components/ui/sidebar.mjs +700 -182
- package/dist/client/components/ui/skeleton.mjs +33 -8
- package/dist/client/components/ui/sonner.d.mts +2 -3
- package/dist/client/components/ui/sonner.mjs +45 -15
- package/dist/client/components/ui/spinner.mjs +44 -10
- package/dist/client/components/ui/switch.mjs +47 -12
- package/dist/client/components/ui/table.mjs +260 -50
- package/dist/client/components/ui/tabs.mjs +140 -29
- package/dist/client/components/ui/textarea.mjs +33 -8
- package/dist/client/components/ui/toolbar.mjs +105 -23
- package/dist/client/components/ui/tooltip.mjs +130 -29
- package/dist/client/components/widgets/chart-widget.mjs +456 -156
- package/dist/client/components/widgets/progress-widget.mjs +150 -60
- package/dist/client/components/widgets/quick-actions-widget.mjs +175 -87
- package/dist/client/components/widgets/recent-items-widget.mjs +157 -62
- package/dist/client/components/widgets/stats-widget.mjs +153 -42
- package/dist/client/components/widgets/table-widget.mjs +198 -64
- package/dist/client/components/widgets/timeline-widget.mjs +193 -82
- package/dist/client/components/widgets/value-widget.mjs +257 -56
- package/dist/client/components/widgets/widget-skeletons.mjs +390 -108
- package/dist/client/contexts/breadcrumb-context.mjs +44 -16
- package/dist/client/{context → contexts}/focus-context.d.mts +6 -7
- package/dist/client/{context → contexts}/focus-context.mjs +134 -62
- package/dist/client/hooks/typed-hooks.d.mts +38 -12
- package/dist/client/hooks/typed-hooks.mjs +758 -142
- package/dist/client/hooks/use-action.mjs +197 -69
- package/dist/client/hooks/use-admin-config.mjs +39 -10
- package/dist/client/hooks/use-admin-preferences.mjs +118 -15
- package/dist/client/hooks/use-admin-routes.mjs +60 -27
- package/dist/client/hooks/use-audit-history.mjs +157 -0
- package/dist/client/hooks/use-auth.d.mts +14 -15
- package/dist/client/hooks/use-auth.mjs +8 -9
- package/dist/client/hooks/use-collection-fields.mjs +58 -19
- package/dist/client/hooks/use-collection-meta.mjs +45 -13
- package/dist/client/hooks/use-collection-schema.mjs +34 -11
- package/dist/client/hooks/use-collection-validation.mjs +39 -25
- package/dist/client/hooks/use-collection.d.mts +18 -8
- package/dist/client/hooks/use-collection.mjs +560 -101
- package/dist/client/hooks/use-current-user.d.mts +6 -3
- package/dist/client/hooks/use-current-user.mjs +2 -2
- package/dist/client/hooks/use-field-hooks.mjs +73 -65
- package/dist/client/hooks/use-field-options.d.mts +1 -34
- package/dist/client/hooks/use-field-options.mjs +233 -148
- package/dist/client/hooks/use-global-fields.mjs +47 -16
- package/dist/client/hooks/use-global-meta.mjs +57 -11
- package/dist/client/hooks/use-global-schema.mjs +31 -11
- package/dist/client/hooks/use-global.d.mts +13 -2
- package/dist/client/hooks/use-global.mjs +244 -34
- package/dist/client/hooks/use-locks.mjs +331 -124
- package/dist/client/hooks/use-media-query.d.mts +1 -2
- package/dist/client/hooks/use-media-query.mjs +38 -19
- package/dist/client/hooks/use-prefill-params.mjs +2 -2
- package/dist/client/hooks/use-questpie-query-options.mjs +33 -11
- package/dist/client/hooks/use-reactive-fields.d.mts +6 -3
- package/dist/client/hooks/use-reactive-fields.mjs +130 -93
- package/dist/client/hooks/use-realtime-highlight.mjs +115 -53
- package/dist/client/hooks/use-saved-views.mjs +109 -34
- package/dist/client/hooks/use-search-param-toggle.d.mts +12 -0
- package/dist/client/hooks/use-search-param-toggle.mjs +115 -0
- package/dist/client/hooks/use-search.mjs +147 -36
- package/dist/client/hooks/use-server-actions.mjs +191 -0
- package/dist/client/hooks/use-server-validation.mjs +164 -72
- package/dist/client/hooks/use-server-widget-data.d.mts +2 -3
- package/dist/client/hooks/use-server-widget-data.mjs +36 -11
- package/dist/client/hooks/use-setup-status.d.mts +3 -4
- package/dist/client/hooks/use-setup-status.mjs +28 -16
- package/dist/client/hooks/use-sidebar-search-param.d.mts +9 -0
- package/dist/client/hooks/use-sidebar-search-param.mjs +104 -0
- package/dist/client/hooks/use-transition-stage.mjs +125 -0
- package/dist/client/hooks/use-upload-collection.mjs +1 -2
- package/dist/client/hooks/use-upload.mjs +189 -125
- package/dist/client/hooks/use-validation-error-map.mjs +10 -6
- package/dist/client/hooks/use-view-state.mjs +380 -162
- package/dist/client/i18n/hooks.mjs +191 -67
- package/dist/client/i18n/intl-cache.mjs +1 -2
- package/dist/client/i18n/messages.mjs +1 -2
- package/dist/client/i18n/simple.d.mts +1 -2
- package/dist/client/i18n/simple.mjs +1 -2
- package/dist/client/i18n/types.d.mts +1 -2
- package/dist/client/lib/cookies.mjs +9 -0
- package/dist/client/lib/events.mjs +5 -0
- package/dist/client/lib/render-profiler.mjs +51 -0
- package/dist/client/lib/utils.mjs +1 -6
- package/dist/client/preview/block-scope-context.d.mts +5 -6
- package/dist/client/preview/block-scope-context.mjs +50 -27
- package/dist/client/preview/index.d.mts +2 -2
- package/dist/client/preview/preview-banner.d.mts +3 -4
- package/dist/client/preview/preview-banner.mjs +74 -35
- package/dist/client/preview/preview-field.d.mts +9 -10
- package/dist/client/preview/preview-field.mjs +163 -61
- package/dist/client/preview/types.d.mts +1 -2
- package/dist/client/preview/types.mjs +1 -2
- package/dist/client/preview/use-collection-preview.d.mts +1 -2
- package/dist/client/preview/use-collection-preview.mjs +105 -56
- package/dist/client/runtime/content-locales-provider.mjs +87 -36
- package/dist/client/runtime/index.d.mts +1 -3
- package/dist/client/runtime/index.mjs +1 -3
- package/dist/client/runtime/locale-scope.mjs +69 -29
- package/dist/client/runtime/provider.d.mts +18 -9922
- package/dist/client/runtime/provider.mjs +250 -86
- package/dist/client/runtime/routes.d.mts +7 -7
- package/dist/client/runtime/routes.mjs +4 -20
- package/dist/client/runtime/translations-provider.mjs +114 -53
- package/dist/client/scope/picker.d.mts +3 -4
- package/dist/client/scope/picker.mjs +324 -90
- package/dist/client/scope/provider.d.mts +4 -5
- package/dist/client/scope/provider.mjs +30 -22
- package/dist/client/scope/types.d.mts +1 -2
- package/dist/client/styles/index.css +301 -225
- package/dist/client/utils/auto-expand-fields.mjs +23 -5
- package/dist/client/utils/build-field-definitions-from-schema.mjs +10 -7
- package/dist/client/utils/dependency-tracker.mjs +61 -0
- package/dist/client/utils/detect-relations.mjs +1 -2
- package/dist/client/utils/locale-to-flag.d.mts +8 -7
- package/dist/client/utils/locale-to-flag.mjs +1 -2
- package/dist/client/utils/routes.mjs +1 -2
- package/dist/client/views/auth/accept-invite-form.d.mts +3 -4
- package/dist/client/views/auth/accept-invite-form.mjs +414 -121
- package/dist/client/views/auth/auth-layout.d.mts +7 -8
- package/dist/client/views/auth/auth-layout.mjs +93 -30
- package/dist/client/views/auth/forgot-password-form.d.mts +4 -5
- package/dist/client/views/auth/forgot-password-form.mjs +332 -100
- package/dist/client/views/auth/invite-form.mjs +447 -105
- package/dist/client/views/auth/login-form.d.mts +4 -5
- package/dist/client/views/auth/login-form.mjs +340 -120
- package/dist/client/views/auth/reset-password-form.d.mts +4 -5
- package/dist/client/views/auth/reset-password-form.mjs +458 -131
- package/dist/client/views/auth/setup-form.d.mts +4 -5
- package/dist/client/views/auth/setup-form.mjs +481 -141
- package/dist/client/views/collection/auto-form-fields.mjs +686 -266
- package/dist/client/views/collection/bulk-action-toolbar.mjs +392 -203
- package/dist/client/views/collection/cells/complex-cells.mjs +635 -216
- package/dist/client/views/collection/cells/primitive-cells.mjs +332 -102
- package/dist/client/views/collection/cells/relation-cells.mjs +227 -72
- package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +456 -136
- package/dist/client/views/collection/cells/shared/cell-helpers.mjs +49 -2
- package/dist/client/views/collection/cells/shared/relation-chip.mjs +109 -25
- package/dist/client/views/collection/cells/upload-cells.mjs +16 -8
- package/dist/client/views/collection/columns/build-columns.mjs +51 -12
- package/dist/client/views/collection/columns/column-defaults.mjs +17 -2
- package/dist/client/views/collection/field-context.mjs +10 -11
- package/dist/client/views/collection/field-renderer.mjs +237 -40
- package/dist/client/views/collection/form-view.mjs +1108 -445
- package/dist/client/views/collection/table-view.mjs +300 -163
- package/dist/client/views/collection/view-skeletons.mjs +181 -87
- package/dist/client/views/common/global-search.mjs +557 -233
- package/dist/client/views/dashboard/dashboard-grid.mjs +707 -211
- package/dist/client/views/dashboard/dashboard-widget.mjs +145 -58
- package/dist/client/views/dashboard/widget-card.mjs +315 -102
- package/dist/client/views/globals/global-form-view.mjs +1256 -131
- package/dist/client/views/layout/admin-layout-provider.d.mts +18 -21
- package/dist/client/views/layout/admin-layout-provider.mjs +135 -32
- package/dist/client/views/layout/admin-layout.d.mts +14 -32
- package/dist/client/views/layout/admin-layout.mjs +254 -96
- package/dist/client/views/layout/admin-router.d.mts +10 -42
- package/dist/client/views/layout/admin-router.mjs +1086 -426
- package/dist/client/views/layout/admin-sidebar.d.mts +10 -16
- package/dist/client/views/layout/admin-sidebar.mjs +1211 -382
- package/dist/client/views/layout/admin-topbar.mjs +220 -112
- package/dist/client/views/pages/accept-invite-page.d.mts +5 -6
- package/dist/client/views/pages/accept-invite-page.mjs +302 -96
- package/dist/client/views/pages/dashboard-page.d.mts +7 -16
- package/dist/client/views/pages/dashboard-page.mjs +62 -23
- package/dist/client/views/pages/forgot-password-page.d.mts +7 -10
- package/dist/client/views/pages/forgot-password-page.mjs +112 -40
- package/dist/client/views/pages/invite-page.d.mts +6 -7
- package/dist/client/views/pages/invite-page.mjs +121 -46
- package/dist/client/views/pages/login-page.d.mts +8 -15
- package/dist/client/views/pages/login-page.mjs +152 -57
- package/dist/client/views/pages/reset-password-page.d.mts +7 -10
- package/dist/client/views/pages/reset-password-page.mjs +209 -57
- package/dist/client/views/pages/setup-page.d.mts +7 -10
- package/dist/client/views/pages/setup-page.mjs +108 -43
- package/dist/client-module.d.mts +3 -0
- package/dist/client-module.mjs +3 -0
- package/dist/client.d.mts +55 -48
- package/dist/client.mjs +26 -28
- package/dist/components/rich-text/rich-text-renderer.d.mts +3 -4
- package/dist/components/rich-text/rich-text-renderer.mjs +97 -70
- package/dist/index.d.mts +36 -39
- package/dist/index.mjs +26 -28
- package/dist/plugin.d.mts +2 -0
- package/dist/plugin.mjs +3 -0
- package/dist/server/adapters/nextjs.d.mts +13 -14
- package/dist/server/adapters/nextjs.mjs +12 -13
- package/dist/server/adapters/tanstack.d.mts +10 -11
- package/dist/server/adapters/tanstack.mjs +11 -12
- package/dist/server/augmentation/actions.d.mts +279 -0
- package/dist/server/augmentation/common.d.mts +76 -0
- package/dist/server/augmentation/dashboard.d.mts +547 -0
- package/dist/server/augmentation/form-layout.d.mts +303 -0
- package/dist/server/augmentation/index.d.mts +44 -0
- package/dist/server/augmentation/index.mjs +10 -0
- package/dist/server/augmentation/sidebar.d.mts +181 -0
- package/dist/server/augmentation/views.d.mts +237 -0
- package/dist/server/augmentation.d.mts +7 -1523
- package/dist/server/block/index.d.mts +4 -3
- package/dist/server/codegen/admin-client-template.mjs +93 -0
- package/dist/server/codegen/projection-validator.mjs +67 -0
- package/dist/server/fields/blocks.d.mts +10 -78
- package/dist/server/fields/blocks.mjs +74 -115
- package/dist/server/fields/index.d.mts +6 -39
- package/dist/server/fields/index.mjs +6 -7
- package/dist/server/fields/rich-text.d.mts +10 -77
- package/dist/server/fields/rich-text.mjs +59 -100
- package/dist/server/i18n/index.mjs +8 -9
- package/dist/server/i18n/messages/cs.mjs +3 -3
- package/dist/server/i18n/messages/de.mjs +3 -3
- package/dist/server/i18n/messages/en.mjs +217 -3
- package/dist/server/i18n/messages/es.mjs +3 -3
- package/dist/server/i18n/messages/fr.mjs +3 -3
- package/dist/server/i18n/messages/index.mjs +1 -2
- package/dist/server/i18n/messages/pl.mjs +3 -3
- package/dist/server/i18n/messages/pt.mjs +3 -3
- package/dist/server/i18n/messages/sk.mjs +202 -3
- package/dist/server/modules/admin/.generated/module.d.mts +52 -0
- package/dist/server/modules/admin/.generated/module.mjs +78 -0
- package/dist/server/modules/admin/.generated/registries.d.mts +22 -0
- package/dist/server/{auth-helpers.d.mts → modules/admin/auth-helpers.d.mts} +13 -14
- package/dist/server/{auth-helpers.mjs → modules/admin/auth-helpers.mjs} +15 -16
- package/dist/server/{block → modules/admin/block}/block-builder.d.mts +96 -32
- package/dist/server/{block → modules/admin/block}/block-builder.mjs +113 -15
- package/dist/server/modules/admin/block/index.d.mts +3 -0
- package/dist/server/{block → modules/admin/block}/introspection.d.mts +10 -5
- package/dist/server/{block → modules/admin/block}/introspection.mjs +18 -7
- package/dist/server/{block → modules/admin/block}/prefetch.d.mts +17 -17
- package/dist/server/{block → modules/admin/block}/prefetch.mjs +17 -16
- package/dist/server/modules/admin/client/.generated/module.d.mts +94 -0
- package/dist/server/modules/admin/client/.generated/module.mjs +91 -0
- package/dist/server/modules/admin/client/components/badge.d.mts +1 -0
- package/dist/server/modules/admin/client/components/icon.d.mts +1 -0
- package/dist/server/modules/admin/client/fields/array.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/array.mjs +12 -0
- package/dist/server/modules/admin/client/fields/assetPreview.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/assetPreview.mjs +18 -0
- package/dist/server/modules/admin/client/fields/blocks.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/blocks.mjs +12 -0
- package/dist/server/modules/admin/client/fields/boolean.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/boolean.mjs +12 -0
- package/dist/server/modules/admin/client/fields/date.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/date.mjs +12 -0
- package/dist/server/modules/admin/client/fields/datetime.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/datetime.mjs +12 -0
- package/dist/server/modules/admin/client/fields/email.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/email.mjs +12 -0
- package/dist/server/modules/admin/client/fields/json.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/json.mjs +11 -0
- package/dist/server/modules/admin/client/fields/number.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/number.mjs +12 -0
- package/dist/server/modules/admin/client/fields/object.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/object.mjs +12 -0
- package/dist/server/modules/admin/client/fields/relation.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/relation.mjs +12 -0
- package/dist/server/modules/admin/client/fields/richText.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/richText.mjs +11 -0
- package/dist/server/modules/admin/client/fields/select.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/select.mjs +12 -0
- package/dist/server/modules/admin/client/fields/text.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/text.mjs +12 -0
- package/dist/server/modules/admin/client/fields/textarea.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/textarea.mjs +12 -0
- package/dist/server/modules/admin/client/fields/time.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/time.mjs +12 -0
- package/dist/server/modules/admin/client/fields/upload.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/upload.mjs +12 -0
- package/dist/server/modules/admin/client/fields/url.d.mts +6 -0
- package/dist/server/modules/admin/client/fields/url.mjs +12 -0
- package/dist/server/modules/admin/client/index.d.mts +1 -0
- package/dist/server/modules/admin/client/pages/dashboard.d.mts +6 -0
- package/dist/server/modules/admin/client/pages/dashboard.mjs +11 -0
- package/dist/server/modules/admin/client/pages/forgotPassword.d.mts +6 -0
- package/dist/server/modules/admin/client/pages/forgotPassword.mjs +11 -0
- package/dist/server/modules/admin/client/pages/login.d.mts +6 -0
- package/dist/server/modules/admin/client/pages/login.mjs +11 -0
- package/dist/server/modules/admin/client/pages/resetPassword.d.mts +6 -0
- package/dist/server/modules/admin/client/pages/resetPassword.mjs +11 -0
- package/dist/server/modules/admin/client/pages/setup.d.mts +6 -0
- package/dist/server/modules/admin/client/pages/setup.mjs +11 -0
- package/dist/server/modules/admin/client/views/collection-form.mjs +10 -0
- package/dist/server/modules/admin/client/views/collection-table.mjs +10 -0
- package/dist/server/modules/admin/client/views/global-form.mjs +10 -0
- package/dist/server/modules/admin/client/widgets/chart.d.mts +6 -0
- package/dist/server/modules/admin/client/widgets/chart.mjs +7 -0
- package/dist/server/modules/admin/client/widgets/progress.d.mts +6 -0
- package/dist/server/modules/admin/client/widgets/progress.mjs +7 -0
- package/dist/server/modules/admin/client/widgets/quickActions.d.mts +6 -0
- package/dist/server/modules/admin/client/widgets/quickActions.mjs +7 -0
- package/dist/server/modules/admin/client/widgets/recentItems.d.mts +6 -0
- package/dist/server/modules/admin/client/widgets/recentItems.mjs +7 -0
- package/dist/server/modules/admin/client/widgets/stats.d.mts +6 -0
- package/dist/server/modules/admin/client/widgets/stats.mjs +7 -0
- package/dist/server/modules/admin/client/widgets/table.d.mts +6 -0
- package/dist/server/modules/admin/client/widgets/table.mjs +7 -0
- package/dist/server/modules/admin/client/widgets/timeline.d.mts +6 -0
- package/dist/server/modules/admin/client/widgets/timeline.mjs +7 -0
- package/dist/server/modules/admin/client/widgets/value.d.mts +6 -0
- package/dist/server/modules/admin/client/widgets/value.mjs +7 -0
- package/dist/server/modules/admin/collections/account.d.mts +77 -0
- package/dist/server/modules/admin/collections/account.mjs +23 -0
- package/dist/server/modules/admin/collections/admin-locks.d.mts +90 -0
- package/dist/server/modules/admin/collections/admin-locks.mjs +16 -0
- package/dist/server/modules/admin/collections/admin-preferences.d.mts +69 -0
- package/dist/server/modules/admin/collections/admin-preferences.mjs +16 -0
- package/dist/server/modules/admin/collections/admin-saved-views.d.mts +83 -0
- package/dist/server/modules/admin/collections/admin-saved-views.mjs +16 -0
- package/dist/server/modules/admin/collections/apikey.d.mts +99 -0
- package/dist/server/modules/admin/collections/apikey.mjs +15 -0
- package/dist/server/modules/admin/collections/assets.d.mts +72 -0
- package/dist/server/modules/admin/collections/assets.mjs +71 -0
- package/dist/server/modules/admin/collections/session.d.mts +69 -0
- package/dist/server/modules/admin/collections/session.mjs +15 -0
- package/dist/server/modules/admin/collections/user.d.mts +85 -0
- package/dist/server/modules/admin/collections/user.mjs +204 -0
- package/dist/server/modules/admin/collections/verification.d.mts +63 -0
- package/dist/server/modules/admin/collections/verification.mjs +15 -0
- package/dist/server/modules/admin/components/badge.d.mts +10 -0
- package/dist/server/modules/admin/components/badge.mjs +10 -0
- package/dist/server/modules/admin/components/icon.d.mts +9 -0
- package/dist/server/modules/admin/components/icon.mjs +11 -0
- package/dist/server/modules/admin/config/admin.mjs +34 -0
- package/dist/server/modules/admin/dto/admin-config.dto.mjs +102 -0
- package/dist/server/modules/admin/factories.mjs +172 -0
- package/dist/server/modules/admin/index.d.mts +1060 -16846
- package/dist/server/modules/admin/index.mjs +17 -240
- package/dist/server/modules/admin/modules.mjs +11 -0
- package/dist/server/modules/admin/plugin.mjs +13 -0
- package/dist/server/modules/admin/routes/admin-config.d.mts +28 -0
- package/dist/server/modules/admin/routes/admin-config.mjs +552 -0
- package/dist/server/modules/admin/{functions → routes}/execute-action.d.mts +17 -32
- package/dist/server/modules/admin/{functions → routes}/execute-action.mjs +146 -44
- package/dist/server/modules/admin/routes/locales.d.mts +18 -0
- package/dist/server/modules/admin/routes/locales.mjs +69 -0
- package/dist/server/modules/admin/{functions → routes}/preview.d.mts +25 -15
- package/dist/server/modules/admin/{functions → routes}/preview.mjs +84 -97
- package/dist/server/modules/admin/{functions → routes}/reactive.d.mts +19 -44
- package/dist/server/modules/admin/{functions → routes}/reactive.mjs +89 -117
- package/dist/server/modules/admin/routes/route-helpers.d.mts +23 -0
- package/dist/server/modules/admin/routes/route-helpers.mjs +76 -0
- package/dist/server/modules/admin/{functions → routes}/setup.d.mts +11 -32
- package/dist/server/modules/admin/routes/setup.mjs +114 -0
- package/dist/server/modules/admin/routes/translations.d.mts +26 -0
- package/dist/server/modules/admin/routes/translations.mjs +114 -0
- package/dist/server/modules/admin/routes/widget-data.d.mts +32 -0
- package/dist/server/modules/admin/routes/widget-data.mjs +62 -0
- package/dist/server/modules/admin/views/form.d.mts +8 -0
- package/dist/server/modules/admin/views/form.mjs +7 -0
- package/dist/server/modules/admin/views/global-form.d.mts +8 -0
- package/dist/server/modules/admin/views/global-form.mjs +7 -0
- package/dist/server/modules/admin/views/table.d.mts +8 -0
- package/dist/server/modules/admin/views/table.mjs +7 -0
- package/dist/server/modules/admin-preferences/collections/{admin-preferences.collection.mjs → admin-preferences.mjs} +13 -24
- package/dist/server/modules/admin-preferences/collections/locks.collection.mjs +18 -42
- package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +99 -0
- package/dist/server/modules/admin-preferences/collections/saved-views.mjs +38 -0
- package/dist/server/modules/audit/.generated/module.d.mts +60 -0
- package/dist/server/modules/audit/.generated/module.mjs +30 -0
- package/dist/server/modules/audit/collections/audit-log.d.mts +214 -0
- package/dist/server/modules/audit/collections/audit-log.mjs +107 -0
- package/dist/server/modules/audit/config/admin.mjs +21 -0
- package/dist/server/modules/audit/config/app.mjs +262 -0
- package/dist/server/modules/audit/index.d.mts +2 -0
- package/dist/server/modules/audit/jobs/audit-cleanup.d.mts +13 -0
- package/dist/server/modules/audit/jobs/audit-cleanup.mjs +28 -0
- package/dist/server/plugin.d.mts +26 -0
- package/dist/server/plugin.mjs +385 -0
- package/dist/server/proxy-factories.d.mts +85 -0
- package/dist/server/proxy-factories.mjs +302 -0
- package/dist/server/registry-helpers.d.mts +83 -0
- package/dist/server/registry-helpers.mjs +104 -0
- package/dist/server.d.mts +30 -18
- package/dist/server.mjs +19 -16
- package/dist/shared/preview-utils.d.mts +2 -3
- package/dist/shared/preview-utils.mjs +2 -3
- package/dist/shared/types/saved-views.types.d.mts +2 -2
- package/package.json +50 -40
- package/skills/questpie-admin/SKILL.md +397 -0
- package/skills/questpie-admin/blocks/SKILL.md +305 -0
- package/skills/questpie-admin/custom-ui/SKILL.md +307 -0
- package/skills/questpie-admin/views/SKILL.md +442 -0
- package/dist/_virtual/rolldown_runtime.mjs +0 -18
- package/dist/augmentation.d.mts.map +0 -1
- package/dist/client/blocks/block-registry.d.mts +0 -199
- package/dist/client/blocks/block-registry.d.mts.map +0 -1
- package/dist/client/blocks/block-registry.mjs +0 -88
- package/dist/client/blocks/block-registry.mjs.map +0 -1
- package/dist/client/blocks/block-renderer.d.mts.map +0 -1
- package/dist/client/blocks/block-renderer.mjs.map +0 -1
- package/dist/client/blocks/prefetch.d.mts +0 -45
- package/dist/client/blocks/prefetch.d.mts.map +0 -1
- package/dist/client/blocks/prefetch.mjs +0 -26
- package/dist/client/blocks/prefetch.mjs.map +0 -1
- package/dist/client/blocks/types.d.mts.map +0 -1
- package/dist/client/blocks/types.mjs.map +0 -1
- package/dist/client/builder/admin-builder.d.mts +0 -112
- package/dist/client/builder/admin-builder.d.mts.map +0 -1
- package/dist/client/builder/admin-builder.mjs +0 -185
- package/dist/client/builder/admin-builder.mjs.map +0 -1
- package/dist/client/builder/admin-types.d.mts.map +0 -1
- package/dist/client/builder/admin.d.mts.map +0 -1
- package/dist/client/builder/admin.mjs.map +0 -1
- package/dist/client/builder/defaults/components.mjs +0 -20
- package/dist/client/builder/defaults/components.mjs.map +0 -1
- package/dist/client/builder/defaults/core.d.mts +0 -354
- package/dist/client/builder/defaults/core.d.mts.map +0 -1
- package/dist/client/builder/defaults/core.mjs +0 -49
- package/dist/client/builder/defaults/core.mjs.map +0 -1
- package/dist/client/builder/defaults/fields.mjs +0 -328
- package/dist/client/builder/defaults/fields.mjs.map +0 -1
- package/dist/client/builder/defaults/pages.mjs +0 -58
- package/dist/client/builder/defaults/pages.mjs.map +0 -1
- package/dist/client/builder/defaults/starter.d.mts +0 -351
- package/dist/client/builder/defaults/starter.d.mts.map +0 -1
- package/dist/client/builder/defaults/starter.mjs +0 -28
- package/dist/client/builder/defaults/starter.mjs.map +0 -1
- package/dist/client/builder/defaults/views.mjs +0 -27
- package/dist/client/builder/defaults/views.mjs.map +0 -1
- package/dist/client/builder/defaults/widgets.mjs +0 -31
- package/dist/client/builder/defaults/widgets.mjs.map +0 -1
- package/dist/client/builder/field/field.d.mts.map +0 -1
- package/dist/client/builder/field/field.mjs.map +0 -1
- package/dist/client/builder/index.d.mts.map +0 -1
- package/dist/client/builder/page/page.d.mts.map +0 -1
- package/dist/client/builder/page/page.mjs.map +0 -1
- package/dist/client/builder/proxies.d.mts +0 -2
- package/dist/client/builder/proxies.mjs +0 -24
- package/dist/client/builder/proxies.mjs.map +0 -1
- package/dist/client/builder/qa.d.mts +0 -50
- package/dist/client/builder/qa.d.mts.map +0 -1
- package/dist/client/builder/qa.mjs +0 -42
- package/dist/client/builder/qa.mjs.map +0 -1
- package/dist/client/builder/registry.d.mts.map +0 -1
- package/dist/client/builder/types/action-registry.d.mts +0 -2
- package/dist/client/builder/types/action-registry.mjs.map +0 -1
- package/dist/client/builder/types/action-types.d.mts.map +0 -1
- package/dist/client/builder/types/collection-types.d.mts +0 -199
- package/dist/client/builder/types/collection-types.d.mts.map +0 -1
- package/dist/client/builder/types/collection-types.mjs.map +0 -1
- package/dist/client/builder/types/common.d.mts.map +0 -1
- package/dist/client/builder/types/field-types.d.mts.map +0 -1
- package/dist/client/builder/types/field-types.mjs.map +0 -1
- package/dist/client/builder/types/global-types.d.mts +0 -22
- package/dist/client/builder/types/global-types.d.mts.map +0 -1
- package/dist/client/builder/types/ui-config.d.mts.map +0 -1
- package/dist/client/builder/types/views.d.mts +0 -89
- package/dist/client/builder/types/views.d.mts.map +0 -1
- package/dist/client/builder/types/widget-types.d.mts.map +0 -1
- package/dist/client/builder/validation.mjs.map +0 -1
- package/dist/client/builder/view/view.d.mts.map +0 -1
- package/dist/client/builder/view/view.mjs.map +0 -1
- package/dist/client/builder/widget/widget.d.mts.map +0 -1
- package/dist/client/builder/widget/widget.mjs.map +0 -1
- package/dist/client/components/actions/action-button.d.mts +0 -2
- package/dist/client/components/actions/action-button.mjs.map +0 -1
- package/dist/client/components/actions/action-dialog.d.mts +0 -2
- package/dist/client/components/actions/action-dialog.mjs.map +0 -1
- package/dist/client/components/actions/confirmation-dialog.d.mts +0 -2
- package/dist/client/components/actions/confirmation-dialog.mjs.map +0 -1
- package/dist/client/components/actions/header-actions.d.mts +0 -2
- package/dist/client/components/actions/header-actions.mjs.map +0 -1
- package/dist/client/components/actions/index.d.mts +0 -4
- package/dist/client/components/admin-link.d.mts.map +0 -1
- package/dist/client/components/admin-link.mjs.map +0 -1
- package/dist/client/components/auth/auth-guard.d.mts.map +0 -1
- package/dist/client/components/auth/auth-guard.mjs.map +0 -1
- package/dist/client/components/auth/auth-loading.d.mts.map +0 -1
- package/dist/client/components/auth/auth-loading.mjs.map +0 -1
- package/dist/client/components/auth/index.d.mts +0 -2
- package/dist/client/components/blocks/block-canvas.mjs.map +0 -1
- package/dist/client/components/blocks/block-editor-context.mjs.map +0 -1
- package/dist/client/components/blocks/block-editor-layout.mjs.map +0 -1
- package/dist/client/components/blocks/block-editor-provider.mjs.map +0 -1
- package/dist/client/components/blocks/block-fields-renderer.mjs.map +0 -1
- package/dist/client/components/blocks/block-insert-button.mjs.map +0 -1
- package/dist/client/components/blocks/block-item-menu.mjs.map +0 -1
- package/dist/client/components/blocks/block-item.mjs.map +0 -1
- package/dist/client/components/blocks/block-library-sidebar.mjs.map +0 -1
- package/dist/client/components/blocks/block-tree.mjs.map +0 -1
- package/dist/client/components/blocks/block-type-icon.mjs.map +0 -1
- package/dist/client/components/blocks/utils/tree-utils.mjs.map +0 -1
- package/dist/client/components/component-renderer.d.mts.map +0 -1
- package/dist/client/components/component-renderer.mjs.map +0 -1
- package/dist/client/components/error-boundary.mjs.map +0 -1
- package/dist/client/components/fields/array-field.d.mts +0 -44
- package/dist/client/components/fields/array-field.d.mts.map +0 -1
- package/dist/client/components/fields/array-field.mjs.map +0 -1
- package/dist/client/components/fields/asset-preview-field.d.mts +0 -52
- package/dist/client/components/fields/asset-preview-field.d.mts.map +0 -1
- package/dist/client/components/fields/asset-preview-field.mjs.map +0 -1
- package/dist/client/components/fields/blocks-field/blocks-field.d.mts +0 -41
- package/dist/client/components/fields/blocks-field/blocks-field.d.mts.map +0 -1
- package/dist/client/components/fields/blocks-field/blocks-field.mjs.map +0 -1
- package/dist/client/components/fields/blocks-field/index.d.mts +0 -1
- package/dist/client/components/fields/boolean-field.d.mts +0 -30
- package/dist/client/components/fields/boolean-field.d.mts.map +0 -1
- package/dist/client/components/fields/boolean-field.mjs.map +0 -1
- package/dist/client/components/fields/custom-field.d.mts +0 -3
- package/dist/client/components/fields/date-field.d.mts +0 -22
- package/dist/client/components/fields/date-field.d.mts.map +0 -1
- package/dist/client/components/fields/date-field.mjs.map +0 -1
- package/dist/client/components/fields/datetime-field.d.mts +0 -23
- package/dist/client/components/fields/datetime-field.d.mts.map +0 -1
- package/dist/client/components/fields/datetime-field.mjs.map +0 -1
- package/dist/client/components/fields/email-field.d.mts +0 -19
- package/dist/client/components/fields/email-field.d.mts.map +0 -1
- package/dist/client/components/fields/email-field.mjs.map +0 -1
- package/dist/client/components/fields/embedded-collection.d.mts +0 -3
- package/dist/client/components/fields/field-types.d.mts +0 -571
- package/dist/client/components/fields/field-types.d.mts.map +0 -1
- package/dist/client/components/fields/field-utils.d.mts +0 -1
- package/dist/client/components/fields/field-utils.mjs.map +0 -1
- package/dist/client/components/fields/field-wrapper.d.mts +0 -3
- package/dist/client/components/fields/field-wrapper.mjs.map +0 -1
- package/dist/client/components/fields/index.d.mts +0 -33
- package/dist/client/components/fields/json-field.d.mts +0 -84
- package/dist/client/components/fields/json-field.d.mts.map +0 -1
- package/dist/client/components/fields/json-field.mjs.map +0 -1
- package/dist/client/components/fields/locale-badge.d.mts +0 -1
- package/dist/client/components/fields/locale-badge.mjs.map +0 -1
- package/dist/client/components/fields/number-field.d.mts +0 -23
- package/dist/client/components/fields/number-field.d.mts.map +0 -1
- package/dist/client/components/fields/number-field.mjs.map +0 -1
- package/dist/client/components/fields/object-array-field.d.mts +0 -2
- package/dist/client/components/fields/object-array-field.mjs.map +0 -1
- package/dist/client/components/fields/object-field.d.mts +0 -32
- package/dist/client/components/fields/object-field.d.mts.map +0 -1
- package/dist/client/components/fields/object-field.mjs.map +0 -1
- package/dist/client/components/fields/relation/displays/cards-display.d.mts +0 -2
- package/dist/client/components/fields/relation/displays/cards-display.mjs.map +0 -1
- package/dist/client/components/fields/relation/displays/chips-display.d.mts +0 -2
- package/dist/client/components/fields/relation/displays/chips-display.mjs.map +0 -1
- package/dist/client/components/fields/relation/displays/grid-display.d.mts +0 -2
- package/dist/client/components/fields/relation/displays/grid-display.mjs.map +0 -1
- package/dist/client/components/fields/relation/displays/index.d.mts +0 -6
- package/dist/client/components/fields/relation/displays/list-display.d.mts +0 -2
- package/dist/client/components/fields/relation/displays/list-display.mjs.map +0 -1
- package/dist/client/components/fields/relation/displays/table-display.d.mts +0 -2
- package/dist/client/components/fields/relation/displays/table-display.mjs.map +0 -1
- package/dist/client/components/fields/relation/displays/types.d.mts +0 -22
- package/dist/client/components/fields/relation/displays/types.d.mts.map +0 -1
- package/dist/client/components/fields/relation/displays/types.mjs.map +0 -1
- package/dist/client/components/fields/relation/index.d.mts +0 -3
- package/dist/client/components/fields/relation/relation-items-display.d.mts +0 -5
- package/dist/client/components/fields/relation/relation-items-display.mjs.map +0 -1
- package/dist/client/components/fields/relation-field.d.mts +0 -134
- package/dist/client/components/fields/relation-field.d.mts.map +0 -1
- package/dist/client/components/fields/relation-field.mjs.map +0 -1
- package/dist/client/components/fields/relation-picker.d.mts +0 -4
- package/dist/client/components/fields/relation-picker.mjs.map +0 -1
- package/dist/client/components/fields/relation-select.d.mts +0 -3
- package/dist/client/components/fields/relation-select.mjs.map +0 -1
- package/dist/client/components/fields/reverse-relation-field.d.mts +0 -2
- package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/extensions.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/image-popover.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/index.d.mts +0 -4
- package/dist/client/components/fields/rich-text-editor/index.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/link-popover.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/presets.d.mts +0 -11
- package/dist/client/components/fields/rich-text-editor/presets.d.mts.map +0 -1
- package/dist/client/components/fields/rich-text-editor/presets.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/slash-commands.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/table-controls.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/toolbar.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/types.d.mts +0 -78
- package/dist/client/components/fields/rich-text-editor/types.d.mts.map +0 -1
- package/dist/client/components/fields/rich-text-editor/types.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/utils.mjs.map +0 -1
- package/dist/client/components/fields/rich-text-editor/variants.d.mts +0 -2
- package/dist/client/components/fields/rich-text-field.d.mts +0 -14
- package/dist/client/components/fields/rich-text-field.d.mts.map +0 -1
- package/dist/client/components/fields/rich-text-field.mjs.map +0 -1
- package/dist/client/components/fields/select-field.d.mts +0 -25
- package/dist/client/components/fields/select-field.d.mts.map +0 -1
- package/dist/client/components/fields/select-field.mjs.map +0 -1
- package/dist/client/components/fields/status-field.d.mts +0 -2
- package/dist/client/components/fields/text-field.d.mts +0 -22
- package/dist/client/components/fields/text-field.d.mts.map +0 -1
- package/dist/client/components/fields/text-field.mjs.map +0 -1
- package/dist/client/components/fields/textarea-field.d.mts +0 -22
- package/dist/client/components/fields/textarea-field.d.mts.map +0 -1
- package/dist/client/components/fields/textarea-field.mjs.map +0 -1
- package/dist/client/components/fields/time-field.d.mts +0 -20
- package/dist/client/components/fields/time-field.d.mts.map +0 -1
- package/dist/client/components/fields/time-field.mjs.map +0 -1
- package/dist/client/components/fields/upload-field.d.mts +0 -97
- package/dist/client/components/fields/upload-field.d.mts.map +0 -1
- package/dist/client/components/fields/upload-field.mjs.map +0 -1
- package/dist/client/components/filter-builder/columns-tab.d.mts +0 -1
- package/dist/client/components/filter-builder/columns-tab.mjs.map +0 -1
- package/dist/client/components/filter-builder/filter-builder-sheet.d.mts +0 -1
- package/dist/client/components/filter-builder/filter-builder-sheet.mjs.map +0 -1
- package/dist/client/components/filter-builder/filters-tab.d.mts +0 -1
- package/dist/client/components/filter-builder/filters-tab.mjs.map +0 -1
- package/dist/client/components/filter-builder/index.d.mts +0 -5
- package/dist/client/components/filter-builder/saved-views-tab.d.mts +0 -1
- package/dist/client/components/filter-builder/saved-views-tab.mjs.map +0 -1
- package/dist/client/components/index.d.mts +0 -80
- package/dist/client/components/locale-switcher.d.mts +0 -2
- package/dist/client/components/locale-switcher.mjs.map +0 -1
- package/dist/client/components/media/media-grid.mjs.map +0 -1
- package/dist/client/components/media/media-picker-dialog.mjs.map +0 -1
- package/dist/client/components/preview/live-preview-mode.mjs.map +0 -1
- package/dist/client/components/preview/preview-pane.mjs.map +0 -1
- package/dist/client/components/primitives/asset-preview.mjs.map +0 -1
- package/dist/client/components/primitives/checkbox-input.mjs.map +0 -1
- package/dist/client/components/primitives/date-input.mjs.map +0 -1
- package/dist/client/components/primitives/dropzone.mjs.map +0 -1
- package/dist/client/components/primitives/number-input.mjs.map +0 -1
- package/dist/client/components/primitives/select-multi.mjs.map +0 -1
- package/dist/client/components/primitives/select-single.mjs.map +0 -1
- package/dist/client/components/primitives/text-input.mjs.map +0 -1
- package/dist/client/components/primitives/textarea-input.mjs.map +0 -1
- package/dist/client/components/primitives/time-input.mjs.map +0 -1
- package/dist/client/components/primitives/toggle-input.mjs.map +0 -1
- package/dist/client/components/primitives/types.d.mts +0 -14
- package/dist/client/components/primitives/types.d.mts.map +0 -1
- package/dist/client/components/primitives/types.mjs.map +0 -1
- package/dist/client/components/sheets/index.d.mts +0 -1
- package/dist/client/components/sheets/resource-sheet.d.mts +0 -1
- package/dist/client/components/sheets/resource-sheet.mjs.map +0 -1
- package/dist/client/components/ui/accordion.d.mts +0 -2
- package/dist/client/components/ui/accordion.mjs.map +0 -1
- package/dist/client/components/ui/alert.mjs.map +0 -1
- package/dist/client/components/ui/avatar.d.mts +0 -3
- package/dist/client/components/ui/badge.d.mts +0 -3
- package/dist/client/components/ui/badge.mjs.map +0 -1
- package/dist/client/components/ui/button.d.mts +0 -3
- package/dist/client/components/ui/button.mjs.map +0 -1
- package/dist/client/components/ui/card.d.mts +0 -2
- package/dist/client/components/ui/card.mjs.map +0 -1
- package/dist/client/components/ui/checkbox.d.mts +0 -2
- package/dist/client/components/ui/checkbox.mjs.map +0 -1
- package/dist/client/components/ui/combobox.d.mts +0 -3
- package/dist/client/components/ui/command.mjs.map +0 -1
- package/dist/client/components/ui/dialog.d.mts +0 -3
- package/dist/client/components/ui/dialog.mjs.map +0 -1
- package/dist/client/components/ui/drawer.mjs.map +0 -1
- package/dist/client/components/ui/dropdown-menu.d.mts +0 -3
- package/dist/client/components/ui/dropdown-menu.mjs.map +0 -1
- package/dist/client/components/ui/empty-state.mjs.map +0 -1
- package/dist/client/components/ui/field.d.mts +0 -3
- package/dist/client/components/ui/field.mjs.map +0 -1
- package/dist/client/components/ui/input-group.d.mts +0 -4
- package/dist/client/components/ui/input-group.mjs.map +0 -1
- package/dist/client/components/ui/input.d.mts +0 -2
- package/dist/client/components/ui/input.mjs.map +0 -1
- package/dist/client/components/ui/kbd.mjs.map +0 -1
- package/dist/client/components/ui/label.d.mts +0 -2
- package/dist/client/components/ui/label.mjs.map +0 -1
- package/dist/client/components/ui/popover.d.mts +0 -3
- package/dist/client/components/ui/popover.mjs.map +0 -1
- package/dist/client/components/ui/responsive-dialog.mjs.map +0 -1
- package/dist/client/components/ui/scroll-area.d.mts +0 -2
- package/dist/client/components/ui/search-input.mjs.map +0 -1
- package/dist/client/components/ui/select.d.mts +0 -3
- package/dist/client/components/ui/select.mjs.map +0 -1
- package/dist/client/components/ui/separator.d.mts +0 -2
- package/dist/client/components/ui/separator.mjs.map +0 -1
- package/dist/client/components/ui/sheet.d.mts +0 -3
- package/dist/client/components/ui/sheet.mjs.map +0 -1
- package/dist/client/components/ui/sidebar.d.mts +0 -8
- package/dist/client/components/ui/sidebar.mjs.map +0 -1
- package/dist/client/components/ui/skeleton.d.mts +0 -1
- package/dist/client/components/ui/skeleton.mjs.map +0 -1
- package/dist/client/components/ui/sonner.d.mts.map +0 -1
- package/dist/client/components/ui/sonner.mjs.map +0 -1
- package/dist/client/components/ui/spinner.d.mts +0 -1
- package/dist/client/components/ui/spinner.mjs.map +0 -1
- package/dist/client/components/ui/switch.d.mts +0 -2
- package/dist/client/components/ui/switch.mjs.map +0 -1
- package/dist/client/components/ui/table.d.mts +0 -2
- package/dist/client/components/ui/table.mjs.map +0 -1
- package/dist/client/components/ui/tabs.d.mts +0 -3
- package/dist/client/components/ui/tabs.mjs.map +0 -1
- package/dist/client/components/ui/textarea.d.mts +0 -2
- package/dist/client/components/ui/textarea.mjs.map +0 -1
- package/dist/client/components/ui/toolbar.mjs.map +0 -1
- package/dist/client/components/ui/tooltip.d.mts +0 -2
- package/dist/client/components/ui/tooltip.mjs.map +0 -1
- package/dist/client/components/widgets/chart-widget.d.mts +0 -57
- package/dist/client/components/widgets/chart-widget.d.mts.map +0 -1
- package/dist/client/components/widgets/chart-widget.mjs.map +0 -1
- package/dist/client/components/widgets/progress-widget.d.mts +0 -41
- package/dist/client/components/widgets/progress-widget.d.mts.map +0 -1
- package/dist/client/components/widgets/progress-widget.mjs.map +0 -1
- package/dist/client/components/widgets/quick-actions-widget.d.mts +0 -29
- package/dist/client/components/widgets/quick-actions-widget.d.mts.map +0 -1
- package/dist/client/components/widgets/quick-actions-widget.mjs.map +0 -1
- package/dist/client/components/widgets/recent-items-widget.d.mts +0 -51
- package/dist/client/components/widgets/recent-items-widget.d.mts.map +0 -1
- package/dist/client/components/widgets/recent-items-widget.mjs.map +0 -1
- package/dist/client/components/widgets/stats-widget.d.mts +0 -55
- package/dist/client/components/widgets/stats-widget.d.mts.map +0 -1
- package/dist/client/components/widgets/stats-widget.mjs.map +0 -1
- package/dist/client/components/widgets/table-widget.d.mts +0 -31
- package/dist/client/components/widgets/table-widget.d.mts.map +0 -1
- package/dist/client/components/widgets/table-widget.mjs.map +0 -1
- package/dist/client/components/widgets/timeline-widget.d.mts +0 -51
- package/dist/client/components/widgets/timeline-widget.d.mts.map +0 -1
- package/dist/client/components/widgets/timeline-widget.mjs.map +0 -1
- package/dist/client/components/widgets/value-widget.d.mts +0 -39
- package/dist/client/components/widgets/value-widget.d.mts.map +0 -1
- package/dist/client/components/widgets/value-widget.mjs.map +0 -1
- package/dist/client/components/widgets/widget-skeletons.mjs.map +0 -1
- package/dist/client/context/focus-context.d.mts.map +0 -1
- package/dist/client/context/focus-context.mjs.map +0 -1
- package/dist/client/contexts/breadcrumb-context.mjs.map +0 -1
- package/dist/client/hooks/typed-hooks.d.mts.map +0 -1
- package/dist/client/hooks/typed-hooks.mjs.map +0 -1
- package/dist/client/hooks/use-action.mjs.map +0 -1
- package/dist/client/hooks/use-admin-config.mjs.map +0 -1
- package/dist/client/hooks/use-admin-preferences.mjs.map +0 -1
- package/dist/client/hooks/use-admin-routes.mjs.map +0 -1
- package/dist/client/hooks/use-auth.d.mts.map +0 -1
- package/dist/client/hooks/use-auth.mjs.map +0 -1
- package/dist/client/hooks/use-collection-fields.mjs.map +0 -1
- package/dist/client/hooks/use-collection-meta.mjs.map +0 -1
- package/dist/client/hooks/use-collection-schema.mjs.map +0 -1
- package/dist/client/hooks/use-collection-validation.mjs.map +0 -1
- package/dist/client/hooks/use-collection.d.mts.map +0 -1
- package/dist/client/hooks/use-collection.mjs.map +0 -1
- package/dist/client/hooks/use-current-user.d.mts.map +0 -1
- package/dist/client/hooks/use-current-user.mjs.map +0 -1
- package/dist/client/hooks/use-field-hooks.mjs.map +0 -1
- package/dist/client/hooks/use-field-options.d.mts.map +0 -1
- package/dist/client/hooks/use-field-options.mjs.map +0 -1
- package/dist/client/hooks/use-global-fields.mjs.map +0 -1
- package/dist/client/hooks/use-global-meta.mjs.map +0 -1
- package/dist/client/hooks/use-global-schema.mjs.map +0 -1
- package/dist/client/hooks/use-global.d.mts.map +0 -1
- package/dist/client/hooks/use-global.mjs.map +0 -1
- package/dist/client/hooks/use-locks.mjs.map +0 -1
- package/dist/client/hooks/use-media-query.d.mts.map +0 -1
- package/dist/client/hooks/use-media-query.mjs.map +0 -1
- package/dist/client/hooks/use-prefill-params.mjs.map +0 -1
- package/dist/client/hooks/use-questpie-query-options.mjs.map +0 -1
- package/dist/client/hooks/use-reactive-fields.d.mts.map +0 -1
- package/dist/client/hooks/use-reactive-fields.mjs.map +0 -1
- package/dist/client/hooks/use-realtime-highlight.mjs.map +0 -1
- package/dist/client/hooks/use-saved-views.mjs.map +0 -1
- package/dist/client/hooks/use-search.mjs.map +0 -1
- package/dist/client/hooks/use-server-validation.mjs.map +0 -1
- package/dist/client/hooks/use-server-widget-data.d.mts.map +0 -1
- package/dist/client/hooks/use-server-widget-data.mjs.map +0 -1
- package/dist/client/hooks/use-setup-status.d.mts.map +0 -1
- package/dist/client/hooks/use-setup-status.mjs.map +0 -1
- package/dist/client/hooks/use-upload-collection.mjs.map +0 -1
- package/dist/client/hooks/use-upload.d.mts +0 -23
- package/dist/client/hooks/use-upload.d.mts.map +0 -1
- package/dist/client/hooks/use-upload.mjs.map +0 -1
- package/dist/client/hooks/use-validation-error-map.mjs.map +0 -1
- package/dist/client/hooks/use-view-state.mjs.map +0 -1
- package/dist/client/i18n/hooks.mjs.map +0 -1
- package/dist/client/i18n/intl-cache.mjs.map +0 -1
- package/dist/client/i18n/messages.mjs.map +0 -1
- package/dist/client/i18n/simple.d.mts.map +0 -1
- package/dist/client/i18n/simple.mjs.map +0 -1
- package/dist/client/i18n/types.d.mts.map +0 -1
- package/dist/client/lib/utils.d.mts +0 -1
- package/dist/client/lib/utils.mjs.map +0 -1
- package/dist/client/preview/block-scope-context.d.mts.map +0 -1
- package/dist/client/preview/block-scope-context.mjs.map +0 -1
- package/dist/client/preview/preview-banner.d.mts.map +0 -1
- package/dist/client/preview/preview-banner.mjs.map +0 -1
- package/dist/client/preview/preview-field.d.mts.map +0 -1
- package/dist/client/preview/preview-field.mjs.map +0 -1
- package/dist/client/preview/types.d.mts.map +0 -1
- package/dist/client/preview/types.mjs.map +0 -1
- package/dist/client/preview/use-collection-preview.d.mts.map +0 -1
- package/dist/client/preview/use-collection-preview.mjs.map +0 -1
- package/dist/client/runtime/content-locales-provider.mjs.map +0 -1
- package/dist/client/runtime/locale-scope.mjs.map +0 -1
- package/dist/client/runtime/provider.d.mts.map +0 -1
- package/dist/client/runtime/provider.mjs.map +0 -1
- package/dist/client/runtime/routes.d.mts.map +0 -1
- package/dist/client/runtime/routes.mjs.map +0 -1
- package/dist/client/runtime/translations-provider.d.mts +0 -2
- package/dist/client/runtime/translations-provider.mjs.map +0 -1
- package/dist/client/scope/picker.d.mts.map +0 -1
- package/dist/client/scope/picker.mjs.map +0 -1
- package/dist/client/scope/provider.d.mts.map +0 -1
- package/dist/client/scope/provider.mjs.map +0 -1
- package/dist/client/scope/types.d.mts.map +0 -1
- package/dist/client/utils/auto-expand-fields.mjs.map +0 -1
- package/dist/client/utils/build-field-definitions-from-schema.mjs.map +0 -1
- package/dist/client/utils/detect-relations.mjs.map +0 -1
- package/dist/client/utils/locale-to-flag.d.mts.map +0 -1
- package/dist/client/utils/locale-to-flag.mjs.map +0 -1
- package/dist/client/utils/routes.mjs.map +0 -1
- package/dist/client/views/auth/accept-invite-form.d.mts.map +0 -1
- package/dist/client/views/auth/accept-invite-form.mjs.map +0 -1
- package/dist/client/views/auth/auth-layout.d.mts.map +0 -1
- package/dist/client/views/auth/auth-layout.mjs.map +0 -1
- package/dist/client/views/auth/forgot-password-form.d.mts.map +0 -1
- package/dist/client/views/auth/forgot-password-form.mjs.map +0 -1
- package/dist/client/views/auth/index.d.mts +0 -7
- package/dist/client/views/auth/invite-form.d.mts +0 -1
- package/dist/client/views/auth/invite-form.mjs.map +0 -1
- package/dist/client/views/auth/login-form.d.mts.map +0 -1
- package/dist/client/views/auth/login-form.mjs.map +0 -1
- package/dist/client/views/auth/reset-password-form.d.mts.map +0 -1
- package/dist/client/views/auth/reset-password-form.mjs.map +0 -1
- package/dist/client/views/auth/setup-form.d.mts.map +0 -1
- package/dist/client/views/auth/setup-form.mjs.map +0 -1
- package/dist/client/views/collection/auto-form-fields.d.mts +0 -4
- package/dist/client/views/collection/auto-form-fields.mjs.map +0 -1
- package/dist/client/views/collection/bulk-action-toolbar.mjs.map +0 -1
- package/dist/client/views/collection/cells/complex-cells.d.mts +0 -46
- package/dist/client/views/collection/cells/complex-cells.d.mts.map +0 -1
- package/dist/client/views/collection/cells/complex-cells.mjs.map +0 -1
- package/dist/client/views/collection/cells/index.d.mts +0 -7
- package/dist/client/views/collection/cells/primitive-cells.d.mts +0 -76
- package/dist/client/views/collection/cells/primitive-cells.d.mts.map +0 -1
- package/dist/client/views/collection/cells/primitive-cells.mjs.map +0 -1
- package/dist/client/views/collection/cells/relation-cells.d.mts +0 -21
- package/dist/client/views/collection/cells/relation-cells.d.mts.map +0 -1
- package/dist/client/views/collection/cells/relation-cells.mjs.map +0 -1
- package/dist/client/views/collection/cells/shared/asset-thumbnail.d.mts +0 -1
- package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs.map +0 -1
- package/dist/client/views/collection/cells/shared/cell-helpers.d.mts +0 -2
- package/dist/client/views/collection/cells/shared/cell-helpers.mjs.map +0 -1
- package/dist/client/views/collection/cells/shared/relation-chip.d.mts +0 -1
- package/dist/client/views/collection/cells/shared/relation-chip.mjs.map +0 -1
- package/dist/client/views/collection/cells/upload-cells.d.mts +0 -25
- package/dist/client/views/collection/cells/upload-cells.d.mts.map +0 -1
- package/dist/client/views/collection/cells/upload-cells.mjs.map +0 -1
- package/dist/client/views/collection/columns/build-columns.d.mts +0 -2
- package/dist/client/views/collection/columns/build-columns.mjs.map +0 -1
- package/dist/client/views/collection/columns/column-defaults.d.mts +0 -2
- package/dist/client/views/collection/columns/column-defaults.mjs.map +0 -1
- package/dist/client/views/collection/columns/index.d.mts +0 -3
- package/dist/client/views/collection/columns/types.d.mts +0 -2
- package/dist/client/views/collection/field-context.mjs.map +0 -1
- package/dist/client/views/collection/field-renderer.mjs.map +0 -1
- package/dist/client/views/collection/form-view.d.mts +0 -112
- package/dist/client/views/collection/form-view.d.mts.map +0 -1
- package/dist/client/views/collection/form-view.mjs.map +0 -1
- package/dist/client/views/collection/index.d.mts +0 -9
- package/dist/client/views/collection/table-view.d.mts +0 -102
- package/dist/client/views/collection/table-view.d.mts.map +0 -1
- package/dist/client/views/collection/table-view.mjs.map +0 -1
- package/dist/client/views/collection/view-skeletons.mjs.map +0 -1
- package/dist/client/views/common/global-search.d.mts +0 -1
- package/dist/client/views/common/global-search.mjs.map +0 -1
- package/dist/client/views/common/index.d.mts +0 -1
- package/dist/client/views/dashboard/dashboard-grid.mjs.map +0 -1
- package/dist/client/views/dashboard/dashboard-widget.mjs.map +0 -1
- package/dist/client/views/dashboard/widget-card.mjs.map +0 -1
- package/dist/client/views/globals/global-form-view.d.mts +0 -74
- package/dist/client/views/globals/global-form-view.d.mts.map +0 -1
- package/dist/client/views/globals/global-form-view.mjs.map +0 -1
- package/dist/client/views/index.d.mts +0 -28
- package/dist/client/views/layout/admin-layout-provider.d.mts.map +0 -1
- package/dist/client/views/layout/admin-layout-provider.mjs.map +0 -1
- package/dist/client/views/layout/admin-layout.d.mts.map +0 -1
- package/dist/client/views/layout/admin-layout.mjs.map +0 -1
- package/dist/client/views/layout/admin-root.d.mts +0 -7
- package/dist/client/views/layout/admin-router.d.mts.map +0 -1
- package/dist/client/views/layout/admin-router.mjs.map +0 -1
- package/dist/client/views/layout/admin-sidebar.d.mts.map +0 -1
- package/dist/client/views/layout/admin-sidebar.mjs.map +0 -1
- package/dist/client/views/layout/admin-topbar.mjs.map +0 -1
- package/dist/client/views/layout/index.d.mts +0 -5
- package/dist/client/views/pages/accept-invite-page.d.mts.map +0 -1
- package/dist/client/views/pages/accept-invite-page.mjs.map +0 -1
- package/dist/client/views/pages/dashboard-page.d.mts.map +0 -1
- package/dist/client/views/pages/dashboard-page.mjs.map +0 -1
- package/dist/client/views/pages/forgot-password-page.d.mts.map +0 -1
- package/dist/client/views/pages/forgot-password-page.mjs.map +0 -1
- package/dist/client/views/pages/index.d.mts +0 -7
- package/dist/client/views/pages/invite-page.d.mts.map +0 -1
- package/dist/client/views/pages/invite-page.mjs.map +0 -1
- package/dist/client/views/pages/login-page.d.mts.map +0 -1
- package/dist/client/views/pages/login-page.mjs.map +0 -1
- package/dist/client/views/pages/reset-password-page.d.mts.map +0 -1
- package/dist/client/views/pages/reset-password-page.mjs.map +0 -1
- package/dist/client/views/pages/setup-page.d.mts.map +0 -1
- package/dist/client/views/pages/setup-page.mjs.map +0 -1
- package/dist/client.d.mts.map +0 -1
- package/dist/components/rich-text/rich-text-renderer.d.mts.map +0 -1
- package/dist/components/rich-text/rich-text-renderer.mjs.map +0 -1
- package/dist/server/adapters/nextjs.d.mts.map +0 -1
- package/dist/server/adapters/nextjs.mjs.map +0 -1
- package/dist/server/adapters/tanstack.d.mts.map +0 -1
- package/dist/server/adapters/tanstack.mjs.map +0 -1
- package/dist/server/augmentation.d.mts.map +0 -1
- package/dist/server/auth-helpers.d.mts.map +0 -1
- package/dist/server/auth-helpers.mjs.map +0 -1
- package/dist/server/block/block-builder.d.mts.map +0 -1
- package/dist/server/block/block-builder.mjs.map +0 -1
- package/dist/server/block/introspection.d.mts.map +0 -1
- package/dist/server/block/introspection.mjs.map +0 -1
- package/dist/server/block/prefetch.d.mts.map +0 -1
- package/dist/server/block/prefetch.mjs.map +0 -1
- package/dist/server/fields/blocks.d.mts.map +0 -1
- package/dist/server/fields/blocks.mjs.map +0 -1
- package/dist/server/fields/index.d.mts.map +0 -1
- package/dist/server/fields/index.mjs.map +0 -1
- package/dist/server/fields/rich-text.d.mts.map +0 -1
- package/dist/server/fields/rich-text.mjs.map +0 -1
- package/dist/server/i18n/index.d.mts +0 -16
- package/dist/server/i18n/index.d.mts.map +0 -1
- package/dist/server/i18n/index.mjs.map +0 -1
- package/dist/server/i18n/messages/cs.mjs.map +0 -1
- package/dist/server/i18n/messages/de.mjs.map +0 -1
- package/dist/server/i18n/messages/en.mjs.map +0 -1
- package/dist/server/i18n/messages/es.mjs.map +0 -1
- package/dist/server/i18n/messages/fr.mjs.map +0 -1
- package/dist/server/i18n/messages/index.mjs.map +0 -1
- package/dist/server/i18n/messages/pl.mjs.map +0 -1
- package/dist/server/i18n/messages/pt.mjs.map +0 -1
- package/dist/server/i18n/messages/sk.mjs.map +0 -1
- package/dist/server/index.d.mts +0 -20
- package/dist/server/modules/admin/functions/admin-config.mjs +0 -348
- package/dist/server/modules/admin/functions/admin-config.mjs.map +0 -1
- package/dist/server/modules/admin/functions/execute-action.d.mts.map +0 -1
- package/dist/server/modules/admin/functions/execute-action.mjs.map +0 -1
- package/dist/server/modules/admin/functions/locales.mjs +0 -80
- package/dist/server/modules/admin/functions/locales.mjs.map +0 -1
- package/dist/server/modules/admin/functions/preview.d.mts.map +0 -1
- package/dist/server/modules/admin/functions/preview.mjs.map +0 -1
- package/dist/server/modules/admin/functions/reactive.d.mts.map +0 -1
- package/dist/server/modules/admin/functions/reactive.mjs.map +0 -1
- package/dist/server/modules/admin/functions/setup.d.mts.map +0 -1
- package/dist/server/modules/admin/functions/setup.mjs +0 -131
- package/dist/server/modules/admin/functions/setup.mjs.map +0 -1
- package/dist/server/modules/admin/functions/translations.mjs +0 -125
- package/dist/server/modules/admin/functions/translations.mjs.map +0 -1
- package/dist/server/modules/admin/functions/widget-data.d.mts +0 -33
- package/dist/server/modules/admin/functions/widget-data.d.mts.map +0 -1
- package/dist/server/modules/admin/functions/widget-data.mjs +0 -70
- package/dist/server/modules/admin/functions/widget-data.mjs.map +0 -1
- package/dist/server/modules/admin/index.d.mts.map +0 -1
- package/dist/server/modules/admin/index.mjs.map +0 -1
- package/dist/server/modules/admin-preferences/collections/admin-preferences.collection.d.mts +0 -3
- package/dist/server/modules/admin-preferences/collections/admin-preferences.collection.mjs.map +0 -1
- package/dist/server/modules/admin-preferences/collections/locks.collection.d.mts +0 -3
- package/dist/server/modules/admin-preferences/collections/locks.collection.mjs.map +0 -1
- package/dist/server/modules/admin-preferences/collections/saved-views.collection.d.mts +0 -1490
- package/dist/server/modules/admin-preferences/collections/saved-views.collection.d.mts.map +0 -1
- package/dist/server/modules/admin-preferences/collections/saved-views.collection.mjs +0 -57
- package/dist/server/modules/admin-preferences/collections/saved-views.collection.mjs.map +0 -1
- package/dist/server/patch.d.mts +0 -100
- package/dist/server/patch.d.mts.map +0 -1
- package/dist/server/patch.mjs +0 -1062
- package/dist/server/patch.mjs.map +0 -1
- package/dist/shared/preview-utils.d.mts.map +0 -1
- package/dist/shared/preview-utils.mjs.map +0 -1
- package/dist/shared/types/saved-views.types.d.mts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"focus-context.d.mts","names":[],"sources":["../../../src/client/context/focus-context.tsx"],"sourcesContent":[],"mappings":";;;;;;;;;;AA6IA;AAWA;AAOgB,KAxIJ,UAAA,GAwIqB;EASjB,IAAA,EAAA,MAAA;AAkBhB,CAAA,GAAgB;EAgEA,IAAA,EAAA,OAAA;;;;;;;;;;;KA7NJ,iBAAA;;SAEH;;;;;;;;;;;;;;KAyBG,kBAAA;YACA,OAAA,CAAM;;0BAEQ;;iBAGV,aAAA;;;GAA2C,qBAAkB,mBAAA,CAAA,GAAA,CAAA;;;;iBA+E7D,QAAA,CAAA,GAAY;;;;iBAWZ,gBAAA,CAAA,GAAoB;;;;iBAOpB,iBAAA;;;;iBASA,iBAAA;;;;;;;;;iBAkBA,qBAAA;;;;IAOb;;;;;iBAyDa,mBAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"focus-context.mjs","names":["React","newState: FocusState"],"sources":["../../../src/client/context/focus-context.tsx"],"sourcesContent":["/**\n * Focus Context\n *\n * State machine for managing field focus across the form editor.\n * Supports focusing regular fields and nested block fields.\n * Used for preview click-to-focus functionality.\n */\n\n\"use client\";\n\nimport * as React from \"react\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Focus state types:\n * - idle: nothing focused\n * - field: regular field focused (e.g., \"title\", \"slug\")\n * - block: block field focused, optionally with specific field within block\n * - relation: relation field focused (opens ResourceSheet for editing)\n */\nexport type FocusState =\n | { type: \"idle\" }\n | { type: \"field\"; fieldPath: string }\n | { type: \"block\"; blockId: string; fieldPath?: string }\n | { type: \"relation\"; fieldPath: string; targetCollection?: string };\n\nexport type FocusContextValue = {\n /** Current focus state */\n state: FocusState;\n /** Focus a regular field by path */\n focusField: (fieldPath: string) => void;\n /** Focus a block, optionally a specific field within it */\n focusBlock: (blockId: string, fieldPath?: string) => void;\n /** Focus a relation field (opens ResourceSheet) */\n focusRelation: (fieldPath: string, targetCollection?: string) => void;\n /** Clear focus */\n clearFocus: () => void;\n /** Check if a field is focused */\n isFieldFocused: (fieldPath: string) => boolean;\n /** Check if a block is focused */\n isBlockFocused: (blockId: string) => boolean;\n};\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst FocusContext = React.createContext<FocusContextValue | null>(null);\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport type FocusProviderProps = {\n children: React.ReactNode;\n /** Callback when focus changes - useful for scrolling to field */\n onFocusChange?: (state: FocusState) => void;\n};\n\nexport function FocusProvider({ children, onFocusChange }: FocusProviderProps) {\n const [state, setState] = React.useState<FocusState>({ type: \"idle\" });\n\n // Use functional setState for stable callbacks (React best practice)\n const focusField = React.useCallback(\n (fieldPath: string) => {\n const newState: FocusState = { type: \"field\", fieldPath };\n setState(newState);\n onFocusChange?.(newState);\n },\n [onFocusChange],\n );\n\n const focusBlock = React.useCallback(\n (blockId: string, fieldPath?: string) => {\n const newState: FocusState = { type: \"block\", blockId, fieldPath };\n setState(newState);\n onFocusChange?.(newState);\n },\n [onFocusChange],\n );\n\n const focusRelation = React.useCallback(\n (fieldPath: string, targetCollection?: string) => {\n const newState: FocusState = {\n type: \"relation\",\n fieldPath,\n targetCollection,\n };\n setState(newState);\n onFocusChange?.(newState);\n },\n [onFocusChange],\n );\n\n const clearFocus = React.useCallback(() => {\n const newState: FocusState = { type: \"idle\" };\n setState(newState);\n onFocusChange?.(newState);\n }, [onFocusChange]);\n\n // Derive focused field/block from state for direct comparison\n const focusedFieldPath = state.type === \"field\" ? state.fieldPath : undefined;\n const focusedBlockId = state.type === \"block\" ? state.blockId : undefined;\n\n const value = React.useMemo(\n (): FocusContextValue => ({\n state,\n focusField,\n focusBlock,\n focusRelation,\n clearFocus,\n // Simple equality checks - no callback overhead\n isFieldFocused: (path: string) => focusedFieldPath === path,\n isBlockFocused: (id: string) => focusedBlockId === id,\n }),\n [\n state,\n focusField,\n focusBlock,\n focusRelation,\n clearFocus,\n focusedFieldPath,\n focusedBlockId,\n ],\n );\n\n return (\n <FocusContext.Provider value={value}>{children}</FocusContext.Provider>\n );\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Use the focus context\n */\nexport function useFocus(): FocusContextValue {\n const context = React.useContext(FocusContext);\n if (!context) {\n throw new Error(\"useFocus must be used within a FocusProvider\");\n }\n return context;\n}\n\n/**\n * Use focus context if available (doesn't throw)\n */\nexport function useFocusOptional(): FocusContextValue | null {\n return React.useContext(FocusContext);\n}\n\n/**\n * Hook for checking if a specific field is focused\n */\nexport function useIsFieldFocused(fieldPath: string): boolean {\n const context = React.useContext(FocusContext);\n if (!context) return false;\n return context.isFieldFocused(fieldPath);\n}\n\n/**\n * Hook for checking if a specific block is focused\n */\nexport function useIsBlockFocused(blockId: string): boolean {\n const context = React.useContext(FocusContext);\n if (!context) return false;\n return context.isBlockFocused(blockId);\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Parse a preview field path into focus state with optional context hints\n * Examples:\n * - \"title\" → { type: \"field\", fieldPath: \"title\" }\n * - \"content._values.abc123.title\" → { type: \"block\", blockId: \"abc123\", fieldPath: \"title\" }\n * - \"author\" + { fieldType: \"relation\" } → { type: \"relation\", fieldPath: \"author\" }\n * - \"title\" + { blockId: \"abc123\" } → { type: \"block\", blockId: \"abc123\", fieldPath: \"title\" }\n */\nexport function parsePreviewFieldPath(\n path: string,\n context?: {\n blockId?: string;\n fieldType?: \"regular\" | \"block\" | \"relation\";\n targetCollection?: string;\n },\n): FocusState {\n // Relation field from context\n if (context?.fieldType === \"relation\") {\n return {\n type: \"relation\",\n fieldPath: path,\n targetCollection: context.targetCollection,\n };\n }\n\n // Check if it's a block field path (content._values.{id}.{field})\n const blockMatch = path.match(/^content\\._values\\.([^.]+)(?:\\.(.+))?$/);\n if (blockMatch) {\n const [, blockId, fieldPath] = blockMatch;\n return { type: \"block\", blockId, fieldPath };\n }\n\n // Legacy block path format (content.blocks.{id}.{field})\n const legacyBlockMatch = path.match(/^content\\.blocks\\.([^.]+)(?:\\.(.+))?$/);\n if (legacyBlockMatch) {\n const [, blockId, fieldPath] = legacyBlockMatch;\n return { type: \"block\", blockId, fieldPath };\n }\n\n // Block field from context hint\n if (context?.blockId) {\n // Extract relative field path if present\n const relativeField = extractRelativeField(path, context.blockId);\n return {\n type: \"block\",\n blockId: context.blockId,\n fieldPath: relativeField,\n };\n }\n\n // Regular field\n return { type: \"field\", fieldPath: path };\n}\n\n/**\n * Extract relative field path from a full path given a block ID\n * Examples:\n * - extractRelativeField(\"content._values.abc123.title\", \"abc123\") → \"title\"\n * - extractRelativeField(\"title\", \"abc123\") → \"title\"\n */\nfunction extractRelativeField(path: string, blockId: string): string {\n const prefix = `content._values.${blockId}.`;\n if (path.startsWith(prefix)) {\n return path.slice(prefix.length);\n }\n return path;\n}\n\n/**\n * Scroll a field into view and focus it.\n * Finds the field wrapper by data-field-path within the preview form scope.\n */\nexport function scrollFieldIntoView(fieldPath: string): void {\n // First try to find within the preview form scope (to avoid matching fields in other forms)\n const formScope = document.querySelector<HTMLElement>(\n \"[data-preview-form-scope]\",\n );\n const searchRoot = formScope ?? document;\n\n const wrapper = searchRoot.querySelector<HTMLElement>(\n `[data-field-path=\"${fieldPath}\"]`,\n );\n if (!wrapper) return;\n\n // Find first focusable element inside the wrapper\n const focusable = wrapper.querySelector<HTMLElement>(\n 'input:not([type=\"hidden\"]), textarea, button, select, [tabindex]:not([tabindex=\"-1\"]), [contenteditable=\"true\"]',\n );\n\n const target = focusable ?? wrapper;\n target.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n\n if (focusable) {\n // Use requestAnimationFrame to focus after scroll starts\n requestAnimationFrame(() => {\n // Pull focus from iframe back to parent window\n window.focus();\n focusable.focus();\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"breadcrumb-context.mjs","names":["React"],"sources":["../../../src/client/contexts/breadcrumb-context.tsx"],"sourcesContent":["import * as React from \"react\";\nimport type { I18nText } from \"../i18n/types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Simple icon component type for breadcrumbs\n */\ntype BreadcrumbIcon = React.ComponentType<{ className?: string }>;\n\n/**\n * Menu item for breadcrumb dropdown\n */\nexport interface BreadcrumbMenuItem {\n label: I18nText;\n href: string;\n icon?: BreadcrumbIcon;\n}\n\n/**\n * Single breadcrumb item\n */\nexport interface Breadcrumb {\n /**\n * Display label (supports I18nText for localization)\n */\n label: I18nText;\n\n /**\n * Navigation href (optional - last item usually doesn't have one)\n */\n href?: string;\n\n /**\n * Icon component (optional)\n */\n icon?: BreadcrumbIcon;\n\n /**\n * Dropdown menu items for quick navigation\n * e.g., switch between collections or items\n */\n menu?: {\n items: BreadcrumbMenuItem[];\n };\n}\n\n/**\n * Breadcrumb context value\n */\ninterface BreadcrumbContextValue {\n breadcrumbs: Breadcrumb[];\n setBreadcrumbs: (breadcrumbs: Breadcrumb[]) => void;\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst BreadcrumbContext = React.createContext<BreadcrumbContextValue | null>(\n null,\n);\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport interface BreadcrumbProviderProps {\n children: React.ReactNode;\n}\n\nexport function BreadcrumbProvider({\n children,\n}: BreadcrumbProviderProps): React.ReactElement {\n const [breadcrumbs, setBreadcrumbs] = React.useState<Breadcrumb[]>([]);\n\n const value = React.useMemo(\n () => ({\n breadcrumbs,\n setBreadcrumbs,\n }),\n [breadcrumbs],\n );\n\n return (\n <BreadcrumbContext.Provider value={value}>\n {children}\n </BreadcrumbContext.Provider>\n );\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Get breadcrumb context\n * @throws if used outside BreadcrumbProvider\n */\nexport function useBreadcrumbContext(): BreadcrumbContextValue {\n const context = React.useContext(BreadcrumbContext);\n if (!context) {\n throw new Error(\n \"useBreadcrumbContext must be used within a BreadcrumbProvider\",\n );\n }\n return context;\n}\n\n/**\n * Get breadcrumb context (optional - returns null if not in provider)\n */\nexport function useBreadcrumbContextOptional(): BreadcrumbContextValue | null {\n return React.useContext(BreadcrumbContext);\n}\n\n/**\n * Set breadcrumbs for the current page\n * Automatically cleans up on unmount\n *\n * @example\n * ```tsx\n * function PostsListPage() {\n * useBreadcrumbs([\n * { label: \"Dashboard\", href: \"/admin\", icon: House },\n * { label: \"Posts\", icon: Article },\n * ]);\n *\n * return <div>...</div>;\n * }\n * ```\n */\nexport function useBreadcrumbs(breadcrumbs: Breadcrumb[]): void {\n const context = useBreadcrumbContextOptional();\n\n React.useEffect(() => {\n if (!context) return;\n\n context.setBreadcrumbs(breadcrumbs);\n\n return () => {\n context.setBreadcrumbs([]);\n };\n }, [context, breadcrumbs]);\n}\n\n/**\n * Get current breadcrumbs (read-only)\n */\nexport function useCurrentBreadcrumbs(): Breadcrumb[] {\n const context = useBreadcrumbContextOptional();\n return context?.breadcrumbs ?? [];\n}\n"],"mappings":";;;;AA6DA,MAAM,oBAAoBA,QAAM,cAC9B,KACD;AAUD,SAAgB,mBAAmB,EACjC,YAC8C;CAC9C,MAAM,CAAC,aAAa,kBAAkBA,QAAM,SAAuB,EAAE,CAAC;CAEtE,MAAM,QAAQA,QAAM,eACX;EACL;EACA;EACD,GACD,CAAC,YAAY,CACd;AAED,QACE,oBAAC,kBAAkB;EAAgB;EAChC;GAC0B;;;;;AAyBjC,SAAgB,+BAA8D;AAC5E,QAAOA,QAAM,WAAW,kBAAkB;;;;;AAoC5C,SAAgB,wBAAsC;AAEpD,QADgB,8BAA8B,EAC9B,eAAe,EAAE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typed-hooks.d.mts","names":[],"sources":["../../../src/client/hooks/typed-hooks.ts"],"sourcesContent":[],"mappings":";;;;;;;;KA6CK,eAkD4C,CAAA,aAlDf,QAkDe,CAAA,GAAA,CAAA,CAAA,GAAA,MAjD1C,IAiD0C,CAAA,QAAA,CAAA,CAAA,aAAA,CAAA,GAAA,MAAA;;;;KA5C5C,WA8Ce,CAAA,aA9CU,QA8CV,CAAA,GAAA,CAAA,CAAA,GA7CnB,IA6CmB,SA7CN,QA6CM,CAAA,KAAA,QAAA,CAAA,GAAA,MA5CV,OA4CU,CAAA,SAAA,CAAA,GAAA,MAAA,GAAA,KAAA;AAM6B,UA3ChC,UA2CgC,CAAA,aA3CR,QA2CQ,CAAA,GAAA,CAAA,CAAA,CAAA;EAAhB;;;EAEb,iBAAA,EAAA,CAAA,UAzCW,eAyCX,CAzC2B,IAyC3B,CAAA,CAAA,CAAA,UAAA,EAxCN,CAwCM,EAAA,OAAA,CAAA,EAAA,GAAA,EAAA,YAAA,CAAA,EAtCH,IAsCG,CAtCE,eAsCF,EAAA,UAAA,GAAA,SAAA,CAAA,EAAA,GAAA,GAAA;EAM6B;;;EAExB,kBAAA,EAAA,CAAA,UAxCO,eAwCP,CAxCuB,IAwCvB,CAAA,CAAA,CAAA,UAAA,EAvCX,CAuCW,EAAA,OAMF,CANE,EAAA;IAAL,KAAA,CAAA,EAAA,GAAA;IAMe,cAAA,CAAA,EAAA,OAAA;EAAZ,CAAA,EAAA,YAAA,CAAA,EA3CN,IA2CM,CA3CD,eA2CC,EAAA,UAAA,GAAA,SAAA,CAAA,EAAA,GAAA,GAAA;EACT;;;EAQ2B,iBAAA,EAAA,CAAA,UA9CV,eA8CU,CA9CM,IA8CN,CAAA,CAAA,CAAA,UAAA,EA7C3B,CA6C2B,EAAA,EAAA,EAAA,MAAA,EAAA,OAEhB,CAFgB,EAAA;IAAZ,cAAA,CAAA,EAAA,OAAA;IACf,IAAA,CAAA,EA1CJ,MA0CI,CAAA,MAAA,EAAA,OAAA,CAAA;EACW,CAAA,EAAA,YAAA,CAAA,EAzCR,IAyCQ,CAzCH,eAyCG,EAAA,UAAA,GAAA,SAAA,CAAA,EAAA,GAAA,GAAA;EAAL;;AAmCpB;EACc,mBAAA,EAAA,CAAA,UAvEmB,eAuEnB,CAvEmC,IAuEnC,CAAA,CAAA,CAAA,UAAA,EAtEA,CAsEA,EAAA,eAAA,CAAA,EArEM,IAqEN,CArEW,kBAqEX,EAAA,YAAA,CAAA,EAAA,GAAA,GAAA;EACE;;;kCAhEiB,gBAAgB,mBACnC,qBACM,KAAK;;;;kCAMQ,gBAAgB,mBACnC,qBACM,KAAK;;;;wBAMF,YAAY,mBACrB,iCAEG,KAAK;;;;8BAMO,YAAY,mBAC3B,qBACM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmCT,8BACF,kBACT,WAAW"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typed-hooks.mjs","names":[],"sources":["../../../src/client/hooks/typed-hooks.ts"],"sourcesContent":["/**\n * Typed Hooks Factory\n *\n * Creates type-safe React hooks for collections and globals without module augmentation.\n * This is the recommended approach for new projects.\n *\n * @example\n * ```ts\n * // In your admin setup file:\n * import type { AppCMS } from './server/cms';\n * import { createTypedHooks } from '@questpie/admin/client';\n *\n * export const {\n * useCollectionList,\n * useCollectionItem,\n * useCollectionCreate,\n * useCollectionUpdate,\n * useCollectionDelete,\n * useCollectionCount,\n * useGlobal,\n * useGlobalUpdate,\n * } = createTypedHooks<AppCMS>();\n * ```\n */\n\nimport { createQuestpieQueryOptions } from \"@questpie/tanstack-query\";\nimport {\n\ttype UseMutationOptions,\n\ttype UseQueryOptions,\n\tuseMutation,\n\tuseQuery,\n\tuseQueryClient,\n} from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport type { QuestpieClient } from \"questpie/client\";\nimport { selectClient, useAdminStore, useScopedLocale } from \"../runtime\";\nimport { selectContentLocale } from \"../runtime/provider\";\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\n/**\n * Extract collection names from a Questpie app\n */\ntype CollectionNames<TApp extends Questpie<any>> =\n\tkeyof TApp[\"config\"][\"collections\"] & string;\n\n/**\n * Extract global names from a Questpie app\n */\ntype GlobalNames<TApp extends Questpie<any>> =\n\tTApp extends Questpie<infer TConfig>\n\t\t? keyof TConfig[\"globals\"] & string\n\t\t: never;\n\n// ============================================================================\n// Typed Hooks Interface\n// ============================================================================\n\nexport interface TypedHooks<TApp extends Questpie<any>> {\n\t/**\n\t * Hook to fetch collection list with filters, sorting, pagination\n\t */\n\tuseCollectionList: <K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\toptions?: any,\n\t\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\t) => any;\n\n\t/**\n\t * Hook to count collection items with optional filters\n\t */\n\tuseCollectionCount: <K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\toptions?: { where?: any; includeDeleted?: boolean },\n\t\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\t) => any;\n\n\t/**\n\t * Hook to fetch single collection item\n\t */\n\tuseCollectionItem: <K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\tid: string,\n\t\toptions?: {\n\t\t\tlocaleFallback?: boolean;\n\t\t\twith?: Record<string, boolean>;\n\t\t},\n\t\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\t) => any;\n\n\t/**\n\t * Hook to create collection item\n\t */\n\tuseCollectionCreate: <K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n\t) => any;\n\n\t/**\n\t * Hook to update collection item\n\t */\n\tuseCollectionUpdate: <K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n\t) => any;\n\n\t/**\n\t * Hook to delete collection item\n\t */\n\tuseCollectionDelete: <K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n\t) => any;\n\n\t/**\n\t * Hook to fetch global settings\n\t */\n\tuseGlobal: <K extends GlobalNames<TApp>>(\n\t\tglobalName: K,\n\t\toptions?: any,\n\t\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\t) => any;\n\n\t/**\n\t * Hook to update global settings\n\t */\n\tuseGlobalUpdate: <K extends GlobalNames<TApp>>(\n\t\tglobalName: K,\n\t\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n\t) => any;\n}\n\n// ============================================================================\n// Factory Implementation\n// ============================================================================\n\n/**\n * Create type-safe hooks for collections and globals.\n *\n * This factory creates hooks that are typed to your specific CMS configuration,\n * providing autocomplete for collection/global names without module augmentation.\n *\n * @example\n * ```ts\n * import type { AppCMS } from './server/cms';\n * import { createTypedHooks } from '@questpie/admin/client';\n *\n * // Create typed hooks\n * export const {\n * useCollectionList,\n * useCollectionItem,\n * useCollectionCreate,\n * useCollectionUpdate,\n * useCollectionDelete,\n * useGlobal,\n * useGlobalUpdate,\n * } = createTypedHooks<AppCMS>();\n *\n * // Usage - collection names are autocompleted!\n * const { data } = useCollectionList(\"barbers\");\n * const { data: settings } = useGlobal(\"siteSettings\");\n * ```\n */\nexport function createTypedHooks<\n\tTApp extends Questpie<any>,\n>(): TypedHooks<TApp> {\n\t// Collection list hook\n\tfunction useCollectionList<K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\toptions?: any,\n\t\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\t): any {\n\t\tconst client = useAdminStore(selectClient);\n\t\tconst { locale: contentLocale } = useScopedLocale();\n\t\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\t\tconst queryOpts = createQuestpieQueryOptions(\n\t\t\tclient as any,\n\t\t\t{\n\t\t\t\tkeyPrefix,\n\t\t\t\tlocale: contentLocale,\n\t\t\t} as any,\n\t\t);\n\n\t\treturn useQuery({\n\t\t\t...(queryOpts as any).collections[collection as string].find({\n\t\t\t\t...options,\n\t\t\t\tlocale: contentLocale,\n\t\t\t} as any),\n\t\t\t...queryOptions,\n\t\t});\n\t}\n\n\t// Collection count hook\n\tfunction useCollectionCount<K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\toptions?: { where?: any; includeDeleted?: boolean },\n\t\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\t): any {\n\t\tconst client = useAdminStore(selectClient);\n\t\tconst { locale: contentLocale } = useScopedLocale();\n\t\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\t\tconst queryOpts = createQuestpieQueryOptions(\n\t\t\tclient as any,\n\t\t\t{\n\t\t\t\tkeyPrefix,\n\t\t\t\tlocale: contentLocale,\n\t\t\t} as any,\n\t\t);\n\n\t\treturn useQuery({\n\t\t\t...(queryOpts as any).collections[collection as string].count({\n\t\t\t\t...options,\n\t\t\t\tlocale: contentLocale,\n\t\t\t} as any),\n\t\t\t...queryOptions,\n\t\t});\n\t}\n\n\t// Collection item hook\n\tfunction useCollectionItem<K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\tid: string,\n\t\toptions?: {\n\t\t\tlocaleFallback?: boolean;\n\t\t\twith?: Record<string, boolean>;\n\t\t},\n\t\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\t): any {\n\t\tconst client = useAdminStore(selectClient);\n\t\tconst { locale: contentLocale } = useScopedLocale();\n\t\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\t\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\t\tkeyPrefix,\n\t\t\tlocale: contentLocale,\n\t\t});\n\n\t\treturn useQuery({\n\t\t\t...(queryOpts as any).collections[collection as string].findOne({\n\t\t\t\twhere: { id },\n\t\t\t\tlocale: contentLocale,\n\t\t\t\t...options,\n\t\t\t}),\n\t\t\t...queryOptions,\n\t\t});\n\t}\n\n\t// Collection create hook\n\tfunction useCollectionCreate<K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n\t): any {\n\t\tconst client = useAdminStore(selectClient);\n\t\tconst { locale: contentLocale } = useScopedLocale();\n\t\tconst queryClient = useQueryClient();\n\t\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\t\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\t\tkeyPrefix,\n\t\t\tlocale: contentLocale,\n\t\t});\n\n\t\tconst baseOptions = queryOpts.collections[collection as string].create();\n\t\tconst listQueryKey = queryOpts.key([\n\t\t\t\"collections\",\n\t\t\tcollection as string,\n\t\t\t\"find\",\n\t\t\tcontentLocale,\n\t\t]);\n\t\tconst countQueryKey = queryOpts.key([\n\t\t\t\"collections\",\n\t\t\tcollection as string,\n\t\t\t\"count\",\n\t\t\tcontentLocale,\n\t\t]);\n\n\t\treturn useMutation({\n\t\t\t...baseOptions,\n\t\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t\t},\n\t\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: listQueryKey,\n\t\t\t\t});\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: countQueryKey,\n\t\t\t\t});\n\t\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t\t},\n\t\t\t...mutationOptions,\n\t\t} as any);\n\t}\n\n\t// Collection update hook\n\tfunction useCollectionUpdate<K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n\t): any {\n\t\tconst client = useAdminStore(selectClient);\n\t\tconst { locale: contentLocale } = useScopedLocale();\n\t\tconst queryClient = useQueryClient();\n\t\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\t\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\t\tkeyPrefix,\n\t\t\tlocale: contentLocale,\n\t\t});\n\n\t\tconst baseOptions = queryOpts.collections[collection as string].update();\n\t\tconst listQueryKey = queryOpts.key([\n\t\t\t\"collections\",\n\t\t\tcollection as string,\n\t\t\t\"find\",\n\t\t\tcontentLocale,\n\t\t]);\n\t\tconst countQueryKey = queryOpts.key([\n\t\t\t\"collections\",\n\t\t\tcollection as string,\n\t\t\t\"count\",\n\t\t\tcontentLocale,\n\t\t]);\n\t\tconst itemQueryKey = queryOpts.key([\n\t\t\t\"collections\",\n\t\t\tcollection as string,\n\t\t\t\"findOne\",\n\t\t\tcontentLocale,\n\t\t]);\n\n\t\treturn useMutation({\n\t\t\t...baseOptions,\n\t\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t\t},\n\t\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: listQueryKey,\n\t\t\t\t});\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: countQueryKey,\n\t\t\t\t});\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: itemQueryKey,\n\t\t\t\t});\n\t\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t\t},\n\t\t\t...mutationOptions,\n\t\t} as any);\n\t}\n\n\t// Collection delete hook\n\tfunction useCollectionDelete<K extends CollectionNames<TApp>>(\n\t\tcollection: K,\n\t\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n\t): any {\n\t\tconst client = useAdminStore(selectClient);\n\t\tconst { locale: contentLocale } = useScopedLocale();\n\t\tconst queryClient = useQueryClient();\n\t\tconst keyPrefix = [\"questpie\", \"collections\"] as const;\n\t\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\t\tkeyPrefix,\n\t\t\tlocale: contentLocale,\n\t\t});\n\n\t\tconst baseOptions = queryOpts.collections[collection as string].delete();\n\t\tconst listQueryKey = queryOpts.key([\n\t\t\t\"collections\",\n\t\t\tcollection as string,\n\t\t\t\"find\",\n\t\t\tcontentLocale,\n\t\t]);\n\t\tconst countQueryKey = queryOpts.key([\n\t\t\t\"collections\",\n\t\t\tcollection as string,\n\t\t\t\"count\",\n\t\t\tcontentLocale,\n\t\t]);\n\t\tconst itemQueryKey = queryOpts.key([\n\t\t\t\"collections\",\n\t\t\tcollection as string,\n\t\t\t\"findOne\",\n\t\t\tcontentLocale,\n\t\t]);\n\n\t\treturn useMutation({\n\t\t\t...baseOptions,\n\t\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t\t},\n\t\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: listQueryKey,\n\t\t\t\t});\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: countQueryKey,\n\t\t\t\t});\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: itemQueryKey,\n\t\t\t\t});\n\t\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t\t},\n\t\t\t...mutationOptions,\n\t\t} as any);\n\t}\n\n\t// Global hook\n\tfunction useGlobal<K extends GlobalNames<TApp>>(\n\t\tglobalName: K,\n\t\toptions?: any,\n\t\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\t): any {\n\t\tconst client = useAdminStore(selectClient);\n\t\tconst contentLocale = useAdminStore(selectContentLocale);\n\t\tconst keyPrefix = [\"questpie\", \"globals\"] as const;\n\t\tconst queryOpts = createQuestpieQueryOptions(\n\t\t\tclient as any,\n\t\t\t{\n\t\t\t\tkeyPrefix,\n\t\t\t\tlocale: contentLocale,\n\t\t\t} as any,\n\t\t);\n\n\t\treturn useQuery({\n\t\t\t...(queryOpts as any).globals[globalName as string].get({\n\t\t\t\t...options,\n\t\t\t\tlocale: contentLocale,\n\t\t\t} as any),\n\t\t\t...queryOptions,\n\t\t});\n\t}\n\n\t// Global update hook\n\tfunction useGlobalUpdate<K extends GlobalNames<TApp>>(\n\t\tglobalName: K,\n\t\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n\t): any {\n\t\tconst client = useAdminStore(selectClient);\n\t\tconst contentLocale = useAdminStore(selectContentLocale);\n\t\tconst queryClient = useQueryClient();\n\t\tconst keyPrefix = [\"questpie\", \"globals\"] as const;\n\t\tconst queryOpts = createQuestpieQueryOptions(\n\t\t\tclient as any,\n\t\t\t{\n\t\t\t\tkeyPrefix,\n\t\t\t\tlocale: contentLocale,\n\t\t\t} as any,\n\t\t);\n\n\t\tconst globalQueryKey = queryOpts.key([\n\t\t\t\"globals\",\n\t\t\tglobalName as string,\n\t\t\t\"get\",\n\t\t\tcontentLocale,\n\t\t]);\n\n\t\treturn useMutation({\n\t\t\t...(queryOpts as any).globals[globalName as string].update(),\n\t\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t\t},\n\t\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: globalQueryKey,\n\t\t\t\t});\n\t\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t\t},\n\t\t\t...mutationOptions,\n\t\t} as any);\n\t}\n\n\treturn {\n\t\tuseCollectionList,\n\t\tuseCollectionCount,\n\t\tuseCollectionItem,\n\t\tuseCollectionCreate,\n\t\tuseCollectionUpdate,\n\t\tuseCollectionDelete,\n\t\tuseGlobal,\n\t\tuseGlobalUpdate,\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-action.mjs","names":["React","actions: Required<ActionsConfig<TItem>>"],"sources":["../../../src/client/hooks/use-action.ts"],"sourcesContent":["/**\n * useAction Hook\n *\n * Provides action helpers and state management for collection actions.\n * Handles action execution, navigation, and API calls.\n */\n\n\"use client\";\n\nimport { createQuestpieQueryOptions } from \"@questpie/tanstack-query\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport { toast } from \"sonner\";\nimport { getDefaultActionsConfig } from \"../builder/types/action-registry\";\nimport type {\n ActionContext,\n ActionDefinition,\n ActionHelpers,\n ActionQueryClient,\n ActionsConfig,\n HeaderActionsConfig,\n} from \"../builder/types/action-types\";\nimport { useTranslation } from \"../i18n/hooks\";\nimport {\n selectAuthClient,\n selectBasePath,\n selectClient,\n selectContentLocale,\n selectNavigate,\n useAdminStore,\n} from \"../runtime/provider\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** Query key prefix for CMS queries (must match use-collection.ts) */\nconst QUERY_KEY_PREFIX = [\"questpie\", \"collections\"] as const;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseActionHelpersOptions {\n /** Collection name */\n collection: string;\n /** Custom refresh callback */\n onRefresh?: () => void;\n}\n\nexport interface UseActionHelpersReturn {\n /** Action helpers to pass to action components */\n helpers: ActionHelpers;\n}\n\nexport interface UseActionsOptions<TItem = any> {\n /** Collection name */\n collection: string;\n /** Actions configuration from collection config */\n actionsConfig?: ActionsConfig<TItem>;\n /** Custom refresh callback */\n onRefresh?: () => void;\n}\n\nexport interface UseActionsReturn<TItem = any> {\n /** Action helpers */\n helpers: ActionHelpers;\n /** Resolved actions config (with defaults) */\n actions: Required<ActionsConfig<TItem>>;\n /** Currently active dialog action */\n dialogAction: ActionDefinition<TItem> | null;\n /** Set active dialog action */\n setDialogAction: (action: ActionDefinition<TItem> | null) => void;\n /** Item for dialog action (for row actions) */\n dialogItem: TItem | null;\n /** Set item for dialog action */\n setDialogItem: (item: TItem | null) => void;\n /** Open dialog for an action */\n openDialog: (action: ActionDefinition<TItem>, item?: TItem) => void;\n /** Close dialog */\n closeDialog: () => void;\n}\n\n// ============================================================================\n// useActionHelpers Hook\n// ============================================================================\n\n/**\n * Hook to create action helpers for a collection\n *\n * @example\n * ```tsx\n * const { helpers } = useActionHelpers({ collection: \"posts\" });\n *\n * return (\n * <HeaderActions\n * actions={headerActions}\n * collection=\"posts\"\n * helpers={helpers}\n * />\n * );\n * ```\n */\nexport function useActionHelpers({\n collection,\n onRefresh,\n}: UseActionHelpersOptions): UseActionHelpersReturn {\n const basePath = useAdminStore(selectBasePath);\n const navigate = useAdminStore(selectNavigate);\n const client = useAdminStore(selectClient);\n const contentLocale = useAdminStore(selectContentLocale);\n const queryClient = useQueryClient();\n const { t } = useTranslation();\n\n // Create query options proxy for key building (same as use-collection hooks)\n const queryOpts = React.useMemo(\n () =>\n createQuestpieQueryOptions(client as any, {\n keyPrefix: QUERY_KEY_PREFIX,\n locale: contentLocale,\n }),\n [client, contentLocale],\n );\n\n const helpers: ActionHelpers = React.useMemo(\n () => ({\n navigate,\n toast: {\n success: toast.success,\n error: toast.error,\n info: toast.info,\n warning: toast.warning,\n },\n t,\n invalidateCollection: async (targetCollection?: string) => {\n const col = targetCollection || collection;\n // Invalidate list and count queries for the collection\n await queryClient.invalidateQueries({\n queryKey: queryOpts.key([\"collections\", col, \"find\", contentLocale]),\n });\n await queryClient.invalidateQueries({\n queryKey: queryOpts.key([\"collections\", col, \"count\", contentLocale]),\n });\n // Call custom refresh handler\n onRefresh?.();\n },\n invalidateItem: async (itemId: string, targetCollection?: string) => {\n const col = targetCollection || collection;\n // Invalidate findOne query for specific item\n await queryClient.invalidateQueries({\n queryKey: queryOpts.key([\n \"collections\",\n col,\n \"findOne\",\n contentLocale,\n { id: itemId },\n ]),\n });\n // Also invalidate list queries since item data changed\n await queryClient.invalidateQueries({\n queryKey: queryOpts.key([\"collections\", col, \"find\", contentLocale]),\n });\n },\n invalidateAll: async () => {\n // Invalidate all CMS queries\n await queryClient.invalidateQueries({\n queryKey: [...QUERY_KEY_PREFIX],\n });\n // Call custom refresh handler\n onRefresh?.();\n },\n refresh: () => {\n // Invalidate collection queries (better than page reload)\n queryClient.invalidateQueries({\n queryKey: queryOpts.key([\n \"collections\",\n collection,\n \"find\",\n contentLocale,\n ]),\n });\n queryClient.invalidateQueries({\n queryKey: queryOpts.key([\n \"collections\",\n collection,\n \"count\",\n contentLocale,\n ]),\n });\n // Call custom refresh handler\n onRefresh?.();\n },\n closeDialog: () => {\n // This will be overridden by the component managing dialog state\n },\n basePath,\n }),\n [\n navigate,\n queryClient,\n queryOpts,\n collection,\n contentLocale,\n onRefresh,\n basePath,\n t,\n ],\n );\n\n return { helpers };\n}\n\n// ============================================================================\n// useActions Hook\n// ============================================================================\n\n/**\n * Hook to manage collection actions with dialog state\n *\n * @example\n * ```tsx\n * const {\n * helpers,\n * actions,\n * dialogAction,\n * dialogItem,\n * openDialog,\n * closeDialog,\n * } = useActions({\n * collection: \"posts\",\n * actionsConfig: config.actions,\n * });\n *\n * return (\n * <>\n * <HeaderActions\n * actions={actions.header}\n * collection=\"posts\"\n * helpers={helpers}\n * onOpenDialog={openDialog}\n * />\n *\n * {dialogAction && (\n * <ActionDialog\n * open={!!dialogAction}\n * onOpenChange={(open) => !open && closeDialog()}\n * action={dialogAction}\n * collection=\"posts\"\n * item={dialogItem}\n * helpers={helpers}\n * />\n * )}\n * </>\n * );\n * ```\n */\nexport function useActions<TItem = any>({\n collection,\n actionsConfig,\n onRefresh,\n}: UseActionsOptions<TItem>): UseActionsReturn<TItem> {\n const [dialogAction, setDialogAction] =\n React.useState<ActionDefinition<TItem> | null>(null);\n const [dialogItem, setDialogItem] = React.useState<TItem | null>(null);\n\n // Get default actions if not provided\n const defaultActions = React.useMemo(\n () => getDefaultActionsConfig<TItem>(),\n [],\n );\n\n // Merge provided config with defaults\n const actions: Required<ActionsConfig<TItem>> = React.useMemo(\n () => ({\n header: actionsConfig?.header ??\n defaultActions.header ?? { primary: [], secondary: [] },\n bulk: actionsConfig?.bulk ?? defaultActions.bulk ?? [],\n }),\n [actionsConfig, defaultActions],\n );\n\n // Close dialog handler\n const closeDialog = React.useCallback(() => {\n setDialogAction(null);\n setDialogItem(null);\n }, []);\n\n // Get base helpers\n const { helpers: baseHelpers } = useActionHelpers({\n collection,\n onRefresh: () => {\n onRefresh?.();\n },\n });\n\n // Enhanced helpers with dialog control\n const helpers: ActionHelpers = React.useMemo(\n () => ({\n ...baseHelpers,\n closeDialog,\n }),\n [baseHelpers, closeDialog],\n );\n\n // Open dialog for an action\n const openDialog = React.useCallback(\n (action: ActionDefinition<TItem>, item?: TItem) => {\n setDialogAction(action);\n setDialogItem(item ?? null);\n },\n [],\n );\n\n return {\n helpers,\n actions,\n dialogAction,\n setDialogAction,\n dialogItem,\n setDialogItem,\n openDialog,\n closeDialog,\n };\n}\n\n// ============================================================================\n// useActionExecution Hook\n// ============================================================================\n\nexport interface UseActionExecutionOptions<TItem = any> {\n /** Collection name */\n collection: string;\n /** Action helpers */\n helpers: ActionHelpers;\n}\n\n/**\n * Hook for executing individual actions\n *\n * Provides a function to execute an action with proper error handling\n * and loading state management.\n */\nexport function useActionExecution<TItem = any>({\n collection,\n helpers,\n}: UseActionExecutionOptions<TItem>) {\n const client = useAdminStore(selectClient);\n const authClient = useAdminStore(selectAuthClient);\n const queryClient = useQueryClient();\n const [isExecuting, setIsExecuting] = React.useState(false);\n\n // Wrapped query client for action context\n const actionQueryClient: ActionQueryClient = React.useMemo(\n () => ({\n invalidateQueries: (filters) => queryClient.invalidateQueries(filters),\n refetchQueries: (filters) => queryClient.refetchQueries(filters),\n resetQueries: (filters) => queryClient.resetQueries(filters),\n }),\n [queryClient],\n );\n\n const executeAction = React.useCallback(\n async (\n action: ActionDefinition<TItem>,\n item?: TItem,\n items?: TItem[],\n ): Promise<void> => {\n const ctx: ActionContext<TItem> = {\n item,\n items,\n collection,\n helpers,\n queryClient: actionQueryClient,\n authClient,\n };\n\n setIsExecuting(true);\n try {\n const { handler } = action;\n\n switch (handler.type) {\n case \"navigate\": {\n const path =\n typeof handler.path === \"function\"\n ? handler.path(item!)\n : handler.path;\n helpers.navigate(\n `${helpers.basePath}/collections/${collection}/${path}`,\n );\n break;\n }\n\n case \"api\": {\n // Replace {id} placeholder in endpoint\n const endpoint = handler.endpoint.replace(\n \"{id}\",\n String((item as any)?.id || \"\"),\n );\n\n // Execute API call\n const method = (handler.method || \"POST\").toLowerCase();\n\n // Get collection-specific client\n const collectionClient = (client as any).collections?.[collection];\n\n if (collectionClient) {\n if (method === \"delete\" && collectionClient.delete) {\n await collectionClient.delete({ id: (item as any)?.id });\n helpers.toast.success(\"Item deleted successfully\");\n } else {\n // For other methods, show info (actual implementation would call the API)\n helpers.toast.info(`${handler.method || \"POST\"} ${endpoint}`);\n }\n } else {\n helpers.toast.info(\n `API call: ${handler.method || \"POST\"} ${endpoint}`,\n );\n }\n\n helpers.refresh();\n break;\n }\n\n case \"custom\": {\n await handler.fn(ctx);\n break;\n }\n\n case \"dialog\":\n case \"form\": {\n // These are handled by the ActionDialog component\n break;\n }\n\n case \"server\": {\n // Execute server-side action via API\n const serverHandler = handler as {\n type: \"server\";\n actionId: string;\n collection: string;\n };\n try {\n const collectionClient = (client as any).collections?.[\n serverHandler.collection\n ];\n if (collectionClient?.executeAction) {\n const result = await collectionClient.executeAction(\n serverHandler.actionId,\n {\n itemId: (item as any)?.id,\n itemIds: items?.map((i: any) => i?.id).filter(Boolean),\n },\n );\n if (result?.toast) {\n if (result.type === \"error\") {\n helpers.toast.error(result.toast.message);\n } else {\n helpers.toast.success(result.toast.message);\n }\n }\n if (result?.effects?.invalidate) {\n if (result.effects.invalidate === true) {\n await helpers.invalidateAll();\n } else {\n for (const col of result.effects.invalidate) {\n await helpers.invalidateCollection(col);\n }\n }\n }\n if (result?.effects?.closeModal) {\n helpers.closeDialog();\n }\n } else {\n helpers.toast.info(`Server action: ${serverHandler.actionId}`);\n }\n } catch (err) {\n helpers.toast.error(\n err instanceof Error ? err.message : \"Server action failed\",\n );\n }\n break;\n }\n }\n } catch (error) {\n helpers.toast.error(\n error instanceof Error ? error.message : \"Action failed\",\n );\n } finally {\n setIsExecuting(false);\n }\n },\n [collection, helpers, client, authClient, actionQueryClient],\n );\n\n return {\n executeAction,\n isExecuting,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-admin-config.mjs","names":[],"sources":["../../../src/client/hooks/use-admin-config.ts"],"sourcesContent":["/**\n * Hook for fetching server-side admin config\n */\n\nimport {\n\ttype UseQueryOptions,\n\tuseQuery,\n\tuseSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport { selectClient, useAdminStore } from \"../runtime\";\nimport type { AdminConfigResponse } from \"../types/admin-config\";\n\n/** Query key for admin config */\nexport const adminConfigQueryKey = [\"questpie\", \"admin\", \"config\"] as const;\n\n/** Query options factory for admin config */\nexport function getAdminConfigQueryOptions(client: unknown) {\n\treturn {\n\t\tqueryKey: adminConfigQueryKey,\n\t\tqueryFn: async (): Promise<AdminConfigResponse> => {\n\t\t\tif (!client || !(client as any).rpc) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\treturn (client as any).rpc.getAdminConfig();\n\t\t},\n\t\tstaleTime: 5 * 60 * 1000,\n\t\tgcTime: 30 * 60 * 1000,\n\t};\n}\n\n/** Standard query hook - returns loading/error states */\nexport function useAdminConfig(\n\tqueryOptions?: Omit<\n\t\tUseQueryOptions<AdminConfigResponse>,\n\t\t\"queryKey\" | \"queryFn\"\n\t>,\n) {\n\tconst client = useAdminStore(selectClient);\n\n\treturn useQuery<AdminConfigResponse>({\n\t\t...getAdminConfigQueryOptions(client),\n\t\t...queryOptions,\n\t});\n}\n\n/** Suspense query hook - suspends until data is ready, no loading checks needed */\nexport function useSuspenseAdminConfig() {\n\tconst client = useAdminStore(selectClient);\n\n\treturn useSuspenseQuery<AdminConfigResponse>({\n\t\t...getAdminConfigQueryOptions(client),\n\t});\n}\n"],"mappings":";;;;;;;;AAaA,MAAa,sBAAsB;CAAC;CAAY;CAAS;CAAS;;AAGlE,SAAgB,2BAA2B,QAAiB;AAC3D,QAAO;EACN,UAAU;EACV,SAAS,YAA0C;AAClD,OAAI,CAAC,UAAU,CAAE,OAAe,IAC/B,QAAO,EAAE;AAEV,UAAQ,OAAe,IAAI,gBAAgB;;EAE5C,WAAW,MAAS;EACpB,QAAQ,OAAU;EAClB;;;AAIF,SAAgB,eACf,cAIC;AAGD,QAAO,SAA8B;EACpC,GAAG,2BAHW,cAAc,aAAa,CAGJ;EACrC,GAAG;EACH,CAAC;;;AAIH,SAAgB,yBAAyB;AAGxC,QAAO,iBAAsC,EAC5C,GAAG,2BAHW,cAAc,aAAa,CAGJ,EACrC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-admin-preferences.mjs","names":[],"sources":["../../../src/client/hooks/use-admin-preferences.ts"],"sourcesContent":["import {\n\tuseMutation,\n\tuseQuery,\n\tuseQueryClient,\n\tuseSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport { useAdminStore } from \"../runtime/provider.js\";\nimport { useCurrentUser } from \"./use-current-user.js\";\n\n// ============================================================================\n// Query Keys & Options\n// ============================================================================\n\n/**\n * Get query key for admin preference\n */\nexport function getAdminPreferenceQueryKey(\n\tuserId: string | undefined,\n\tkey: string,\n) {\n\treturn [\"adminPreferences\", userId, key] as const;\n}\n\n/**\n * Query options factory for admin preference.\n * Can be used with TanStack Query's prefetching or with useSuspenseQuery.\n *\n * @param client - CMS client instance\n * @param userId - User ID (required for query to work)\n * @param key - Preference key\n *\n * @example\n * ```ts\n * // Prefetch in loader\n * await queryClient.ensureQueryData(\n * getAdminPreferenceQueryOptions(client, userId, \"viewState:posts\")\n * );\n * ```\n */\nexport function getAdminPreferenceQueryOptions<T>(\n\tclient: any,\n\tuserId: string | undefined,\n\tkey: string,\n) {\n\treturn {\n\t\tqueryKey: getAdminPreferenceQueryKey(userId, key),\n\t\tqueryFn: async (): Promise<T | null> => {\n\t\t\tif (!userId) return null;\n\n\t\t\tconst result = await client.collections.adminPreferences.findOne({\n\t\t\t\twhere: { userId, key },\n\t\t\t});\n\n\t\t\treturn (result?.value as T) ?? null;\n\t\t},\n\t\tenabled: !!client && !!userId,\n\t\tstaleTime: 30 * 1000, // 30 seconds\n\t};\n}\n\n/**\n * Admin Preference entity from the database\n */\nexport interface AdminPreference<T = unknown> {\n\tid: string;\n\tuserId: string;\n\tkey: string;\n\tvalue: T;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\n/**\n * Hook to fetch a single admin preference by key\n *\n * @param key - Preference key (e.g., \"viewState:posts\")\n * @returns Query result with preference data or null if not found\n *\n * @example\n * ```tsx\n * const { data, isLoading } = useAdminPreference<ViewConfiguration>(\"viewState:posts\");\n * if (isLoading) return <Loading />;\n * const viewConfig = data ?? defaultConfig;\n * ```\n */\nexport function useAdminPreference<T = unknown>(key: string) {\n\tconst client = useAdminStore((s) => s.client);\n\tconst user = useCurrentUser();\n\n\treturn useQuery({\n\t\tqueryKey: [\"adminPreferences\", user?.id, key],\n\t\tqueryFn: async (): Promise<T | null> => {\n\t\t\tif (!user?.id) return null;\n\n\t\t\tconst result = await client.collections.adminPreferences.findOne({\n\t\t\t\twhere: { userId: user.id, key },\n\t\t\t});\n\n\t\t\treturn (result?.value as T) ?? null;\n\t\t},\n\t\tenabled: !!client && !!user?.id,\n\t});\n}\n\n/**\n * Hook to set an admin preference\n *\n * Creates or updates the preference for the current user.\n *\n * @param key - Preference key (e.g., \"viewState:posts\")\n * @returns Mutation for setting the preference\n *\n * @example\n * ```tsx\n * const { mutate: setPreference, isPending } = useSetAdminPreference<ViewConfiguration>(\"viewState:posts\");\n *\n * const handleSave = () => {\n * setPreference(viewConfig);\n * };\n * ```\n */\nexport function useSetAdminPreference<T = unknown>(key: string) {\n\tconst client = useAdminStore((s) => s.client);\n\tconst user = useCurrentUser();\n\tconst queryClient = useQueryClient();\n\n\treturn useMutation({\n\t\tmutationFn: async (value: T) => {\n\t\t\tif (!user?.id) {\n\t\t\t\tthrow new Error(\"User must be logged in to save preferences\");\n\t\t\t}\n\n\t\t\tconst collections = client?.collections as\n\t\t\t\t| Record<string, any>\n\t\t\t\t| undefined;\n\t\t\tif (!collections?.adminPreferences) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"adminPreferences collection not available. Make sure to use adminModule in your CMS setup.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Try to find existing preference\n\t\t\tconst existing = await collections.adminPreferences.findOne({\n\t\t\t\twhere: { userId: user.id, key },\n\t\t\t});\n\n\t\t\tif (existing) {\n\t\t\t\t// Update existing\n\t\t\t\treturn collections.adminPreferences.update({\n\t\t\t\t\tid: existing.id,\n\t\t\t\t\tdata: { value },\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Create new\n\t\t\treturn collections.adminPreferences.create({\n\t\t\t\tuserId: user.id,\n\t\t\t\tkey,\n\t\t\t\tvalue,\n\t\t\t});\n\t\t},\n\t\tonSuccess: () => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: [\"adminPreferences\", user?.id, key],\n\t\t\t});\n\t\t},\n\t});\n}\n\n/**\n * Hook to delete an admin preference\n *\n * @param key - Preference key (e.g., \"viewState:posts\")\n * @returns Mutation for deleting the preference\n *\n * @example\n * ```tsx\n * const { mutate: deletePreference } = useDeleteAdminPreference(\"viewState:posts\");\n *\n * const handleReset = () => {\n * deletePreference();\n * };\n * ```\n */\nexport function useDeleteAdminPreference(key: string) {\n\tconst client = useAdminStore((s) => s.client);\n\tconst user = useCurrentUser();\n\tconst queryClient = useQueryClient();\n\n\treturn useMutation({\n\t\tmutationFn: async () => {\n\t\t\tif (!user?.id) {\n\t\t\t\tthrow new Error(\"User must be logged in to delete preferences\");\n\t\t\t}\n\n\t\t\tconst collections = client?.collections as\n\t\t\t\t| Record<string, any>\n\t\t\t\t| undefined;\n\t\t\tif (!collections?.adminPreferences) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"adminPreferences collection not available. Make sure to use adminModule in your CMS setup.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Find existing preference\n\t\t\tconst existing = await collections.adminPreferences.findOne({\n\t\t\t\twhere: { userId: user.id, key },\n\t\t\t});\n\n\t\t\tif (existing) {\n\t\t\t\treturn collections.adminPreferences.delete({ id: existing.id });\n\t\t\t}\n\n\t\t\treturn null;\n\t\t},\n\t\tonSuccess: () => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: [\"adminPreferences\", user?.id, key],\n\t\t\t});\n\t\t},\n\t});\n}\n\n// ============================================================================\n// Suspense Hook\n// ============================================================================\n\n/**\n * Suspense-enabled hook to fetch admin preference.\n *\n * Uses useSuspenseQuery so the component will suspend until data is loaded.\n * Must be used within a Suspense boundary and requires userId to be known.\n *\n * @param key - Preference key (e.g., \"viewState:posts\")\n * @param userId - User ID (must be available - use after session is loaded)\n *\n * @example\n * ```tsx\n * function ViewStateInner({ collection, userId }: Props) {\n * // This will suspend until preference is loaded\n * const { data: storedConfig } = useSuspenseAdminPreference<ViewConfiguration>(\n * `viewState:${collection}`,\n * userId\n * );\n *\n * // storedConfig is guaranteed to be loaded (may be null if not found)\n * }\n *\n * // Wrap with Suspense\n * <Suspense fallback={<Loading />}>\n * <ViewStateInner collection=\"posts\" userId={user.id} />\n * </Suspense>\n * ```\n */\nexport function useSuspenseAdminPreference<T = unknown>(\n\tkey: string,\n\tuserId: string,\n) {\n\tconst client = useAdminStore((s) => s.client);\n\n\treturn useSuspenseQuery<T | null>({\n\t\tqueryKey: getAdminPreferenceQueryKey(userId, key),\n\t\tqueryFn: async () => {\n\t\t\tconst result = await client.collections.adminPreferences.findOne({\n\t\t\t\twhere: { userId, key },\n\t\t\t});\n\n\t\t\treturn (result?.value as T) ?? null;\n\t\t},\n\t});\n}\n"],"mappings":";;;;;;;;AAgBA,SAAgB,2BACf,QACA,KACC;AACD,QAAO;EAAC;EAAoB;EAAQ;EAAI;;;;;;;;;;;;;;;;;;;AAqGzC,SAAgB,sBAAmC,KAAa;CAC/D,MAAM,SAAS,eAAe,MAAM,EAAE,OAAO;CAC7C,MAAM,OAAO,gBAAgB;CAC7B,MAAM,cAAc,gBAAgB;AAEpC,QAAO,YAAY;EAClB,YAAY,OAAO,UAAa;AAC/B,OAAI,CAAC,MAAM,GACV,OAAM,IAAI,MAAM,6CAA6C;GAG9D,MAAM,cAAc,QAAQ;AAG5B,OAAI,CAAC,aAAa,iBACjB,OAAM,IAAI,MACT,6FACA;GAIF,MAAM,WAAW,MAAM,YAAY,iBAAiB,QAAQ,EAC3D,OAAO;IAAE,QAAQ,KAAK;IAAI;IAAK,EAC/B,CAAC;AAEF,OAAI,SAEH,QAAO,YAAY,iBAAiB,OAAO;IAC1C,IAAI,SAAS;IACb,MAAM,EAAE,OAAO;IACf,CAAC;AAGH,UAAO,YAAY,iBAAiB,OAAO;IAC1C,QAAQ,KAAK;IACb;IACA;IACA,CAAC;;EAEH,iBAAiB;AAChB,eAAY,kBAAkB,EAC7B,UAAU;IAAC;IAAoB,MAAM;IAAI;IAAI,EAC7C,CAAC;;EAEH,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-admin-routes.mjs","names":["React"],"sources":["../../../src/client/hooks/use-admin-routes.ts"],"sourcesContent":["/**\n * useAdminRoutes Hook\n *\n * React hook for type-safe admin route navigation.\n * Uses the AdminProvider context to get the current admin configuration.\n */\n\nimport type { Questpie } from \"questpie\";\nimport * as React from \"react\";\nimport {\n selectAdmin,\n selectBasePath,\n selectNavigate,\n useAdminStore,\n} from \"../runtime\";\nimport {\n type AdminRoutes,\n type CollectionNames,\n createAdminRoutes,\n createNavigator,\n type GlobalNames,\n} from \"../utils/routes\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseAdminRoutesOptions {\n /** Override the base path (default: from context or \"/admin\") */\n basePath?: string;\n}\n\nexport interface UseAdminRoutesResult<TApp extends Questpie<any>> {\n /** Routes builder */\n routes: AdminRoutes<TApp>;\n\n /** Navigate to dashboard */\n toDashboard: () => void;\n\n /** Navigate to collection list */\n toCollection: <K extends CollectionNames<TApp>>(collection: K) => void;\n\n /** Navigate to collection create */\n toCollectionCreate: <K extends CollectionNames<TApp>>(collection: K) => void;\n\n /** Navigate to collection edit */\n toCollectionEdit: <K extends CollectionNames<TApp>>(\n collection: K,\n id: string,\n ) => void;\n\n /** Navigate to global edit */\n toGlobal: <K extends GlobalNames<TApp>>(global: K) => void;\n\n /** Navigate to custom page */\n toPage: (pageId: string) => void;\n\n /** Get dashboard URL */\n dashboardUrl: () => string;\n\n /** Get collection list URL */\n collectionUrl: <K extends CollectionNames<TApp>>(collection: K) => string;\n\n /** Get collection create URL */\n collectionCreateUrl: <K extends CollectionNames<TApp>>(\n collection: K,\n ) => string;\n\n /** Get collection edit URL */\n collectionEditUrl: <K extends CollectionNames<TApp>>(\n collection: K,\n id: string,\n ) => string;\n\n /** Get global edit URL */\n globalUrl: <K extends GlobalNames<TApp>>(global: K) => string;\n\n /** Get custom page URL */\n pageUrl: (pageId: string) => string | null;\n\n /** Get all page URLs */\n allPageUrls: () => Record<string, string>;\n\n /** Parse current pathname */\n parse: AdminRoutes<TApp>[\"parse\"];\n\n /** Check if pathname matches */\n matches: AdminRoutes<TApp>[\"matches\"];\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook for type-safe admin route navigation\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { toDashboard, toCollection, toCollectionEdit } = useAdminRoutes<AppCMS>()\n *\n * return (\n * <div>\n * <button onClick={toDashboard}>Dashboard</button>\n * <button onClick={() => toCollection('posts')}>View Posts</button>\n * <button onClick={() => toCollectionEdit('posts', '123')}>Edit Post</button>\n * </div>\n * )\n * }\n * ```\n *\n * @example\n * ```tsx\n * // Get URLs without navigating\n * function LinkList() {\n * const { collectionUrl, globalUrl, pageUrl } = useAdminRoutes<AppCMS>()\n *\n * return (\n * <nav>\n * <a href={collectionUrl('posts')}>Posts</a>\n * <a href={collectionUrl('users')}>Users</a>\n * <a href={globalUrl('siteSettings')}>Settings</a>\n * <a href={pageUrl('analytics') ?? '#'}>Analytics</a>\n * </nav>\n * )\n * }\n * ```\n */\nexport function useAdminRoutes<TApp extends Questpie<any>>(\n options: UseAdminRoutesOptions = {},\n): UseAdminRoutesResult<TApp> {\n const admin = useAdminStore(selectAdmin);\n const storeBasePath = useAdminStore(selectBasePath);\n const storeNavigate = useAdminStore(selectNavigate);\n\n const basePath = options.basePath ?? storeBasePath;\n\n // Create routes builder (memoized)\n const routes = React.useMemo(\n () => createAdminRoutes<TApp>(admin, { basePath }),\n [admin, basePath],\n );\n\n // Get navigate function from store\n const navigate = storeNavigate;\n\n // Create navigator (memoized)\n const nav = React.useMemo(\n () => createNavigator(routes, navigate),\n [routes, navigate],\n );\n\n return {\n routes,\n\n // Navigation functions\n toDashboard: nav.dashboard,\n toCollection: nav.collection,\n toCollectionCreate: nav.collectionCreate,\n toCollectionEdit: nav.collectionEdit,\n toGlobal: nav.global,\n toPage: nav.page,\n\n // URL getters\n dashboardUrl: routes.dashboard,\n collectionUrl: routes.collections.list,\n collectionCreateUrl: routes.collections.create,\n collectionEditUrl: routes.collections.edit,\n globalUrl: routes.globals.edit,\n pageUrl: routes.pages.byId,\n allPageUrls: routes.pages.all,\n\n // Parsing & matching\n parse: routes.parse,\n matches: routes.matches,\n };\n}\n\n// ============================================================================\n// Standalone Hook (no context required)\n// ============================================================================\n\n/**\n * Hook for type-safe admin routes without requiring AdminProvider context\n *\n * @example\n * ```tsx\n * import { barbershopAdmin } from './configs/admin'\n *\n * function MyComponent() {\n * const navigate = useNavigate() // from your router\n * const { routes, go } = useAdminRoutesStandalone({\n * admin: barbershopAdmin,\n * basePath: '/admin',\n * navigate,\n * })\n *\n * return <button onClick={go.dashboard}>Dashboard</button>\n * }\n * ```\n */\nexport function useAdminRoutesStandalone<TApp extends Questpie<any>>(options: {\n admin: import(\"../builder/admin\").Admin;\n basePath?: string;\n navigate: (path: string) => void;\n}) {\n const { admin, basePath = \"/admin\", navigate } = options;\n\n const routes = React.useMemo(\n () => createAdminRoutes<TApp>(admin, { basePath }),\n [admin, basePath],\n );\n\n const go = React.useMemo(\n () => createNavigator(routes, navigate),\n [routes, navigate],\n );\n\n return { routes, go };\n}\n\n// ============================================================================\n// Link Component Helper\n// ============================================================================\n\n/**\n * Props for admin link components\n */\nexport interface AdminLinkProps<TApp extends Questpie<any>> {\n /** Link to dashboard */\n to?: \"dashboard\";\n /** Link to collection */\n collection?: CollectionNames<TApp>;\n /** Collection action */\n action?: \"list\" | \"create\" | \"edit\";\n /** Item ID for edit action */\n id?: string;\n /** Link to global */\n global?: GlobalNames<TApp>;\n /** Link to custom page by ID */\n pageId?: string;\n}\n\n/**\n * Get href for admin link props\n *\n * @example\n * ```tsx\n * function AdminLink<TApp extends Questpie<any>>(\n * props: AdminLinkProps<TApp> & { children: React.ReactNode }\n * ) {\n * const { routes } = useAdminRoutes<TApp>()\n * const href = getAdminLinkHref(routes, props)\n * return <a href={href}>{props.children}</a>\n * }\n * ```\n */\nexport function getAdminLinkHref<TApp extends Questpie<any>>(\n routes: AdminRoutes<TApp>,\n props: AdminLinkProps<TApp>,\n): string {\n if (props.to === \"dashboard\") {\n return routes.dashboard();\n }\n\n if (props.collection) {\n const action = props.action ?? \"list\";\n if (action === \"create\") {\n return routes.collections.create(props.collection);\n }\n if (action === \"edit\" && props.id) {\n return routes.collections.edit(props.collection, props.id);\n }\n return routes.collections.list(props.collection);\n }\n\n if (props.global) {\n return routes.globals.edit(props.global);\n }\n\n if (props.pageId) {\n return routes.pages.byId(props.pageId) ?? routes.dashboard();\n }\n\n return routes.dashboard();\n}\n\nexport default useAdminRoutes;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiIA,SAAgB,eACd,UAAiC,EAAE,EACP;CAC5B,MAAM,QAAQ,cAAc,YAAY;CACxC,MAAM,gBAAgB,cAAc,eAAe;CACnD,MAAM,gBAAgB,cAAc,eAAe;CAEnD,MAAM,WAAW,QAAQ,YAAY;CAGrC,MAAM,SAASA,QAAM,cACb,kBAAwB,OAAO,EAAE,UAAU,CAAC,EAClD,CAAC,OAAO,SAAS,CAClB;CAGD,MAAM,WAAW;CAGjB,MAAM,MAAMA,QAAM,cACV,gBAAgB,QAAQ,SAAS,EACvC,CAAC,QAAQ,SAAS,CACnB;AAED,QAAO;EACL;EAGA,aAAa,IAAI;EACjB,cAAc,IAAI;EAClB,oBAAoB,IAAI;EACxB,kBAAkB,IAAI;EACtB,UAAU,IAAI;EACd,QAAQ,IAAI;EAGZ,cAAc,OAAO;EACrB,eAAe,OAAO,YAAY;EAClC,qBAAqB,OAAO,YAAY;EACxC,mBAAmB,OAAO,YAAY;EACtC,WAAW,OAAO,QAAQ;EAC1B,SAAS,OAAO,MAAM;EACtB,aAAa,OAAO,MAAM;EAG1B,OAAO,OAAO;EACd,SAAS,OAAO;EACjB;;;;;;;;;;;;;;;;AAkFH,SAAgB,iBACd,QACA,OACQ;AACR,KAAI,MAAM,OAAO,YACf,QAAO,OAAO,WAAW;AAG3B,KAAI,MAAM,YAAY;EACpB,MAAM,SAAS,MAAM,UAAU;AAC/B,MAAI,WAAW,SACb,QAAO,OAAO,YAAY,OAAO,MAAM,WAAW;AAEpD,MAAI,WAAW,UAAU,MAAM,GAC7B,QAAO,OAAO,YAAY,KAAK,MAAM,YAAY,MAAM,GAAG;AAE5D,SAAO,OAAO,YAAY,KAAK,MAAM,WAAW;;AAGlD,KAAI,MAAM,OACR,QAAO,OAAO,QAAQ,KAAK,MAAM,OAAO;AAG1C,KAAI,MAAM,OACR,QAAO,OAAO,MAAM,KAAK,MAAM,OAAO,IAAI,OAAO,WAAW;AAG9D,QAAO,OAAO,WAAW"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-auth.d.mts","names":[],"sources":["../../../src/client/hooks/use-auth.ts"],"sourcesContent":[],"mappings":";;;;;;AAiMA;;;KA7JK,6BAA6B,iBAChC,UAAU,0BACN,wBAAwB,oBACtB,kBACA,oBACF;;;;KAKM,sBAAA;;;;;;;;;;;;;;;kBAiBM;cACJ;;;;;;KAOT,gCAAgC;;;kBAGnB;cACJ;;cAEA,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmCjB,gCAAgC,wBACrC,yBACR,kBAAkB,iBAAiB,sBAAsB;;;;;;;;;;;;;;;;;;;iBA+E5C,0BAA0B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-auth.mjs","names":[],"sources":["../../../src/client/hooks/use-auth.ts"],"sourcesContent":["/**\n * Auth client utilities for admin package\n *\n * Better Auth handles all auth state management internally.\n * This module provides type-safe client creation helpers with\n * full type inference from your CMS auth configuration.\n *\n * @example\n * ```tsx\n * // In your app, create the auth client once:\n * import { createAdminAuthClient } from '@questpie/admin/hooks'\n * import type { cms } from './server/cms'\n *\n * export const authClient = createAdminAuthClient<typeof cms>({\n * baseURL: 'http://localhost:3000'\n * })\n *\n * // Then use the built-in hooks:\n * function MyComponent() {\n * const { data: session, isPending, error } = authClient.useSession()\n *\n * if (isPending) return <div>Loading...</div>\n * if (!session) return <LoginForm />\n *\n * return <div>Welcome {session.user.name}</div>\n * }\n * ```\n */\n\nimport type { BetterAuthOptions } from \"better-auth\";\nimport { createAuthClient } from \"better-auth/react\";\nimport type { Questpie } from \"questpie\";\n\n/**\n * Extract auth options type from Questpie instance\n */\ntype ExtractAuthOptions<T extends Questpie<any>> =\n T extends Questpie<infer TConfig>\n ? TConfig[\"auth\"] extends BetterAuthOptions\n ? TConfig[\"auth\"]\n : BetterAuthOptions\n : BetterAuthOptions;\n\n/**\n * Options for creating admin auth client\n */\nexport type AdminAuthClientOptions = {\n /**\n * Base URL of the CMS API\n * @example 'http://localhost:3000'\n */\n baseURL: string;\n\n /**\n * Base path for auth routes\n * @default '/cms/auth'\n */\n basePath?: string;\n\n /**\n * Custom fetch implementation\n */\n fetchOptions?: {\n credentials?: RequestCredentials;\n headers?: Record<string, string>;\n };\n};\n\n/**\n * Internal client options type that includes $InferAuth\n */\ntype InternalClientOptions<T extends Questpie<any>> = {\n baseURL: string;\n fetchOptions?: {\n credentials?: RequestCredentials;\n headers?: Record<string, string>;\n };\n $InferAuth: ExtractAuthOptions<T>;\n};\n\n/**\n * Create a type-safe Better Auth client for the admin UI\n *\n * The returned client includes full type inference from your CMS auth configuration:\n * - `useSession()` - React hook for session state (typed based on your user/session schema)\n * - `signIn` methods (email, social providers configured in CMS)\n * - `signOut` - Sign out the current user\n * - `signUp` - Register new users\n * - Plugin-specific hooks (e.g., `useListAccounts` for admin plugin)\n *\n * @example\n * ```tsx\n * import { createAdminAuthClient } from '@questpie/admin/hooks'\n * import type { cms } from './server/cms'\n *\n * // Create client with type inference from your CMS\n * export const authClient = createAdminAuthClient<typeof cms>({\n * baseURL: 'http://localhost:3000'\n * })\n *\n * // Session data is fully typed based on your CMS auth config\n * function App() {\n * const { data: session, isPending } = authClient.useSession()\n *\n * if (isPending) return <Loading />\n * if (!session) return <LoginPage authClient={authClient} />\n *\n * // session.user has all fields from your user schema\n * return <AdminDashboard user={session.user} />\n * }\n * ```\n */\nexport function createAdminAuthClient<T extends Questpie<any>>(\n options: AdminAuthClientOptions,\n): ReturnType<typeof createAuthClient<InternalClientOptions<T>>> {\n const basePath = options.basePath ?? \"/cms/auth\";\n\n return createAuthClient<InternalClientOptions<T>>({\n baseURL: `${options.baseURL}${basePath}`,\n fetchOptions: {\n credentials: options.fetchOptions?.credentials ?? \"include\",\n headers: options.fetchOptions?.headers,\n },\n } as InternalClientOptions<T>);\n}\n\n/**\n * Type helper to extract auth client type from CMS instance\n *\n * @example\n * ```tsx\n * import type { AdminAuthClient } from '@questpie/admin/hooks'\n * import type { cms } from './server/cms'\n *\n * type MyAuthClient = AdminAuthClient<typeof cms>\n * ```\n */\nexport type AdminAuthClient<T extends Questpie<any>> = ReturnType<\n typeof createAdminAuthClient<T>\n>;\n\n/**\n * Type helper to extract session type from auth client\n *\n * @example\n * ```tsx\n * import type { AdminSession } from '@questpie/admin/hooks'\n * import type { cms } from './server/cms'\n *\n * type MySession = AdminSession<typeof cms>\n * // Includes: { user: { id, email, name, role, ... }, session: { ... } }\n * ```\n */\nexport type AdminSession<T extends Questpie<any>> =\n AdminAuthClient<T>[\"$Infer\"][\"Session\"];\n\n/**\n * Type helper to extract user type from CMS auth configuration\n *\n * @example\n * ```tsx\n * import type { AdminUser } from '@questpie/admin/hooks'\n * import type { cms } from './server/cms'\n *\n * type MyUser = AdminUser<typeof cms>\n * ```\n */\nexport type AdminUser<T extends Questpie<any>> = AdminSession<T>[\"user\"];\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nimport { selectAuthClient, useAdminStore } from \"../runtime/provider\";\n\n/**\n * Hook to access the auth client from AdminProvider context.\n *\n * @example\n * ```tsx\n * import { useAuthClient } from '@questpie/admin/hooks'\n *\n * function LoginPage() {\n * const authClient = useAuthClient()\n *\n * const handleLogin = async (email: string, password: string) => {\n * await authClient.signIn.email({ email, password })\n * }\n *\n * return <LoginForm onSubmit={handleLogin} />\n * }\n * ```\n */\nexport function useAuthClient<T = any>(): T {\n const authClient = useAdminStore(selectAuthClient);\n if (!authClient) {\n throw new Error(\n \"useAuthClient: authClient is not provided. \" +\n \"Make sure to pass authClient to AdminProvider.\",\n );\n }\n return authClient as T;\n}\n\n/**\n * Hook to access the auth client from AdminProvider context.\n * Returns null if authClient is not provided (safe version).\n *\n * @example\n * ```tsx\n * const authClient = useAuthClientSafe()\n * if (!authClient) {\n * return <div>Auth not configured</div>\n * }\n * ```\n */\nexport function useAuthClientSafe<T = any>(): T | null {\n return useAdminStore(selectAuthClient) as T | null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgHA,SAAgB,sBACd,SAC+D;CAC/D,MAAM,WAAW,QAAQ,YAAY;AAErC,QAAO,iBAA2C;EAChD,SAAS,GAAG,QAAQ,UAAU;EAC9B,cAAc;GACZ,aAAa,QAAQ,cAAc,eAAe;GAClD,SAAS,QAAQ,cAAc;GAChC;EACF,CAA6B;;;;;;;;;;;;;;;;;;;;AAsEhC,SAAgB,gBAA4B;CAC1C,MAAM,aAAa,cAAc,iBAAiB;AAClD,KAAI,CAAC,WACH,OAAM,IAAI,MACR,4FAED;AAEH,QAAO;;;;;;;;;;;;;;AAeT,SAAgB,oBAAuC;AACrD,QAAO,cAAc,iBAAiB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-collection-fields.mjs","names":[],"sources":["../../../src/client/hooks/use-collection-fields.ts"],"sourcesContent":["/**\n * Hook for resolving field definitions from collection schema\n *\n * Builds FieldDefinition objects from server introspection schema\n * and merges with any local overrides.\n */\n\nimport type { UseQueryOptions } from \"@tanstack/react-query\";\nimport type { CollectionSchema } from \"questpie\";\nimport { useMemo } from \"react\";\nimport type { FieldDefinition } from \"../builder/field/field\";\nimport { selectAdmin, useAdminStore } from \"../runtime\";\nimport {\n type BuildFieldDefinitionsOptions,\n buildFieldDefinitionsFromSchema,\n} from \"../utils/build-field-definitions-from-schema\";\nimport { useCollectionSchema } from \"./use-collection-schema\";\n\nexport interface UseCollectionFieldsOptions {\n /**\n * React Query options for schema fetching\n */\n schemaQueryOptions?: Omit<\n UseQueryOptions<CollectionSchema>,\n \"queryKey\" | \"queryFn\"\n >;\n /**\n * Options for building field definitions from schema\n */\n buildOptions?: BuildFieldDefinitionsOptions;\n /**\n * Local field definitions to merge as overrides\n */\n fallbackFields?: Record<string, FieldDefinition>;\n}\n\nexport function useCollectionFields(\n collection: string,\n options: UseCollectionFieldsOptions = {},\n) {\n const admin = useAdminStore(selectAdmin);\n const {\n data: schema,\n isLoading,\n error,\n } = useCollectionSchema(collection, options.schemaQueryOptions);\n\n const fields = useMemo(() => {\n const fallback = options.fallbackFields ?? {};\n if (!schema || !admin) {\n return fallback;\n }\n\n const registry = admin.getFields() as Record<string, any>;\n const schemaFields = buildFieldDefinitionsFromSchema(\n schema,\n registry,\n options.buildOptions,\n );\n\n return {\n ...schemaFields,\n ...fallback,\n };\n }, [schema, admin, options.buildOptions, options.fallbackFields]);\n\n return { fields, schema, isLoading, error };\n}\n"],"mappings":";;;;;;AAoCA,SAAgB,oBACd,YACA,UAAsC,EAAE,EACxC;CACA,MAAM,QAAQ,cAAc,YAAY;CACxC,MAAM,EACJ,MAAM,QACN,WACA,UACE,oBAAoB,YAAY,QAAQ,mBAAmB;AAqB/D,QAAO;EAAE,QAnBM,cAAc;GAC3B,MAAM,WAAW,QAAQ,kBAAkB,EAAE;AAC7C,OAAI,CAAC,UAAU,CAAC,MACd,QAAO;AAUT,UAAO;IACL,GAPmB,gCACnB,QAFe,MAAM,WAAW,EAIhC,QAAQ,aACT;IAIC,GAAG;IACJ;KACA;GAAC;GAAQ;GAAO,QAAQ;GAAc,QAAQ;GAAe,CAAC;EAEhD;EAAQ;EAAW;EAAO"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-collection-meta.mjs","names":[],"sources":["../../../src/client/hooks/use-collection-meta.ts"],"sourcesContent":["/**\n * Hook for fetching collection metadata from the backend\n *\n * Used to get introspection info about collections like:\n * - Title field configuration (which field to display first)\n * - Whether timestamps are enabled\n * - Whether soft delete is enabled\n * - Localized fields\n * - Virtual fields\n */\n\nimport {\n\ttype UseQueryOptions,\n\tuseQuery,\n\tuseSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport type { CollectionMeta } from \"questpie/client\";\nimport type {\n\tRegisteredCMS,\n\tRegisteredCollectionNames,\n} from \"../builder/registry\";\nimport { selectClient, useAdminStore } from \"../runtime\";\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\n/**\n * Resolved collection names (string if not registered)\n */\ntype ResolvedCollectionNames =\n\tRegisteredCMS extends Questpie<any> ? RegisteredCollectionNames : string;\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook to fetch collection metadata from the backend\n *\n * Returns introspection info useful for building dynamic UIs:\n * - title.fieldName: The field to use as display title (instead of _title)\n * - title.type: \"field\" (sortable) or \"virtual\" (computed)\n * - timestamps: Whether createdAt/updatedAt are enabled\n * - softDelete: Whether soft delete is enabled\n * - localizedFields: Fields that support i18n\n *\n * @example\n * ```tsx\n * const { data: meta } = useCollectionMeta(\"posts\");\n *\n * // Use title.fieldName instead of _title for first column\n * const firstColumn = meta?.title.fieldName || \"_title\";\n *\n * // Only show timestamps columns if enabled\n * if (meta?.timestamps) {\n * columns.push(\"createdAt\", \"updatedAt\");\n * }\n * ```\n */\nexport function useCollectionMeta<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\tqueryOptions?: Omit<UseQueryOptions<CollectionMeta>, \"queryKey\" | \"queryFn\">,\n) {\n\tconst client = useAdminStore(selectClient);\n\n\treturn useQuery<CollectionMeta>({\n\t\tqueryKey: [\"questpie\", \"collections\", collection, \"meta\"],\n\t\tqueryFn: async () => {\n\t\t\treturn (client as any).collections[collection].meta();\n\t\t},\n\t\t// Meta rarely changes, cache aggressively\n\t\tstaleTime: 5 * 60 * 1000, // 5 minutes\n\t\tgcTime: 30 * 60 * 1000, // 30 minutes (formerly cacheTime)\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Query key for collection meta\n * Useful for prefetching or invalidation\n */\nexport function getCollectionMetaQueryKey(collection: string) {\n\treturn [\"questpie\", \"collections\", collection, \"meta\"] as const;\n}\n\n// ============================================================================\n// Query Options Factory\n// ============================================================================\n\n/**\n * Query options factory for collection metadata.\n * Can be used with TanStack Query's prefetching in loaders or with useSuspenseQuery.\n *\n * @example\n * ```ts\n * // In TanStack Start loader\n * export const Route = createFileRoute(\"/admin/collections/:name\")({\n * loader: async ({ context, params }) => {\n * await context.queryClient.ensureQueryData(\n * getCollectionMetaQueryOptions(params.name, context.client)\n * );\n * },\n * });\n * ```\n */\nexport function getCollectionMetaQueryOptions(collection: string, client: any) {\n\treturn {\n\t\tqueryKey: getCollectionMetaQueryKey(collection),\n\t\tqueryFn: async (): Promise<CollectionMeta> => {\n\t\t\treturn client.collections[collection].meta();\n\t\t},\n\t\tstaleTime: 5 * 60 * 1000, // 5 minutes\n\t\tgcTime: 30 * 60 * 1000, // 30 minutes\n\t};\n}\n\n// ============================================================================\n// Suspense Hook\n// ============================================================================\n\n/**\n * Suspense-enabled hook to fetch collection metadata.\n *\n * Uses useSuspenseQuery so the component will suspend until data is loaded.\n * Must be used within a Suspense boundary.\n *\n * @example\n * ```tsx\n * function TableViewInner({ collection }: Props) {\n * // This will suspend until meta is loaded\n * const { data: meta } = useSuspenseCollectionMeta(collection);\n *\n * // meta is guaranteed to be defined here\n * const titleField = meta.title.fieldName;\n * }\n *\n * // Wrap with Suspense\n * <Suspense fallback={<Loading />}>\n * <TableViewInner collection=\"posts\" />\n * </Suspense>\n * ```\n */\nexport function useSuspenseCollectionMeta<K extends ResolvedCollectionNames>(\n\tcollection: K,\n) {\n\tconst client = useAdminStore(selectClient);\n\n\treturn useSuspenseQuery<CollectionMeta>(\n\t\tgetCollectionMetaQueryOptions(collection, client),\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,SAAgB,kBACf,YACA,cACC;CACD,MAAM,SAAS,cAAc,aAAa;AAE1C,QAAO,SAAyB;EAC/B,UAAU;GAAC;GAAY;GAAe;GAAY;GAAO;EACzD,SAAS,YAAY;AACpB,UAAQ,OAAe,YAAY,YAAY,MAAM;;EAGtD,WAAW,MAAS;EACpB,QAAQ,OAAU;EAClB,GAAG;EACH,CAAC;;;;;;AAOH,SAAgB,0BAA0B,YAAoB;AAC7D,QAAO;EAAC;EAAY;EAAe;EAAY;EAAO;;;;;;;;;;;;;;;;;;AAuBvD,SAAgB,8BAA8B,YAAoB,QAAa;AAC9E,QAAO;EACN,UAAU,0BAA0B,WAAW;EAC/C,SAAS,YAAqC;AAC7C,UAAO,OAAO,YAAY,YAAY,MAAM;;EAE7C,WAAW,MAAS;EACpB,QAAQ,OAAU;EAClB;;;;;;;;;;;;;;;;;;;;;;;;AA6BF,SAAgB,0BACf,YACC;AAGD,QAAO,iBACN,8BAA8B,YAHhB,cAAc,aAAa,CAGQ,CACjD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-collection-schema.mjs","names":[],"sources":["../../../src/client/hooks/use-collection-schema.ts"],"sourcesContent":["/**\n * Hook for fetching collection schema from the backend\n *\n * Returns full introspection data including:\n * - Field schemas with metadata and validation\n * - Relations metadata\n * - Access control information for current user\n * - JSON Schema for client-side validation\n */\n\nimport { type UseQueryOptions, useQuery } from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport type { CollectionSchema } from \"questpie/client\";\nimport type {\n RegisteredCMS,\n RegisteredCollectionNames,\n} from \"../builder/registry\";\nimport { selectClient, useAdminStore } from \"../runtime\";\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\n/**\n * Resolved collection names (string if not registered)\n */\ntype ResolvedCollectionNames =\n RegisteredCMS extends Questpie<any> ? RegisteredCollectionNames : string;\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook to fetch collection schema from the backend\n *\n * Returns full introspection data useful for building dynamic forms and UIs:\n * - fields: Complete field metadata including type, label, validation, admin config\n * - relations: Relation metadata with type, target collection(s), and keys\n * - access: Evaluated access control for the current user\n * - validation: JSON Schema for client-side validation\n * - options: Collection options (timestamps, softDelete, versioning)\n *\n * @example\n * ```tsx\n * const { data: schema } = useCollectionSchema(\"posts\");\n *\n * // Build fields dynamically from schema\n * for (const [name, field] of Object.entries(schema?.fields ?? {})) {\n * const FieldComponent = getFieldComponent(field.metadata.type);\n * // Use field.metadata for rendering configuration\n * }\n *\n * // Check user access\n * if (schema?.access.operations.create.allowed) {\n * // Show create button\n * }\n * ```\n */\nexport function useCollectionSchema<K extends ResolvedCollectionNames>(\n collection: K,\n queryOptions?: Omit<\n UseQueryOptions<CollectionSchema>,\n \"queryKey\" | \"queryFn\"\n >,\n) {\n const client = useAdminStore(selectClient);\n\n return useQuery<CollectionSchema>({\n queryKey: getCollectionSchemaQueryKey(collection),\n queryFn: async () => {\n return (client as any).collections[collection].schema();\n },\n // Schema rarely changes, cache aggressively\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 30 * 60 * 1000, // 30 minutes\n ...queryOptions,\n });\n}\n\n/**\n * Query key for collection schema\n * Useful for prefetching or invalidation\n */\nexport function getCollectionSchemaQueryKey(collection: string) {\n return [\"questpie\", \"collections\", collection, \"schema\"] as const;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,SAAgB,oBACd,YACA,cAIA;CACA,MAAM,SAAS,cAAc,aAAa;AAE1C,QAAO,SAA2B;EAChC,UAAU,4BAA4B,WAAW;EACjD,SAAS,YAAY;AACnB,UAAQ,OAAe,YAAY,YAAY,QAAQ;;EAGzD,WAAW,MAAS;EACpB,QAAQ,OAAU;EAClB,GAAG;EACJ,CAAC;;;;;;AAOJ,SAAgB,4BAA4B,YAAoB;AAC9D,QAAO;EAAC;EAAY;EAAe;EAAY;EAAS"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-collection-validation.mjs","names":["resolver: Resolver<TFieldValues>","errors: FieldErrors<FieldValues>"],"sources":["../../../src/client/hooks/use-collection-validation.ts"],"sourcesContent":["/**\n * useCollectionValidation Hook\n *\n * Creates a Zod validation schema from a collection's field definitions.\n * Provides automatic validation with i18n support for react-hook-form.\n */\n\nimport type { ZodErrorMapFn } from \"questpie/shared\";\nimport { useCallback, useMemo } from \"react\";\nimport type { FieldErrors, FieldValues, Resolver } from \"react-hook-form\";\nimport type { z } from \"zod\";\nimport { createFormSchema } from \"../builder/validation\";\nimport { selectAdmin, useAdminStore } from \"../runtime\";\nimport { useCollectionFields } from \"./use-collection-fields\";\nimport { useValidationErrorMap } from \"./use-validation-error-map\";\n\n/**\n * Result of useCollectionValidation hook\n */\nexport interface CollectionValidationResult {\n /** Zod schema for the collection's fields */\n schema: z.ZodTypeAny | undefined;\n /** Error map for i18n support */\n errorMap: ZodErrorMapFn;\n}\n\n/**\n * Get a ready-to-use resolver for react-hook-form\n *\n * This is the recommended hook - provides full automatic validation\n * with i18n error messages. Just pass the result to useForm's resolver.\n *\n * @param collection - Collection name\n * @returns Resolver function for react-hook-form, or undefined if collection not found\n *\n * @example\n * ```tsx\n * function MyForm() {\n * const resolver = useCollectionValidation(\"posts\");\n *\n * const form = useForm({\n * resolver,\n * });\n *\n * // That's it! Validation and i18n errors work automatically.\n * }\n * ```\n */\nexport function useCollectionValidation<\n TFieldValues extends FieldValues = FieldValues,\n>(collection: string): Resolver<TFieldValues> | undefined {\n const admin = useAdminStore(selectAdmin);\n const { fields } = useCollectionFields(collection);\n const schema = useMemo(() => {\n if (!admin) return undefined;\n if (!fields || Object.keys(fields).length === 0) return undefined;\n return createFormSchema(fields, admin.getFields());\n }, [admin, fields]);\n const errorMap = useValidationErrorMap();\n\n const resolver: Resolver<TFieldValues> = useCallback(\n async (values, _context, _options) => {\n if (!schema) {\n return {\n values: values as TFieldValues,\n errors: {} as Record<string, never>,\n };\n }\n\n const result = schema.safeParse(values);\n\n if (result.success) {\n return {\n values: result.data as TFieldValues,\n errors: {} as Record<string, never>,\n };\n }\n\n return {\n values: {} as Record<string, never>,\n errors: zodErrorToFieldErrors(\n result.error,\n errorMap,\n ) as FieldErrors<TFieldValues>,\n };\n },\n [schema, errorMap],\n );\n\n return schema ? resolver : undefined;\n}\n\n/**\n * Convert Zod error to react-hook-form FieldErrors format with i18n support\n */\nfunction zodErrorToFieldErrors(\n error: z.ZodError,\n errorMap: ZodErrorMapFn,\n): FieldErrors<FieldValues> {\n const errors: FieldErrors<FieldValues> = {};\n\n for (const issue of error.issues) {\n const path = issue.path.join(\".\");\n // Apply i18n error map to get translated message\n const { message } = errorMap(issue as Parameters<ZodErrorMapFn>[0]);\n\n if (path && !errors[path]) {\n errors[path] = {\n type: issue.code,\n message,\n };\n }\n }\n\n return errors;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,SAAgB,wBAEd,YAAwD;CACxD,MAAM,QAAQ,cAAc,YAAY;CACxC,MAAM,EAAE,WAAW,oBAAoB,WAAW;CAClD,MAAM,SAAS,cAAc;AAC3B,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,CAAC,UAAU,OAAO,KAAK,OAAO,CAAC,WAAW,EAAG,QAAO;AACxD,SAAO,iBAAiB,QAAQ,MAAM,WAAW,CAAC;IACjD,CAAC,OAAO,OAAO,CAAC;CACnB,MAAM,WAAW,uBAAuB;CAExC,MAAMA,WAAmC,YACvC,OAAO,QAAQ,UAAU,aAAa;AACpC,MAAI,CAAC,OACH,QAAO;GACG;GACR,QAAQ,EAAE;GACX;EAGH,MAAM,SAAS,OAAO,UAAU,OAAO;AAEvC,MAAI,OAAO,QACT,QAAO;GACL,QAAQ,OAAO;GACf,QAAQ,EAAE;GACX;AAGH,SAAO;GACL,QAAQ,EAAE;GACV,QAAQ,sBACN,OAAO,OACP,SACD;GACF;IAEH,CAAC,QAAQ,SAAS,CACnB;AAED,QAAO,SAAS,WAAW;;;;;AAM7B,SAAS,sBACP,OACA,UAC0B;CAC1B,MAAMC,SAAmC,EAAE;AAE3C,MAAK,MAAM,SAAS,MAAM,QAAQ;EAChC,MAAM,OAAO,MAAM,KAAK,KAAK,IAAI;EAEjC,MAAM,EAAE,YAAY,SAAS,MAAsC;AAEnE,MAAI,QAAQ,CAAC,OAAO,MAClB,QAAO,QAAQ;GACb,MAAM,MAAM;GACZ;GACD;;AAIL,QAAO"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-collection.d.mts","names":[],"sources":["../../../src/client/hooks/use-collection.ts"],"sourcesContent":[],"mappings":";;;;;;KAcK,yBAAA;;AAHwB,CAAA;AAGC;;;KAWzB,WAAA,GACJ,aAAsC,SAAhB,QAAgB,CAAA,GAAA,CAAA,GAAA,aAAA,GAAgB,QAAhB,CAAA,GAAA,CAAA;;;AAAwB;KAK1D,uBAAA,GACJ,aAAA,SAAsB,QAAtB,CAAA,GAAA,CAAA,GAAsC,yBAAtC,GAAA,MAAA;;;;AAiBD;;;;;;;AA+EA;AAA4C,iBA/E5B,iBA+E4B,CAAA,UA/EA,uBA+EA,CAAA,CAAA,UAAA,EA9E/B,CA8E+B,EAAA,OAAA,CAAA,EAAA,GAAA,EAAA,YAAA,CAAA,EA5E5B,IA4E4B,CA5EvB,eA4EuB,EAAA,UAAA,GAAA,SAAA,CAAA,EAAA,eAAA,CAAA,EA3EzB,yBA2EyB,CAAA,EAAA,GAAA;;AAmJ5C;;;;;;;;;;iBAnJgB,4BAA4B,qCAC/B,yBAEF,KACT,WACC,eAAe,4BAA4B;;SAKrC;kBAEO,KAAK;;;;;;;;;;;;;iBA0BL,8BAA8B,qCACjC,qBACM,KAAK;;;;;;;;;;;;;iBAgDR,8BAA8B,qCACjC,qBACM,KAAK;;;;;;;;;;;;;iBAyDR,8BAA8B,qCACjC,qBACM,KAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-collection.mjs","names":[],"sources":["../../../src/client/hooks/use-collection.ts"],"sourcesContent":["import {\n\ttype UseMutationOptions,\n\ttype UseQueryOptions,\n\tuseMutation,\n\tuseQuery,\n} from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport type { QuestpieClient } from \"questpie/client\";\nimport type {\n\tRegisteredCMS,\n\tRegisteredCollectionNames,\n} from \"../builder/registry\";\nimport { useQuestpieQueryOptions } from \"./use-questpie-query-options\";\n\ntype CollectionRealtimeOptions = {\n\trealtime?: boolean;\n};\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\n/**\n * Resolved CMS type (Questpie<any> if not registered)\n */\ntype ResolvedCMS =\n\tRegisteredCMS extends Questpie<any> ? RegisteredCMS : Questpie<any>;\n\n/**\n * Resolved collection names (string if not registered)\n */\ntype ResolvedCollectionNames =\n\tRegisteredCMS extends Questpie<any> ? RegisteredCollectionNames : string;\n\n// ============================================================================\n// Collection Hooks\n// ============================================================================\n\n/**\n * Hook to fetch collection list with filters, sorting, pagination\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { data } = useCollectionList(\"barbers\");\n * ```\n */\nexport function useCollectionList<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\toptions?: any,\n\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\trealtimeOptions?: CollectionRealtimeOptions,\n): any {\n\tconst { queryOpts, locale } = useQuestpieQueryOptions();\n\n\tconst findOptions = {\n\t\t...options,\n\t\tlocale,\n\t};\n\n\t// Pass realtime option to query options builder - this uses streamedQuery internally\n\tconst baseQuery = (queryOpts as any).collections[collection as string].find(\n\t\tfindOptions as any,\n\t\t{ realtime: realtimeOptions?.realtime },\n\t);\n\n\treturn useQuery({\n\t\t...baseQuery,\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Hook to count collection items with optional filters\n *\n * More efficient than useCollectionList when you only need the count.\n * Uses dedicated count endpoint that doesn't fetch actual documents.\n *\n * @example\n * ```tsx\n * // Count all items\n * const { data: count } = useCollectionCount(\"barbers\");\n *\n * // Count with filter\n * const { data: count } = useCollectionCount(\"appointments\", {\n * where: { status: \"pending\" }\n * });\n * ```\n */\nexport function useCollectionCount<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\toptions?: { where?: any; includeDeleted?: boolean },\n\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\trealtimeOptions?: CollectionRealtimeOptions,\n): any {\n\tconst { queryOpts, locale } = useQuestpieQueryOptions();\n\n\tconst countOptions = {\n\t\t...options,\n\t\tlocale,\n\t};\n\n\t// Pass realtime option to query options builder - this uses streamedQuery internally\n\t// The reducer in tanstack-query already extracts totalDocs from the snapshot\n\tconst baseQuery = (queryOpts as any).collections[collection as string].count(\n\t\tcountOptions as any,\n\t\t{ realtime: realtimeOptions?.realtime },\n\t);\n\n\treturn useQuery({\n\t\t...baseQuery,\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Hook to fetch single collection item\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { data } = useCollectionItem(\"barbers\", \"123\");\n * ```\n */\nexport function useCollectionItem<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\tid: string,\n\toptions?: Omit<\n\t\tParameters<\n\t\t\tQuestpieClient<ResolvedCMS>[\"collections\"][K & string][\"findOne\"]\n\t\t>[0],\n\t\t\"where\"\n\t> & {\n\t\tlocaleFallback?: boolean;\n\t\twith?: Record<string, boolean>;\n\t},\n\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n): any {\n\tconst { queryOpts, locale } = useQuestpieQueryOptions();\n\n\treturn useQuery({\n\t\t...(queryOpts as any).collections[collection as string].findOne({\n\t\t\twhere: { id },\n\t\t\tlocale,\n\t\t\t...options,\n\t\t}),\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Hook to create collection item\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { mutate } = useCollectionCreate(\"barbers\");\n * mutate({ name: \"John\", ... });\n * ```\n */\nexport function useCollectionCreate<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n): any {\n\tconst { queryOpts, queryClient, locale } = useQuestpieQueryOptions();\n\n\tconst baseOptions = queryOpts.collections[collection as string].create();\n\tconst listQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"find\",\n\t\tlocale,\n\t]);\n\tconst countQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"count\",\n\t\tlocale,\n\t]);\n\n\treturn useMutation({\n\t\t...baseOptions,\n\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t},\n\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: listQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: countQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t},\n\t\t...mutationOptions,\n\t} as any);\n}\n\n/**\n * Hook to update collection item\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { mutate } = useCollectionUpdate(\"barbers\");\n * mutate({ id: \"123\", data: { name: \"John\" } });\n * ```\n */\nexport function useCollectionUpdate<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n): any {\n\tconst { queryOpts, queryClient, locale } = useQuestpieQueryOptions();\n\n\tconst baseOptions = queryOpts.collections[collection as string].update();\n\tconst listQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"find\",\n\t\tlocale,\n\t]);\n\tconst countQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"count\",\n\t\tlocale,\n\t]);\n\tconst itemQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"findOne\",\n\t\tlocale,\n\t]);\n\n\treturn useMutation({\n\t\t...baseOptions,\n\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t},\n\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: listQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: countQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: itemQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t},\n\t\t...mutationOptions,\n\t} as any);\n}\n\n/**\n * Hook to delete collection item\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { mutate } = useCollectionDelete(\"barbers\");\n * mutate(\"123\");\n * ```\n */\nexport function useCollectionDelete<K extends ResolvedCollectionNames>(\n\tcollection: K,\n\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n): any {\n\tconst { queryOpts, queryClient, locale } = useQuestpieQueryOptions();\n\n\tconst baseOptions = queryOpts.collections[collection as string].delete();\n\tconst listQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"find\",\n\t\tlocale,\n\t]);\n\tconst countQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"count\",\n\t\tlocale,\n\t]);\n\tconst itemQueryKey = queryOpts.key([\n\t\t\"collections\",\n\t\tcollection as string,\n\t\t\"findOne\",\n\t\tlocale,\n\t]);\n\n\treturn useMutation({\n\t\t...baseOptions,\n\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t},\n\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: listQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: countQueryKey,\n\t\t\t});\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: itemQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t},\n\t\t...mutationOptions,\n\t} as any);\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-current-user.d.mts","names":[],"sources":["../../../src/client/hooks/use-current-user.ts"],"sourcesContent":[],"mappings":";;AAkCA;AAuCA;;;;;;;;;;;;;;;;;;;;;;;;;UAvCiB,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;iBAuCD,uBAAuB,cAAc"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-current-user.mjs","names":[],"sources":["../../../src/client/hooks/use-current-user.ts"],"sourcesContent":["/**\n * Current User Hooks\n *\n * Convenience hooks for accessing the current user from Better Auth session.\n * These hooks use the authClient.useSession() internally.\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const user = useCurrentUser();\n * const isAdmin = useIsAdmin();\n *\n * if (!user) return <LoginPrompt />;\n *\n * return (\n * <div>\n * <h1>{user.name}</h1>\n * {isAdmin && <AdminBadge />}\n * </div>\n * );\n * }\n * ```\n */\n\nimport { useAuthClientSafe } from \"./use-auth\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Basic user type from Better Auth session\n * Extended by the actual CMS user schema\n */\nexport interface BasicUser {\n id: string;\n email: string;\n name?: string | null;\n image?: string | null;\n role?: string | null;\n emailVerified?: boolean;\n banned?: boolean;\n banReason?: string | null;\n}\n\n/**\n * Session state returned by useSession hooks\n */\nexport interface SessionState<TUser = BasicUser> {\n user: TUser | null;\n isPending: boolean;\n error: Error | null;\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Get the current authenticated user from session.\n *\n * Returns null if:\n * - No auth client is configured\n * - User is not authenticated\n * - Session is still loading (use useSessionState for loading state)\n *\n * @example\n * ```tsx\n * const user = useCurrentUser();\n * if (!user) return <LoginPage />;\n * return <div>Hello {user.name}</div>;\n * ```\n */\nexport function useCurrentUser<TUser = BasicUser>(): TUser | null {\n const authClient = useAuthClientSafe();\n\n if (!authClient) {\n return null;\n }\n\n const { data: session } = authClient.useSession();\n return (session?.user as TUser) ?? null;\n}\n\n/**\n * Get full session state including loading and error.\n *\n * @example\n * ```tsx\n * const { user, isPending, error } = useSessionState();\n *\n * if (isPending) return <Loading />;\n * if (error) return <Error message={error.message} />;\n * if (!user) return <LoginPage />;\n *\n * return <Dashboard user={user} />;\n * ```\n */\nexport function useSessionState<TUser = BasicUser>(): SessionState<TUser> {\n const authClient = useAuthClientSafe();\n\n if (!authClient) {\n return {\n user: null,\n isPending: false,\n error: null,\n };\n }\n\n const { data: session, isPending, error } = authClient.useSession();\n\n return {\n user: (session?.user as TUser) ?? null,\n isPending,\n error: error ?? null,\n };\n}\n\n/**\n * Check if the current user is authenticated.\n *\n * Returns false while session is loading.\n * For loading-aware check, use useSessionState().\n *\n * @example\n * ```tsx\n * const isAuthenticated = useIsAuthenticated();\n * if (!isAuthenticated) return <LoginButton />;\n * ```\n */\nexport function useIsAuthenticated(): boolean {\n const authClient = useAuthClientSafe();\n\n if (!authClient) {\n return false;\n }\n\n const { data: session, isPending } = authClient.useSession();\n return !isPending && session?.user != null;\n}\n\n/**\n * Check if the current user has the admin role.\n *\n * @example\n * ```tsx\n * const isAdmin = useIsAdmin();\n * if (!isAdmin) return <AccessDenied />;\n * ```\n */\nexport function useIsAdmin(): boolean {\n const user = useCurrentUser();\n return user?.role === \"admin\";\n}\n\n/**\n * Check if the current user has a specific role.\n *\n * @example\n * ```tsx\n * const canEdit = useHasRole(\"admin\") || useHasRole(\"editor\");\n * ```\n */\nexport function useHasRole(role: string): boolean {\n const user = useCurrentUser();\n return user?.role === role;\n}\n\n/**\n * Check if the current user has any of the specified roles.\n *\n * @example\n * ```tsx\n * const canManageUsers = useHasAnyRole([\"admin\", \"moderator\"]);\n * ```\n */\nexport function useHasAnyRole(roles: string[]): boolean {\n const user = useCurrentUser();\n return user?.role != null && roles.includes(user.role);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEA,SAAgB,iBAAkD;CAChE,MAAM,aAAa,mBAAmB;AAEtC,KAAI,CAAC,WACH,QAAO;CAGT,MAAM,EAAE,MAAM,YAAY,WAAW,YAAY;AACjD,QAAQ,SAAS,QAAkB;;;;;;;;;;;;;;;;AAiBrC,SAAgB,kBAA0D;CACxE,MAAM,aAAa,mBAAmB;AAEtC,KAAI,CAAC,WACH,QAAO;EACL,MAAM;EACN,WAAW;EACX,OAAO;EACR;CAGH,MAAM,EAAE,MAAM,SAAS,WAAW,UAAU,WAAW,YAAY;AAEnE,QAAO;EACL,MAAO,SAAS,QAAkB;EAClC;EACA,OAAO,SAAS;EACjB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-field-hooks.mjs","names":["React","deps: string[]","resolvedValue: any"],"sources":["../../../src/client/hooks/use-field-hooks.ts"],"sourcesContent":["/**\n * Field Hooks\n *\n * React hooks for field-level compute, onChange handlers, and async options.\n * Uses Proxy-based dependency tracking for automatic reactivity.\n *\n * Best Practices:\n * - useWatch() hook for reactive form values (React pattern)\n * - form.getValues() only inside callbacks/effects (one-time reads)\n * - useMemo for computed values to avoid unnecessary recalculations\n */\n\nimport * as React from \"react\";\nimport { useFormContext, useWatch } from \"react-hook-form\";\nimport type {\n\tFieldHookContext,\n\tSelectOption,\n} from \"../builder/types/field-types\";\n\n// ============================================================================\n// Proxy Tracking Utilities\n// ============================================================================\n\n/**\n * Result of tracking dependencies via Proxy\n */\ninterface TrackingResult<T> {\n\tresult: T;\n\tdeps: string[];\n}\n\n/**\n * Track which fields are accessed during a function call using Proxy.\n * Returns the result and the list of accessed field names.\n */\nfunction trackDependencies<T>(\n\tvalues: Record<string, any>,\n\tfn: (values: Record<string, any>) => T,\n): TrackingResult<T> {\n\tconst deps: string[] = [];\n\n\tconst proxy = new Proxy(values, {\n\t\tget(target, prop: string) {\n\t\t\tif (typeof prop === \"string\" && !prop.startsWith(\"_\")) {\n\t\t\t\tdeps.push(prop);\n\t\t\t}\n\t\t\treturn target[prop];\n\t\t},\n\t});\n\n\tconst result = fn(proxy);\n\treturn { result, deps: [...new Set(deps)] }; // dedupe\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseFieldHooksOptions {\n\t/**\n\t * Field name\n\t */\n\tfieldName: string;\n\n\t/**\n\t * Field name with prefix (for nested fields)\n\t */\n\tfullFieldName: string;\n\n\t/**\n\t * Current locale\n\t */\n\tlocale?: string;\n\n\t/**\n\t * Compute function (proxy-tracked)\n\t */\n\tcompute?: (values: Record<string, any>) => any;\n\n\t/**\n\t * onChange callback from field config\n\t */\n\tonChange?: (value: any, ctx: FieldHookContext) => void | Promise<void>;\n\n\t/**\n\t * Default value (static, sync function, or async function)\n\t */\n\tdefaultValue?:\n\t\t| any\n\t\t| ((values: Record<string, any>) => any)\n\t\t| ((values: Record<string, any>) => Promise<any>);\n\n\t/**\n\t * Async options loader (proxy-tracked)\n\t */\n\tloadOptions?: (values: Record<string, any>) => Promise<SelectOption[]>;\n\n\t/**\n\t * Static options (from config)\n\t */\n\tstaticOptions?: SelectOption[];\n}\n\nexport interface UseFieldHooksResult {\n\t/**\n\t * Wrapped onChange handler that calls user's onChange hook\n\t */\n\thandleChange: (value: any) => void;\n\n\t/**\n\t * Computed value (if compute is provided)\n\t */\n\tcomputedValue: any;\n\n\t/**\n\t * Whether this field has a compute function (implies readonly)\n\t */\n\tisComputed: boolean;\n\n\t/**\n\t * Resolved options (from static, sync function, or async loader)\n\t */\n\toptions: SelectOption[] | undefined;\n\n\t/**\n\t * Whether options are loading\n\t */\n\toptionsLoading: boolean;\n}\n\n// ============================================================================\n// Hook Context Factory\n// ============================================================================\n\nfunction createHookContext(\n\tform: ReturnType<typeof useFormContext>,\n\tfieldName: string,\n\tlocale?: string,\n): FieldHookContext {\n\treturn {\n\t\tfieldName,\n\t\tlocale,\n\t\tsetValue: (name: string, value: any) => {\n\t\t\tform.setValue(name, value, {\n\t\t\t\tshouldDirty: true,\n\t\t\t\tshouldTouch: true,\n\t\t\t\tshouldValidate: false,\n\t\t\t});\n\t\t},\n\t\tgetValues: () => form.getValues(),\n\t\tgetValue: (name: string) => form.getValues(name),\n\t};\n}\n\n// ============================================================================\n// Main Hook\n// ============================================================================\n\n/**\n * Hook for implementing field-level hooks (compute, onChange, loadOptions).\n * Uses Proxy-based dependency tracking for automatic reactivity.\n *\n * @example\n * ```tsx\n * const { handleChange, computedValue, isComputed, options, optionsLoading } = useFieldHooks({\n * fieldName: 'pricePerMinute',\n * fullFieldName: 'pricePerMinute',\n * compute: (values) => values.price / values.duration,\n * });\n * ```\n */\nexport function useFieldHooks({\n\tfieldName,\n\tfullFieldName,\n\tlocale,\n\tcompute,\n\tonChange,\n\tdefaultValue,\n\tloadOptions,\n\tstaticOptions,\n}: UseFieldHooksOptions): UseFieldHooksResult {\n\tconst form = useFormContext();\n\tconst [asyncOptions, setAsyncOptions] = React.useState<\n\t\tSelectOption[] | undefined\n\t>(undefined);\n\tconst [optionsLoading, setOptionsLoading] = React.useState(false);\n\n\t// Track dependencies for loadOptions (stored in state to trigger re-render when detected)\n\tconst [loadOptionsDeps, setLoadOptionsDeps] = React.useState<string[]>([]);\n\n\t// Create stable hook context\n\tconst hookCtx = React.useMemo(\n\t\t() => createHookContext(form, fieldName, locale),\n\t\t[form, fieldName, locale],\n\t);\n\n\t// ========================================================================\n\t// Watch form values reactively (React best practice: useWatch hook)\n\t// ========================================================================\n\n\t// Watch all form values for compute reactivity\n\t// useWatch properly integrates with React's lifecycle\n\tconst watchedValues = useWatch({ control: form.control });\n\tconst allValues = React.useMemo(\n\t\t() => (watchedValues ?? {}) as Record<string, any>,\n\t\t[watchedValues],\n\t);\n\n\t// ========================================================================\n\t// Detect loadOptions dependencies (run once)\n\t// ========================================================================\n\n\tReact.useEffect(() => {\n\t\tif (!loadOptions) return;\n\n\t\t// Run loadOptions once with a tracking proxy to detect deps\n\t\tconst values = form.getValues();\n\t\tconst deps: string[] = [];\n\t\tconst proxy = new Proxy(values, {\n\t\t\tget(target, prop: string) {\n\t\t\t\tif (typeof prop === \"string\" && !prop.startsWith(\"_\")) {\n\t\t\t\t\tdeps.push(prop);\n\t\t\t\t}\n\t\t\t\treturn target[prop];\n\t\t\t},\n\t\t});\n\n\t\t// Call loadOptions to track deps, catch and ignore errors\n\t\ttry {\n\t\t\tloadOptions(proxy);\n\t\t} catch {\n\t\t\t// Ignore - we just wanted to track access\n\t\t}\n\n\t\tconst uniqueDeps = [...new Set(deps)];\n\t\tsetLoadOptionsDeps(uniqueDeps);\n\t}, [loadOptions, form]);\n\n\t// ========================================================================\n\t// Computed Value (reactive via useWatch + useMemo)\n\t// ========================================================================\n\n\t// Use useMemo for computed value - recomputes when allValues change\n\t// This is the proper React pattern: derived state via useMemo\n\tconst computedValue = React.useMemo(() => {\n\t\tif (!compute) return undefined;\n\t\ttry {\n\t\t\treturn compute(allValues);\n\t\t} catch (error) {\n\t\t\tconsole.error(`Compute error for ${fieldName}:`, error);\n\t\t\treturn undefined;\n\t\t}\n\t}, [compute, allValues, fieldName]);\n\n\t// ========================================================================\n\t// Default Value Effect\n\t// ========================================================================\n\n\tconst defaultValueInitialized = React.useRef(false);\n\n\tReact.useEffect(() => {\n\t\tif (defaultValueInitialized.current) return;\n\t\tif (defaultValue === undefined) return;\n\t\t// Don't set default for computed fields\n\t\tif (compute) {\n\t\t\tdefaultValueInitialized.current = true;\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentValue = form.getValues(fullFieldName);\n\t\tif (currentValue !== undefined && currentValue !== null) {\n\t\t\tdefaultValueInitialized.current = true;\n\t\t\treturn;\n\t\t}\n\n\t\tconst initDefaultValue = async () => {\n\t\t\tlet resolvedValue: any;\n\n\t\t\tif (typeof defaultValue === \"function\") {\n\t\t\t\tconst values = form.getValues();\n\t\t\t\tresolvedValue = await Promise.resolve(defaultValue(values));\n\t\t\t} else {\n\t\t\t\tresolvedValue = defaultValue;\n\t\t\t}\n\n\t\t\t// Double-check value hasn't been set while we were resolving\n\t\t\tconst currentVal = form.getValues(fullFieldName);\n\t\t\tif (currentVal === undefined || currentVal === null) {\n\t\t\t\tform.setValue(fullFieldName, resolvedValue, {\n\t\t\t\t\tshouldDirty: false,\n\t\t\t\t\tshouldTouch: false,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tdefaultValueInitialized.current = true;\n\t\t};\n\n\t\tinitDefaultValue();\n\t}, [defaultValue, fullFieldName, form, compute]);\n\n\t// ========================================================================\n\t// Async Options Loader (reactive via tracked deps)\n\t// ========================================================================\n\n\t// Extract only the tracked dependency values for comparison\n\tconst trackedDepValues = React.useMemo(() => {\n\t\tif (!loadOptionsDeps.length) return [];\n\t\treturn loadOptionsDeps.map((dep) => allValues[dep]);\n\t}, [loadOptionsDeps, allValues]);\n\n\t// Stable serialization for deep comparison\n\tconst trackedDepKey = React.useMemo(\n\t\t() => JSON.stringify(trackedDepValues),\n\t\t[trackedDepValues],\n\t);\n\n\tconst initialOptionsLoadDone = React.useRef(false);\n\tconst prevDepKeyRef = React.useRef<string>(\"\");\n\n\tReact.useEffect(() => {\n\t\tif (!loadOptions) return;\n\n\t\t// Skip if deps haven't been detected yet\n\t\tif (loadOptionsDeps.length === 0 && !initialOptionsLoadDone.current) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if this is initial load or deps changed\n\t\tconst depsChanged =\n\t\t\t!initialOptionsLoadDone.current ||\n\t\t\tprevDepKeyRef.current !== trackedDepKey;\n\n\t\tif (!depsChanged) return;\n\n\t\tprevDepKeyRef.current = trackedDepKey;\n\t\tinitialOptionsLoadDone.current = true;\n\n\t\tconst fetchOptions = async () => {\n\t\t\tsetOptionsLoading(true);\n\t\t\ttry {\n\t\t\t\t// Use allValues (from useWatch) for the loadOptions call\n\t\t\t\tconst options = await loadOptions(allValues);\n\t\t\t\tsetAsyncOptions(options);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`Failed to load options for ${fieldName}:`, error);\n\t\t\t\tsetAsyncOptions([]);\n\t\t\t} finally {\n\t\t\t\tsetOptionsLoading(false);\n\t\t\t}\n\t\t};\n\n\t\tfetchOptions();\n\t}, [loadOptions, loadOptionsDeps, trackedDepKey, allValues, fieldName]);\n\n\t// ========================================================================\n\t// onChange Handler\n\t// ========================================================================\n\n\tconst handleChange = React.useCallback(\n\t\t(value: any) => {\n\t\t\t// Don't allow changes for computed fields\n\t\t\tif (compute) return;\n\n\t\t\t// Set the value first\n\t\t\t// Note: shouldValidate is false to avoid blocking on complex fields like richText\n\t\t\t// Validation will still happen on form submit\n\t\t\tform.setValue(fullFieldName, value, {\n\t\t\t\tshouldDirty: true,\n\t\t\t\tshouldTouch: true,\n\t\t\t\tshouldValidate: false,\n\t\t\t});\n\n\t\t\t// Then call user's onChange if provided\n\t\t\tif (onChange) {\n\t\t\t\tconst runOnChange = async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait Promise.resolve(onChange(value, hookCtx));\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tconsole.error(`onChange error for ${fieldName}:`, error);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\trunOnChange();\n\t\t\t}\n\t\t},\n\t\t[form, fullFieldName, onChange, hookCtx, fieldName, compute],\n\t);\n\n\t// ========================================================================\n\t// Resolve Options\n\t// ========================================================================\n\n\tconst options = React.useMemo(() => {\n\t\t// Async options take priority\n\t\tif (loadOptions) {\n\t\t\treturn asyncOptions;\n\t\t}\n\t\t// Static options\n\t\treturn staticOptions;\n\t}, [loadOptions, asyncOptions, staticOptions]);\n\n\treturn {\n\t\thandleChange,\n\t\tcomputedValue,\n\t\tisComputed: !!compute,\n\t\toptions,\n\t\toptionsLoading,\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-field-options.d.mts","names":[],"sources":["../../../src/client/hooks/use-field-options.ts"],"sourcesContent":[],"mappings":";;;;;;;AAyKC,UAtJgB,UAAA,CAsJhB;EACA,KAAA,EAAA,MAAA,GAAA,MAAA;EACA,KAAA,EAAA,MAAA,GAtJgB,MAsJhB,CAAA,MAAA,EAAA,MAAA,CAAA;;;;;AAGgD,UAnJhC,sBAAA,CAmJgC;;;;;;;;kBAxIhC;;kBAGA;;;;;;;;;;;UAeA,qBAAA;;WAEP;;;;;;;;;;;;;;;;SAwBF;;;;;;;;;;;;;;;;;;;;;;;;iBAmFQ,eAAA;;;;;;;;;GASb,yBAAyB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-field-options.mjs","names":["result: Record<string, any>","React"],"sources":["../../../src/client/hooks/use-field-options.ts"],"sourcesContent":["/**\n * Field Options Hook\n *\n * Fetches dynamic options for select/relation fields from the server.\n * Supports search, pagination, and dependency-based refetching.\n */\n\nimport type { SerializedOptionsConfig } from \"questpie\";\nimport * as React from \"react\";\nimport { useFormContext, useWatch } from \"react-hook-form\";\nimport { useAdminStore } from \"../runtime/provider.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Option item\n */\nexport interface OptionItem {\n\tvalue: string | number;\n\tlabel: string | Record<string, string>;\n}\n\n/**\n * Options for useFieldOptions hook\n */\nexport interface UseFieldOptionsOptions {\n\t/** Collection or global name */\n\tcollection: string;\n\n\t/** Entity type - collection or global */\n\tmode?: \"collection\" | \"global\";\n\n\t/** Field path */\n\tfield: string;\n\n\t/** Options config from introspection */\n\toptionsConfig?: SerializedOptionsConfig;\n\n\t/** Static options (fallback if no dynamic config) */\n\tstaticOptions?: OptionItem[];\n\n\t/** Initial search query */\n\tinitialSearch?: string;\n\n\t/** Items per page */\n\tlimit?: number;\n\n\t/** Whether to enable fetching */\n\tenabled?: boolean;\n}\n\n/**\n * Result from useFieldOptions hook\n */\nexport interface UseFieldOptionsResult {\n\t/** Current options */\n\toptions: OptionItem[];\n\n\t/** Whether options are loading */\n\tisLoading: boolean;\n\n\t/** Whether more options are available */\n\thasMore: boolean;\n\n\t/** Total count (if available) */\n\ttotal?: number;\n\n\t/** Current search query */\n\tsearch: string;\n\n\t/** Set search query */\n\tsetSearch: (search: string) => void;\n\n\t/** Load more options (pagination) */\n\tloadMore: () => void;\n\n\t/** Refresh options */\n\trefresh: () => void;\n\n\t/** Error */\n\terror: Error | null;\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Get sibling data for a field path (for fields inside arrays)\n */\nfunction getSiblingData(\n\tvalues: Record<string, any>,\n\tfieldPath: string,\n): Record<string, any> | null {\n\tconst parts = fieldPath.split(\".\");\n\tconst numericIndex = parts.findIndex((p) => /^\\d+$/.test(p));\n\n\tif (numericIndex === -1) {\n\t\treturn null;\n\t}\n\n\tconst arrayItemPath = parts.slice(0, numericIndex + 1).join(\".\");\n\n\tlet sibling = values;\n\tfor (const part of arrayItemPath.split(\".\")) {\n\t\tif (sibling && typeof sibling === \"object\") {\n\t\t\tsibling = sibling[part];\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn typeof sibling === \"object\" ? sibling : null;\n}\n\n/**\n * Get watched dependency values\n */\nfunction getWatchedValues(\n\tallValues: Record<string, any>,\n\tsiblingData: Record<string, any> | null,\n\twatchDeps: string[],\n): Record<string, any> {\n\tconst result: Record<string, any> = {};\n\n\tfor (const dep of watchDeps) {\n\t\tif (dep.startsWith(\"$sibling.\")) {\n\t\t\tconst siblingKey = dep.slice(\"$sibling.\".length);\n\t\t\tresult[dep] = siblingData?.[siblingKey];\n\t\t} else if (!dep.startsWith(\"$\")) {\n\t\t\tresult[dep] = allValues[dep];\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook to fetch dynamic options for select/relation fields.\n * Supports search, pagination, and dependency-based refetching.\n *\n * @example\n * ```tsx\n * const { options, isLoading, search, setSearch, loadMore } = useFieldOptions({\n * collection: \"orders\",\n * field: \"items.0.city\",\n * optionsConfig: schema.fields.city.reactive?.options,\n * });\n *\n * return (\n * <Select\n * options={options}\n * isLoading={isLoading}\n * onInputChange={setSearch}\n * onMenuScrollToBottom={loadMore}\n * />\n * );\n * ```\n */\nexport function useFieldOptions({\n\tcollection,\n\tmode = \"collection\",\n\tfield,\n\toptionsConfig,\n\tstaticOptions,\n\tinitialSearch = \"\",\n\tlimit = 20,\n\tenabled = true,\n}: UseFieldOptionsOptions): UseFieldOptionsResult {\n\tconst client = useAdminStore((s) => s.client);\n\tconst form = useFormContext();\n\n\t// State\n\tconst [options, setOptions] = React.useState<OptionItem[]>([]);\n\tconst [isLoading, setIsLoading] = React.useState(false);\n\tconst [hasMore, setHasMore] = React.useState(false);\n\tconst [total, setTotal] = React.useState<number | undefined>();\n\tconst [search, setSearch] = React.useState(initialSearch);\n\tconst [page, setPage] = React.useState(0);\n\tconst [error, setError] = React.useState<Error | null>(null);\n\n\t// Watch form values for deps\n\tconst watchedValues = useWatch({ control: form.control });\n\tconst formValues = React.useMemo(\n\t\t() => (watchedValues ?? {}) as Record<string, any>,\n\t\t[watchedValues],\n\t);\n\n\t// Get sibling data\n\tconst siblingData = React.useMemo(\n\t\t() => getSiblingData(formValues, field),\n\t\t[formValues, field],\n\t);\n\n\t// Get watched dep values for comparison\n\tconst watchDeps = optionsConfig?.watch ?? [];\n\tconst depValues = React.useMemo(\n\t\t() => getWatchedValues(formValues, siblingData, watchDeps),\n\t\t[formValues, siblingData, watchDeps],\n\t);\n\tconst depKey = JSON.stringify(depValues);\n\n\t// Previous dep key for change detection\n\tconst prevDepKeyRef = React.useRef(depKey);\n\n\t// Fetch options from server\n\tconst fetchOptions = React.useCallback(\n\t\tasync (currentPage: number, append: boolean = false) => {\n\t\t\t// If no dynamic config, use static options\n\t\t\tif (!optionsConfig || !client) {\n\t\t\t\tif (staticOptions) {\n\t\t\t\t\tlet filtered = staticOptions;\n\t\t\t\t\tif (search) {\n\t\t\t\t\t\tconst searchLower = search.toLowerCase();\n\t\t\t\t\t\tfiltered = staticOptions.filter((opt) => {\n\t\t\t\t\t\t\tconst label =\n\t\t\t\t\t\t\t\ttypeof opt.label === \"string\"\n\t\t\t\t\t\t\t\t\t? opt.label\n\t\t\t\t\t\t\t\t\t: Object.values(opt.label).join(\" \");\n\t\t\t\t\t\t\treturn label.toLowerCase().includes(searchLower);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tsetOptions(filtered);\n\t\t\t\t\tsetHasMore(false);\n\t\t\t\t\tsetTotal(filtered.length);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetIsLoading(true);\n\t\t\tsetError(null);\n\n\t\t\ttry {\n\t\t\t\tconst response = await (client.rpc as any).fieldOptions({\n\t\t\t\t\tcollection,\n\t\t\t\t\ttype: mode,\n\t\t\t\t\tfield,\n\t\t\t\t\tformData: formValues,\n\t\t\t\t\tsiblingData,\n\t\t\t\t\tsearch,\n\t\t\t\t\tpage: currentPage,\n\t\t\t\t\tlimit,\n\t\t\t\t});\n\n\t\t\t\tconst newOptions = response.options as OptionItem[];\n\n\t\t\t\tif (append) {\n\t\t\t\t\tsetOptions((prev) => [...prev, ...newOptions]);\n\t\t\t\t} else {\n\t\t\t\t\tsetOptions(newOptions);\n\t\t\t\t}\n\n\t\t\t\tsetHasMore(response.hasMore ?? false);\n\t\t\t\tsetTotal(response.total);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(\"Field options error:\", err);\n\t\t\t\tsetError(err instanceof Error ? err : new Error(String(err)));\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tclient,\n\t\t\tcollection,\n\t\t\tmode,\n\t\t\tfield,\n\t\t\tformValues,\n\t\t\tsiblingData,\n\t\t\tsearch,\n\t\t\tlimit,\n\t\t\toptionsConfig,\n\t\t\tstaticOptions,\n\t\t],\n\t);\n\n\t// Effect to fetch options when deps change\n\tReact.useEffect(() => {\n\t\tif (!enabled) return;\n\n\t\t// Check if deps changed\n\t\tif (prevDepKeyRef.current !== depKey) {\n\t\t\tprevDepKeyRef.current = depKey;\n\t\t\tsetPage(0);\n\t\t\tfetchOptions(0, false);\n\t\t}\n\t}, [enabled, depKey, fetchOptions]);\n\n\t// Effect to fetch options when search changes\n\tconst searchDebounceRef = React.useRef<ReturnType<typeof setTimeout> | null>(\n\t\tnull,\n\t);\n\n\tReact.useEffect(() => {\n\t\tif (!enabled) return;\n\n\t\tif (searchDebounceRef.current) {\n\t\t\tclearTimeout(searchDebounceRef.current);\n\t\t}\n\n\t\tsearchDebounceRef.current = setTimeout(() => {\n\t\t\tsetPage(0);\n\t\t\tfetchOptions(0, false);\n\t\t}, 300); // Debounce search\n\n\t\treturn () => {\n\t\t\tif (searchDebounceRef.current) {\n\t\t\t\tclearTimeout(searchDebounceRef.current);\n\t\t\t}\n\t\t};\n\t}, [enabled, search, fetchOptions]);\n\n\t// Initial fetch\n\tReact.useEffect(() => {\n\t\tif (enabled) {\n\t\t\tfetchOptions(0, false);\n\t\t}\n\t\t// Only run on mount\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, []);\n\n\t// Load more handler\n\tconst loadMore = React.useCallback(() => {\n\t\tif (isLoading || !hasMore) return;\n\t\tconst nextPage = page + 1;\n\t\tsetPage(nextPage);\n\t\tfetchOptions(nextPage, true);\n\t}, [isLoading, hasMore, page, fetchOptions]);\n\n\t// Refresh handler\n\tconst refresh = React.useCallback(() => {\n\t\tsetPage(0);\n\t\tfetchOptions(0, false);\n\t}, [fetchOptions]);\n\n\treturn {\n\t\toptions,\n\t\tisLoading,\n\t\thasMore,\n\t\ttotal,\n\t\tsearch,\n\t\tsetSearch,\n\t\tloadMore,\n\t\trefresh,\n\t\terror,\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-global-fields.mjs","names":[],"sources":["../../../src/client/hooks/use-global-fields.ts"],"sourcesContent":["/**\n * Hook for resolving field definitions from global schema\n *\n * Builds FieldDefinition objects from server introspection schema.\n */\n\nimport type { UseQueryOptions } from \"@tanstack/react-query\";\nimport type { GlobalSchema } from \"questpie\";\nimport { useMemo } from \"react\";\nimport type { FieldDefinition } from \"../builder/field/field\";\nimport { selectAdmin, useAdminStore } from \"../runtime\";\nimport {\n type BuildFieldDefinitionsOptions,\n buildFieldDefinitionsFromSchema,\n} from \"../utils/build-field-definitions-from-schema\";\nimport { useGlobalSchema } from \"./use-global-schema\";\n\nexport interface UseGlobalFieldsOptions {\n /**\n * React Query options for schema fetching\n */\n schemaQueryOptions?: Omit<\n UseQueryOptions<GlobalSchema>,\n \"queryKey\" | \"queryFn\"\n >;\n /**\n * Options for building field definitions from schema\n */\n buildOptions?: BuildFieldDefinitionsOptions;\n}\n\nexport function useGlobalFields(\n globalName: string,\n options: UseGlobalFieldsOptions = {},\n) {\n const admin = useAdminStore(selectAdmin);\n const {\n data: schema,\n isLoading,\n error,\n } = useGlobalSchema(globalName, options.schemaQueryOptions);\n\n const fields = useMemo(() => {\n if (!schema || !admin) return {};\n const registry = admin.getFields() as Record<string, any>;\n return buildFieldDefinitionsFromSchema(\n schema,\n registry,\n options.buildOptions,\n );\n }, [schema, admin, options.buildOptions]);\n\n return { fields, schema, isLoading, error };\n}\n"],"mappings":";;;;;;AA+BA,SAAgB,gBACd,YACA,UAAkC,EAAE,EACpC;CACA,MAAM,QAAQ,cAAc,YAAY;CACxC,MAAM,EACJ,MAAM,QACN,WACA,UACE,gBAAgB,YAAY,QAAQ,mBAAmB;AAY3D,QAAO;EAAE,QAVM,cAAc;AAC3B,OAAI,CAAC,UAAU,CAAC,MAAO,QAAO,EAAE;AAEhC,UAAO,gCACL,QAFe,MAAM,WAAW,EAIhC,QAAQ,aACT;KACA;GAAC;GAAQ;GAAO,QAAQ;GAAa,CAAC;EAExB;EAAQ;EAAW;EAAO"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-global-meta.mjs","names":[],"sources":["../../../src/client/hooks/use-global-meta.ts"],"sourcesContent":["/**\n * Hook for fetching global metadata from the backend\n *\n * Used to get introspection info about globals like:\n * - Whether timestamps are enabled\n * - Whether versioning is enabled\n * - Localized fields\n * - Virtual fields\n */\n\nimport {\n\ttype UseQueryOptions,\n\tuseQuery,\n\tuseSuspenseQuery,\n} from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport type { GlobalMeta } from \"questpie/client\";\nimport type { RegisteredCMS, RegisteredGlobalNames } from \"../builder/registry\";\nimport { selectClient, useAdminStore } from \"../runtime\";\n\ntype ResolvedGlobalNames =\n\tRegisteredCMS extends Questpie<any> ? RegisteredGlobalNames : string;\n\n/**\n * Hook to fetch global metadata from the backend\n *\n * Returns metadata useful for building dynamic UIs:\n * - timestamps: Whether createdAt/updatedAt are enabled\n * - versioning: Whether versioning is enabled\n * - localizedFields: Fields that support i18n\n * - virtualFields: Fields that are computed\n *\n * @example\n * ```tsx\n * const { data: meta } = useGlobalMeta(\"siteSettings\");\n *\n * if (meta?.timestamps) {\n * console.log(\"Timestamps enabled for this global\");\n * }\n * ```\n */\nexport function useGlobalMeta<K extends ResolvedGlobalNames>(\n\tglobal: K,\n\tqueryOptions?: Omit<UseQueryOptions<GlobalMeta>, \"queryKey\" | \"queryFn\">,\n) {\n\tconst client = useAdminStore(selectClient);\n\n\treturn useQuery<GlobalMeta>({\n\t\tqueryKey: getGlobalMetaQueryKey(global),\n\t\tqueryFn: async () => {\n\t\t\treturn (client as any).globals[global].meta();\n\t\t},\n\t\tstaleTime: 5 * 60 * 1000,\n\t\tgcTime: 30 * 60 * 1000,\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Query key for global meta\n * Useful for prefetching or invalidation\n */\nexport function getGlobalMetaQueryKey(global: string) {\n\treturn [\"questpie\", \"globals\", global, \"meta\"] as const;\n}\n\n/**\n * Query options factory for global metadata\n * Can be used with TanStack Query's prefetching in loaders or with useSuspenseQuery\n *\n * @example\n * ```ts\n * // In TanStack Start loader\n * export const Route = createFileRoute(\"/admin/globals/:name\")({\n * loader: async ({ context, params }) => {\n * await context.queryClient.ensureQueryData(\n * getGlobalMetaQueryOptions(params.name, context.client)\n * );\n * },\n * });\n * ```\n */\nexport function getGlobalMetaQueryOptions(global: string, client: any) {\n\treturn {\n\t\tqueryKey: getGlobalMetaQueryKey(global),\n\t\tqueryFn: async (): Promise<GlobalMeta> => {\n\t\t\treturn client.globals[global].meta();\n\t\t},\n\t\tstaleTime: 5 * 60 * 1000,\n\t\tgcTime: 30 * 60 * 1000,\n\t};\n}\n\n/**\n * Suspense-enabled hook to fetch global metadata\n *\n * Uses useSuspenseQuery so the component will suspend until data is loaded\n * Must be used within a Suspense boundary\n *\n * @example\n * ```tsx\n * function GlobalFormViewInner({ global }: Props) {\n * const { data: meta } = useSuspenseGlobalMeta(global);\n * // meta is guaranteed to be defined here\n * console.log(meta.localizedFields);\n * }\n *\n * // Wrap with Suspense\n * <Suspense fallback={<Loading />}>\n * <GlobalFormViewInner global=\"siteSettings\" />\n * </Suspense>\n * ```\n */\nexport function useSuspenseGlobalMeta<K extends ResolvedGlobalNames>(\n\tglobal: K,\n) {\n\tconst client = useAdminStore(selectClient);\n\n\treturn useSuspenseQuery<GlobalMeta>(\n\t\tgetGlobalMetaQueryOptions(global, client),\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,SAAgB,cACf,QACA,cACC;CACD,MAAM,SAAS,cAAc,aAAa;AAE1C,QAAO,SAAqB;EAC3B,UAAU,sBAAsB,OAAO;EACvC,SAAS,YAAY;AACpB,UAAQ,OAAe,QAAQ,QAAQ,MAAM;;EAE9C,WAAW,MAAS;EACpB,QAAQ,OAAU;EAClB,GAAG;EACH,CAAC;;;;;;AAOH,SAAgB,sBAAsB,QAAgB;AACrD,QAAO;EAAC;EAAY;EAAW;EAAQ;EAAO"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-global-schema.mjs","names":[],"sources":["../../../src/client/hooks/use-global-schema.ts"],"sourcesContent":["/**\n * Hook for fetching global schema from the backend\n *\n * Returns introspection data including fields, access, and validation.\n */\n\nimport { type UseQueryOptions, useQuery } from \"@tanstack/react-query\";\nimport type { GlobalSchema, Questpie } from \"questpie\";\nimport type { RegisteredCMS, RegisteredGlobalNames } from \"../builder/registry\";\nimport { selectClient, useAdminStore } from \"../runtime\";\n\n// ==========================================================================\n// Type Helpers\n// ==========================================================================\n\n/**\n * Resolved global names (string if not registered)\n */\ntype ResolvedGlobalNames =\n RegisteredCMS extends Questpie<any> ? RegisteredGlobalNames : string;\n\n// ==========================================================================\n// Hook\n// ==========================================================================\n\nexport function useGlobalSchema<K extends ResolvedGlobalNames>(\n global: K,\n queryOptions?: Omit<UseQueryOptions<GlobalSchema>, \"queryKey\" | \"queryFn\">,\n) {\n const client = useAdminStore(selectClient);\n\n return useQuery<GlobalSchema>({\n queryKey: getGlobalSchemaQueryKey(global),\n queryFn: async () => {\n return (client as any).globals[global].schema();\n },\n staleTime: 5 * 60 * 1000,\n gcTime: 30 * 60 * 1000,\n ...queryOptions,\n });\n}\n\nexport function getGlobalSchemaQueryKey(global: string) {\n return [\"questpie\", \"globals\", global, \"schema\"] as const;\n}\n"],"mappings":";;;;;;;;;AAyBA,SAAgB,gBACd,QACA,cACA;CACA,MAAM,SAAS,cAAc,aAAa;AAE1C,QAAO,SAAuB;EAC5B,UAAU,wBAAwB,OAAO;EACzC,SAAS,YAAY;AACnB,UAAQ,OAAe,QAAQ,QAAQ,QAAQ;;EAEjD,WAAW,MAAS;EACpB,QAAQ,OAAU;EAClB,GAAG;EACJ,CAAC;;AAGJ,SAAgB,wBAAwB,QAAgB;AACtD,QAAO;EAAC;EAAY;EAAW;EAAQ;EAAS"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-global.d.mts","names":[],"sources":["../../../src/client/hooks/use-global.ts"],"sourcesContent":[],"mappings":";;;;;KAiBK,qBAAA;;AAP2E,CAAA;AAOtD;;;KAiBrB,mBAAA,GACJ,aAAsC,SAAhB,QAAgB,CAAA,GAAA,CAAA,GAAA,qBAAA,GAAA,MAAA;;AAiBvC;;;;;;;AA0CA;;;AAEwB,iBA5CR,SA4CQ,CAAA,UA5CY,mBA4CZ,CAAA,CAAA,UAAA,EA3CX,CA2CW,EAAA,OAAA,CAAA,EAAA,GAAA,EAAA,YAAA,CAAA,EAzCR,IAyCQ,CAzCH,eAyCG,EAAA,UAAA,GAAA,SAAA,CAAA,EAAA,eAAA,CAAA,EAxCL,qBAwCK,CAAA,EAAA,GAAA;;;;;;;;;;;;;iBAFR,0BAA0B,iCAC7B,qBACM,KAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-global.mjs","names":[],"sources":["../../../src/client/hooks/use-global.ts"],"sourcesContent":["import { createQuestpieQueryOptions } from \"@questpie/tanstack-query\";\nimport {\n\ttype UseMutationOptions,\n\ttype UseQueryOptions,\n\tuseMutation,\n\tuseQuery,\n\tuseQueryClient,\n} from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport type { QuestpieClient } from \"questpie/client\";\nimport type { RegisteredCMS, RegisteredGlobalNames } from \"../builder/registry\";\nimport {\n\tselectClient,\n\tselectContentLocale,\n\tuseAdminStore,\n} from \"../runtime\";\n\ntype GlobalRealtimeOptions = {\n\trealtime?: boolean;\n};\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\n/**\n * Resolved CMS type (Questpie<any> if not registered)\n */\ntype ResolvedCMS =\n\tRegisteredCMS extends Questpie<any> ? RegisteredCMS : Questpie<any>;\n\n/**\n * Resolved global names (string if not registered)\n */\ntype ResolvedGlobalNames =\n\tRegisteredCMS extends Questpie<any> ? RegisteredGlobalNames : string;\n\n// ============================================================================\n// Global Hooks\n// ============================================================================\n\n/**\n * Hook to fetch global settings\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { data } = useGlobal(\"siteSettings\");\n * ```\n */\nexport function useGlobal<K extends ResolvedGlobalNames>(\n\tglobalName: K,\n\toptions?: any,\n\tqueryOptions?: Omit<UseQueryOptions, \"queryKey\" | \"queryFn\">,\n\trealtimeOptions?: GlobalRealtimeOptions,\n): any {\n\tconst client = useAdminStore(selectClient);\n\tconst contentLocale = useAdminStore(selectContentLocale);\n\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\tkeyPrefix: [\"questpie\", \"globals\"],\n\t\tlocale: contentLocale,\n\t});\n\n\tconst globalOptions = {\n\t\t...options,\n\t\tlocale: contentLocale,\n\t};\n\n\t// Pass realtime option to query options builder - this uses streamedQuery internally\n\tconst baseQuery = (queryOpts as any).globals[globalName as string].get(\n\t\tglobalOptions as any,\n\t\t{ realtime: realtimeOptions?.realtime },\n\t);\n\n\treturn useQuery({\n\t\t...baseQuery,\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Hook to update global settings\n *\n * Uses RegisteredCMS from module augmentation for automatic type inference.\n *\n * @example\n * ```tsx\n * // Types inferred from module augmentation!\n * const { mutate } = useGlobalUpdate(\"siteSettings\");\n * mutate({ data: { siteName: \"New Name\" } });\n * ```\n */\nexport function useGlobalUpdate<K extends ResolvedGlobalNames>(\n\tglobalName: K,\n\tmutationOptions?: Omit<UseMutationOptions, \"mutationFn\">,\n): any {\n\tconst client = useAdminStore(selectClient);\n\tconst contentLocale = useAdminStore(selectContentLocale);\n\tconst queryClient = useQueryClient();\n\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\tkeyPrefix: [\"questpie\", \"globals\"],\n\t\tlocale: contentLocale,\n\t});\n\n\tconst globalQueryKey = queryOpts.key([\n\t\t\"globals\",\n\t\tglobalName as string,\n\t\t\"get\",\n\t\tcontentLocale,\n\t]);\n\n\treturn useMutation({\n\t\t...(queryOpts as any).globals[globalName as string].update(),\n\t\tonSuccess: (data: any, variables: any, context: any) => {\n\t\t\t(mutationOptions?.onSuccess as any)?.(data, variables, context);\n\t\t},\n\t\tonSettled: (data: any, error: any, variables: any, context: any) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: globalQueryKey,\n\t\t\t});\n\t\t\t(mutationOptions?.onSettled as any)?.(data, error, variables, context);\n\t\t},\n\t\t...mutationOptions,\n\t} as any);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoDA,SAAgB,UACf,YACA,SACA,cACA,iBACM;CACN,MAAM,SAAS,cAAc,aAAa;CAC1C,MAAM,gBAAgB,cAAc,oBAAoB;CACxD,MAAM,YAAY,2BAA2B,QAAe;EAC3D,WAAW,CAAC,YAAY,UAAU;EAClC,QAAQ;EACR,CAAC;CAEF,MAAM,gBAAgB;EACrB,GAAG;EACH,QAAQ;EACR;AAQD,QAAO,SAAS;EACf,GANkB,UAAkB,QAAQ,YAAsB,IAClE,eACA,EAAE,UAAU,iBAAiB,UAAU,CACvC;EAIA,GAAG;EACH,CAAC;;;;;;;;;;;;;;AAeH,SAAgB,gBACf,YACA,iBACM;CACN,MAAM,SAAS,cAAc,aAAa;CAC1C,MAAM,gBAAgB,cAAc,oBAAoB;CACxD,MAAM,cAAc,gBAAgB;CACpC,MAAM,YAAY,2BAA2B,QAAe;EAC3D,WAAW,CAAC,YAAY,UAAU;EAClC,QAAQ;EACR,CAAC;CAEF,MAAM,iBAAiB,UAAU,IAAI;EACpC;EACA;EACA;EACA;EACA,CAAC;AAEF,QAAO,YAAY;EAClB,GAAI,UAAkB,QAAQ,YAAsB,QAAQ;EAC5D,YAAY,MAAW,WAAgB,YAAiB;AACvD,IAAC,iBAAiB,aAAoB,MAAM,WAAW,QAAQ;;EAEhE,YAAY,MAAW,OAAY,WAAgB,YAAiB;AACnE,eAAY,kBAAkB,EAC7B,UAAU,gBACV,CAAC;AACF,IAAC,iBAAiB,aAAoB,MAAM,OAAO,WAAW,QAAQ;;EAEvE,GAAG;EACH,CAAQ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-locks.mjs","names":[],"sources":["../../../src/client/hooks/use-locks.ts"],"sourcesContent":["/**\n * Hooks for document locking (collaborative editing awareness)\n *\n * Provides realtime tracking of who is editing which documents.\n * Used in table view to show lock indicators and in form view to manage locks.\n */\n\nimport {\n\ttype UseMutationOptions,\n\tuseMutation,\n\tuseQuery,\n\tuseQueryClient,\n} from \"@tanstack/react-query\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport { useCurrentUser } from \"./use-current-user\";\nimport { useQuestpieQueryOptions } from \"./use-questpie-query-options\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Default lock duration in milliseconds (60 seconds)\n * Lock expires if not refreshed within this time.\n * Form should call refresh() on user activity (typing, clicking).\n */\nexport const LOCK_DURATION_MS = 60_000;\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface LockUser {\n\tid: string;\n\tname?: string | null;\n\temail: string;\n\timage?: string | null;\n}\n\nexport interface LockInfo {\n\tid: string;\n\tresourceType: \"collection\" | \"global\";\n\tresource: string;\n\tresourceId: string;\n\tuser: LockUser | string;\n\tsessionId: string;\n\texpiresAt: Date | string;\n\tcreatedAt?: Date | string;\n\tupdatedAt?: Date | string;\n}\n\n/** Helper to get user info from lock (handles both expanded and non-expanded) */\nexport function getLockUser(lock: LockInfo): LockUser | null {\n\tif (typeof lock.user === \"string\") return null;\n\treturn lock.user;\n}\n\n/** Helper to get user ID from lock */\nexport function getLockUserId(lock: LockInfo): string {\n\tif (typeof lock.user === \"string\") return lock.user;\n\treturn lock.user.id;\n}\n\n/**\n * Generate a unique session ID for this browser tab.\n * Persisted in sessionStorage so it survives page refreshes but not tab close.\n */\nfunction getSessionId(): string {\n\tif (typeof window === \"undefined\") return \"server\";\n\n\tconst key = \"__questpie_lock_session_id__\";\n\tlet sessionId = sessionStorage.getItem(key);\n\n\tif (!sessionId) {\n\t\tsessionId = crypto.randomUUID();\n\t\tsessionStorage.setItem(key, sessionId);\n\t}\n\n\treturn sessionId;\n}\n\nexport interface UseLockOptions {\n\t/** Resource type: collection or global */\n\tresourceType: \"collection\" | \"global\";\n\t/** Resource name (collection slug or global slug) */\n\tresource: string;\n\t/** Document ID to lock */\n\tresourceId: string;\n\t/** Whether to auto-acquire lock on mount (default: true) */\n\tautoAcquire?: boolean;\n\t/** Callback when lock is acquired */\n\tonAcquired?: (lock: LockInfo) => void;\n\t/** Callback when lock acquisition fails (someone else has it) */\n\tonBlocked?: (lock: LockInfo) => void;\n\t/** Callback when lock is released */\n\tonReleased?: () => void;\n}\n\nexport interface UseLockResult {\n\t/** Current lock info if we have the lock */\n\tlock: LockInfo | null;\n\t/** Lock info if someone else has the lock */\n\tblockedBy: LockInfo | null;\n\t/** Whether we currently hold the lock */\n\tisLocked: boolean;\n\t/** Whether someone else holds the lock */\n\tisBlocked: boolean;\n\t/** Whether same user has it open in another tab */\n\tisOpenElsewhere: boolean;\n\t/** Whether lock operations are in progress */\n\tisPending: boolean;\n\t/** Acquire the lock manually */\n\tacquire: () => Promise<LockInfo | null>;\n\t/** Release the lock manually */\n\trelease: () => Promise<void>;\n\t/** Refresh the lock (extend expiration) */\n\trefresh: () => Promise<void>;\n}\n\nexport interface UseLocksOptions {\n\t/** Resource type: collection or global */\n\tresourceType: \"collection\" | \"global\";\n\t/** Resource name (collection slug or global slug) */\n\tresource: string;\n\t/** Whether realtime updates are enabled */\n\trealtime?: boolean;\n}\n\nexport interface UseLocksResult {\n\t/** Map of resourceId -> lock info */\n\tlocks: Map<string, LockInfo>;\n\t/** Check if a specific resource is locked */\n\tisLocked: (resourceId: string) => boolean;\n\t/** Get lock info for a specific resource */\n\tgetLock: (resourceId: string) => LockInfo | undefined;\n\t/** Check if current user owns the lock */\n\tisOwnLock: (resourceId: string) => boolean;\n\t/** Whether data is loading */\n\tisLoading: boolean;\n}\n\n// ============================================================================\n// useLocks - Track all locks for a resource (for table view)\n// ============================================================================\n\n/**\n * Track all active locks for a collection/global.\n *\n * Used in table views to show who is editing which rows.\n *\n * @example\n * ```tsx\n * const { locks, isLocked, getLock } = useLocks({\n * resourceType: \"collection\",\n * resource: \"posts\",\n * realtime: true,\n * });\n *\n * // In table row\n * {isLocked(row.id) && (\n * <LockIndicator user={getLock(row.id)?.userName} />\n * )}\n * ```\n */\nexport function useLocks(options: UseLocksOptions): UseLocksResult {\n\tconst { resourceType, resource, realtime = true } = options;\n\tconst { queryOpts } = useQuestpieQueryOptions();\n\tconst currentUser = useCurrentUser();\n\n\t// Query active locks for this resource (with user data expanded)\n\tconst { data: rawData, isLoading } = useQuery({\n\t\t...(queryOpts as any).collections.adminLocks.find(\n\t\t\t{\n\t\t\t\twhere: {\n\t\t\t\t\tresourceType,\n\t\t\t\t\tresource,\n\t\t\t\t\t// Only get non-expired locks\n\t\t\t\t\texpiresAt: { gt: new Date() },\n\t\t\t\t},\n\t\t\t\twith: { user: true },\n\t\t\t},\n\t\t\t{ realtime },\n\t\t),\n\t});\n\n\tconst data = rawData as { docs?: LockInfo[] } | undefined;\n\n\t// Build lock map\n\tconst locks = new Map<string, LockInfo>();\n\tif (data?.docs) {\n\t\tfor (const lock of data.docs) {\n\t\t\tlocks.set(lock.resourceId, lock);\n\t\t}\n\t}\n\n\tconst isLocked = useCallback(\n\t\t(resourceId: string) => locks.has(resourceId),\n\t\t[locks],\n\t);\n\n\tconst getLock = useCallback(\n\t\t(resourceId: string) => locks.get(resourceId),\n\t\t[locks],\n\t);\n\n\tconst isOwnLock = useCallback(\n\t\t(resourceId: string) => {\n\t\t\tconst lock = locks.get(resourceId);\n\t\t\tif (!lock) return false;\n\t\t\treturn getLockUserId(lock) === currentUser?.id;\n\t\t},\n\t\t[locks, currentUser?.id],\n\t);\n\n\treturn {\n\t\tlocks,\n\t\tisLocked,\n\t\tgetLock,\n\t\tisOwnLock,\n\t\tisLoading,\n\t};\n}\n\n// ============================================================================\n// useLock - Manage a single document lock (for form view)\n// ============================================================================\n\n/**\n * Manage a document lock for editing.\n *\n * Automatically acquires lock on mount, sends heartbeats, and releases on unmount.\n *\n * @example\n * ```tsx\n * function EditForm({ collection, id }) {\n * const { isLocked, isBlocked, blockedBy } = useLock({\n * resourceType: \"collection\",\n * resource: collection,\n * resourceId: id,\n * });\n *\n * if (isBlocked) {\n * return <LockedBanner user={blockedBy?.userName} />;\n * }\n *\n * return <Form disabled={!isLocked} />;\n * }\n * ```\n */\nexport function useLock(options: UseLockOptions): UseLockResult {\n\tconst {\n\t\tresourceType,\n\t\tresource,\n\t\tresourceId,\n\t\tautoAcquire = true,\n\t\tonAcquired,\n\t\tonBlocked,\n\t\tonReleased,\n\t} = options;\n\n\tconst { queryOpts } = useQuestpieQueryOptions();\n\tconst queryClient = useQueryClient();\n\tconst currentUser = useCurrentUser();\n\n\tconst lockIdRef = useRef<string | null>(null);\n\n\t// Query existing lock for this resource (with user data expanded)\n\tconst { data: rawExistingLockData, isLoading: isCheckingLock } = useQuery({\n\t\t...(queryOpts as any).collections.adminLocks.find({\n\t\t\twhere: {\n\t\t\t\tresourceType,\n\t\t\t\tresource,\n\t\t\t\tresourceId,\n\t\t\t\texpiresAt: { gt: new Date() },\n\t\t\t},\n\t\t\twith: { user: true },\n\t\t\tlimit: 1,\n\t\t}),\n\t\tenabled: !!resourceId,\n\t});\n\n\tconst existingLockData = rawExistingLockData as\n\t\t| { docs?: LockInfo[] }\n\t\t| undefined;\n\tconst existingLock = existingLockData?.docs?.[0] ?? null;\n\n\t// Lock is \"own\" only if it's from this exact browser tab (same sessionId)\n\tconst sessionId = getSessionId();\n\tconst isOwnSession = existingLock?.sessionId === sessionId;\n\tconst isOwnUser = existingLock\n\t\t? getLockUserId(existingLock) === currentUser?.id\n\t\t: false;\n\n\t// For UI: show as blocked only if different user has the lock\n\t// Same user in different tab can see they have it open elsewhere\n\tconst blockedBy = existingLock && !isOwnUser ? existingLock : null;\n\tconst ownLockElsewhere = existingLock && isOwnUser && !isOwnSession;\n\n\t// Create lock mutation\n\tconst createMutation = useMutation({\n\t\tmutationFn: async () => {\n\t\t\tif (!currentUser) throw new Error(\"Not authenticated\");\n\n\t\t\tconst expiresAt = new Date(Date.now() + LOCK_DURATION_MS);\n\n\t\t\tconst result = await (queryOpts as any).collections.adminLocks.create({\n\t\t\t\tresourceType,\n\t\t\t\tresource,\n\t\t\t\tresourceId,\n\t\t\t\tuser: currentUser.id,\n\t\t\t\tsessionId,\n\t\t\t\texpiresAt,\n\t\t\t});\n\n\t\t\treturn result as LockInfo;\n\t\t},\n\t\tonSuccess: (lock) => {\n\t\t\tlockIdRef.current = lock.id;\n\t\t\tonAcquired?.(lock);\n\n\t\t\t// Invalidate locks query\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: [\"collections\", \"adminLocks\"],\n\t\t\t});\n\t\t},\n\t});\n\n\t// Update lock mutation (for heartbeat)\n\tconst updateMutation = useMutation({\n\t\tmutationFn: async () => {\n\t\t\tif (!lockIdRef.current) return;\n\n\t\t\tconst expiresAt = new Date(Date.now() + LOCK_DURATION_MS);\n\n\t\t\tawait (queryOpts as any).collections.adminLocks.update({\n\t\t\t\tid: lockIdRef.current,\n\t\t\t\tdata: { expiresAt },\n\t\t\t});\n\t\t},\n\t});\n\n\t// Delete lock mutation\n\tconst deleteMutation = useMutation({\n\t\tmutationFn: async () => {\n\t\t\tif (!lockIdRef.current) return;\n\n\t\t\tawait (queryOpts as any).collections.adminLocks.delete({\n\t\t\t\tid: lockIdRef.current,\n\t\t\t});\n\t\t},\n\t\tonSuccess: () => {\n\t\t\tlockIdRef.current = null;\n\t\t\tonReleased?.();\n\n\t\t\t// Invalidate locks query\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: [\"collections\", \"adminLocks\"],\n\t\t\t});\n\t\t},\n\t});\n\n\t// Acquire lock\n\tconst acquire = useCallback(async () => {\n\t\t// Check if already locked by someone else (different user)\n\t\tif (existingLock && !isOwnUser) {\n\t\t\tonBlocked?.(existingLock);\n\t\t\treturn null;\n\t\t}\n\n\t\t// If we already have the lock in this session, just use it\n\t\tif (isOwnSession && existingLock) {\n\t\t\tlockIdRef.current = existingLock.id;\n\t\t\treturn existingLock;\n\t\t}\n\n\t\t// Same user but different tab - they can open, but need own lock\n\t\t// Or no existing lock - acquire new one\n\t\ttry {\n\t\t\tconst lock = await createMutation.mutateAsync();\n\t\t\treturn lock;\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to acquire lock:\", error);\n\t\t\treturn null;\n\t\t}\n\t}, [existingLock, isOwnUser, isOwnSession, createMutation, onBlocked]);\n\n\t// Release lock\n\tconst release = useCallback(async () => {\n\t\tif (lockIdRef.current) {\n\t\t\ttry {\n\t\t\t\tawait deleteMutation.mutateAsync();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to release lock:\", error);\n\t\t\t}\n\t\t}\n\t}, [deleteMutation]);\n\n\t// Refresh lock (extend expiration)\n\tconst refresh = useCallback(async () => {\n\t\tif (lockIdRef.current) {\n\t\t\ttry {\n\t\t\t\tawait updateMutation.mutateAsync();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to refresh lock:\", error);\n\t\t\t}\n\t\t}\n\t}, [updateMutation]);\n\n\t// Auto-acquire on mount\n\tuseEffect(() => {\n\t\tif (!autoAcquire || !resourceId || !currentUser || isCheckingLock) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Wait for existing lock check to complete\n\t\tif (existingLock !== undefined) {\n\t\t\tif (blockedBy) {\n\t\t\t\tonBlocked?.(blockedBy);\n\t\t\t} else {\n\t\t\t\tacquire();\n\t\t\t}\n\t\t}\n\t}, [\n\t\tautoAcquire,\n\t\tresourceId,\n\t\tcurrentUser,\n\t\tisCheckingLock,\n\t\texistingLock,\n\t\tblockedBy,\n\t\tacquire,\n\t\tonBlocked,\n\t]);\n\n\t// No automatic heartbeat - form will call refresh() on user activity\n\n\t// Release on unmount\n\tuseEffect(() => {\n\t\tconst mutate = deleteMutation.mutate;\n\t\treturn () => {\n\t\t\tif (lockIdRef.current) {\n\t\t\t\t// Fire and forget - component is unmounting\n\t\t\t\tmutate();\n\t\t\t}\n\t\t};\n\t}, [deleteMutation.mutate]);\n\n\treturn {\n\t\t// Lock info if we own it in this session\n\t\tlock: isOwnSession ? existingLock : null,\n\t\t// Who is blocking us (different user)\n\t\tblockedBy,\n\t\t// True if we have the lock in this session\n\t\tisLocked: isOwnSession && !!existingLock,\n\t\t// True if different user has the lock\n\t\tisBlocked: !!blockedBy,\n\t\t// True if same user has it open in another tab\n\t\tisOpenElsewhere: !!ownLockElsewhere,\n\t\tisPending:\n\t\t\tisCheckingLock ||\n\t\t\tcreateMutation.isPending ||\n\t\t\tupdateMutation.isPending ||\n\t\t\tdeleteMutation.isPending,\n\t\tacquire,\n\t\trelease,\n\t\trefresh,\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-media-query.d.mts","names":[],"sources":["../../../src/client/hooks/use-media-query.ts"],"sourcesContent":[],"mappings":";;AAcA;AA2DA;AAOA;;;;;;;iBAlEgB,aAAA;;;;iBA2DA,WAAA,CAAA;;;;iBAOA,YAAA,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-media-query.mjs","names":["React"],"sources":["../../../src/client/hooks/use-media-query.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n/**\n * Hook to detect media query matches\n *\n * @example\n * ```tsx\n * const isMobile = useMediaQuery(\"(max-width: 768px)\");\n * const isDesktop = useMediaQuery(\"(min-width: 769px)\");\n * const prefersDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n * ```\n */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = React.useState<boolean>(() => {\n // Check if we're on the server\n if (typeof window === \"undefined\") {\n return false;\n }\n return window.matchMedia(query).matches;\n });\n\n React.useEffect(() => {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const mediaQuery = window.matchMedia(query);\n\n // Set initial value\n setMatches(mediaQuery.matches);\n\n // Create listener\n const listener = (event: MediaQueryListEvent) => {\n setMatches(event.matches);\n };\n\n // Add listener (using modern API with fallback)\n if (mediaQuery.addEventListener) {\n mediaQuery.addEventListener(\"change\", listener);\n } else {\n // Fallback for older browsers\n mediaQuery.addListener(listener);\n }\n\n // Cleanup\n return () => {\n if (mediaQuery.removeEventListener) {\n mediaQuery.removeEventListener(\"change\", listener);\n } else {\n mediaQuery.removeListener(listener);\n }\n };\n }, [query]);\n\n return matches;\n}\n\n/**\n * Predefined breakpoints matching Tailwind CSS defaults\n */\nexport const breakpoints = {\n sm: \"(min-width: 640px)\",\n md: \"(min-width: 768px)\",\n lg: \"(min-width: 1024px)\",\n xl: \"(min-width: 1280px)\",\n \"2xl\": \"(min-width: 1536px)\",\n} as const;\n\n/**\n * Hook to check if viewport is mobile (below md breakpoint)\n */\nexport function useIsMobile(): boolean {\n return !useMediaQuery(breakpoints.md);\n}\n\n/**\n * Hook to check if viewport is desktop (md breakpoint and above)\n */\nexport function useIsDesktop(): boolean {\n return useMediaQuery(breakpoints.md);\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,SAAgB,cAAc,OAAwB;CACpD,MAAM,CAAC,SAAS,cAAcA,QAAM,eAAwB;AAE1D,MAAI,OAAO,WAAW,YACpB,QAAO;AAET,SAAO,OAAO,WAAW,MAAM,CAAC;GAChC;AAEF,SAAM,gBAAgB;AACpB,MAAI,OAAO,WAAW,YACpB;EAGF,MAAM,aAAa,OAAO,WAAW,MAAM;AAG3C,aAAW,WAAW,QAAQ;EAG9B,MAAM,YAAY,UAA+B;AAC/C,cAAW,MAAM,QAAQ;;AAI3B,MAAI,WAAW,iBACb,YAAW,iBAAiB,UAAU,SAAS;MAG/C,YAAW,YAAY,SAAS;AAIlC,eAAa;AACX,OAAI,WAAW,oBACb,YAAW,oBAAoB,UAAU,SAAS;OAElD,YAAW,eAAe,SAAS;;IAGtC,CAAC,MAAM,CAAC;AAEX,QAAO;;;;;AAMT,MAAa,cAAc;CACzB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACR;;;;AAKD,SAAgB,cAAuB;AACrC,QAAO,CAAC,cAAc,YAAY,GAAG;;;;;AAMvC,SAAgB,eAAwB;AACtC,QAAO,cAAc,YAAY,GAAG"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-prefill-params.mjs","names":["prefill: Record<string, unknown>"],"sources":["../../../src/client/hooks/use-prefill-params.ts"],"sourcesContent":["/**\n * usePrefillParams Hook\n *\n * Reads prefill parameters from URL query string for pre-populating form fields.\n * Supports the pattern: ?prefill.fieldName=value\n *\n * @example\n * ```tsx\n * // URL: /admin/collections/barbers/create?prefill.services=123\n *\n * const prefill = usePrefillParams();\n * // prefill = { services: \"123\" }\n *\n * <CollectionForm defaultValues={prefill} ... />\n * ```\n */\n\nimport * as React from \"react\";\n\n/**\n * Parse prefill parameters from a URLSearchParams object\n */\nexport function parsePrefillParams(\n searchParams: URLSearchParams,\n): Record<string, unknown> {\n const prefill: Record<string, unknown> = {};\n\n for (const [key, value] of searchParams.entries()) {\n if (key.startsWith(\"prefill.\")) {\n const fieldName = key.slice(\"prefill.\".length);\n if (fieldName) {\n // Try to parse JSON for complex values (arrays, objects)\n try {\n // Check if value looks like JSON\n if (\n value.startsWith(\"[\") ||\n value.startsWith(\"{\") ||\n value === \"true\" ||\n value === \"false\" ||\n value === \"null\" ||\n !isNaN(Number(value))\n ) {\n prefill[fieldName] = JSON.parse(value);\n } else {\n prefill[fieldName] = value;\n }\n } catch {\n // If parsing fails, use as string\n prefill[fieldName] = value;\n }\n }\n }\n }\n\n return prefill;\n}\n\n/**\n * Parse prefill parameters from URL string\n */\nexport function parsePrefillParamsFromUrl(\n url: string,\n): Record<string, unknown> {\n try {\n const urlObj = new URL(url, \"http://localhost\");\n return parsePrefillParams(urlObj.searchParams);\n } catch {\n return {};\n }\n}\n\n/**\n * Hook to read prefill parameters from current URL\n *\n * @returns Object with field names as keys and prefill values\n */\nexport function usePrefillParams(): Record<string, unknown> {\n const [prefill, setPrefill] = React.useState<Record<string, unknown>>({});\n\n React.useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n // Parse initial URL\n const searchParams = new URLSearchParams(window.location.search);\n setPrefill(parsePrefillParams(searchParams));\n\n // Listen for URL changes (for SPA navigation)\n const handlePopState = () => {\n const params = new URLSearchParams(window.location.search);\n setPrefill(parsePrefillParams(params));\n };\n\n window.addEventListener(\"popstate\", handlePopState);\n return () => window.removeEventListener(\"popstate\", handlePopState);\n }, []);\n\n return prefill;\n}\n\n/**\n * Build URL with prefill parameters\n *\n * @param baseUrl - Base URL to add params to\n * @param prefillData - Object with field names and values to prefill\n * @returns URL with prefill query params\n *\n * @example\n * ```ts\n * buildPrefillUrl(\"/admin/collections/barbers/create\", { services: \"123\" })\n * // Returns: \"/admin/collections/barbers/create?prefill.services=123\"\n *\n * buildPrefillUrl(\"/admin/collections/posts/create\", { tags: [\"a\", \"b\"] })\n * // Returns: \"/admin/collections/posts/create?prefill.tags=%5B%22a%22%2C%22b%22%5D\"\n * ```\n */\nexport function buildPrefillUrl(\n baseUrl: string,\n prefillData: Record<string, unknown>,\n): string {\n const url = new URL(baseUrl, \"http://localhost\");\n\n for (const [key, value] of Object.entries(prefillData)) {\n if (value !== undefined && value !== null) {\n const stringValue =\n typeof value === \"object\" ? JSON.stringify(value) : String(value);\n url.searchParams.set(`prefill.${key}`, stringValue);\n }\n }\n\n // Return path + search (without origin for relative URLs)\n return url.pathname + url.search;\n}\n\nexport default usePrefillParams;\n"],"mappings":";;;;;;AAsBA,SAAgB,mBACd,cACyB;CACzB,MAAMA,UAAmC,EAAE;AAE3C,MAAK,MAAM,CAAC,KAAK,UAAU,aAAa,SAAS,CAC/C,KAAI,IAAI,WAAW,WAAW,EAAE;EAC9B,MAAM,YAAY,IAAI,MAAM,EAAkB;AAC9C,MAAI,UAEF,KAAI;AAEF,OACE,MAAM,WAAW,IAAI,IACrB,MAAM,WAAW,IAAI,IACrB,UAAU,UACV,UAAU,WACV,UAAU,UACV,CAAC,MAAM,OAAO,MAAM,CAAC,CAErB,SAAQ,aAAa,KAAK,MAAM,MAAM;OAEtC,SAAQ,aAAa;UAEjB;AAEN,WAAQ,aAAa;;;AAM7B,QAAO;;;;;;;;;;;;;;;;;;AA6DT,SAAgB,gBACd,SACA,aACQ;CACR,MAAM,MAAM,IAAI,IAAI,SAAS,mBAAmB;AAEhD,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,CACpD,KAAI,UAAU,UAAa,UAAU,MAAM;EACzC,MAAM,cACJ,OAAO,UAAU,WAAW,KAAK,UAAU,MAAM,GAAG,OAAO,MAAM;AACnE,MAAI,aAAa,IAAI,WAAW,OAAO,YAAY;;AAKvD,QAAO,IAAI,WAAW,IAAI"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-questpie-query-options.mjs","names":[],"sources":["../../../src/client/hooks/use-questpie-query-options.ts"],"sourcesContent":["import { createQuestpieQueryOptions } from \"@questpie/tanstack-query\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport {\n\tselectClient,\n\tuseAdminStore,\n\tuseScopedLocale,\n} from \"../runtime\";\n\n/**\n * Shared hook that creates questpie query options with the current client and scoped locale.\n * Deduplicates the common pattern used across collection/global hooks.\n */\nexport function useQuestpieQueryOptions(\n\tkeyPrefix: readonly string[] = [\"questpie\", \"collections\"],\n) {\n\tconst client = useAdminStore(selectClient);\n\tconst { locale } = useScopedLocale();\n\tconst queryClient = useQueryClient();\n\tconst queryOpts = createQuestpieQueryOptions(client as any, {\n\t\tkeyPrefix,\n\t\tlocale,\n\t});\n\n\treturn { queryOpts, queryClient, locale, client } as const;\n}\n"],"mappings":";;;;;;;;;;AAYA,SAAgB,wBACf,YAA+B,CAAC,YAAY,cAAc,EACzD;CACD,MAAM,SAAS,cAAc,aAAa;CAC1C,MAAM,EAAE,WAAW,iBAAiB;CACpC,MAAM,cAAc,gBAAgB;AAMpC,QAAO;EAAE,WALS,2BAA2B,QAAe;GAC3D;GACA;GACA,CAAC;EAEkB;EAAa;EAAQ;EAAQ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-reactive-fields.d.mts","names":[],"sources":["../../../src/client/hooks/use-reactive-fields.ts"],"sourcesContent":[],"mappings":";;;;;;;AAkEa,UA/CI,kBAAA,CA+CJ;EAwFG,MAAA,CAAA,EAAA,OAAA;EACf,QAAA,CAAA,EAAA,OAAA;EACA,QAAA,CAAA,EAAA,OAAA;;;;;AAI6B,UApIb,mBAAA,CAoIa;EAAuB,KAAA,EAAA,MAAA;;;;;;;;UA1HpC,wBAAA;;;;;;mBAQC,eAAe;;;;;;;;;UAYhB,uBAAA;;eAEH,eAAe;;;;SAMrB;;;;;;;;;;;;;;;;;;;;iBAwFQ,iBAAA;;;;;;GAMb,2BAA2B"}
|