@questpie/admin 1.1.1 → 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 +256 -488
- package/dist/augmentation.d.mts +414 -0
- package/dist/client/blocks/block-renderer.d.mts +45 -0
- package/dist/client/blocks/block-renderer.mjs +105 -0
- package/dist/client/blocks/index.d.mts +2 -0
- package/dist/client/blocks/types.d.mts +68 -0
- package/dist/client/blocks/types.mjs +19 -0
- package/dist/client/builder/admin-types.d.mts +40 -0
- package/dist/client/builder/admin.d.mts +110 -0
- package/dist/client/builder/admin.mjs +151 -0
- package/dist/client/builder/field/field.d.mts +51 -0
- package/dist/client/builder/field/field.mjs +37 -0
- package/dist/client/builder/index.d.mts +31 -0
- package/dist/client/builder/page/page.d.mts +24 -0
- package/dist/client/builder/page/page.mjs +31 -0
- package/dist/client/builder/registry.d.mts +50 -0
- package/dist/client/builder/types/action-registry.mjs +276 -0
- package/dist/client/builder/types/action-types.d.mts +226 -0
- package/dist/client/builder/types/collection-types.mjs +10 -0
- package/dist/client/builder/types/common.d.mts +46 -0
- package/dist/client/builder/types/field-types.d.mts +592 -0
- package/dist/client/builder/types/field-types.mjs +18 -0
- package/dist/client/builder/types/ui-config.d.mts +158 -0
- package/dist/client/builder/types/widget-types.d.mts +562 -0
- package/dist/client/builder/validation.d.mts +33 -0
- package/dist/client/builder/validation.mjs +227 -0
- package/dist/client/builder/view/view.d.mts +49 -0
- package/dist/client/builder/view/view.mjs +27 -0
- package/dist/client/builder/widget/widget.d.mts +27 -0
- package/dist/client/builder/widget/widget.mjs +21 -0
- package/dist/client/components/actions/action-button.mjs +245 -0
- package/dist/client/components/actions/action-dialog.mjs +559 -0
- package/dist/client/components/actions/confirmation-dialog.mjs +201 -0
- package/dist/client/components/actions/header-actions.mjs +210 -0
- package/dist/client/components/admin-link.d.mts +66 -0
- package/dist/client/components/admin-link.mjs +171 -0
- package/dist/client/components/auth/auth-guard.d.mts +50 -0
- package/dist/client/components/auth/auth-guard.mjs +60 -0
- package/dist/client/components/auth/auth-loading.d.mts +35 -0
- package/dist/client/components/auth/auth-loading.mjs +55 -0
- package/dist/client/components/blocks/block-canvas.mjs +159 -0
- package/dist/client/components/blocks/block-editor-context.mjs +125 -0
- package/dist/client/components/blocks/block-editor-layout.mjs +199 -0
- package/dist/client/components/blocks/block-editor-provider.mjs +235 -0
- package/dist/client/components/blocks/block-fields-renderer.mjs +240 -0
- package/dist/client/components/blocks/block-insert-button.mjs +189 -0
- package/dist/client/components/blocks/block-item-menu.mjs +363 -0
- package/dist/client/components/blocks/block-item.mjs +434 -0
- package/dist/client/components/blocks/block-library-sidebar.mjs +285 -0
- package/dist/client/components/blocks/block-tree.mjs +103 -0
- package/dist/client/components/blocks/block-type-icon.mjs +95 -0
- package/dist/client/components/blocks/utils/tree-utils.mjs +185 -0
- package/dist/client/components/component-renderer.d.mts +114 -0
- package/dist/client/components/component-renderer.mjs +258 -0
- package/dist/client/components/error-boundary.mjs +144 -0
- package/dist/client/components/fields/array-field.mjs +506 -0
- package/dist/client/components/fields/asset-preview-field.mjs +159 -0
- package/dist/client/components/fields/blocks-field/blocks-field.mjs +209 -0
- package/dist/client/components/fields/boolean-field.mjs +77 -0
- package/dist/client/components/fields/date-field.mjs +76 -0
- package/dist/client/components/fields/datetime-field.mjs +74 -0
- package/dist/client/components/fields/email-field.mjs +67 -0
- package/dist/client/components/fields/field-utils.mjs +64 -0
- package/dist/client/components/fields/field-wrapper.mjs +124 -0
- package/dist/client/components/fields/json-field.mjs +461 -0
- package/dist/client/components/fields/locale-badge.mjs +25 -0
- package/dist/client/components/fields/number-field.mjs +73 -0
- package/dist/client/components/fields/object-array-field.mjs +707 -0
- package/dist/client/components/fields/object-field.mjs +686 -0
- package/dist/client/components/fields/relation/displays/cards-display.mjs +254 -0
- package/dist/client/components/fields/relation/displays/chips-display.mjs +173 -0
- package/dist/client/components/fields/relation/displays/grid-display.mjs +209 -0
- package/dist/client/components/fields/relation/displays/list-display.mjs +247 -0
- package/dist/client/components/fields/relation/displays/table-display.mjs +309 -0
- package/dist/client/components/fields/relation/displays/types.mjs +72 -0
- package/dist/client/components/fields/relation/relation-items-display.mjs +143 -0
- package/dist/client/components/fields/relation-field.mjs +161 -0
- package/dist/client/components/fields/relation-picker.mjs +296 -0
- package/dist/client/components/fields/relation-select.mjs +232 -0
- package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +105 -0
- package/dist/client/components/fields/rich-text-editor/extensions.mjs +144 -0
- package/dist/client/components/fields/rich-text-editor/image-popover.mjs +221 -0
- package/dist/client/components/fields/rich-text-editor/index.mjs +520 -0
- package/dist/client/components/fields/rich-text-editor/link-popover.mjs +85 -0
- package/dist/client/components/fields/rich-text-editor/presets.mjs +123 -0
- package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +188 -0
- package/dist/client/components/fields/rich-text-editor/table-controls.mjs +433 -0
- package/dist/client/components/fields/rich-text-editor/toolbar.mjs +541 -0
- package/dist/client/components/fields/rich-text-editor/types.mjs +30 -0
- package/dist/client/components/fields/rich-text-editor/utils.mjs +50 -0
- package/dist/client/components/fields/rich-text-field.mjs +64 -0
- package/dist/client/components/fields/select-field.mjs +88 -0
- package/dist/client/components/fields/text-field.mjs +72 -0
- package/dist/client/components/fields/textarea-field.mjs +71 -0
- package/dist/client/components/fields/time-field.mjs +67 -0
- package/dist/client/components/fields/upload-field.mjs +621 -0
- package/dist/client/components/filter-builder/columns-tab.mjs +325 -0
- package/dist/client/components/filter-builder/filter-builder-sheet.mjs +456 -0
- package/dist/client/components/filter-builder/filters-tab.mjs +663 -0
- package/dist/client/components/filter-builder/saved-views-tab.mjs +278 -0
- 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 +251 -0
- package/dist/client/components/media/media-grid.mjs +314 -0
- package/dist/client/components/media/media-picker-dialog.mjs +563 -0
- package/dist/client/components/preview/live-preview-mode.mjs +503 -0
- package/dist/client/components/preview/preview-pane.mjs +388 -0
- package/dist/client/components/primitives/asset-preview.mjs +771 -0
- package/dist/client/components/primitives/checkbox-input.mjs +59 -0
- package/dist/client/components/primitives/date-input.mjs +461 -0
- package/dist/client/components/primitives/dropzone.mjs +368 -0
- package/dist/client/components/primitives/number-input.mjs +117 -0
- package/dist/client/components/primitives/select-multi.mjs +590 -0
- package/dist/client/components/primitives/select-single.mjs +473 -0
- package/dist/client/components/primitives/text-input.mjs +45 -0
- package/dist/client/components/primitives/textarea-input.mjs +43 -0
- package/dist/client/components/primitives/time-input.mjs +145 -0
- package/dist/client/components/primitives/toggle-input.mjs +51 -0
- package/dist/client/components/primitives/types.mjs +12 -0
- package/dist/client/components/sheets/resource-sheet.mjs +86 -0
- package/dist/client/components/ui/accordion.mjs +169 -0
- package/dist/client/components/ui/alert.mjs +85 -0
- package/dist/client/components/ui/badge.mjs +76 -0
- package/dist/client/components/ui/button.mjs +84 -0
- package/dist/client/components/ui/card.mjs +206 -0
- package/dist/client/components/ui/checkbox.mjs +82 -0
- package/dist/client/components/ui/command.mjs +239 -0
- package/dist/client/components/ui/dialog.mjs +296 -0
- package/dist/client/components/ui/drawer.mjs +278 -0
- package/dist/client/components/ui/dropdown-menu.mjs +315 -0
- package/dist/client/components/ui/empty-state.mjs +99 -0
- package/dist/client/components/ui/field.mjs +354 -0
- package/dist/client/components/ui/input-group.mjs +201 -0
- package/dist/client/components/ui/input.mjs +46 -0
- package/dist/client/components/ui/kbd.mjs +53 -0
- package/dist/client/components/ui/label.mjs +45 -0
- package/dist/client/components/ui/popover.mjs +176 -0
- package/dist/client/components/ui/responsive-dialog.mjs +308 -0
- package/dist/client/components/ui/search-input.mjs +139 -0
- package/dist/client/components/ui/select.mjs +325 -0
- package/dist/client/components/ui/separator.mjs +47 -0
- package/dist/client/components/ui/sheet.mjs +280 -0
- package/dist/client/components/ui/sidebar.mjs +774 -0
- package/dist/client/components/ui/skeleton.mjs +40 -0
- package/dist/client/components/ui/sonner.d.mts +13 -0
- package/dist/client/components/ui/sonner.mjs +85 -0
- package/dist/client/components/ui/spinner.mjs +52 -0
- package/dist/client/components/ui/switch.mjs +58 -0
- package/dist/client/components/ui/table.mjs +276 -0
- package/dist/client/components/ui/tabs.mjs +160 -0
- package/dist/client/components/ui/textarea.mjs +40 -0
- package/dist/client/components/ui/toolbar.mjs +136 -0
- package/dist/client/components/ui/tooltip.mjs +146 -0
- package/dist/client/components/widgets/chart-widget.mjs +582 -0
- package/dist/client/components/widgets/progress-widget.mjs +200 -0
- package/dist/client/components/widgets/quick-actions-widget.mjs +209 -0
- package/dist/client/components/widgets/recent-items-widget.mjs +196 -0
- package/dist/client/components/widgets/stats-widget.mjs +261 -0
- package/dist/client/components/widgets/table-widget.mjs +273 -0
- package/dist/client/components/widgets/timeline-widget.mjs +279 -0
- package/dist/client/components/widgets/value-widget.mjs +312 -0
- package/dist/client/components/widgets/widget-skeletons.mjs +427 -0
- package/dist/client/contexts/breadcrumb-context.mjs +60 -0
- package/dist/client/contexts/focus-context.d.mts +87 -0
- package/dist/client/contexts/focus-context.mjs +250 -0
- package/dist/client/hooks/typed-hooks.d.mts +110 -0
- package/dist/client/hooks/typed-hooks.mjs +888 -0
- package/dist/client/hooks/use-action.mjs +329 -0
- package/dist/client/hooks/use-admin-config.mjs +69 -0
- package/dist/client/hooks/use-admin-preferences.mjs +171 -0
- package/dist/client/hooks/use-admin-routes.mjs +130 -0
- package/dist/client/hooks/use-audit-history.mjs +157 -0
- package/dist/client/hooks/use-auth.d.mts +97 -0
- package/dist/{use-auth-BoLmWtmU.mjs → client/hooks/use-auth.mjs} +9 -10
- package/dist/client/hooks/use-collection-fields.mjs +71 -0
- package/dist/client/hooks/use-collection-meta.mjs +153 -0
- package/dist/client/hooks/use-collection-schema.mjs +90 -0
- package/dist/client/hooks/use-collection-validation.mjs +88 -0
- package/dist/client/hooks/use-collection.d.mts +96 -0
- package/dist/client/hooks/use-collection.mjs +673 -0
- package/dist/client/hooks/use-current-user.d.mts +60 -0
- package/dist/client/hooks/use-current-user.mjs +79 -0
- package/dist/client/hooks/use-field-hooks.mjs +199 -0
- package/dist/client/hooks/use-field-options.d.mts +57 -0
- package/dist/client/hooks/use-field-options.mjs +269 -0
- package/dist/client/hooks/use-global-fields.mjs +58 -0
- package/dist/client/hooks/use-global-meta.mjs +105 -0
- package/dist/client/hooks/use-global-schema.mjs +53 -0
- package/dist/client/hooks/use-global.d.mts +51 -0
- package/dist/client/hooks/use-global.mjs +284 -0
- package/dist/client/hooks/use-locks.mjs +452 -0
- package/dist/client/hooks/use-media-query.d.mts +22 -0
- package/dist/client/hooks/use-media-query.mjs +81 -0
- package/dist/client/hooks/use-prefill-params.mjs +47 -0
- package/dist/client/hooks/use-questpie-query-options.mjs +50 -0
- package/dist/client/hooks/use-reactive-fields.d.mts +78 -0
- package/dist/client/hooks/use-reactive-fields.mjs +201 -0
- package/dist/client/hooks/use-realtime-highlight.mjs +158 -0
- package/dist/client/hooks/use-saved-views.mjs +140 -0
- 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 +258 -0
- package/dist/client/hooks/use-server-actions.mjs +191 -0
- package/dist/client/hooks/use-server-validation.mjs +291 -0
- package/dist/client/hooks/use-server-widget-data.d.mts +25 -0
- package/dist/client/hooks/use-server-widget-data.mjs +65 -0
- package/dist/client/hooks/use-setup-status.d.mts +38 -0
- package/dist/client/hooks/use-setup-status.mjs +62 -0
- 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 +31 -0
- package/dist/client/hooks/use-upload.mjs +209 -0
- package/dist/client/hooks/use-validation-error-map.mjs +57 -0
- package/dist/client/hooks/use-view-state.mjs +479 -0
- package/dist/client/i18n/hooks.mjs +284 -0
- package/dist/client/i18n/intl-cache.mjs +64 -0
- package/dist/client/i18n/messages.mjs +6 -0
- package/dist/client/i18n/simple.d.mts +21 -0
- package/dist/client/i18n/simple.mjs +156 -0
- package/dist/client/i18n/types.d.mts +109 -0
- 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 +23 -0
- package/dist/client/preview/block-scope-context.d.mts +73 -0
- package/dist/client/preview/block-scope-context.mjs +116 -0
- package/dist/client/preview/index.d.mts +5 -0
- package/dist/client/preview/preview-banner.d.mts +45 -0
- package/dist/client/preview/preview-banner.mjs +134 -0
- package/dist/client/preview/preview-field.d.mts +107 -0
- package/dist/client/preview/preview-field.mjs +227 -0
- package/dist/client/preview/types.d.mts +114 -0
- package/dist/client/preview/types.mjs +20 -0
- package/dist/client/preview/use-collection-preview.d.mts +70 -0
- package/dist/client/preview/use-collection-preview.mjs +163 -0
- package/dist/client/runtime/content-locales-provider.d.mts +1 -0
- package/dist/client/runtime/content-locales-provider.mjs +136 -0
- package/dist/client/runtime/index.d.mts +5 -0
- package/dist/client/runtime/index.mjs +6 -0
- package/dist/client/runtime/locale-scope.d.mts +2 -0
- package/dist/client/runtime/locale-scope.mjs +108 -0
- package/dist/client/runtime/provider.d.mts +203 -0
- package/dist/client/runtime/provider.mjs +393 -0
- package/dist/client/runtime/routes.d.mts +49 -0
- package/dist/client/runtime/routes.mjs +91 -0
- package/dist/client/runtime/translations-provider.mjs +242 -0
- package/dist/client/scope/index.d.mts +3 -0
- package/dist/client/scope/picker.d.mts +53 -0
- package/dist/client/scope/picker.mjs +395 -0
- package/dist/client/scope/provider.d.mts +103 -0
- package/dist/client/scope/provider.mjs +167 -0
- package/dist/client/scope/types.d.mts +111 -0
- package/dist/client/styles/index.css +344 -188
- package/dist/client/utils/auto-expand-fields.mjs +83 -0
- package/dist/client/utils/build-field-definitions-from-schema.mjs +259 -0
- package/dist/client/utils/dependency-tracker.mjs +61 -0
- package/dist/client/utils/detect-relations.mjs +45 -0
- package/dist/client/utils/locale-to-flag.d.mts +119 -0
- package/dist/client/utils/locale-to-flag.mjs +129 -0
- package/dist/client/utils/routes.mjs +195 -0
- package/dist/client/views/auth/accept-invite-form.d.mts +72 -0
- package/dist/client/views/auth/accept-invite-form.mjs +473 -0
- package/dist/client/views/auth/auth-layout.d.mts +43 -0
- package/dist/client/views/auth/auth-layout.mjs +116 -0
- package/dist/client/views/auth/forgot-password-form.d.mts +58 -0
- package/dist/client/views/auth/forgot-password-form.mjs +386 -0
- package/dist/client/views/auth/invite-form.mjs +497 -0
- package/dist/client/views/auth/login-form.d.mts +75 -0
- package/dist/client/views/auth/login-form.mjs +387 -0
- package/dist/client/views/auth/reset-password-form.d.mts +65 -0
- package/dist/client/views/auth/reset-password-form.mjs +515 -0
- package/dist/client/views/auth/setup-form.d.mts +60 -0
- package/dist/client/views/auth/setup-form.mjs +526 -0
- package/dist/client/views/collection/auto-form-fields.mjs +873 -0
- package/dist/client/views/collection/bulk-action-toolbar.mjs +480 -0
- package/dist/client/views/collection/cells/complex-cells.mjs +746 -0
- package/dist/client/views/collection/cells/primitive-cells.mjs +395 -0
- package/dist/client/views/collection/cells/relation-cells.mjs +260 -0
- package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +509 -0
- package/dist/client/views/collection/cells/shared/cell-helpers.mjs +125 -0
- package/dist/client/views/collection/cells/shared/relation-chip.mjs +121 -0
- package/dist/client/views/collection/cells/upload-cells.mjs +28 -0
- package/dist/client/views/collection/columns/build-columns.mjs +195 -0
- package/dist/client/views/collection/columns/column-defaults.mjs +123 -0
- package/dist/client/views/collection/field-context.mjs +126 -0
- package/dist/client/views/collection/field-renderer.mjs +368 -0
- package/dist/client/views/collection/form-view.mjs +1566 -0
- package/dist/client/views/collection/table-view.mjs +832 -0
- package/dist/client/views/collection/view-skeletons.mjs +215 -0
- package/dist/client/views/common/global-search.mjs +700 -0
- package/dist/client/views/dashboard/dashboard-grid.mjs +881 -0
- package/dist/client/views/dashboard/dashboard-widget.mjs +265 -0
- package/dist/client/views/dashboard/widget-card.mjs +372 -0
- package/dist/client/views/globals/global-form-view.mjs +1306 -0
- package/dist/client/views/layout/admin-layout-provider.d.mts +137 -0
- package/dist/client/views/layout/admin-layout-provider.mjs +193 -0
- package/dist/client/views/layout/admin-layout.d.mts +133 -0
- package/dist/client/views/layout/admin-layout.mjs +302 -0
- package/dist/client/views/layout/admin-router.d.mts +93 -0
- package/dist/client/views/layout/admin-router.mjs +1254 -0
- package/dist/client/views/layout/admin-sidebar.d.mts +99 -0
- package/dist/client/views/layout/admin-sidebar.mjs +1379 -0
- package/dist/client/views/layout/admin-topbar.mjs +236 -0
- package/dist/client/views/pages/accept-invite-page.d.mts +66 -0
- package/dist/client/views/pages/accept-invite-page.mjs +349 -0
- package/dist/client/views/pages/dashboard-page.d.mts +43 -0
- package/dist/client/views/pages/dashboard-page.mjs +84 -0
- package/dist/client/views/pages/forgot-password-page.d.mts +56 -0
- package/dist/client/views/pages/forgot-password-page.mjs +152 -0
- package/dist/client/views/pages/invite-page.d.mts +70 -0
- package/dist/client/views/pages/invite-page.mjs +161 -0
- package/dist/client/views/pages/login-page.d.mts +69 -0
- package/dist/client/views/pages/login-page.mjs +193 -0
- package/dist/client/views/pages/reset-password-page.d.mts +63 -0
- package/dist/client/views/pages/reset-password-page.mjs +257 -0
- package/dist/client/views/pages/setup-page.d.mts +61 -0
- package/dist/client/views/pages/setup-page.mjs +156 -0
- package/dist/client-module.d.mts +3 -0
- package/dist/client-module.mjs +3 -0
- package/dist/client.d.mts +99 -3
- package/dist/client.mjs +52 -12
- package/dist/components/rich-text/index.d.mts +1 -0
- package/dist/components/rich-text/rich-text-renderer.d.mts +103 -0
- package/dist/components/rich-text/rich-text-renderer.mjs +237 -0
- package/dist/index.d.mts +59 -3
- package/dist/index.mjs +52 -12
- package/dist/plugin.d.mts +2 -0
- package/dist/plugin.mjs +3 -0
- package/dist/server/adapters/nextjs.d.mts +120 -0
- package/dist/server/adapters/nextjs.mjs +110 -0
- package/dist/server/adapters/tanstack.d.mts +132 -0
- package/dist/server/adapters/tanstack.mjs +89 -0
- 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 -0
- package/dist/server/block/index.d.mts +4 -0
- 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 +71 -0
- package/dist/server/fields/blocks.mjs +151 -0
- package/dist/server/fields/index.d.mts +15 -0
- package/dist/server/fields/index.mjs +15 -0
- package/dist/server/fields/rich-text.d.mts +68 -0
- package/dist/server/fields/rich-text.mjs +147 -0
- package/dist/server/i18n/index.mjs +43 -0
- package/dist/server/i18n/messages/cs.mjs +461 -0
- package/dist/server/i18n/messages/de.mjs +461 -0
- package/dist/server/i18n/messages/en.mjs +707 -0
- package/dist/server/i18n/messages/es.mjs +461 -0
- package/dist/server/i18n/messages/fr.mjs +461 -0
- package/dist/server/i18n/messages/index.mjs +23 -0
- package/dist/server/i18n/messages/pl.mjs +461 -0
- package/dist/server/i18n/messages/pt.mjs +464 -0
- package/dist/server/i18n/messages/sk.mjs +689 -0
- 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/modules/admin/auth-helpers.d.mts +142 -0
- package/dist/server/modules/admin/auth-helpers.mjs +107 -0
- package/dist/server/modules/admin/block/block-builder.d.mts +383 -0
- package/dist/server/modules/admin/block/block-builder.mjs +315 -0
- package/dist/server/modules/admin/block/index.d.mts +3 -0
- package/dist/server/modules/admin/block/introspection.d.mts +89 -0
- package/dist/server/modules/admin/block/introspection.mjs +100 -0
- package/dist/server/modules/admin/block/prefetch.d.mts +78 -0
- package/dist/server/modules/admin/block/prefetch.mjs +241 -0
- 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 +1093 -0
- package/dist/server/modules/admin/index.mjs +26 -0
- 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/routes/execute-action.d.mts +92 -0
- package/dist/server/modules/admin/routes/execute-action.mjs +433 -0
- 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/routes/preview.d.mts +80 -0
- package/dist/server/modules/admin/routes/preview.mjs +230 -0
- package/dist/server/modules/admin/routes/reactive.d.mts +74 -0
- package/dist/server/modules/admin/routes/reactive.mjs +350 -0
- 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/routes/setup.d.mts +63 -0
- 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.mjs +37 -0
- package/dist/server/modules/admin-preferences/collections/locks.collection.mjs +55 -0
- 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 +33 -250
- package/dist/server.mjs +22 -832
- package/dist/shared/preview-utils.d.mts +53 -0
- package/dist/{preview-utils-BKQ9-TMa.mjs → shared/preview-utils.mjs} +2 -3
- package/dist/{saved-views.types-BMsz5mCy.d.mts → shared/types/saved-views.types.d.mts} +7 -2
- package/dist/shared.d.mts +3 -57
- package/dist/shared.mjs +1 -1
- package/package.json +56 -51
- 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/auth-layout-M8K8_q5R.mjs +0 -181
- package/dist/auth-layout-M8K8_q5R.mjs.map +0 -1
- package/dist/bulk-upload-dialog-D7w7W1Hl.mjs +0 -273
- package/dist/bulk-upload-dialog-D7w7W1Hl.mjs.map +0 -1
- package/dist/card-BKHjBQfw.mjs +0 -58
- package/dist/card-BKHjBQfw.mjs.map +0 -1
- package/dist/client-D1DqawtP.d.mts +0 -13403
- package/dist/client-D1DqawtP.d.mts.map +0 -1
- package/dist/client-njX1rZmi.mjs +0 -22612
- package/dist/client-njX1rZmi.mjs.map +0 -1
- package/dist/content-locales-provider-BXvuIgfg.mjs +0 -1650
- package/dist/content-locales-provider-BXvuIgfg.mjs.map +0 -1
- package/dist/dashboard-page-B4PGEdc2.mjs +0 -2500
- package/dist/dashboard-page-B4PGEdc2.mjs.map +0 -1
- package/dist/dashboard-page-mCY0pgZv.mjs +0 -3
- package/dist/dropzone-Do3awXKd.mjs +0 -634
- package/dist/dropzone-Do3awXKd.mjs.map +0 -1
- package/dist/forgot-password-page-Bcp-An4Y.mjs +0 -221
- package/dist/forgot-password-page-Bcp-An4Y.mjs.map +0 -1
- package/dist/forgot-password-page-CEwsdLwn.mjs +0 -3
- package/dist/index-B4H3amCD.d.mts +0 -2753
- package/dist/index-B4H3amCD.d.mts.map +0 -1
- package/dist/login-page-BUnpCbCa.mjs +0 -3
- package/dist/login-page-CP4gA-dl.mjs +0 -298
- package/dist/login-page-CP4gA-dl.mjs.map +0 -1
- package/dist/preview-utils-BKQ9-TMa.mjs.map +0 -1
- package/dist/reset-password-page-BqfDmLxA.mjs +0 -281
- package/dist/reset-password-page-BqfDmLxA.mjs.map +0 -1
- package/dist/reset-password-page-CufHz3h3.mjs +0 -3
- package/dist/runtime-6VZM878K.mjs +0 -69
- package/dist/runtime-6VZM878K.mjs.map +0 -1
- package/dist/saved-views.types-BMsz5mCy.d.mts.map +0 -1
- package/dist/server.d.mts.map +0 -1
- package/dist/server.mjs.map +0 -1
- package/dist/setup-page-BNNzt_Z6.mjs +0 -3
- package/dist/setup-page-YAP_fzqh.mjs +0 -264
- package/dist/setup-page-YAP_fzqh.mjs.map +0 -1
- package/dist/shared.d.mts.map +0 -1
- package/dist/use-auth-BoLmWtmU.mjs.map +0 -1
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: questpie-admin
|
|
3
|
+
description: QUESTPIE admin panel setup branding theming sidebar dashboard media localization live-preview auth dark-mode CSS variables configuration
|
|
4
|
+
type: skill
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# QUESTPIE Admin Panel
|
|
8
|
+
|
|
9
|
+
The QUESTPIE admin panel is a **projection of your server schema** — not the framework itself. It reads collections, globals, and config via introspection and generates a full admin interface. Your backend works without it.
|
|
10
|
+
|
|
11
|
+
## Sub-Skills
|
|
12
|
+
|
|
13
|
+
| Skill | Covers |
|
|
14
|
+
| ------------------------------------------------ | -------------------------------------------------------------------------------------- |
|
|
15
|
+
| [questpie-admin/views](./views/SKILL.md) | List views, form views, dashboard, sidebar, filters, bulk actions, visibility, history |
|
|
16
|
+
| [questpie-admin/blocks](./blocks/SKILL.md) | Block definitions, fields, prefetch, renderers, block picker |
|
|
17
|
+
| [questpie-admin/custom-ui](./custom-ui/SKILL.md) | Custom fields, custom views, registries, reactive fields, widgets |
|
|
18
|
+
|
|
19
|
+
## Tech Stack
|
|
20
|
+
|
|
21
|
+
- **React** + **Tailwind CSS v4** + **shadcn** components
|
|
22
|
+
- **@base-ui/react** primitives (NOT @radix-ui)
|
|
23
|
+
- **@iconify/react** with Phosphor icon set (`ph:icon-name`)
|
|
24
|
+
- **sonner** for toasts — `toast.error()`, `toast.success()`
|
|
25
|
+
- Brutalist flat design: `--radius: 0px`, no shadows
|
|
26
|
+
|
|
27
|
+
## Setup
|
|
28
|
+
|
|
29
|
+
### 1. Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bun add @questpie/admin
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2. Server Plugin
|
|
36
|
+
|
|
37
|
+
```ts title="questpie.config.ts"
|
|
38
|
+
import { adminPlugin } from "@questpie/admin/plugin";
|
|
39
|
+
import { runtimeConfig } from "questpie";
|
|
40
|
+
|
|
41
|
+
export default runtimeConfig({
|
|
42
|
+
plugins: [adminPlugin()],
|
|
43
|
+
app: { url: process.env.APP_URL || "http://localhost:3000" },
|
|
44
|
+
db: { url: process.env.DATABASE_URL },
|
|
45
|
+
secret: process.env.APP_SECRET,
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The plugin tells codegen to discover admin-specific file conventions: `sidebar.ts`, `dashboard.ts`, `branding.ts`, `blocks/`, `admin-locale.ts`.
|
|
50
|
+
|
|
51
|
+
### 3. Modules
|
|
52
|
+
|
|
53
|
+
```ts title="modules.ts"
|
|
54
|
+
import { adminModule, auditModule } from "@questpie/admin/server";
|
|
55
|
+
|
|
56
|
+
export default [adminModule, auditModule] as const;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Module | Provides |
|
|
60
|
+
| ------------- | ------------------------------------- |
|
|
61
|
+
| `adminModule` | User collection, auth pages, admin UI |
|
|
62
|
+
| `auditModule` | Audit log collection, timeline widget |
|
|
63
|
+
|
|
64
|
+
### 4. Convention Files
|
|
65
|
+
|
|
66
|
+
```ts title="sidebar.ts"
|
|
67
|
+
import { sidebar } from "#questpie";
|
|
68
|
+
|
|
69
|
+
export default sidebar({
|
|
70
|
+
sections: [
|
|
71
|
+
{ id: "overview", title: { en: "Overview" } },
|
|
72
|
+
{ id: "content", title: { en: "Content" } },
|
|
73
|
+
],
|
|
74
|
+
items: [
|
|
75
|
+
{
|
|
76
|
+
sectionId: "overview",
|
|
77
|
+
type: "link",
|
|
78
|
+
label: { en: "Dashboard" },
|
|
79
|
+
href: "/admin",
|
|
80
|
+
icon: { type: "icon", props: { name: "ph:house" } },
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
sectionId: "content",
|
|
84
|
+
type: "collection",
|
|
85
|
+
collection: "posts",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```ts title="branding.ts"
|
|
92
|
+
import { branding } from "#questpie";
|
|
93
|
+
|
|
94
|
+
export default branding({
|
|
95
|
+
name: { en: "My App Admin" },
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 5. Codegen
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
bunx questpie generate
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 6. Mount the Admin
|
|
106
|
+
|
|
107
|
+
```ts title="routes/admin/$.tsx"
|
|
108
|
+
import { AdminRouter } from "@questpie/admin/client";
|
|
109
|
+
import { admin } from "@/questpie/admin/admin";
|
|
110
|
+
|
|
111
|
+
export default function AdminPage() {
|
|
112
|
+
return <AdminRouter admin={admin} />;
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The admin client config is auto-generated by codegen at `admin/.generated/client.ts`. No manual builder setup needed.
|
|
117
|
+
|
|
118
|
+
## Branding
|
|
119
|
+
|
|
120
|
+
```ts title="branding.ts"
|
|
121
|
+
import { branding } from "#questpie";
|
|
122
|
+
|
|
123
|
+
export default branding({
|
|
124
|
+
name: { en: "Barbershop Control", sk: "Riadenie barbershopu" },
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
| Option | Type | Description |
|
|
129
|
+
| ------ | ---------------- | -------------------------------- |
|
|
130
|
+
| `name` | `string \| i18n` | App name shown in sidebar header |
|
|
131
|
+
| `logo` | `string` | Logo URL or path |
|
|
132
|
+
|
|
133
|
+
## Theming (CSS Variables)
|
|
134
|
+
|
|
135
|
+
The admin uses CSS variables for all theming. Override them in your own CSS file.
|
|
136
|
+
|
|
137
|
+
### Light Theme (`:root`)
|
|
138
|
+
|
|
139
|
+
| Variable | Default | Purpose |
|
|
140
|
+
| ---------------------- | --------- | -------------------------------- |
|
|
141
|
+
| `--background` | `#FFFFFF` | Page background |
|
|
142
|
+
| `--foreground` | `#0A0A0A` | Primary text |
|
|
143
|
+
| `--card` | `#F8F8F8` | Cards, panels, sidebar |
|
|
144
|
+
| `--popover` | `#FFFFFF` | Dropdowns, tooltips, dialogs |
|
|
145
|
+
| `--muted` | `#F0F0F0` | Hover states, table headers |
|
|
146
|
+
| `--muted-foreground` | `#666666` | Secondary text, placeholders |
|
|
147
|
+
| `--primary` | `#B700FF` | Brand accent (CTAs, focus rings) |
|
|
148
|
+
| `--primary-foreground` | `#FFFFFF` | Text on primary backgrounds |
|
|
149
|
+
| `--destructive` | `#FF3D57` | Errors, delete actions |
|
|
150
|
+
| `--success` | `#00E676` | Positive states |
|
|
151
|
+
| `--warning` | `#FFB300` | Caution states |
|
|
152
|
+
| `--info` | `#40C4FF` | Informational emphasis |
|
|
153
|
+
| `--border` | `#E0E0E0` | All structural borders |
|
|
154
|
+
| `--ring` | `#B700FF` | Focus ring color |
|
|
155
|
+
| `--radius` | `0px` | Border radius (0 = brutalist) |
|
|
156
|
+
|
|
157
|
+
### Dark Theme (`.dark` class)
|
|
158
|
+
|
|
159
|
+
Dark mode uses the `.dark` class on the root element. Key overrides:
|
|
160
|
+
|
|
161
|
+
| Variable | Dark Value |
|
|
162
|
+
| -------------- | ---------- |
|
|
163
|
+
| `--background` | `#0A0A0A` |
|
|
164
|
+
| `--foreground` | `#FFFFFF` |
|
|
165
|
+
| `--card` | `#111111` |
|
|
166
|
+
| `--border` | `#333333` |
|
|
167
|
+
| `--muted` | `#1A1A1A` |
|
|
168
|
+
|
|
169
|
+
### Typography
|
|
170
|
+
|
|
171
|
+
| Variable | Value |
|
|
172
|
+
| ------------- | ------------------------------------------------------------------- |
|
|
173
|
+
| `--font-sans` | `"Geist Variable"` — body text, descriptions |
|
|
174
|
+
| `--font-mono` | `"JetBrains Mono Variable"` — UI chrome: nav, buttons, tabs, badges |
|
|
175
|
+
|
|
176
|
+
### Sidebar Variables
|
|
177
|
+
|
|
178
|
+
Separate tokens for independent sidebar theming: `--sidebar`, `--sidebar-foreground`, `--sidebar-primary`, `--sidebar-accent`, `--sidebar-border`, `--sidebar-ring`.
|
|
179
|
+
|
|
180
|
+
### Custom Theme
|
|
181
|
+
|
|
182
|
+
1. Copy the admin CSS file
|
|
183
|
+
2. Change variable values
|
|
184
|
+
3. Import your copy instead
|
|
185
|
+
4. Zero component changes needed
|
|
186
|
+
|
|
187
|
+
## Content Localization
|
|
188
|
+
|
|
189
|
+
When collections have `.localized()` fields, the admin shows a locale switcher:
|
|
190
|
+
|
|
191
|
+
```ts title="questpie.config.ts"
|
|
192
|
+
export default runtimeConfig({
|
|
193
|
+
localization: {
|
|
194
|
+
defaultLocale: "en",
|
|
195
|
+
locales: [
|
|
196
|
+
{ code: "en", label: { en: "English" }, flagCountryCode: "gb" },
|
|
197
|
+
{ code: "sk", label: { en: "Slovak" } },
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The admin tracks content locale separately from UI locale. Only localized field values change when switching.
|
|
204
|
+
|
|
205
|
+
## Media & Uploads
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
avatar: f.upload({
|
|
209
|
+
to: "assets",
|
|
210
|
+
mimeTypes: ["image/*"],
|
|
211
|
+
maxSize: 5_000_000,
|
|
212
|
+
}),
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
The admin renders drag-and-drop upload, image preview, file info, and remove button.
|
|
216
|
+
|
|
217
|
+
## Live Preview (V2)
|
|
218
|
+
|
|
219
|
+
Live Preview V2 uses a direct `postMessage` patch bus for instant same-tab feedback. Save/autosave is persistence only — NOT the live transport. Realtime (SSE/WebSocket) is reserved for detached or shared preview sessions.
|
|
220
|
+
|
|
221
|
+
For full architecture details, see: `/docs/workspace/live-preview/architecture`
|
|
222
|
+
|
|
223
|
+
### Server Config
|
|
224
|
+
|
|
225
|
+
Add `.preview()` to a collection to enable split-screen editing:
|
|
226
|
+
|
|
227
|
+
```ts title="collections/pages.ts"
|
|
228
|
+
export const pages = collection("pages")
|
|
229
|
+
.fields(({ f }) => ({
|
|
230
|
+
title: f.text({ required: true, localized: true }),
|
|
231
|
+
slug: f.text({ required: true }),
|
|
232
|
+
content: f.blocks({ localized: true }),
|
|
233
|
+
}))
|
|
234
|
+
.preview({
|
|
235
|
+
url: ({ record }) => {
|
|
236
|
+
const slug = record.slug as string;
|
|
237
|
+
return slug === "home" ? "/?preview=true" : `/${slug}?preview=true`;
|
|
238
|
+
},
|
|
239
|
+
watch: ["title", "slug", "content"],
|
|
240
|
+
strategy: "hybrid", // "instant" | "server" | "hybrid"
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
| Strategy | Behavior |
|
|
245
|
+
| ----------- | ------------------------------------------------------------------- |
|
|
246
|
+
| `"instant"` | Patches applied locally only — fastest, no server round-trip |
|
|
247
|
+
| `"server"` | Every change round-trips through server before preview updates |
|
|
248
|
+
| `"hybrid"` | Local patches for instant response + server reconcile derived data |
|
|
249
|
+
|
|
250
|
+
### Frontend Integration
|
|
251
|
+
|
|
252
|
+
Use `useQuestpiePreview` (replaces the old `useCollectionPreview`) with `<PreviewRoot>`, `<PreviewField>`, and `<PreviewBlock>` components:
|
|
253
|
+
|
|
254
|
+
```tsx
|
|
255
|
+
import { useQuestpiePreview, PreviewRoot, PreviewField } from "@questpie/admin/client";
|
|
256
|
+
|
|
257
|
+
function PagePreview({ initialData }) {
|
|
258
|
+
const router = useRouter();
|
|
259
|
+
const { data } = useQuestpiePreview({
|
|
260
|
+
initialData,
|
|
261
|
+
reconcile: () => router.invalidate(),
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
return (
|
|
265
|
+
<PreviewRoot>
|
|
266
|
+
<h1><PreviewField path="title">{data.title}</PreviewField></h1>
|
|
267
|
+
</PreviewRoot>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Key Principles
|
|
273
|
+
|
|
274
|
+
- Same-tab preview = direct `postMessage` patch bus (NOT save-driven reload)
|
|
275
|
+
- Save/autosave = persistence only
|
|
276
|
+
- Realtime = extension for detached/shared preview only
|
|
277
|
+
- Each message carries `sessionId`, `seq`, `timestamp`, `protocolVersion`
|
|
278
|
+
- Preview wrappers must prevent accidental navigation in the iframe
|
|
279
|
+
|
|
280
|
+
## History & Versions
|
|
281
|
+
|
|
282
|
+
Enable `auditModule` for activity timeline. Enable `.versioning()` on collections for snapshot restore:
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
export const pages = collection("pages")
|
|
286
|
+
.versioning({ drafts: true, maxVersions: 20 })
|
|
287
|
+
.fields(({ f }) => ({ ... }));
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Scope (Multi-Tenancy)
|
|
291
|
+
|
|
292
|
+
The admin provides scope primitives for multi-tenant applications. Import from `@questpie/admin/client`.
|
|
293
|
+
|
|
294
|
+
### ScopeProvider
|
|
295
|
+
|
|
296
|
+
Wraps the admin to enable scope selection. Manages scope ID in React state and persists to localStorage.
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
import { ScopeProvider } from "@questpie/admin/client";
|
|
300
|
+
|
|
301
|
+
<ScopeProvider
|
|
302
|
+
headerName="x-selected-workspace" // HTTP header for scope ID
|
|
303
|
+
storageKey="admin-workspace" // localStorage key
|
|
304
|
+
defaultScope={null} // default value
|
|
305
|
+
>
|
|
306
|
+
<AdminLayout>...</AdminLayout>
|
|
307
|
+
</ScopeProvider>;
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### ScopePicker
|
|
311
|
+
|
|
312
|
+
Dropdown for selecting the current scope. Place in sidebar via `slots.afterBrand`:
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
import { ScopePicker } from "@questpie/admin/client";
|
|
316
|
+
|
|
317
|
+
<AdminLayout
|
|
318
|
+
admin={admin}
|
|
319
|
+
basePath="/admin"
|
|
320
|
+
slots={{
|
|
321
|
+
afterBrand: (
|
|
322
|
+
<div className="px-3 py-2 border-b">
|
|
323
|
+
<ScopePicker
|
|
324
|
+
collection="workspaces"
|
|
325
|
+
labelField="name"
|
|
326
|
+
allowClear
|
|
327
|
+
compact
|
|
328
|
+
/>
|
|
329
|
+
</div>
|
|
330
|
+
),
|
|
331
|
+
}}
|
|
332
|
+
/>;
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Three data sources: `collection` (queries a collection), `options` (static array), `loadOptions` (async function).
|
|
336
|
+
|
|
337
|
+
### useScopedFetch / createScopedFetch
|
|
338
|
+
|
|
339
|
+
Inject scope header into all API calls:
|
|
340
|
+
|
|
341
|
+
```tsx
|
|
342
|
+
import { useScopedFetch, createScopedFetch } from "@questpie/admin/client";
|
|
343
|
+
|
|
344
|
+
// React hook
|
|
345
|
+
const scopedFetch = useScopedFetch();
|
|
346
|
+
const client = useMemo(
|
|
347
|
+
() => createClient({ baseURL: "/api", fetch: scopedFetch }),
|
|
348
|
+
[scopedFetch],
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
// Non-React
|
|
352
|
+
const scopedFetch = createScopedFetch("x-selected-workspace", () =>
|
|
353
|
+
getScopeId(),
|
|
354
|
+
);
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### useScope / useScopeSafe
|
|
358
|
+
|
|
359
|
+
Access current scope state in any component:
|
|
360
|
+
|
|
361
|
+
```tsx
|
|
362
|
+
import { useScope, useScopeSafe } from "@questpie/admin/client";
|
|
363
|
+
|
|
364
|
+
const { scopeId, setScope, clearScope, headerName } = useScope(); // throws outside ScopeProvider
|
|
365
|
+
const scope = useScopeSafe(); // returns null outside ScopeProvider
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
For the full server-side setup (context resolver, type augmentation, access rules), see the `questpie-core/multi-tenancy` skill.
|
|
369
|
+
|
|
370
|
+
## Common Mistakes
|
|
371
|
+
|
|
372
|
+
1. **CRITICAL: Using `asChild` prop** — QUESTPIE admin uses `@base-ui/react`, which uses the `render` prop. `asChild` is a Radix pattern and does NOT work here.
|
|
373
|
+
|
|
374
|
+
```tsx
|
|
375
|
+
// WRONG
|
|
376
|
+
<DialogTrigger asChild><Button>Open</Button></DialogTrigger>
|
|
377
|
+
// CORRECT
|
|
378
|
+
<DialogTrigger render={<Button>Open</Button>} />
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
2. **CRITICAL: Importing from `@radix-ui/*`** — use `@base-ui/react` instead.
|
|
382
|
+
|
|
383
|
+
3. **HIGH: Using `@phosphor-icons/react`** — use `@iconify/react` with `ph:` prefix.
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
// WRONG
|
|
387
|
+
import { CaretDown } from "@phosphor-icons/react";
|
|
388
|
+
// CORRECT
|
|
389
|
+
import { Icon } from "@iconify/react";
|
|
390
|
+
<Icon icon="ph:caret-down" width={16} height={16} />;
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
4. **HIGH: Using lucide-react icons** — use `@iconify/react` with Phosphor icon set.
|
|
394
|
+
|
|
395
|
+
5. **MEDIUM: Custom `<button>` or `<div>` instead of shadcn components** — use `<Button>`, `<Card>`, etc.
|
|
396
|
+
|
|
397
|
+
6. **MEDIUM: `console.error` for user errors** — use `toast.error()` from `sonner`.
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: questpie-admin/blocks
|
|
3
|
+
description: QUESTPIE blocks content-blocks page-builder block-definition fields prefetch renderers block-picker categories nested-blocks upload relation
|
|
4
|
+
type: skill
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# QUESTPIE Blocks
|
|
8
|
+
|
|
9
|
+
This skill builds on questpie-admin.
|
|
10
|
+
|
|
11
|
+
Blocks are reusable content components for page builders. Define them server-side with fields and admin metadata, then render them client-side with React components.
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
Server: block("hero") Client: HeroRenderer
|
|
15
|
+
.fields({ title, image }) -> Receives { values, data }
|
|
16
|
+
.admin({ label, icon }) Returns JSX
|
|
17
|
+
.prefetch({ with: {...} })
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Defining Blocks
|
|
21
|
+
|
|
22
|
+
Blocks are defined in `blocks/` using the `block()` factory:
|
|
23
|
+
|
|
24
|
+
```ts title="blocks/hero.ts"
|
|
25
|
+
import { block } from "#questpie";
|
|
26
|
+
|
|
27
|
+
export const heroBlock = block("hero")
|
|
28
|
+
.admin(({ c }) => ({
|
|
29
|
+
label: { en: "Hero Section", sk: "Hero sekcia" },
|
|
30
|
+
icon: c.icon("ph:image"),
|
|
31
|
+
category: "sections",
|
|
32
|
+
}))
|
|
33
|
+
.fields(({ f }) => ({
|
|
34
|
+
title: f.text({ localized: true, required: true }),
|
|
35
|
+
subtitle: f.textarea({ localized: true }),
|
|
36
|
+
backgroundImage: f.upload({ to: "assets" }),
|
|
37
|
+
overlayOpacity: f.number({ defaultValue: 60 }),
|
|
38
|
+
alignment: f.select({
|
|
39
|
+
options: ["left", "center", "right"],
|
|
40
|
+
defaultValue: "center",
|
|
41
|
+
}),
|
|
42
|
+
ctaText: f.text({ localized: true }),
|
|
43
|
+
ctaLink: f.text(),
|
|
44
|
+
}))
|
|
45
|
+
.prefetch({ with: { backgroundImage: true } });
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Admin Metadata
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
.admin(({ c }) => ({
|
|
52
|
+
label: { en: "Hero Section" }, // Display name in block picker
|
|
53
|
+
icon: c.icon("ph:image"), // Icon in block picker (Phosphor set)
|
|
54
|
+
category: "sections", // Group in block picker
|
|
55
|
+
}))
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Multiple Blocks Per File
|
|
59
|
+
|
|
60
|
+
Export multiple named blocks from one file:
|
|
61
|
+
|
|
62
|
+
```ts title="blocks/layout.ts"
|
|
63
|
+
import { block } from "#questpie";
|
|
64
|
+
|
|
65
|
+
export const twoColumnBlock = block("twoColumn")
|
|
66
|
+
.admin(({ c }) => ({
|
|
67
|
+
label: { en: "Two Columns" },
|
|
68
|
+
icon: c.icon("ph:columns"),
|
|
69
|
+
category: "layout",
|
|
70
|
+
}))
|
|
71
|
+
.fields(({ f }) => ({
|
|
72
|
+
left: f.blocks(),
|
|
73
|
+
right: f.blocks(),
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
export const spacerBlock = block("spacer")
|
|
77
|
+
.admin(({ c }) => ({
|
|
78
|
+
label: { en: "Spacer" },
|
|
79
|
+
icon: c.icon("ph:arrows-out-line-vertical"),
|
|
80
|
+
category: "layout",
|
|
81
|
+
}))
|
|
82
|
+
.fields(({ f }) => ({
|
|
83
|
+
height: f.select({
|
|
84
|
+
options: ["sm", "md", "lg", "xl"],
|
|
85
|
+
defaultValue: "md",
|
|
86
|
+
}),
|
|
87
|
+
}));
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Using Blocks in Collections
|
|
91
|
+
|
|
92
|
+
Add a `blocks` field to any collection:
|
|
93
|
+
|
|
94
|
+
```ts title="collections/pages.ts"
|
|
95
|
+
import { collection } from "#questpie";
|
|
96
|
+
|
|
97
|
+
export const pages = collection("pages").fields(({ f }) => ({
|
|
98
|
+
title: f.text({ required: true, localized: true }),
|
|
99
|
+
slug: f.text({ required: true }),
|
|
100
|
+
content: f.blocks({ localized: true }),
|
|
101
|
+
}));
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The admin renders a visual block editor for this field.
|
|
105
|
+
|
|
106
|
+
## Prefetch
|
|
107
|
+
|
|
108
|
+
Blocks often reference related data (images, linked records). Use `.prefetch()` to load them alongside block values.
|
|
109
|
+
|
|
110
|
+
### Declarative Prefetch
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
.prefetch({
|
|
114
|
+
with: {
|
|
115
|
+
backgroundImage: true, // Load the full image record
|
|
116
|
+
},
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Nested Prefetch
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
.prefetch({
|
|
124
|
+
with: {
|
|
125
|
+
featuredBarber: {
|
|
126
|
+
with: {
|
|
127
|
+
avatar: true,
|
|
128
|
+
services: true,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
})
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Functional Prefetch
|
|
136
|
+
|
|
137
|
+
For complex queries, use a function. The `ctx` parameter provides fully typed `collections` and `globals` via `AppContext` augmentation — no imports needed:
|
|
138
|
+
|
|
139
|
+
```ts title="blocks/featured.ts"
|
|
140
|
+
import { block } from "#questpie";
|
|
141
|
+
|
|
142
|
+
export const featuredBlock = block("featured")
|
|
143
|
+
.fields(({ f }) => ({
|
|
144
|
+
heading: f.text({ required: true }),
|
|
145
|
+
}))
|
|
146
|
+
.prefetch(async ({ values, ctx }) => {
|
|
147
|
+
return {
|
|
148
|
+
posts: (await ctx.collections.posts.find({ limit: 5 })).docs,
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Using Prefetched Data in Renderers
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
function HeroRenderer({ values, data }: BlockProps<"hero">) {
|
|
157
|
+
// values.backgroundImage = "asset-id-123" (just the ID)
|
|
158
|
+
// data.backgroundImage = { url: "/api/assets/...", filename: "hero.jpg", ... }
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<section>
|
|
162
|
+
{data?.backgroundImage?.url && (
|
|
163
|
+
<img src={data.backgroundImage.url} alt="" />
|
|
164
|
+
)}
|
|
165
|
+
<h1>{values.title}</h1>
|
|
166
|
+
</section>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Block Renderers
|
|
172
|
+
|
|
173
|
+
React components that receive block data and return JSX.
|
|
174
|
+
|
|
175
|
+
### Defining a Renderer
|
|
176
|
+
|
|
177
|
+
```tsx title="admin/blocks/hero.tsx"
|
|
178
|
+
import type { BlockProps } from "@questpie/admin/client";
|
|
179
|
+
|
|
180
|
+
export function HeroRenderer({ values, data }: BlockProps<"hero">) {
|
|
181
|
+
return (
|
|
182
|
+
<section
|
|
183
|
+
className="relative flex items-center justify-center"
|
|
184
|
+
style={{ minHeight: "60vh" }}
|
|
185
|
+
>
|
|
186
|
+
{data?.backgroundImage?.url && (
|
|
187
|
+
<img
|
|
188
|
+
src={data.backgroundImage.url}
|
|
189
|
+
alt=""
|
|
190
|
+
className="absolute inset-0 w-full h-full object-cover"
|
|
191
|
+
/>
|
|
192
|
+
)}
|
|
193
|
+
<div className="relative text-center">
|
|
194
|
+
<h1 className="text-5xl font-bold">{values.title}</h1>
|
|
195
|
+
{values.subtitle && <p className="text-xl mt-4">{values.subtitle}</p>}
|
|
196
|
+
{values.ctaText && (
|
|
197
|
+
<a href={values.ctaLink} className="mt-6 inline-block btn">
|
|
198
|
+
{values.ctaText}
|
|
199
|
+
</a>
|
|
200
|
+
)}
|
|
201
|
+
</div>
|
|
202
|
+
</section>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### BlockProps
|
|
208
|
+
|
|
209
|
+
| Property | Type | Description |
|
|
210
|
+
| ---------- | ----------- | -------------------------------------------------- |
|
|
211
|
+
| `values` | `object` | Block field values (title, subtitle, etc.) |
|
|
212
|
+
| `data` | `object` | Prefetched relation data (images, related records) |
|
|
213
|
+
| `children` | `ReactNode` | Nested block content |
|
|
214
|
+
|
|
215
|
+
### Registering Renderers
|
|
216
|
+
|
|
217
|
+
```tsx title="admin/blocks/index.tsx"
|
|
218
|
+
import { HeroRenderer } from "./hero";
|
|
219
|
+
import { GalleryRenderer } from "./gallery";
|
|
220
|
+
import { CTARenderer } from "./cta";
|
|
221
|
+
|
|
222
|
+
export const renderers = {
|
|
223
|
+
hero: HeroRenderer,
|
|
224
|
+
gallery: GalleryRenderer,
|
|
225
|
+
cta: CTARenderer,
|
|
226
|
+
};
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Frontend Rendering
|
|
230
|
+
|
|
231
|
+
Use block renderers on the public frontend:
|
|
232
|
+
|
|
233
|
+
```tsx title="components/page-renderer.tsx"
|
|
234
|
+
import { renderers } from "@/questpie/admin/blocks";
|
|
235
|
+
|
|
236
|
+
function PageRenderer({ page }) {
|
|
237
|
+
return (
|
|
238
|
+
<div>
|
|
239
|
+
{page.content?.map((block, i) => {
|
|
240
|
+
const Renderer = renderers[block.type];
|
|
241
|
+
if (!Renderer) return null;
|
|
242
|
+
return <Renderer key={i} values={block.values} data={block.data} />;
|
|
243
|
+
})}
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Common Mistakes
|
|
250
|
+
|
|
251
|
+
1. **HIGH: Not using `ctx.collections.*` in functional prefetch** — use the context-injected collections directly. Do NOT import `app` from `#questpie` inside block files (causes circular dependencies).
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
// WRONG — importing app creates circular dependency
|
|
255
|
+
import { app } from "#questpie";
|
|
256
|
+
.prefetch(async ({ values, ctx }) => {
|
|
257
|
+
const posts = await app.collections.posts.find({});
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
// CORRECT — use ctx.collections directly
|
|
261
|
+
.prefetch(async ({ values, ctx }) => {
|
|
262
|
+
const posts = await ctx.collections.posts.find({});
|
|
263
|
+
})
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
2. **HIGH: Importing from `.generated/` inside block files** — block files are imported BY `.generated/index.ts`, so importing from it back creates circular dependencies. Use the `ctx` parameter instead.
|
|
267
|
+
|
|
268
|
+
3. **MEDIUM: Block renderer not exported as default or named export** — codegen discovers named exports from block renderer files. Ensure the component is exported.
|
|
269
|
+
|
|
270
|
+
4. **MEDIUM: Using `{ with: { field: true } }` prefetch for complex queries** — declarative prefetch only loads related records by ID. For filtered/sorted/limited queries, use functional prefetch instead.
|
|
271
|
+
|
|
272
|
+
5. **MEDIUM: Forgetting `.prefetch()` for upload fields** — without prefetch, `values.backgroundImage` is just an ID string. Add `{ with: { backgroundImage: true } }` to get the full asset record with `url`.
|
|
273
|
+
|
|
274
|
+
6. **LOW: Missing `category` in `.admin()`** — blocks without a category won't be grouped in the block picker, making it harder to find them.
|
|
275
|
+
|
|
276
|
+
## Blocks in Live Preview
|
|
277
|
+
|
|
278
|
+
When a collection has `.preview()` configured, blocks participate in the live preview patch bus.
|
|
279
|
+
|
|
280
|
+
### PreviewBlock Wrapper
|
|
281
|
+
|
|
282
|
+
Use `<PreviewBlock>` in your frontend to mark block regions for live preview focus and patch targeting:
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
import { PreviewBlock } from "@questpie/admin/client";
|
|
286
|
+
|
|
287
|
+
function PageRenderer({ blocks, previewData }) {
|
|
288
|
+
return blocks.map((block) => {
|
|
289
|
+
const Renderer = renderers[block.type];
|
|
290
|
+
return (
|
|
291
|
+
<PreviewBlock key={block.id} id={block.id}>
|
|
292
|
+
<Renderer values={block.values} data={block.data} />
|
|
293
|
+
</PreviewBlock>
|
|
294
|
+
);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
When the editor focuses a block, `<PreviewBlock>` highlights it in the preview. Patches target individual blocks by ID for granular updates.
|
|
300
|
+
|
|
301
|
+
### Block Prefetch and Server Reconcile
|
|
302
|
+
|
|
303
|
+
In `"hybrid"` preview strategy, blocks with functional `.prefetch()` trigger a server reconcile when their field values change. For example, a "featured posts" block with a `limit` field will re-run its prefetch handler on the server to fetch updated data, while simple field changes (title, subtitle) apply instantly via the local patch bus.
|
|
304
|
+
|
|
305
|
+
Blocks with declarative prefetch (`{ with: { image: true } }`) resolve relations during reconcile — the preview shows the image URL immediately after the server round-trip completes, not just the asset ID.
|