@questpie/admin 0.0.1 → 1.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 +439 -424
- package/dist/auth-layout-M8K8_q5R.mjs +181 -0
- package/dist/auth-layout-M8K8_q5R.mjs.map +1 -0
- package/dist/bulk-upload-dialog-h7zXD78Y.mjs +274 -0
- package/dist/bulk-upload-dialog-h7zXD78Y.mjs.map +1 -0
- package/dist/{components/ui/card.mjs → card-BKHjBQfw.mjs} +8 -8
- package/dist/card-BKHjBQfw.mjs.map +1 -0
- package/dist/client/styles/index.css +434 -0
- package/dist/client-BCGpkAz6.mjs +22635 -0
- package/dist/client-BCGpkAz6.mjs.map +1 -0
- package/dist/client-CcWZbkBP.d.mts +13585 -0
- package/dist/client-CcWZbkBP.d.mts.map +1 -0
- package/dist/client.d.mts +3 -0
- package/dist/client.mjs +14 -0
- package/dist/content-locales-provider-BXvuIgfg.mjs +1650 -0
- package/dist/content-locales-provider-BXvuIgfg.mjs.map +1 -0
- package/dist/dashboard-page-B4PGEdc2.mjs +2500 -0
- package/dist/dashboard-page-B4PGEdc2.mjs.map +1 -0
- package/dist/dashboard-page-CVlyR40m.mjs +6 -0
- package/dist/dropzone-Do3awXKd.mjs +634 -0
- package/dist/dropzone-Do3awXKd.mjs.map +1 -0
- package/dist/{views/auth/forgot-password-form.mjs → forgot-password-page-Bcp-An4Y.mjs} +87 -14
- package/dist/forgot-password-page-Bcp-An4Y.mjs.map +1 -0
- package/dist/forgot-password-page-CIILVhfo.mjs +7 -0
- package/dist/index-B9Xwk4hi.d.mts +2753 -0
- package/dist/index-B9Xwk4hi.d.mts.map +1 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +14 -0
- package/dist/login-page-8K7fo0qK.mjs +7 -0
- package/dist/login-page-CP4gA-dl.mjs +298 -0
- package/dist/login-page-CP4gA-dl.mjs.map +1 -0
- package/dist/preview-utils-BKQ9-TMa.mjs +65 -0
- package/dist/preview-utils-BKQ9-TMa.mjs.map +1 -0
- package/dist/{views/auth/reset-password-form.mjs → reset-password-page-BqfDmLxA.mjs} +111 -14
- package/dist/reset-password-page-BqfDmLxA.mjs.map +1 -0
- package/dist/reset-password-page-DLATv0xQ.mjs +7 -0
- package/dist/runtime-6VZM878K.mjs +69 -0
- package/dist/runtime-6VZM878K.mjs.map +1 -0
- package/dist/saved-views.types-BMsz5mCy.d.mts +42 -0
- package/dist/saved-views.types-BMsz5mCy.d.mts.map +1 -0
- package/dist/server.d.mts +250 -0
- package/dist/server.d.mts.map +1 -0
- package/dist/server.mjs +832 -0
- package/dist/server.mjs.map +1 -0
- package/dist/setup-page-CMZ5P_OE.mjs +6 -0
- package/dist/setup-page-YAP_fzqh.mjs +264 -0
- package/dist/setup-page-YAP_fzqh.mjs.map +1 -0
- package/dist/shared.d.mts +57 -0
- package/dist/shared.d.mts.map +1 -0
- package/dist/shared.mjs +3 -0
- package/dist/{hooks/use-auth.mjs → use-auth-BoLmWtmU.mjs} +42 -30
- package/dist/use-auth-BoLmWtmU.mjs.map +1 -0
- package/package.json +48 -197
- package/.turbo/turbo-build.log +0 -108
- package/CHANGELOG.md +0 -10
- package/STATUS.md +0 -917
- package/VALIDATION.md +0 -602
- package/components.json +0 -24
- package/dist/__tests__/setup.mjs +0 -38
- package/dist/__tests__/test-utils.mjs +0 -45
- package/dist/__tests__/vitest.d.mjs +0 -3
- package/dist/components/admin-app.mjs +0 -69
- package/dist/components/fields/array-field.mjs +0 -190
- package/dist/components/fields/checkbox-field.mjs +0 -34
- package/dist/components/fields/custom-field.mjs +0 -32
- package/dist/components/fields/date-field.mjs +0 -41
- package/dist/components/fields/datetime-field.mjs +0 -42
- package/dist/components/fields/email-field.mjs +0 -37
- package/dist/components/fields/embedded-collection.mjs +0 -253
- package/dist/components/fields/field-types.mjs +0 -1
- package/dist/components/fields/field-utils.mjs +0 -10
- package/dist/components/fields/field-wrapper.mjs +0 -34
- package/dist/components/fields/index.mjs +0 -23
- package/dist/components/fields/json-field.mjs +0 -243
- package/dist/components/fields/locale-badge.mjs +0 -16
- package/dist/components/fields/number-field.mjs +0 -39
- package/dist/components/fields/password-field.mjs +0 -37
- package/dist/components/fields/relation-field.mjs +0 -104
- package/dist/components/fields/relation-picker.mjs +0 -229
- package/dist/components/fields/relation-select.mjs +0 -188
- package/dist/components/fields/rich-text-editor/index.mjs +0 -897
- package/dist/components/fields/select-field.mjs +0 -41
- package/dist/components/fields/switch-field.mjs +0 -34
- package/dist/components/fields/text-field.mjs +0 -38
- package/dist/components/fields/textarea-field.mjs +0 -38
- package/dist/components/index.mjs +0 -59
- package/dist/components/primitives/checkbox-input.mjs +0 -127
- package/dist/components/primitives/date-input.mjs +0 -303
- package/dist/components/primitives/index.mjs +0 -12
- package/dist/components/primitives/number-input.mjs +0 -104
- package/dist/components/primitives/select-input.mjs +0 -177
- package/dist/components/primitives/tag-input.mjs +0 -135
- package/dist/components/primitives/text-input.mjs +0 -39
- package/dist/components/primitives/textarea-input.mjs +0 -37
- package/dist/components/primitives/toggle-input.mjs +0 -31
- package/dist/components/primitives/types.mjs +0 -12
- package/dist/components/ui/accordion.mjs +0 -55
- package/dist/components/ui/avatar.mjs +0 -54
- package/dist/components/ui/badge.mjs +0 -34
- package/dist/components/ui/button.mjs +0 -48
- package/dist/components/ui/checkbox.mjs +0 -21
- package/dist/components/ui/combobox.mjs +0 -163
- package/dist/components/ui/dialog.mjs +0 -95
- package/dist/components/ui/dropdown-menu.mjs +0 -138
- package/dist/components/ui/field.mjs +0 -113
- package/dist/components/ui/input-group.mjs +0 -82
- package/dist/components/ui/input.mjs +0 -17
- package/dist/components/ui/label.mjs +0 -15
- package/dist/components/ui/popover.mjs +0 -56
- package/dist/components/ui/scroll-area.mjs +0 -38
- package/dist/components/ui/select.mjs +0 -100
- package/dist/components/ui/separator.mjs +0 -16
- package/dist/components/ui/sheet.mjs +0 -90
- package/dist/components/ui/sidebar.mjs +0 -387
- package/dist/components/ui/skeleton.mjs +0 -14
- package/dist/components/ui/spinner.mjs +0 -16
- package/dist/components/ui/switch.mjs +0 -22
- package/dist/components/ui/table.mjs +0 -68
- package/dist/components/ui/tabs.mjs +0 -48
- package/dist/components/ui/textarea.mjs +0 -15
- package/dist/components/ui/tooltip.mjs +0 -44
- package/dist/config/component-registry.mjs +0 -38
- package/dist/config/index.mjs +0 -129
- package/dist/hooks/admin-provider.mjs +0 -70
- package/dist/hooks/index.mjs +0 -7
- package/dist/hooks/store.mjs +0 -178
- package/dist/hooks/use-collection-db.mjs +0 -146
- package/dist/hooks/use-collection.mjs +0 -112
- package/dist/hooks/use-global.mjs +0 -46
- package/dist/hooks/use-mobile.mjs +0 -20
- package/dist/lib/utils.mjs +0 -10
- package/dist/styles/index.css +0 -336
- package/dist/styles/index.mjs +0 -1
- package/dist/utils/index.mjs +0 -9
- package/dist/views/auth/auth-layout.mjs +0 -52
- package/dist/views/auth/index.mjs +0 -6
- package/dist/views/auth/login-form.mjs +0 -156
- package/dist/views/collection/auto-form-fields.mjs +0 -525
- package/dist/views/collection/collection-form.mjs +0 -91
- package/dist/views/collection/collection-list.mjs +0 -76
- package/dist/views/collection/form-field.mjs +0 -42
- package/dist/views/collection/index.mjs +0 -6
- package/dist/views/common/index.mjs +0 -4
- package/dist/views/common/locale-switcher.mjs +0 -39
- package/dist/views/common/version-history.mjs +0 -272
- package/dist/views/index.mjs +0 -9
- package/dist/views/layout/admin-layout.mjs +0 -40
- package/dist/views/layout/admin-router.mjs +0 -95
- package/dist/views/layout/admin-sidebar.mjs +0 -63
- package/dist/views/layout/index.mjs +0 -5
- package/src/__tests__/setup.ts +0 -44
- package/src/__tests__/test-utils.tsx +0 -49
- package/src/__tests__/vitest.d.ts +0 -9
- package/src/components/admin-app.tsx +0 -221
- package/src/components/fields/array-field.tsx +0 -237
- package/src/components/fields/checkbox-field.tsx +0 -47
- package/src/components/fields/custom-field.tsx +0 -50
- package/src/components/fields/date-field.tsx +0 -65
- package/src/components/fields/datetime-field.tsx +0 -67
- package/src/components/fields/email-field.tsx +0 -51
- package/src/components/fields/embedded-collection.tsx +0 -315
- package/src/components/fields/field-types.ts +0 -162
- package/src/components/fields/field-utils.ts +0 -6
- package/src/components/fields/field-wrapper.tsx +0 -52
- package/src/components/fields/index.ts +0 -66
- package/src/components/fields/json-field.tsx +0 -440
- package/src/components/fields/locale-badge.tsx +0 -15
- package/src/components/fields/number-field.tsx +0 -57
- package/src/components/fields/password-field.tsx +0 -51
- package/src/components/fields/relation-field.tsx +0 -243
- package/src/components/fields/relation-picker.tsx +0 -402
- package/src/components/fields/relation-select.tsx +0 -327
- package/src/components/fields/rich-text-editor/index.tsx +0 -1337
- package/src/components/fields/select-field.tsx +0 -61
- package/src/components/fields/switch-field.tsx +0 -47
- package/src/components/fields/text-field.tsx +0 -55
- package/src/components/fields/textarea-field.tsx +0 -55
- package/src/components/index.ts +0 -40
- package/src/components/primitives/checkbox-input.tsx +0 -193
- package/src/components/primitives/date-input.tsx +0 -401
- package/src/components/primitives/index.ts +0 -24
- package/src/components/primitives/number-input.tsx +0 -132
- package/src/components/primitives/select-input.tsx +0 -296
- package/src/components/primitives/tag-input.tsx +0 -200
- package/src/components/primitives/text-input.tsx +0 -49
- package/src/components/primitives/textarea-input.tsx +0 -46
- package/src/components/primitives/toggle-input.tsx +0 -36
- package/src/components/primitives/types.ts +0 -235
- package/src/components/ui/accordion.tsx +0 -72
- package/src/components/ui/avatar.tsx +0 -106
- package/src/components/ui/badge.tsx +0 -48
- package/src/components/ui/button.tsx +0 -53
- package/src/components/ui/card.tsx +0 -94
- package/src/components/ui/checkbox.tsx +0 -27
- package/src/components/ui/combobox.tsx +0 -290
- package/src/components/ui/dialog.tsx +0 -151
- package/src/components/ui/dropdown-menu.tsx +0 -254
- package/src/components/ui/field.tsx +0 -227
- package/src/components/ui/input-group.tsx +0 -149
- package/src/components/ui/input.tsx +0 -20
- package/src/components/ui/label.tsx +0 -18
- package/src/components/ui/popover.tsx +0 -88
- package/src/components/ui/scroll-area.tsx +0 -53
- package/src/components/ui/select.tsx +0 -192
- package/src/components/ui/separator.tsx +0 -23
- package/src/components/ui/sheet.tsx +0 -127
- package/src/components/ui/sidebar.tsx +0 -723
- package/src/components/ui/skeleton.tsx +0 -13
- package/src/components/ui/spinner.tsx +0 -10
- package/src/components/ui/switch.tsx +0 -32
- package/src/components/ui/table.tsx +0 -99
- package/src/components/ui/tabs.tsx +0 -82
- package/src/components/ui/textarea.tsx +0 -18
- package/src/components/ui/tooltip.tsx +0 -70
- package/src/config/component-registry.ts +0 -190
- package/src/config/index.ts +0 -1099
- package/src/hooks/README.md +0 -269
- package/src/hooks/admin-provider.tsx +0 -110
- package/src/hooks/index.ts +0 -41
- package/src/hooks/store.ts +0 -248
- package/src/hooks/use-auth.ts +0 -168
- package/src/hooks/use-collection-db.ts +0 -209
- package/src/hooks/use-collection.ts +0 -156
- package/src/hooks/use-global.ts +0 -69
- package/src/hooks/use-mobile.ts +0 -21
- package/src/lib/utils.ts +0 -6
- package/src/styles/index.css +0 -340
- package/src/utils/index.ts +0 -6
- package/src/views/auth/auth-layout.tsx +0 -77
- package/src/views/auth/forgot-password-form.tsx +0 -192
- package/src/views/auth/index.ts +0 -21
- package/src/views/auth/login-form.tsx +0 -229
- package/src/views/auth/reset-password-form.tsx +0 -232
- package/src/views/collection/auto-form-fields.tsx +0 -982
- package/src/views/collection/collection-form.tsx +0 -186
- package/src/views/collection/collection-list.tsx +0 -223
- package/src/views/collection/form-field.tsx +0 -52
- package/src/views/collection/index.ts +0 -15
- package/src/views/common/index.ts +0 -8
- package/src/views/common/locale-switcher.tsx +0 -45
- package/src/views/common/version-history.tsx +0 -406
- package/src/views/index.ts +0 -25
- package/src/views/layout/admin-layout.tsx +0 -117
- package/src/views/layout/admin-router.tsx +0 -206
- package/src/views/layout/admin-sidebar.tsx +0 -185
- package/src/views/layout/index.ts +0 -12
- package/tsconfig.json +0 -13
- package/tsconfig.tsbuildinfo +0 -1
- package/tsdown.config.ts +0 -13
- package/vitest.config.ts +0 -29
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-BCGpkAz6.mjs","names":["state: TState","prefill: Record<string, unknown>","state: TState","state: TState","state: TState","state: SectionBuilderState","section","sections: SidebarSection<TSectionIds>[]","sidebar","state: TState","result: TranslationsMap","state: TState","listViews: Record<string, any>","editViews: Record<string, any>","section","Select","SelectPrimitive","Checkbox","CheckboxPrimitive","Checkbox","gridColumnClasses: Record<number, string>","containerGridColumnClasses: Record<number, string>","LOCALE_TO_COUNTRY: Record<string, string>","MenuPrimitive","mapping: Record<string, string>","field","field","Popover","PopoverPrimitive","Popover","field","format","field","format","field","React","field","field","field","Command","CommandPrimitive","useIsMobile","Command","Popover","useIsMobile","Command","Popover","field","Switch","SwitchPrimitive","Switch","field","field","field","SheetPrimitive","React","field","Dialog","React","Select","value","field","EMPTY_BLOCK_CONTENT: BlockContent","TooltipPrimitive","Tooltip","Tooltip","getBlockLabel","entries: BlockTypeStat[]","React","Dialog","React","actionQueryClient: ActionQueryClient","ctx: ActionContext<TItem>","collection","schema: z.ZodTypeAny","ctx: ZodBuildContext","shape: Record<string, z.ZodTypeAny>","customValidators: Array<{\n name: string;\n validate: NonNullable<FieldValidationConfig[\"validate\"]>;\n }>","withFields: Record<string, boolean>","fieldsToCheck: string[]","withRelations: Record<string, boolean>","pagePathById: Record<string, string>","pageIdByPath: Record<string, string>","pageConfigByPath: Record<string, PageDefinition<string>>","collections: AdminRoutes<TApp>[\"collections\"]","collection","globals: AdminRoutes<TApp>[\"globals\"]","global","pages: AdminRoutes<TApp>[\"pages\"]","result: Record<string, string>","matches: AdminRoutes<TApp>[\"matches\"]","result: Record<string, unknown>","processedValues: Record<string, Record<string, unknown>>","collection","React","deps: string[]","resolvedValue: any","React","result: any","collection","formFieldProps: FormFieldProps","content: React.ReactNode","collection","React","section","sidebar","result: any","errors: FieldErrors","React","ctx: ActionContext<TItem>","collection","React","newState: FocusState","React","React","useIsMobile","collection","useCollectionList","collection","useCollectionItem","useCollectionCreate","useCollectionUpdate","useCollectionDelete","useGlobal","useGlobalUpdate","QUERY_KEY_PREFIX","React","collection","actions: Required<ActionsConfig<TItem>>","React","collection","resolver: Resolver<TFieldValues>","errors: FieldErrors<FieldValues>","EMPTY_CONFIG: ViewConfiguration","field","collection","React","collection","configFormActions: FormViewActionsConfig | undefined","formActions: FormViewActionsConfig | undefined","actionQueryClient: ActionQueryClient","actionHelpers: ActionHelpers","actionContext: ActionContext","Dialog","React","React","React","collection","Tooltip","getFileIcon","File","isImage","React","React","getBlockDisplayLabel","block","React","Popover","block","removedIds: string[]","newIds: string[]","newValues: Record<string, Record<string, unknown>>","ids: string[]","countBlocks","values: Record<string, unknown>","field","React","getBlockLabel","Separator","block","getBlockLabel","React","React","block","React","activeId","block","React","React","actions: BlockEditorActions","newBlock: BlockNode","block","state: BlockEditorState","content: BlockContent","React","name","countBlocks","React","collection","renderFields","field","Dialog","React","renderFields","FIELD_TYPES_NEEDING_FIELD_DEF","component: React.ComponentType<{\n\t\tvalue: unknown;\n\t\trow?: unknown;\n\t\tfieldDef?: FieldDefinition;\n\t}>","accessorKey: string","React","collection","global","collection","collection","React","collection","field","collection","collection","displayProps: RelationDisplayProps","React","options: any","error","React","options: any","error","field","React","options: any","actions: {\n\t\t\tonEdit?: (item: any) => void;\n\t\t\tonRemove?: (item: any) => void;\n\t\t}","Popover","LinkIcon","ImageIcon","TableIcon","React","iconWeight: IconWeight","TiptapBubbleMenu","React","SlashCommandList","component: ReactRenderer<SlashCommandListHandle> | null","popup: Instance[] | null","starterKitConfig: Record<string, any>","extensions: TiptapExtension[]","Link","Image","Table","commands: SlashCommandItem[]","File","isImage","React","React","React","collection","andConditions: any[]","Select","React","collection","url: string | undefined","Popover","React","Popover","PRESET_MINIMAL: Required<RichTextFeatures>","PRESET_SIMPLE: Required<RichTextFeatures>","PRESET_STANDARD: Required<RichTextFeatures>","PRESET_ADVANCED: Required<RichTextFeatures>","defaultFeatures: Required<RichTextFeatures>","React","value","field","field","React","field","collection","parts: string[]","t","React","field","collection","parts: string[]","t","state: TState","shape: Record<string, z.ZodTypeAny>","itemSchema: z.ZodTypeAny","schema: z.ZodTypeAny","blockNodeSchema: z.ZodType<any>","actionQueryClient: ActionQueryClient","React","ctx: ActionContext<TItem>","collection","field","Checkbox","visibleFields: AvailableField[]","OPERATOR_KEYS: Record<string, string>","TEXT_OPERATORS: FilterOperator[]","NUMBER_OPERATORS: FilterOperator[]","DATE_OPERATORS: FilterOperator[]","BOOLEAN_OPERATORS: FilterOperator[]","SELECT_OPERATORS: FilterOperator[]","RELATION_SINGLE_OPERATORS: FilterOperator[]","RELATION_MULTI_OPERATORS: FilterOperator[]","PRESENCE_OPERATORS: FilterOperator[]","field","React","newFilter: FilterRule","Select","collection","Table","TableHeader","TableRow","TableCell","React","actionQueryClient: ActionQueryClient","ctx: ActionContext<TItem[]>","collection","defaultCols: string[]","defaultCols","availableFields: ColumnField[]","field","columnConfigs: ColumnConfig<string>[]","titleLabel: I18nText","CellComponent: React.ComponentType<{\n\t\t\tvalue: unknown;\n\t\t\trow?: unknown;\n\t\t\tfieldDef?: FieldDefinition;\n\t\t}>","accessorKey: string","columnDef: ColumnDef<TData>","collection","options: any","whereConditions: Record<string, any>","field","availableFields: AvailableField[]","selectCol: ColumnDef<any>","t","Checkbox","orderedColumns: ColumnDef<any>[]","React","config","Table","TableHeader","TableRow","TableCell","state: TState","sidebarBuilder","Spinner","Spinner","defaultStyles: RichTextStyles","textNode: ReactNode","React","React","open","Separator","Toaster","Sonner","React","items: SearchItem[]","File","React","Tooltip","React","React","Toaster","cachedQueryClient: QueryClient | undefined","QueryClientClass","innerContent: React.ReactNode","Select","React","DefaultLogo","React","Spinner","Combobox","ComboboxPrimitive","React","React","requirements: PrefetchRequirement[]","prefetchResult: BlockPrefetchResult","blockId: string","blockType: string","cause: unknown","React","field","React"],"sources":["../src/client/builder/proxies.ts","../src/client/builder/block/block-builder.ts","../src/client/hooks/use-prefill-params.ts","../src/client/builder/collection/action-registry.ts","../src/client/builder/collection/collection-builder.ts","../src/client/builder/collection/collection.ts","../src/client/builder/global/global-builder.ts","../src/client/builder/global/global.ts","../src/client/builder/page/page.ts","../src/client/builder/sidebar/sidebar-builder.ts","../src/client/builder/widget/widget.ts","../src/client/builder/admin-builder.ts","../src/client/components/ui/select.tsx","../src/client/components/ui/textarea.tsx","../src/client/components/fields/locale-badge.tsx","../src/client/components/ui/checkbox.tsx","../src/client/components/primitives/checkbox-input.tsx","../src/client/components/fields/field-utils.ts","../src/client/utils/locale-to-flag.ts","../src/client/components/ui/dropdown-menu.tsx","../src/client/components/locale-switcher.tsx","../src/client/components/fields/field-wrapper.tsx","../src/client/components/fields/checkbox-field.tsx","../src/client/components/fields/custom-field.tsx","../src/client/components/ui/popover.tsx","../src/client/components/primitives/date-input.tsx","../src/client/components/fields/date-field.tsx","../src/client/components/fields/datetime-field.tsx","../src/client/components/primitives/text-input.tsx","../src/client/components/fields/email-field.tsx","../src/client/components/fields/json-field.tsx","../src/client/components/primitives/number-input.tsx","../src/client/components/fields/number-field.tsx","../src/client/components/fields/password-field.tsx","../src/client/components/ui/input-group.tsx","../src/client/components/ui/command.tsx","../src/client/components/primitives/types.ts","../src/client/components/primitives/select-multi.tsx","../src/client/components/primitives/select-single.tsx","../src/client/components/fields/select-field.tsx","../src/client/components/ui/switch.tsx","../src/client/components/primitives/toggle-input.tsx","../src/client/components/fields/switch-field.tsx","../src/client/components/fields/text-field.tsx","../src/client/components/primitives/textarea-input.tsx","../src/client/components/fields/textarea-field.tsx","../src/client/views/collection/form-field.tsx","../src/client/components/ui/sheet.tsx","../src/client/components/fields/object-array-field.tsx","../src/client/components/fields/array-field.tsx","../src/client/blocks/types.ts","../src/client/components/ui/tooltip.tsx","../src/client/views/collection/cells/shared/cell-helpers.ts","../src/client/views/collection/cells/complex-cells.tsx","../src/client/components/actions/confirmation-dialog.tsx","../src/client/components/actions/action-button.tsx","../src/client/builder/validation.ts","../src/client/builder/types/field-types.ts","../src/client/utils/auto-expand-fields.ts","../src/client/utils/detect-relations.ts","../src/client/utils/routes.ts","../src/client/utils/wrap-localized.ts","../src/client/utils/index.ts","../src/client/views/collection/field-context.ts","../src/client/hooks/use-collection-meta.ts","../src/client/hooks/use-field-hooks.ts","../src/client/views/collection/field-renderer.tsx","../src/client/views/collection/auto-form-fields.tsx","../src/client/components/actions/action-dialog.tsx","../src/client/context/focus-context.tsx","../src/client/preview/types.ts","../src/client/components/preview/preview-pane.tsx","../src/client/components/preview/live-preview-mode.tsx","../src/client/hooks/typed-hooks.ts","../src/client/hooks/use-action.ts","../src/client/hooks/use-current-user.ts","../src/client/hooks/use-admin-preferences.ts","../src/client/hooks/use-admin-routes.ts","../src/client/hooks/use-validation-error-map.ts","../src/client/hooks/use-collection-validation.ts","../src/client/hooks/use-global.ts","../src/client/hooks/use-saved-views.ts","../src/client/hooks/use-view-state.ts","../src/client/hooks/use-search.ts","../src/client/views/collection/form-view.tsx","../src/client/views/globals/global-form-view.tsx","../src/client/components/sheets/resource-sheet.tsx","../src/client/views/collection/cells/shared/relation-chip.tsx","../src/client/views/collection/cells/relation-cells.tsx","../src/client/views/collection/cells/shared/asset-thumbnail.tsx","../src/client/views/collection/cells/upload-cells.tsx","../src/client/components/fields/asset-preview-field.tsx","../src/client/components/ui/resizable.tsx","../src/client/components/blocks/block-editor-context.tsx","../src/client/components/blocks/block-type-icon.tsx","../src/client/components/blocks/block-library.tsx","../src/client/components/blocks/block-insert-button.tsx","../src/client/components/blocks/utils/tree-utils.ts","../src/client/components/blocks/block-item-menu.tsx","../src/client/components/blocks/block-item.tsx","../src/client/components/blocks/block-tree.tsx","../src/client/components/blocks/block-canvas.tsx","../src/client/components/blocks/block-form.tsx","../src/client/components/blocks/block-editor-layout.tsx","../src/client/components/blocks/block-editor-provider.tsx","../src/client/components/fields/blocks-field/blocks-field.tsx","../src/client/components/fields/embedded-collection.tsx","../src/client/components/fields/object-field.tsx","../src/client/components/fields/relation/displays/types.ts","../src/client/components/admin-link.tsx","../src/client/components/fields/relation/displays/chips-display.tsx","../src/client/components/fields/relation/displays/list-display.tsx","../src/client/components/fields/relation/displays/table-display.tsx","../src/client/components/fields/relation/displays/cards-display.tsx","../src/client/components/fields/relation/displays/grid-display.tsx","../src/client/components/fields/relation/relation-items-display.tsx","../src/client/components/fields/relation-picker.tsx","../src/client/components/fields/relation-select.tsx","../src/client/components/fields/relation-field.tsx","../src/client/components/fields/reverse-relation-field.tsx","../src/client/components/fields/rich-text-editor/table-controls.tsx","../src/client/components/fields/rich-text-editor/toolbar.tsx","../src/client/components/fields/rich-text-editor/bubble-menu.tsx","../src/client/components/fields/rich-text-editor/slash-commands.tsx","../src/client/components/fields/rich-text-editor/extensions.tsx","../src/client/components/primitives/asset-preview.tsx","../src/client/components/media/media-grid.tsx","../src/client/components/media/media-picker-dialog.tsx","../src/client/components/fields/rich-text-editor/image-popover.tsx","../src/client/components/fields/rich-text-editor/link-popover.tsx","../src/client/components/fields/rich-text-editor/presets.ts","../src/client/components/fields/rich-text-editor/types.ts","../src/client/components/fields/rich-text-editor/utils.ts","../src/client/components/fields/rich-text-editor/index.tsx","../src/client/components/fields/rich-text-field.tsx","../src/client/components/primitives/time-input.tsx","../src/client/components/fields/time-field.tsx","../src/client/components/fields/upload-field.tsx","../src/client/components/fields/upload-many-field.tsx","../src/client/builder/field/field.ts","../src/client/builder/defaults/fields.tsx","../src/client/builder/defaults/pages.ts","../src/client/components/actions/header-actions.tsx","../src/client/components/filter-builder/columns-tab.tsx","../src/client/components/filter-builder/filters-tab.tsx","../src/client/i18n/messages/sk.ts","../src/client/components/filter-builder/saved-views-tab.tsx","../src/client/components/filter-builder/filter-builder-sheet.tsx","../src/client/components/ui/empty-state.tsx","../src/client/components/ui/kbd.tsx","../src/client/components/ui/search-input.tsx","../src/client/components/ui/table.tsx","../src/client/components/ui/toolbar.tsx","../src/client/views/collection/bulk-action-toolbar.tsx","../src/client/builder/collection/types.ts","../src/client/views/collection/columns/column-defaults.ts","../src/client/views/collection/columns/build-columns.tsx","../src/client/views/collection/table-view.tsx","../src/client/builder/view/view.ts","../src/client/builder/defaults/views.ts","../src/client/builder/defaults/core.ts","../src/client/builder/qa.ts","../src/client/builder/defaults/collections/assets.tsx","../src/client/builder/defaults/collections/user.ts","../src/client/builder/defaults/starter.ts","../src/client/builder/helpers.ts","../src/client/components/ui/spinner.tsx","../src/client/components/auth/auth-loading.tsx","../src/client/components/auth/auth-guard.tsx","../src/components/rich-text/rich-text-renderer.tsx","../src/client/views/auth/accept-invite-form.tsx","../src/client/views/globals/global-form.tsx","../src/client/hooks/use-mobile.ts","../src/client/components/ui/sidebar.tsx","../src/client/components/ui/sonner.tsx","../src/client/contexts/breadcrumb-context.tsx","../src/client/views/common/global-search.tsx","../src/client/views/layout/admin-sidebar.tsx","../src/client/views/layout/admin-topbar.tsx","../src/client/views/layout/admin-layout.tsx","../src/client/views/layout/admin-layout-provider.tsx","../src/client/views/auth/invite-form.tsx","../src/client/views/pages/invite-page.tsx","../src/client/views/pages/accept-invite-page.tsx","../src/client/components/ui/combobox.tsx","../src/client/views/layout/admin-router.tsx","../src/client/preview/block-scope-context.tsx","../src/client/blocks/block-renderer.tsx","../src/client/blocks/prefetch.ts","../src/client/components/preview/form-with-preview.tsx","../src/client/preview/preview-field.tsx","../src/client/preview/preview-banner.tsx","../src/client/preview/use-collection-preview.ts"],"sourcesContent":["/**\n * Proxy Types for Type-Safe Builder APIs\n *\n * These provide autocomplete and type safety in builder callbacks.\n */\n\nimport type { BlockDefinition } from \"./block/types\";\nimport type { FieldDefinition } from \"./field/field\";\nimport type { EditViewDefinition, ListViewDefinition } from \"./view/view\";\n\n// ============================================================================\n// Field Proxies\n// ============================================================================\n\n/**\n * Field Proxy - Maps field names to themselves for autocomplete\n *\n * Usage: ({ f }) => ({ columns: [f.name, f.email] })\n */\nexport type FieldProxy<TFields extends Record<string, any>> = {\n\t[K in keyof TFields]: K;\n};\n\n/**\n * Creates a field proxy at runtime\n */\nexport function createFieldProxy<TFields extends Record<string, any>>(\n\tfields: TFields,\n): FieldProxy<TFields> {\n\tconst proxy = {} as any;\n\tfor (const key in fields) {\n\t\tproxy[key] = key;\n\t}\n\treturn proxy;\n}\n\n/**\n * Helper type to inject block names into BlocksFieldConfig.\n *\n * When a field config has `allowedBlocks`, this replaces string[] with\n * the actual block names from the registry for type-safe autocomplete.\n */\ntype InjectBlocksConfig<\n\tTConfig,\n\tTBlocks extends Record<string, BlockDefinition>,\n> = TConfig extends { allowedBlocks?: string[] }\n\t? Omit<TConfig, \"allowedBlocks\"> & {\n\t\t\tallowedBlocks?: (keyof TBlocks & string)[];\n\t\t}\n\t: TConfig;\n\n/**\n * Helper type to inject field registry into nested callbacks.\n *\n * When a config type has `fields` or `item` callbacks (like ObjectFieldConfig, ArrayFieldConfig),\n * this replaces the `any` or generic `r` parameter with the actual field registry type.\n * This enables type-safe autocomplete in nested field definitions.\n */\ntype InjectFieldRegistry<\n\tTConfig,\n\tTFields extends Record<string, FieldDefinition<any, any>>,\n\tTBlocks extends Record<string, BlockDefinition> = Record<\n\t\tstring,\n\t\tBlockDefinition\n\t>,\n> = TConfig extends {\n\tfields?: (ctx: { r: any }) => any;\n}\n\t? Omit<TConfig, \"fields\"> & {\n\t\t\tfields?: (ctx: {\n\t\t\t\tr: FieldRegistryProxy<TFields, TBlocks>;\n\t\t\t}) => ReturnType<NonNullable<TConfig[\"fields\"]>>;\n\t\t}\n\t: TConfig extends { item?: (ctx: { r: any }) => any }\n\t\t? Omit<TConfig, \"item\"> & {\n\t\t\t\titem?: (ctx: {\n\t\t\t\t\tr: FieldRegistryProxy<TFields, TBlocks>;\n\t\t\t\t}) => ReturnType<NonNullable<TConfig[\"item\"]>>;\n\t\t\t}\n\t\t: TConfig;\n\n/**\n * Apply all config injections (blocks, nested fields)\n */\ntype InjectAllConfig<\n\tTConfig,\n\tTFields extends Record<string, FieldDefinition<any, any>>,\n\tTBlocks extends Record<string, BlockDefinition>,\n> = InjectBlocksConfig<InjectFieldRegistry<TConfig, TFields, TBlocks>, TBlocks>;\n\n/**\n * Field Registry Proxy - Type-safe field builder methods\n *\n * Usage: ({ r }) => ({ name: r.text({ maxLength: 100 }) })\n *\n * For fields with nested callbacks (object, array), the registry type\n * is automatically injected so nested `r` has full autocomplete.\n *\n * For blocks fields, the `allowedBlocks` option is typed to only accept\n * block names from the registered blocks.\n *\n * @typeParam TFields - Field definitions from admin registry\n * @typeParam TBlocks - Block definitions from admin registry\n */\nexport type FieldRegistryProxy<\n\tTFields extends Record<string, FieldDefinition<any, any>>,\n\tTBlocks extends Record<string, BlockDefinition> = Record<\n\t\tstring,\n\t\tBlockDefinition\n\t>,\n> = {\n\t[K in keyof TFields]: TFields[K] extends FieldDefinition<\n\t\tinfer TName,\n\t\tinfer TFieldOptions\n\t>\n\t\t? (\n\t\t\t\toptions?: InjectAllConfig<TFieldOptions, TFields, TBlocks>,\n\t\t\t) => FieldDefinition<\n\t\t\t\tTName,\n\t\t\t\tInjectAllConfig<TFieldOptions, TFields, TBlocks>\n\t\t\t>\n\t\t: never;\n};\n\n/**\n * Creates a field registry proxy at runtime\n */\nexport function createFieldRegistryProxy<\n\tTFields extends Record<string, FieldDefinition<any, any>>,\n>(fields: TFields): FieldRegistryProxy<TFields> {\n\tconst proxy = {} as any;\n\tfor (const key in fields) {\n\t\tproxy[key] = (options?: any) => {\n\t\t\tconst fieldDef = fields[key];\n\t\t\t// Important: Access getters explicitly to ensure they're evaluated\n\t\t\t// FieldBuilder uses getters for 'name', 'field', 'cell', '~options'\n\t\t\treturn {\n\t\t\t\tname: fieldDef.name,\n\t\t\t\t\"~options\": { ...fieldDef[\"~options\"], ...options },\n\t\t\t\tfield: fieldDef.field,\n\t\t\t\tcell: fieldDef.cell,\n\t\t\t} as FieldDefinition;\n\t\t};\n\t}\n\treturn proxy;\n}\n\n// ============================================================================\n// View Proxies\n// ============================================================================\n\n/**\n * Helper type to make config optional when it's unknown or empty object\n */\ntype ViewConfigArg<TConfig> = unknown extends TConfig\n\t? TConfig | undefined\n\t: TConfig;\n\n/**\n * View Registry Proxy - Type-safe view builder methods\n *\n * Usage: ({ v, f }) => v.table({ columns: [f.name] })\n *\n * The config parameter is typed based on what the view component expects.\n * If the component has `viewConfig?: TableViewConfig`, you get autocomplete\n * for `TableViewConfig` properties.\n *\n * @example\n * ```ts\n * .list(({ v, f }) => v.table({\n * columns: [f.name, f.email], // <- typed from TableViewConfig\n * searchable: true,\n * }))\n * ```\n */\nexport type ViewRegistryProxy<TViews extends Record<string, any>> = {\n\t[K in keyof TViews]: TViews[K] extends ListViewDefinition<\n\t\tany,\n\t\tinfer TListConfig\n\t>\n\t\t? (config?: ViewConfigArg<TListConfig>) => TViews[K]\n\t\t: TViews[K] extends EditViewDefinition<any, infer TEditConfig>\n\t\t\t? (config?: ViewConfigArg<TEditConfig>) => TViews[K]\n\t\t\t: never;\n};\n\n/**\n * Creates a view registry proxy at runtime\n */\nexport function createViewRegistryProxy<TViews extends Record<string, any>>(\n\tviews: TViews,\n): ViewRegistryProxy<TViews> {\n\tconst proxy = {} as any;\n\tfor (const key in views) {\n\t\tproxy[key] = (config?: any) => {\n\t\t\tconst view = views[key];\n\t\t\t// Access state directly to avoid getter issues with class instances\n\t\t\tconst existingConfig = view.state?.[\"~config\"] ?? view[\"~config\"] ?? {};\n\t\t\treturn {\n\t\t\t\tname: view.name,\n\t\t\t\tkind: view.kind,\n\t\t\t\tcomponent: view.component,\n\t\t\t\tstate: view.state,\n\t\t\t\t\"~config\": { ...existingConfig, ...config },\n\t\t\t};\n\t\t};\n\t}\n\treturn proxy;\n}\n","/**\n * Block Builder\n *\n * Fluent API for defining block types for the visual page builder.\n * Blocks are UI-only - server stores them as JSONB with $i18n markers.\n *\n * @example\n * ```ts\n * const heroBlock = qa<AppCMS>()\n * .use(adminModule)\n * .block(\"hero\")\n * .label({ en: \"Hero Section\", sk: \"Hero sekcia\" })\n * .icon(\"Image\")\n * .category(\"sections\")\n * .fields(({ r }) => ({\n * title: r.text({ label: \"Title\", localized: true, required: true }),\n * subtitle: r.textarea({ label: \"Subtitle\", localized: true }),\n * alignment: r.select({\n * label: \"Alignment\",\n * options: [\n * { value: \"left\", label: \"Left\" },\n * { value: \"center\", label: \"Center\" },\n * { value: \"right\", label: \"Right\" },\n * ],\n * defaultValue: \"center\"\n * }),\n * }))\n * .renderer(HeroRenderer)\n * .build();\n * ```\n */\n\nimport type * as React from \"react\";\nimport type {\n\tBlockCategory,\n\tBlockPrefetch,\n\tBlockRendererProps,\n} from \"../../blocks/types.js\";\nimport type { I18nText } from \"../../i18n/types.js\";\nimport type { AdminBuilder } from \"../admin-builder.js\";\nimport type { ExtractBlocks, ExtractFields } from \"../admin-types.js\";\nimport type { createRegistryProxy } from \"../defaults/fields.js\";\nimport type { FieldDefinition } from \"../field/field.js\";\nimport {\n\tcreateFieldRegistryProxy,\n\ttype FieldRegistryProxy,\n} from \"../proxies.js\";\nimport type { BlockBuilderState, BlockDefinition } from \"./types.js\";\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\n/**\n * Helper to get fields from AdminApp - simplifies conditional type chains\n */\ntype AdminAppFields<TAdminApp> =\n\tExtractFields<TAdminApp> extends Record<string, any>\n\t\t? ExtractFields<TAdminApp>\n\t\t: {};\n\n/**\n * Helper to get blocks from AdminApp\n */\ntype AdminAppBlocks<TAdminApp> =\n\tExtractBlocks<TAdminApp> extends Record<string, any>\n\t\t? ExtractBlocks<TAdminApp>\n\t\t: {};\n\n/**\n * Legacy type alias for backwards compatibility.\n * @deprecated Use FieldRegistryProxy from \"../proxies.js\" instead\n */\nexport type LegacyFieldRegistryProxy = ReturnType<typeof createRegistryProxy>;\n\n/**\n * Block builder class with fluent API.\n */\nexport class BlockBuilder<TState extends BlockBuilderState> {\n\tconstructor(public readonly state: TState) {}\n\n\t/**\n\t * Connect to admin app for type-safe field registry access.\n\t * This enables autocomplete for custom fields defined in the admin app.\n\t *\n\t * @example\n\t * ```ts\n\t * const heroBlock = block(\"hero\")\n\t * .use(admin) // Connect to admin for field registry\n\t * .fields(({ r }) => ({\n\t * // Now r has access to admin's custom fields!\n\t * content: r.richText({ label: \"Content\" }),\n\t * }))\n\t * ```\n\t */\n\tuse<TAdminApp extends AdminBuilder<any>>(\n\t\tadminApp: TAdminApp,\n\t): BlockBuilder<Omit<TState, \"~adminApp\"> & { \"~adminApp\": TAdminApp }> {\n\t\treturn new BlockBuilder({\n\t\t\t...this.state,\n\t\t\t\"~adminApp\": adminApp,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Set the display label for the block.\n\t * Shown in the block picker and block tree.\n\t */\n\tlabel(label: I18nText): BlockBuilder<TState & { label: I18nText }> {\n\t\treturn new BlockBuilder({ ...this.state, label });\n\t}\n\n\t/**\n\t * Set the description for the block.\n\t * Shown in the block picker to help users understand the block's purpose.\n\t */\n\tdescription(\n\t\tdescription: I18nText,\n\t): BlockBuilder<TState & { description: I18nText }> {\n\t\treturn new BlockBuilder({ ...this.state, description });\n\t}\n\n\t/**\n\t * Set the icon for the block.\n\t * Use Phosphor icon names (e.g., \"Image\", \"Columns\", \"TextAa\").\n\t */\n\ticon(icon: string): BlockBuilder<TState & { icon: string }> {\n\t\treturn new BlockBuilder({ ...this.state, icon });\n\t}\n\n\t/**\n\t * Set the category for grouping in the block picker.\n\t */\n\tcategory(\n\t\tcategory: BlockCategory,\n\t): BlockBuilder<TState & { category: BlockCategory }> {\n\t\treturn new BlockBuilder({ ...this.state, category });\n\t}\n\n\t/**\n\t * Define fields for this block.\n\t * Fields marked with `localized: true` will be stored with $i18n markers.\n\t *\n\t * Requires an admin builder registry via `.use(admin)` or `builder.block()`.\n\t * The field registry is inferred from the admin builder chain.\n\t *\n\t * @example\n\t * ```ts\n\t * .fields(({ r }) => ({\n\t * title: r.text({ label: \"Title\", localized: true }),\n\t * columns: r.select({ label: \"Columns\", options: [...] }),\n\t * }))\n\t * ```\n\t */\n\tfields<TFields extends Record<string, FieldDefinition>>(\n\t\tcallback: (ctx: {\n\t\t\tr: FieldRegistryProxy<\n\t\t\t\tAdminAppFields<TState[\"~adminApp\"]>,\n\t\t\t\tAdminAppBlocks<TState[\"~adminApp\"]>\n\t\t\t>;\n\t\t}) => TFields,\n\t): BlockBuilder<TState & { fields: TFields }> {\n\t\t// Extract field registry from admin app if available\n\t\tconst adminApp = this.state[\"~adminApp\"] as AdminBuilder<any> | undefined;\n\t\tif (!adminApp) {\n\t\t\tthrow new Error(\n\t\t\t\t\"BlockBuilder.fields requires an admin builder registry. Use qa<AppCMS>().use(adminModule).block(...), or qa.block(...).use(builder).\",\n\t\t\t);\n\t\t}\n\t\tconst adminFields =\n\t\t\tadminApp && typeof adminApp === \"object\" && \"state\" in adminApp\n\t\t\t\t? (adminApp as any).state?.fields || {}\n\t\t\t\t: {};\n\n\t\tconst r = createFieldRegistryProxy(adminFields);\n\t\tconst fields = callback({ r } as any);\n\t\treturn new BlockBuilder({ ...this.state, fields });\n\t}\n\n\t/**\n\t * Allow this block to contain child blocks.\n\t * Used for layout blocks like columns, grids, containers.\n\t *\n\t * @param allow - Whether children are allowed\n\t * @param options - Optional constraints\n\t * @param options.max - Maximum number of children\n\t * @param options.allowedTypes - Allowed child block types (if not set, all are allowed)\n\t *\n\t * @example\n\t * ```ts\n\t * // Allow up to 4 children of any type\n\t * .allowChildren(true, { max: 4 })\n\t *\n\t * // Allow only specific child types\n\t * .allowChildren(true, { allowedTypes: [\"text\", \"image\"] })\n\t * ```\n\t */\n\tallowChildren(\n\t\tallow: boolean,\n\t\toptions?: { max?: number; allowedTypes?: string[] },\n\t): BlockBuilder<\n\t\tTState & {\n\t\t\tallowChildren: boolean;\n\t\t\tmaxChildren?: number;\n\t\t\tallowedChildTypes?: string[];\n\t\t}\n\t> {\n\t\treturn new BlockBuilder({\n\t\t\t...this.state,\n\t\t\tallowChildren: allow,\n\t\t\tmaxChildren: options?.max,\n\t\t\tallowedChildTypes: options?.allowedTypes,\n\t\t});\n\t}\n\n\t/**\n\t * Set the renderer component for this block.\n\t * The renderer receives BlockRendererProps with values and optional children.\n\t *\n\t * @example\n\t * ```ts\n\t * function HeroRenderer({ id, values, isSelected }: BlockRendererProps) {\n\t * return (\n\t * <section data-block-id={id}>\n\t * <h1>{values.title}</h1>\n\t * <p>{values.subtitle}</p>\n\t * </section>\n\t * );\n\t * }\n\t *\n\t * .renderer(HeroRenderer)\n\t * ```\n\t */\n\trenderer<TValues = Record<string, unknown>>(\n\t\tcomponent: React.ComponentType<BlockRendererProps<TValues>>,\n\t): BlockBuilder<\n\t\tTState & { renderer: React.ComponentType<BlockRendererProps<TValues>> }\n\t> {\n\t\treturn new BlockBuilder({\n\t\t\t...this.state,\n\t\t\trenderer: component as React.ComponentType<BlockRendererProps<any>>,\n\t\t});\n\t}\n\n\t/**\n\t * Set the prefetch function for SSR data fetching.\n\t * Called during SSR to fetch data needed by the block.\n\t *\n\t * @example\n\t * ```ts\n\t * .prefetch(async ({ values, locale }) => {\n\t * // Fetch related products for this block\n\t * return await fetchProducts(values.productIds, locale);\n\t * })\n\t * ```\n\t */\n\tprefetch<TData>(\n\t\tfn: BlockPrefetch<TData>,\n\t): BlockBuilder<TState & { prefetch: BlockPrefetch<TData> }> {\n\t\treturn new BlockBuilder({\n\t\t\t...this.state,\n\t\t\tprefetch: fn as BlockPrefetch<any>,\n\t\t});\n\t}\n\n\t/**\n\t * Build the block definition.\n\t * Validates that required properties are set.\n\t *\n\t * @throws Error if name or renderer is not set\n\t */\n\tbuild(): BlockDefinition<TState> {\n\t\tif (!this.state.name) {\n\t\t\tthrow new Error(\"Block name is required\");\n\t\t}\n\t\tif (!this.state.renderer) {\n\t\t\tthrow new Error(`Block \"${this.state.name}\" requires a renderer`);\n\t\t}\n\t\treturn this.state as unknown as BlockDefinition<TState>;\n\t}\n}\n\n/**\n * Create a new block builder.\n *\n * @param name - Unique block type name (e.g., \"hero\", \"columns\", \"text\")\n *\n * @example\n * ```ts\n * const textBlock = block(\"text\")\n * .use(admin)\n * .label({ en: \"Text\" })\n * .category(\"content\")\n * .fields(({ r }) => ({\n * content: r.richText({ label: \"Content\", localized: true }),\n * }))\n * .renderer(TextRenderer)\n * .build();\n * ```\n */\nexport function block<TName extends string>(\n\tname: TName,\n): BlockBuilder<{ name: TName }> {\n\treturn new BlockBuilder({ name });\n}\n","/**\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","/**\n * Action Registry\n *\n * Provides built-in action factories and the action registry proxy\n * for type-safe action configuration in collection builders.\n */\n\nimport { Copy, Plus, Trash } from \"@phosphor-icons/react\";\nimport { buildPrefillUrl } from \"../../hooks/use-prefill-params\";\nimport type { FormViewActionsConfig } from \"../types/field-types\";\nimport type {\n\tActionContext,\n\tActionDefinition,\n\tActionsConfig,\n\tHeaderActionsConfig,\n} from \"./action-types\";\n\n// ============================================================================\n// Action Registry Proxy Type\n// ============================================================================\n\n/**\n * Proxy type for building actions with autocomplete\n */\nexport interface ActionRegistryProxy<TItem = any> {\n\t/**\n\t * Create action - navigates to create page (header action)\n\t */\n\tcreate(opts?: Partial<ActionDefinition<TItem>>): ActionDefinition<TItem>;\n\n\t/**\n\t * Duplicate action - creates a copy of the selected item\n\t * For bulk: shows only when 1 item selected\n\t * For form: always visible\n\t */\n\tduplicate(opts?: Partial<ActionDefinition<TItem>>): ActionDefinition<TItem>;\n\n\t/**\n\t * Delete action - deletes single item with confirmation (form action)\n\t */\n\tdelete(opts?: Partial<ActionDefinition<TItem>>): ActionDefinition<TItem>;\n\n\t/**\n\t * Delete many action - bulk delete selected items\n\t */\n\tdeleteMany(opts?: Partial<ActionDefinition<TItem>>): ActionDefinition<TItem>;\n\n\t/**\n\t * Custom action - define a fully custom action\n\t */\n\taction(def: ActionDefinition<TItem>): ActionDefinition<TItem>;\n}\n\n// ============================================================================\n// Built-in Action Factories\n// ============================================================================\n\n/**\n * Create a \"Create\" action\n */\nfunction createCreateAction<TItem>(\n\topts?: Partial<ActionDefinition<TItem>>,\n): ActionDefinition<TItem> {\n\treturn {\n\t\tid: \"create\",\n\t\tlabel: \"Create\",\n\t\ticon: Plus,\n\t\tvariant: \"default\",\n\t\thandler: {\n\t\t\ttype: \"navigate\",\n\t\t\tpath: \"create\",\n\t\t},\n\t\t...opts,\n\t};\n}\n\n/**\n * Create a \"Duplicate\" action (bulk action, shows only when 1 item selected)\n */\nfunction createDuplicateAction<TItem>(\n\topts?: Partial<ActionDefinition<TItem>>,\n): ActionDefinition<TItem> {\n\treturn {\n\t\tid: \"duplicate\",\n\t\tlabel: \"Duplicate\",\n\t\ticon: Copy,\n\t\tvariant: \"ghost\",\n\t\t// Default visibility: only show when exactly 1 item selected\n\t\tvisible: (ctx) => {\n\t\t\t// For bulk context, ctx.item is an array\n\t\t\tif (Array.isArray(ctx.item)) {\n\t\t\t\treturn ctx.item.length === 1;\n\t\t\t}\n\t\t\t// For form context, ctx.item is a single item\n\t\t\treturn !!ctx.item;\n\t\t},\n\t\thandler: {\n\t\t\ttype: \"custom\",\n\t\t\tfn: async (ctx: ActionContext<TItem>) => {\n\t\t\t\t// Get the item - either single item or first from array\n\t\t\t\tconst item = Array.isArray(ctx.item) ? ctx.item[0] : ctx.item;\n\t\t\t\tif (!item) return;\n\n\t\t\t\t// Clone the item, removing id and timestamps\n\t\t\t\tconst { id, createdAt, updatedAt, ...data } = item as any;\n\n\t\t\t\t// Navigate to create page with prefilled data\n\t\t\t\tconst createPath = `${ctx.helpers.basePath}/collections/${ctx.collection}/create`;\n\t\t\t\tconst prefillUrl = buildPrefillUrl(createPath, data);\n\t\t\t\tctx.helpers.navigate(prefillUrl);\n\t\t\t},\n\t\t},\n\t\t...opts,\n\t};\n}\n\n/**\n * Create a \"Delete Many\" (bulk delete) action\n *\n * Note: The actual deletion is handled by BulkActionToolbar via onBulkDelete callback.\n * This action definition just configures the UI and confirmation.\n */\nfunction createDeleteManyAction<TItem>(\n\topts?: Partial<ActionDefinition<TItem>>,\n): ActionDefinition<TItem> {\n\treturn {\n\t\tid: \"deleteMany\",\n\t\tlabel: \"Delete Selected\",\n\t\ticon: Trash,\n\t\tvariant: \"destructive\",\n\t\tconfirmation: {\n\t\t\ttitle: \"Delete selected items?\",\n\t\t\tdescription:\n\t\t\t\t\"This action cannot be undone. All selected items will be permanently deleted.\",\n\t\t\tconfirmLabel: \"Delete All\",\n\t\t\tdestructive: true,\n\t\t},\n\t\thandler: {\n\t\t\t// Handler is a no-op as deletion is handled by BulkActionToolbar\n\t\t\t// when it detects action.id === \"deleteMany\" and calls onBulkDelete\n\t\t\ttype: \"custom\",\n\t\t\tfn: async () => {\n\t\t\t\t// No-op: actual deletion handled by BulkActionToolbar.onBulkDelete\n\t\t\t},\n\t\t},\n\t\t...opts,\n\t};\n}\n\n/**\n * Create a \"Delete\" action for single item (form view)\n */\nfunction createDeleteAction<TItem>(\n\topts?: Partial<ActionDefinition<TItem>>,\n): ActionDefinition<TItem> {\n\treturn {\n\t\tid: \"delete\",\n\t\tlabel: \"Delete\",\n\t\ticon: Trash,\n\t\tvariant: \"destructive\",\n\t\tconfirmation: {\n\t\t\ttitle: \"Delete item?\",\n\t\t\tdescription:\n\t\t\t\t\"This action cannot be undone. The item will be permanently deleted.\",\n\t\t\tconfirmLabel: \"Delete\",\n\t\t\tdestructive: true,\n\t\t},\n\t\thandler: {\n\t\t\ttype: \"api\",\n\t\t\tendpoint: \"{id}\",\n\t\t\tmethod: \"DELETE\",\n\t\t},\n\t\t...opts,\n\t};\n}\n\n// ============================================================================\n// Create Action Registry Proxy\n// ============================================================================\n\n/**\n * Creates an action registry proxy for type-safe action building\n */\nexport function createActionRegistryProxy<\n\tTItem = any,\n>(): ActionRegistryProxy<TItem> {\n\treturn {\n\t\tcreate: (opts) => createCreateAction<TItem>(opts),\n\t\tduplicate: (opts) => createDuplicateAction<TItem>(opts),\n\t\tdelete: (opts) => createDeleteAction<TItem>(opts),\n\t\tdeleteMany: (opts) => createDeleteManyAction<TItem>(opts),\n\t\taction: (def) => def,\n\t};\n}\n\n// ============================================================================\n// Default Actions\n// ============================================================================\n\n/**\n * Get default header actions for a collection\n */\nexport function getDefaultHeaderActions<\n\tTItem = any,\n>(): HeaderActionsConfig<TItem> {\n\treturn {\n\t\tprimary: [createCreateAction<TItem>()],\n\t\tsecondary: [],\n\t};\n}\n\n/**\n * Get default bulk actions for a collection\n */\nexport function getDefaultBulkActions<\n\tTItem = any,\n>(): ActionDefinition<TItem>[] {\n\treturn [createDeleteManyAction<TItem>(), createDuplicateAction<TItem>()];\n}\n\n/**\n * Get default form actions for a collection (edit view)\n */\nexport function getDefaultFormActions<\n\tTItem = any,\n>(): FormViewActionsConfig<TItem> {\n\treturn {\n\t\tprimary: [],\n\t\tsecondary: [createDuplicateAction<TItem>(), createDeleteAction<TItem>()],\n\t};\n}\n\n/**\n * Get complete default actions config\n */\nexport function getDefaultActionsConfig<TItem = any>(): ActionsConfig<TItem> {\n\treturn {\n\t\theader: getDefaultHeaderActions<TItem>(),\n\t\tbulk: getDefaultBulkActions<TItem>(),\n\t};\n}\n","/**\n * Collection Builder\n *\n * For configuring UI for a backend collection.\n * Single generic TState pattern with ~adminApp for type safety.\n */\n\nimport type { Questpie } from \"questpie\";\nimport type { I18nText } from \"../../i18n/types.js\";\nimport type { AdminBuilder } from \"../admin-builder\";\nimport type {\n\tExtractBackendApp,\n\tExtractBlocks,\n\tExtractEditViews,\n\tExtractFields,\n\tExtractListViews,\n} from \"../admin-types\";\nimport type { FieldDefinition } from \"../field/field\";\nimport type { CollectionFieldKeys } from \"../index\";\nimport {\n\tcreateFieldProxy,\n\tcreateFieldRegistryProxy,\n\tcreateViewRegistryProxy,\n\ttype FieldProxy,\n\ttype FieldRegistryProxy,\n\ttype ViewRegistryProxy,\n} from \"../proxies\";\nimport type { IconComponent } from \"../types/common\";\nimport {\n\ttype ActionRegistryProxy,\n\tcreateActionRegistryProxy,\n\tgetDefaultActionsConfig,\n} from \"./action-registry\";\nimport type {\n\tAutoSaveConfig,\n\tCollectionBuilderState,\n\tColumnConfig,\n\tPreviewConfig,\n} from \"./types\";\n\n/**\n * Get valid field keys for a collection based on backend schema\n * Falls back to string when app type is not available\n */\ntype ValidFieldKeys<TState extends CollectionBuilderState> =\n\tExtractBackendApp<TState[\"~adminApp\"]> extends Questpie<any>\n\t\t? CollectionFieldKeys<\n\t\t\t\tExtractBackendApp<TState[\"~adminApp\"]>,\n\t\t\t\tTState[\"name\"]\n\t\t\t>\n\t\t: string;\n\n/**\n * Helper to get fields from AdminApp - simplifies conditional type chains\n */\ntype AdminAppFields<TAdminApp> =\n\tExtractFields<TAdminApp> extends Record<string, any>\n\t\t? ExtractFields<TAdminApp>\n\t\t: {};\n\n/**\n * Helper to get list views from AdminApp\n */\ntype AdminAppListViews<TAdminApp> =\n\tExtractListViews<TAdminApp> extends Record<string, any>\n\t\t? ExtractListViews<TAdminApp>\n\t\t: {};\n\n/**\n * Helper to get edit views from AdminApp\n */\ntype AdminAppEditViews<TAdminApp> =\n\tExtractEditViews<TAdminApp> extends Record<string, any>\n\t\t? ExtractEditViews<TAdminApp>\n\t\t: {};\n\n/**\n * Helper to get blocks from AdminApp\n */\ntype AdminAppBlocks<TAdminApp> =\n\tExtractBlocks<TAdminApp> extends Record<string, any>\n\t\t? ExtractBlocks<TAdminApp>\n\t\t: {};\n\n/**\n * Extract field names from collection fields for type-safe form config\n */\ntype CollectionFieldNames<TState extends CollectionBuilderState> =\n\tTState[\"fields\"] extends Record<string, any>\n\t\t? keyof TState[\"fields\"] & string\n\t\t: string;\n\n/**\n * Type-safe ListViewConfig that constrains field names to defined fields\n */\ntype TypedListViewConfig<TFieldNames extends string> = {\n\tcolumns?: ColumnConfig<TFieldNames>[];\n\twith?: string[];\n\tdefaultSort?: {\n\t\tfield: TFieldNames;\n\t\tdirection: \"asc\" | \"desc\";\n\t};\n\tsearchable?: boolean;\n\tsearchFields?: TFieldNames[];\n\tselectable?: boolean;\n\tpaginated?: boolean;\n\tpageSize?: number;\n\tpageSizeOptions?: number[];\n};\n\n/**\n * Type-safe FormViewConfig that constrains field names to defined fields\n */\ntype TypedFormViewConfig<TFieldNames extends string> = {\n\tsidebar?: {\n\t\tposition?: \"left\" | \"right\";\n\t\twidth?: string;\n\t\tfields?: TFieldNames[];\n\t\tsections?: TypedSectionConfig<TFieldNames>[];\n\t\ttabs?: TypedTabConfig<TFieldNames>[];\n\t};\n\ttabs?: TypedTabConfig<TFieldNames>[];\n\tsections?: TypedSectionConfig<TFieldNames>[];\n\tfields?: TFieldNames[];\n\tshowVersionHistory?: boolean;\n};\n\ntype TypedSectionConfig<TFieldNames extends string> = {\n\tid?: string;\n\ttitle?: I18nText;\n\tdescription?: I18nText;\n\tfields?: (TFieldNames | { field: TFieldNames; className?: string })[];\n\ttabs?: TypedTabConfig<TFieldNames>[];\n\tsections?: TypedSectionConfig<TFieldNames>[];\n\tcolumns?: number;\n\tgap?: number;\n\tclassName?: string;\n\tcollapsible?: boolean;\n\tdefaultOpen?: boolean;\n\thidden?: boolean | ((values: Record<string, any>) => boolean);\n};\n\ntype TypedTabConfig<TFieldNames extends string> = {\n\tid: string;\n\tlabel: I18nText;\n\ticon?: IconComponent;\n\tfields?: (TFieldNames | { field: TFieldNames; className?: string })[];\n\tsections?: TypedSectionConfig<TFieldNames>[];\n\ttabs?: TypedTabConfig<TFieldNames>[];\n\thidden?: boolean | ((values: Record<string, any>) => boolean);\n};\n\nexport class CollectionBuilder<TState extends CollectionBuilderState> {\n\tconstructor(public readonly state: TState) {}\n\n\t/**\n\t * Merge admin module into state for type-safe field/view access\n\t */\n\tuse<TAdminApp extends AdminBuilder<any>>(\n\t\tadminApp: TAdminApp,\n\t): CollectionBuilder<Omit<TState, \"~adminApp\"> & { \"~adminApp\": TAdminApp }> {\n\t\treturn new CollectionBuilder({\n\t\t\t...this.state,\n\t\t\t\"~adminApp\": adminApp,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Set collection metadata\n\t */\n\tmeta(meta: {\n\t\tlabel?: I18nText;\n\t\ticon?: IconComponent;\n\t\tdescription?: I18nText;\n\t}): CollectionBuilder<TState> {\n\t\treturn new CollectionBuilder({\n\t\t\t...this.state,\n\t\t\t...meta,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Configure fields with callback: ({ r }) => ({ ... })\n\t * r = field registry proxy with access to TState[\"~adminApp\"] fields and blocks\n\t *\n\t * Field keys MUST match backend collection schema!\n\t */\n\tfields<TNewFields extends Record<string, FieldDefinition<any, any>>>(\n\t\tcallback: (ctx: {\n\t\t\tr: FieldRegistryProxy<\n\t\t\t\tAdminAppFields<TState[\"~adminApp\"]>,\n\t\t\t\tAdminAppBlocks<TState[\"~adminApp\"]>\n\t\t\t>;\n\t\t}) => TNewFields,\n\t): CollectionBuilder<\n\t\tOmit<TState, \"fields\"> & {\n\t\t\tfields: TNewFields;\n\t\t}\n\t> {\n\t\t// Extract field registry from admin app\n\t\tconst adminApp = this.state[\"~adminApp\"];\n\t\tconst adminFields =\n\t\t\tadminApp && \"state\" in adminApp\n\t\t\t\t? (adminApp as any).state?.fields || {}\n\t\t\t\t: {};\n\n\t\tconst r = createFieldRegistryProxy(adminFields);\n\t\tconst newFields = callback({ r } as any);\n\n\t\t// Note: FieldDefinition.name contains the field TYPE (e.g., \"text\", \"textarea\", \"relation\"),\n\t\t// NOT the field key. The field key is the object key in the fields record.\n\t\t// We must NOT overwrite .name as that would break field type detection.\n\n\t\treturn new CollectionBuilder({\n\t\t\t...this.state,\n\t\t\tfields: newFields,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Configure list view layout\n\t *\n\t * @param callback - Receives `{ v, f, a, r }` with type-safe proxies\n\t * @returns View config with columns, sorting, search options, and actions\n\t *\n\t * @example\n\t * ```ts\n\t * .list(({ v, f, a }) => v.table({\n\t * columns: [f.name, f.email, { field: f.status, width: '100px' }],\n\t * defaultSort: { field: f.createdAt, direction: 'desc' },\n\t * searchFields: [f.name, f.email],\n\t * actions: {\n\t * header: {\n\t * primary: [a.create()],\n\t * secondary: [a.action({ id: 'export', label: 'Export' })],\n\t * },\n\t * bulk: [a.deleteMany()],\n\t * },\n\t * }))\n\t * ```\n\t */\n\tlist<TViewResult>(\n\t\tcallback: (ctx: {\n\t\t\tv: ViewRegistryProxy<AdminAppListViews<TState[\"~adminApp\"]>>;\n\t\t\tf: TState[\"fields\"] extends Record<string, any>\n\t\t\t\t? FieldProxy<TState[\"fields\"]>\n\t\t\t\t: Record<string, never>;\n\t\t\ta: ActionRegistryProxy<any>;\n\t\t\tr: FieldRegistryProxy<\n\t\t\t\tAdminAppFields<TState[\"~adminApp\"]>,\n\t\t\t\tAdminAppBlocks<TState[\"~adminApp\"]>\n\t\t\t>;\n\t\t}) => TViewResult,\n\t): CollectionBuilder<Omit<TState, \"list\"> & { list: TViewResult }> {\n\t\tconst adminApp = this.state[\"~adminApp\"];\n\t\tconst adminFields =\n\t\t\tadminApp && \"state\" in adminApp\n\t\t\t\t? (adminApp as any).state?.fields || {}\n\t\t\t\t: {};\n\t\tconst listViews =\n\t\t\tadminApp && \"state\" in adminApp\n\t\t\t\t? (adminApp as any).state?.listViews || {}\n\t\t\t\t: {};\n\n\t\tconst v = createViewRegistryProxy(listViews);\n\t\tconst f = this.state.fields\n\t\t\t? createFieldProxy(this.state.fields)\n\t\t\t: ({} as any);\n\t\tconst a = createActionRegistryProxy<any>();\n\t\tconst r = createFieldRegistryProxy(adminFields);\n\n\t\tconst viewConfig = callback({ v, f, a, r } as any);\n\n\t\t// Apply default actions if not specified\n\t\tif (\n\t\t\tviewConfig &&\n\t\t\ttypeof viewConfig === \"object\" &&\n\t\t\t\"~config\" in viewConfig &&\n\t\t\t!(viewConfig[\"~config\"] as any)?.actions\n\t\t) {\n\t\t\t(viewConfig[\"~config\"] as any).actions = getDefaultActionsConfig();\n\t\t}\n\n\t\treturn new CollectionBuilder({\n\t\t\t...this.state,\n\t\t\tlist: viewConfig,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Configure form view layout\n\t *\n\t * @param callback - Receives `{ v, f, a, r }` with type-safe proxies\n\t * @returns View config with sidebar, tabs, sections, and actions\n\t *\n\t * @example\n\t * ```ts\n\t * .form(({ v, f, a }) => v.form({\n\t * sidebar: {\n\t * position: \"right\",\n\t * fields: [f.status, f.createdAt],\n\t * },\n\t * tabs: [\n\t * {\n\t * id: \"details\",\n\t * label: \"Details\",\n\t * sections: [\n\t * {\n\t * title: \"Basic Info\",\n\t * columns: 2,\n\t * fields: [f.name, f.email],\n\t * },\n\t * ],\n\t * },\n\t * ],\n\t * actions: {\n\t * primary: [a.action({ id: 'publish', label: 'Publish' })],\n\t * secondary: [a.duplicate(), a.action({ id: 'delete', label: 'Delete', variant: 'destructive' })],\n\t * },\n\t * }))\n\t * ```\n\t */\n\tform<TViewResult>(\n\t\tcallback: (ctx: {\n\t\t\tv: ViewRegistryProxy<AdminAppEditViews<TState[\"~adminApp\"]>>;\n\t\t\tf: TState[\"fields\"] extends Record<string, any>\n\t\t\t\t? FieldProxy<TState[\"fields\"]>\n\t\t\t\t: Record<string, never>;\n\t\t\ta: ActionRegistryProxy<any>;\n\t\t\tr: FieldRegistryProxy<\n\t\t\t\tAdminAppFields<TState[\"~adminApp\"]>,\n\t\t\t\tAdminAppBlocks<TState[\"~adminApp\"]>\n\t\t\t>;\n\t\t}) => TViewResult,\n\t): CollectionBuilder<Omit<TState, \"form\"> & { form: TViewResult }> {\n\t\tconst adminApp = this.state[\"~adminApp\"];\n\t\tconst adminFields =\n\t\t\tadminApp && \"state\" in adminApp\n\t\t\t\t? (adminApp as any).state?.fields || {}\n\t\t\t\t: {};\n\t\tconst editViews =\n\t\t\tadminApp && \"state\" in adminApp\n\t\t\t\t? (adminApp as any).state?.editViews || {}\n\t\t\t\t: {};\n\n\t\tconst v = createViewRegistryProxy(editViews);\n\t\tconst f = this.state.fields\n\t\t\t? createFieldProxy(this.state.fields)\n\t\t\t: ({} as any);\n\t\tconst a = createActionRegistryProxy<any>();\n\t\tconst r = createFieldRegistryProxy(adminFields);\n\n\t\tconst viewConfig = callback({ v, f, a, r } as any);\n\n\t\treturn new CollectionBuilder({\n\t\t\t...this.state,\n\t\t\tform: viewConfig,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Configure live preview for this collection\n\t *\n\t * @param config - Preview configuration with URL builder and options\n\t * @returns CollectionBuilder with preview config\n\t *\n\t * @example\n\t * ```ts\n\t * .preview({\n\t * url: (values, locale) => `/${locale}/pages/${values.slug}?preview=true`,\n\t * enabled: true,\n\t * position: \"right\",\n\t * defaultWidth: 50,\n\t * })\n\t * ```\n\t */\n\tpreview(\n\t\tconfig: PreviewConfig,\n\t): CollectionBuilder<Omit<TState, \"preview\"> & { preview: PreviewConfig }> {\n\t\treturn new CollectionBuilder({\n\t\t\t...this.state,\n\t\t\tpreview: config,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Configure autosave behavior for this collection\n\t *\n\t * Enables automatic saving of form changes after a debounce delay.\n\t *\n\t * @param config - Autosave configuration with debounce, indicator, and navigation prevention options\n\t * @returns CollectionBuilder with autosave config\n\t *\n\t * @example\n\t * ```ts\n\t * .autoSave({\n\t * enabled: true,\n\t * debounce: 500, // 0.5s delay before save\n\t * indicator: true, // Show \"Saving...\" badge\n\t * preventNavigation: true // Warn before navigating away\n\t * })\n\t * ```\n\t */\n\tautoSave(\n\t\tconfig: AutoSaveConfig,\n\t): CollectionBuilder<\n\t\tOmit<TState, \"autoSave\"> & { autoSave: AutoSaveConfig }\n\t> {\n\t\treturn new CollectionBuilder({\n\t\t\t...this.state,\n\t\t\tautoSave: config,\n\t\t} as any);\n\t}\n}\n","/**\n * Collection Definition Helper\n */\n\nimport { CollectionBuilder } from \"./collection-builder\";\n\nexport function collection(name: string) {\n return new CollectionBuilder({\n name,\n \"~adminApp\": undefined as any, // Will be set via .use()\n } as const);\n}\n","/**\n * Global Builder\n *\n * For configuring UI for a backend global.\n * Single generic TState pattern with ~adminApp for type safety.\n */\n\nimport type { I18nText } from \"../../i18n/types.js\";\nimport type { AdminBuilder } from \"../admin-builder\";\nimport type {\n\tExtractBlocks,\n\tExtractEditViews,\n\tExtractFields,\n} from \"../admin-types\";\nimport {\n\tcreateFieldProxy,\n\tcreateFieldRegistryProxy,\n\tcreateViewRegistryProxy,\n\ttype FieldProxy,\n\ttype FieldRegistryProxy,\n\ttype ViewRegistryProxy,\n} from \"../proxies\";\nimport type { IconComponent } from \"../types/common\";\nimport type { GlobalBuilderState } from \"./types\";\n\n/**\n * Helper to get fields from AdminApp\n */\ntype AdminAppFields<TAdminApp> =\n\tExtractFields<TAdminApp> extends Record<string, any>\n\t\t? ExtractFields<TAdminApp>\n\t\t: {};\n\n/**\n * Helper to get edit views from AdminApp\n */\ntype AdminAppEditViews<TAdminApp> =\n\tExtractEditViews<TAdminApp> extends Record<string, any>\n\t\t? ExtractEditViews<TAdminApp>\n\t\t: {};\n\n/**\n * Helper to get blocks from AdminApp\n */\ntype AdminAppBlocks<TAdminApp> =\n\tExtractBlocks<TAdminApp> extends Record<string, any>\n\t\t? ExtractBlocks<TAdminApp>\n\t\t: {};\n\nexport class GlobalBuilder<TState extends GlobalBuilderState> {\n\tconstructor(public readonly state: TState) {}\n\n\t/**\n\t * Merge admin module into state\n\t */\n\tuse<TAdminApp extends AdminBuilder<any>>(\n\t\tadminApp: TAdminApp,\n\t): GlobalBuilder<Omit<TState, \"~adminApp\"> & { \"~adminApp\": TAdminApp }> {\n\t\treturn new GlobalBuilder({\n\t\t\t...this.state,\n\t\t\t\"~adminApp\": adminApp,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Set global metadata\n\t */\n\tmeta(meta: {\n\t\tlabel?: I18nText;\n\t\ticon?: IconComponent;\n\t\tdescription?: I18nText;\n\t}): GlobalBuilder<TState> {\n\t\treturn new GlobalBuilder({\n\t\t\t...this.state,\n\t\t\t...meta,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Configure fields: ({ r }) => ({ ... })\n\t * r = field registry proxy (TState[\"~adminApp\"][\"fields\"] with blocks)\n\t */\n\tfields<TNewFields extends Record<string, any>>(\n\t\tcallback: (ctx: {\n\t\t\tr: FieldRegistryProxy<\n\t\t\t\tAdminAppFields<TState[\"~adminApp\"]>,\n\t\t\t\tAdminAppBlocks<TState[\"~adminApp\"]>\n\t\t\t>;\n\t\t}) => TNewFields,\n\t): GlobalBuilder<Omit<TState, \"fields\"> & { fields: TNewFields }> {\n\t\tconst adminApp = this.state[\"~adminApp\"];\n\t\tconst adminFields =\n\t\t\tadminApp && \"state\" in adminApp\n\t\t\t\t? (adminApp as any).state?.fields || {}\n\t\t\t\t: {};\n\n\t\tconst r = createFieldRegistryProxy(adminFields);\n\t\tconst newFields = callback({ r } as any);\n\n\t\treturn new GlobalBuilder({\n\t\t\t...this.state,\n\t\t\tfields: newFields,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Configure form: ({ v, f }) => v.form({ ... })\n\t * v = view registry proxy (TState[\"~adminApp\"][\"editViews\"])\n\t * f = field proxy (TState[\"fields\"])\n\t */\n\tform(\n\t\tcallback: (ctx: {\n\t\t\tv: ViewRegistryProxy<AdminAppEditViews<TState[\"~adminApp\"]>>;\n\t\t\tf: TState[\"fields\"] extends Record<string, any>\n\t\t\t\t? FieldProxy<TState[\"fields\"]>\n\t\t\t\t: Record<string, never>;\n\t\t}) => any,\n\t): GlobalBuilder<TState> {\n\t\tconst adminApp = this.state[\"~adminApp\"];\n\t\tconst editViews =\n\t\t\tadminApp && \"state\" in adminApp\n\t\t\t\t? (adminApp as any).state?.editViews || {}\n\t\t\t\t: {};\n\n\t\tconst v = createViewRegistryProxy(editViews);\n\t\tconst f = this.state.fields\n\t\t\t? createFieldProxy(this.state.fields)\n\t\t\t: ({} as any);\n\n\t\tconst config = callback({ v, f } as any);\n\n\t\treturn new GlobalBuilder({\n\t\t\t...this.state,\n\t\t\tform: config,\n\t\t} as any);\n\t}\n}\n","/**\n * Global Definition Helper\n */\n\nimport { GlobalBuilder } from \"./global-builder\";\n\nexport function global(name: string) {\n return new GlobalBuilder({\n name,\n \"~adminApp\": undefined as any, // Will be set via .use()\n } as const);\n}\n","/**\n * Page Builder\n *\n * Defines custom admin pages outside of collections/globals.\n */\n\nimport type { MaybeLazyComponent } from \"../types/common\";\n\nexport interface PageDefinition<TName extends string = string> {\n readonly name: TName;\n readonly component: any;\n readonly path?: string;\n}\n\nexport interface PageBuilderState {\n readonly name: string;\n readonly component: any;\n readonly path?: string;\n}\n\nexport class PageBuilder<TState extends PageBuilderState> {\n constructor(public readonly state: TState) {}\n\n path(path: string): PageBuilder<Omit<TState, \"path\"> & { path: string }> {\n return new PageBuilder({\n ...this.state,\n path,\n } as any);\n }\n}\n\n/**\n * Create a custom page\n */\nexport function page<\n TName extends string,\n TComponent extends MaybeLazyComponent,\n>(\n name: TName,\n config: { component: TComponent },\n): PageBuilder<{\n name: TName;\n component: TComponent;\n path: undefined;\n}> {\n return new PageBuilder({\n name,\n component: config.component,\n path: undefined,\n } as any);\n}\n","/**\n * Sidebar Builder\n *\n * Fluent API for building type-safe sidebar configurations.\n *\n * @example\n * ```ts\n * // Without type safety (any collection/global name allowed)\n * const sidebar = qa.sidebar()\n * .section(\"content\", s => s\n * .collection(\"posts\")\n * .collection(\"pages\")\n * )\n *\n * // With type safety (only registered names allowed)\n * import type { AppCMS } from './cms';\n *\n * const sidebar = qa.sidebar<AppCMS>()\n * .section(\"content\", s => s\n * .collection(\"posts\") // Autocomplete works!\n * .global(\"siteSettings\") // Autocomplete works!\n * )\n * ```\n */\n\nimport type { Questpie } from \"questpie\";\nimport type { I18nText } from \"../../i18n/types.js\";\nimport type { IconComponent } from \"../types/common\";\nimport type {\n\tSidebarCollectionItem,\n\tSidebarConfig,\n\tSidebarDividerItem,\n\tSidebarGlobalItem,\n\tSidebarItem,\n\tSidebarLinkItem,\n\tSidebarPageItem,\n\tSidebarSection,\n} from \"../types/ui-config\";\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\n/**\n * Extract collection names from CMS type\n */\ntype CollectionNames<TApp> =\n\tTApp extends Questpie<infer TConfig>\n\t\t? keyof TConfig[\"collections\"] & string\n\t\t: string;\n\n/**\n * Extract global names from CMS type\n */\ntype GlobalNames<TApp> =\n\tTApp extends Questpie<infer TConfig>\n\t\t? keyof TConfig[\"globals\"] & string\n\t\t: string;\n\n/**\n * Typed sidebar items with constrained collection/global names.\n */\nexport type TypedSidebarCollectionItem<TCollectionNames extends string> = Omit<\n\tSidebarCollectionItem,\n\t\"collection\"\n> & {\n\tcollection: TCollectionNames;\n};\n\nexport type TypedSidebarGlobalItem<TGlobalNames extends string> = Omit<\n\tSidebarGlobalItem,\n\t\"global\"\n> & {\n\tglobal: TGlobalNames;\n};\n\nexport type TypedSidebarItem<\n\tTCollectionNames extends string,\n\tTGlobalNames extends string,\n> =\n\t| TypedSidebarCollectionItem<TCollectionNames>\n\t| TypedSidebarGlobalItem<TGlobalNames>\n\t| SidebarPageItem\n\t| SidebarLinkItem\n\t| SidebarDividerItem;\n\n/**\n * Typed sidebar item union based on CMS app type.\n */\nexport type SidebarItemForApp<TApp> = TypedSidebarItem<\n\tCollectionNames<TApp>,\n\tGlobalNames<TApp>\n>;\n\n// ============================================================================\n// Section Builder\n// ============================================================================\n\nexport interface SectionBuilderState {\n\tid: string;\n\ttitle?: I18nText;\n\ticon?: IconComponent;\n\tcollapsed?: boolean;\n\titems: SidebarItem[];\n}\n\n/**\n * Section builder with optional type constraints for collection/global names.\n *\n * @template TId - Section ID type\n * @template TCollectionNames - Valid collection names (string if not constrained)\n * @template TGlobalNames - Valid global names (string if not constrained)\n */\nexport class SectionBuilder<\n\tTId extends string = string,\n\tTCollectionNames extends string = string,\n\tTGlobalNames extends string = string,\n> {\n\tconstructor(private state: SectionBuilderState) {}\n\n\tstatic create<\n\t\tTId extends string,\n\t\tTCollectionNames extends string = string,\n\t\tTGlobalNames extends string = string,\n\t>(id: TId): SectionBuilder<TId, TCollectionNames, TGlobalNames> {\n\t\treturn new SectionBuilder({ id, items: [] });\n\t}\n\n\t/**\n\t * Set section title - supports inline translations\n\t */\n\ttitle(title: I18nText): this {\n\t\tthis.state.title = title;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set section icon\n\t */\n\ticon(icon: IconComponent): this {\n\t\tthis.state.icon = icon;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set section as collapsed by default\n\t */\n\tcollapsed(collapsed = true): this {\n\t\tthis.state.collapsed = collapsed;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set section items (replaces existing)\n\t */\n\titems(items: TypedSidebarItem<TCollectionNames, TGlobalNames>[]): this {\n\t\tthis.state.items = items;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add items to the end\n\t */\n\taddItems(items: TypedSidebarItem<TCollectionNames, TGlobalNames>[]): this {\n\t\tthis.state.items = [...this.state.items, ...items];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add items to the beginning\n\t */\n\tprependItems(\n\t\titems: TypedSidebarItem<TCollectionNames, TGlobalNames>[],\n\t): this {\n\t\tthis.state.items = [...items, ...this.state.items];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a single item\n\t */\n\titem(item: TypedSidebarItem<TCollectionNames, TGlobalNames>): this {\n\t\tthis.state.items.push(item);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a collection item.\n\t * When using typed sidebar (qa.sidebar<AppCMS>()), only registered collection names are allowed.\n\t */\n\tcollection(\n\t\tcollection: TCollectionNames,\n\t\toptions?: { label?: I18nText; icon?: IconComponent },\n\t): this {\n\t\tthis.state.items.push({\n\t\t\ttype: \"collection\",\n\t\t\tcollection,\n\t\t\t...options,\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a global item.\n\t * When using typed sidebar (qa.sidebar<AppCMS>()), only registered global names are allowed.\n\t */\n\tglobal(\n\t\tglobal: TGlobalNames,\n\t\toptions?: { label?: I18nText; icon?: IconComponent },\n\t): this {\n\t\tthis.state.items.push({\n\t\t\ttype: \"global\",\n\t\t\tglobal,\n\t\t\t...options,\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a link item\n\t */\n\tlink(\n\t\tlabel: I18nText,\n\t\thref: string,\n\t\toptions?: { icon?: IconComponent; external?: boolean },\n\t): this {\n\t\tthis.state.items.push({\n\t\t\ttype: \"link\",\n\t\t\tlabel,\n\t\t\thref,\n\t\t\t...options,\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a page item\n\t */\n\tpage(\n\t\tpageId: string,\n\t\toptions?: { label?: I18nText; icon?: IconComponent },\n\t): this {\n\t\tthis.state.items.push({\n\t\t\ttype: \"page\",\n\t\t\tpageId,\n\t\t\t...options,\n\t\t});\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a divider\n\t */\n\tdivider(): this {\n\t\tthis.state.items.push({ type: \"divider\" });\n\t\treturn this;\n\t}\n\n\t/**\n\t * Build the section config\n\t */\n\tbuild(): SidebarSection<TId> {\n\t\treturn {\n\t\t\tid: this.state.id as TId,\n\t\t\ttitle: this.state.title,\n\t\t\ticon: this.state.icon,\n\t\t\tcollapsed: this.state.collapsed,\n\t\t\titems: this.state.items,\n\t\t};\n\t}\n\n\t/**\n\t * Get the section ID\n\t */\n\tget id(): TId {\n\t\treturn this.state.id as TId;\n\t}\n}\n\n// ============================================================================\n// Sidebar Builder\n// ============================================================================\n\nexport interface SidebarBuilderState<TSectionIds extends string = string> {\n\tsections: Map<string, SidebarSection<TSectionIds>>;\n\torder: string[];\n}\n\n/**\n * Sidebar builder with optional type constraints for collection/global names.\n *\n * @template TSectionIds - Accumulated section IDs\n * @template TApp - CMS app type for constraining collection/global names (any = no constraints)\n */\nexport class SidebarBuilder<TSectionIds extends string = never, TApp = any> {\n\tprivate state: SidebarBuilderState<TSectionIds>;\n\n\tconstructor(state?: SidebarBuilderState<TSectionIds>) {\n\t\tthis.state = state ?? {\n\t\t\tsections: new Map(),\n\t\t\torder: [],\n\t\t};\n\t}\n\n\t/**\n\t * Create empty sidebar builder\n\t */\n\tstatic create<TApp = any>(): SidebarBuilder<never, TApp> {\n\t\treturn new SidebarBuilder();\n\t}\n\n\t/**\n\t * Create sidebar builder from existing config\n\t */\n\tstatic from<TIds extends string, TApp = any>(\n\t\tconfig: SidebarConfig<TIds>,\n\t): SidebarBuilder<TIds, TApp> {\n\t\tconst builder = new SidebarBuilder<TIds, TApp>();\n\t\tfor (const section of config.sections) {\n\t\t\tbuilder.state.sections.set(section.id, section);\n\t\t\tbuilder.state.order.push(section.id);\n\t\t}\n\t\treturn builder;\n\t}\n\n\t/**\n\t * Add a section.\n\t * The section builder callback receives a typed SectionBuilder with collection/global name constraints.\n\t */\n\tsection<TId extends string>(\n\t\tid: TId,\n\t\tconfigure: (\n\t\t\tsection: SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t\t) => SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t): SidebarBuilder<TSectionIds | TId, TApp> {\n\t\tconst sectionBuilder = SectionBuilder.create<\n\t\t\tTId,\n\t\t\tCollectionNames<TApp>,\n\t\t\tGlobalNames<TApp>\n\t\t>(id);\n\t\tconst configured = configure(sectionBuilder);\n\t\tconst section = configured.build();\n\n\t\tthis.state.sections.set(id, section as any);\n\t\tif (!this.state.order.includes(id)) {\n\t\t\tthis.state.order.push(id);\n\t\t}\n\n\t\treturn this as unknown as SidebarBuilder<TSectionIds | TId, TApp>;\n\t}\n\n\t/**\n\t * Prepend a section (add to beginning)\n\t */\n\tprepend<TId extends string>(\n\t\tid: TId,\n\t\tconfigure: (\n\t\t\tsection: SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t\t) => SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t): SidebarBuilder<TSectionIds | TId, TApp> {\n\t\tconst sectionBuilder = SectionBuilder.create<\n\t\t\tTId,\n\t\t\tCollectionNames<TApp>,\n\t\t\tGlobalNames<TApp>\n\t\t>(id);\n\t\tconst configured = configure(sectionBuilder);\n\t\tconst section = configured.build();\n\n\t\tthis.state.sections.set(id, section as any);\n\t\tthis.state.order = [\n\t\t\tid,\n\t\t\t...this.state.order.filter((existingId) => existingId !== id),\n\t\t];\n\n\t\treturn this as unknown as SidebarBuilder<TSectionIds | TId, TApp>;\n\t}\n\n\t/**\n\t * Append a section (add to end)\n\t */\n\tappend<TId extends string>(\n\t\tid: TId,\n\t\tconfigure: (\n\t\t\tsection: SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t\t) => SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t): SidebarBuilder<TSectionIds | TId, TApp> {\n\t\tconst sectionBuilder = SectionBuilder.create<\n\t\t\tTId,\n\t\t\tCollectionNames<TApp>,\n\t\t\tGlobalNames<TApp>\n\t\t>(id);\n\t\tconst configured = configure(sectionBuilder);\n\t\tconst section = configured.build();\n\n\t\tthis.state.sections.set(id, section as any);\n\t\tthis.state.order = [\n\t\t\t...this.state.order.filter((existingId) => existingId !== id),\n\t\t\tid,\n\t\t];\n\n\t\treturn this as unknown as SidebarBuilder<TSectionIds | TId, TApp>;\n\t}\n\n\t/**\n\t * Insert a section before another section\n\t */\n\tinsertBefore<TId extends string>(\n\t\tbeforeId: TSectionIds,\n\t\tid: TId,\n\t\tconfigure: (\n\t\t\tsection: SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t\t) => SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t): SidebarBuilder<TSectionIds | TId, TApp> {\n\t\tconst sectionBuilder = SectionBuilder.create<\n\t\t\tTId,\n\t\t\tCollectionNames<TApp>,\n\t\t\tGlobalNames<TApp>\n\t\t>(id);\n\t\tconst configured = configure(sectionBuilder);\n\t\tconst section = configured.build();\n\n\t\tthis.state.sections.set(id, section as any);\n\n\t\tconst beforeIndex = this.state.order.indexOf(beforeId);\n\t\tif (beforeIndex !== -1) {\n\t\t\tthis.state.order = [\n\t\t\t\t...this.state.order.slice(0, beforeIndex),\n\t\t\t\tid,\n\t\t\t\t...this.state.order.slice(beforeIndex).filter((i) => i !== id),\n\t\t\t];\n\t\t} else {\n\t\t\tthis.state.order.push(id);\n\t\t}\n\n\t\treturn this as unknown as SidebarBuilder<TSectionIds | TId, TApp>;\n\t}\n\n\t/**\n\t * Insert a section after another section\n\t */\n\tinsertAfter<TId extends string>(\n\t\tafterId: TSectionIds,\n\t\tid: TId,\n\t\tconfigure: (\n\t\t\tsection: SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t\t) => SectionBuilder<TId, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t): SidebarBuilder<TSectionIds | TId, TApp> {\n\t\tconst sectionBuilder = SectionBuilder.create<\n\t\t\tTId,\n\t\t\tCollectionNames<TApp>,\n\t\t\tGlobalNames<TApp>\n\t\t>(id);\n\t\tconst configured = configure(sectionBuilder);\n\t\tconst section = configured.build();\n\n\t\tthis.state.sections.set(id, section as any);\n\n\t\tconst afterIndex = this.state.order.indexOf(afterId);\n\t\tif (afterIndex !== -1) {\n\t\t\tthis.state.order = [\n\t\t\t\t...this.state.order.slice(0, afterIndex + 1).filter((i) => i !== id),\n\t\t\t\tid,\n\t\t\t\t...this.state.order.slice(afterIndex + 1).filter((i) => i !== id),\n\t\t\t];\n\t\t} else {\n\t\t\tthis.state.order.push(id);\n\t\t}\n\n\t\treturn this as unknown as SidebarBuilder<TSectionIds | TId, TApp>;\n\t}\n\n\t/**\n\t * Extend an existing section\n\t */\n\textend(\n\t\tid: TSectionIds,\n\t\tconfigure: (\n\t\t\tsection: SectionBuilder<\n\t\t\t\tTSectionIds,\n\t\t\t\tCollectionNames<TApp>,\n\t\t\t\tGlobalNames<TApp>\n\t\t\t>,\n\t\t) => SectionBuilder<TSectionIds, CollectionNames<TApp>, GlobalNames<TApp>>,\n\t): this {\n\t\tconst existing = this.state.sections.get(id);\n\t\tif (!existing) {\n\t\t\tconsole.warn(\n\t\t\t\t`[SidebarBuilder] Section \"${id}\" not found, skipping extend`,\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\n\t\t// Create builder from existing section\n\t\tconst sectionBuilder = new SectionBuilder<\n\t\t\tTSectionIds,\n\t\t\tCollectionNames<TApp>,\n\t\t\tGlobalNames<TApp>\n\t\t>({\n\t\t\tid: existing.id,\n\t\t\ttitle: existing.title,\n\t\t\ticon: existing.icon,\n\t\t\tcollapsed: existing.collapsed,\n\t\t\titems: [...existing.items],\n\t\t});\n\n\t\tconst configured = configure(sectionBuilder);\n\t\tconst section = configured.build();\n\n\t\tthis.state.sections.set(id, section);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Remove a section\n\t */\n\tremove(id: TSectionIds): this {\n\t\tthis.state.sections.delete(id);\n\t\tthis.state.order = this.state.order.filter((i) => i !== id);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Merge with another sidebar builder\n\t */\n\tmerge<TOtherIds extends string>(\n\t\tother: SidebarBuilder<TOtherIds, TApp>,\n\t): SidebarBuilder<TSectionIds | TOtherIds, TApp> {\n\t\tconst otherConfig = other.build();\n\t\tfor (const section of otherConfig.sections) {\n\t\t\tif (!this.state.sections.has(section.id)) {\n\t\t\t\tthis.state.sections.set(section.id, section as any);\n\t\t\t\tthis.state.order.push(section.id);\n\t\t\t}\n\t\t}\n\t\treturn this as unknown as SidebarBuilder<TSectionIds | TOtherIds, TApp>;\n\t}\n\n\t/**\n\t * Build the sidebar config\n\t */\n\tbuild(): SidebarConfig<TSectionIds> {\n\t\tconst sections: SidebarSection<TSectionIds>[] = [];\n\t\tfor (const id of this.state.order) {\n\t\t\tconst section = this.state.sections.get(id);\n\t\t\tif (section) {\n\t\t\t\tsections.push(section);\n\t\t\t}\n\t\t}\n\t\treturn { sections };\n\t}\n\n\t/**\n\t * Get section IDs (for type inference)\n\t */\n\tget sectionIds(): TSectionIds[] {\n\t\treturn this.state.order as TSectionIds[];\n\t}\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a new sidebar builder\n */\nexport function sidebar<TApp = any>(): SidebarBuilder<never, TApp> {\n\treturn SidebarBuilder.create<TApp>();\n}\n\n/**\n * Create a sidebar builder from existing config\n */\nsidebar.from = <TIds extends string, TApp = any>(\n\tconfig: SidebarConfig<TIds>,\n): SidebarBuilder<TIds, TApp> => SidebarBuilder.from<TIds, TApp>(config);\n\n/**\n * Create a section builder (for standalone use)\n */\nexport function section<\n\tTId extends string,\n\tTCollectionNames extends string = string,\n\tTGlobalNames extends string = string,\n>(id: TId): SectionBuilder<TId, TCollectionNames, TGlobalNames> {\n\treturn SectionBuilder.create<TId, TCollectionNames, TGlobalNames>(id);\n}\n","/**\n * Widget Builder\n *\n * Defines dashboard widgets.\n */\n\nimport type { MaybeLazyComponent } from \"../types/common\";\n\nexport interface WidgetDefinition<\n TName extends string = string,\n TConfig = any,\n> {\n readonly name: TName;\n readonly component: any;\n readonly \"~config\"?: TConfig;\n}\n\nexport interface WidgetBuilderState {\n readonly name: string;\n readonly \"~config\": any;\n readonly component: any;\n}\n\nexport class WidgetBuilder<TState extends WidgetBuilderState> {\n constructor(public readonly state: TState) {}\n\n $config<TNewConfig>(\n config: TNewConfig,\n ): WidgetBuilder<Omit<TState, \"~config\"> & { \"~config\": TNewConfig }> {\n return new WidgetBuilder({\n ...this.state,\n \"~config\": config,\n } as any);\n }\n}\n\n/**\n * Create a dashboard widget\n */\nexport function widget<\n TName extends string,\n TComponent extends MaybeLazyComponent,\n>(\n name: TName,\n config: { component: TComponent },\n): WidgetBuilder<{\n name: TName;\n \"~config\": any;\n component: TComponent;\n}> {\n return new WidgetBuilder({\n name,\n \"~config\": {},\n component: config.component,\n } as any);\n}\n","/**\n * Admin Builder\n *\n * Main builder class - same pattern as QuestpieBuilder.\n * Single generic TState pattern.\n */\n\nimport { DEFAULT_LOCALE_CONFIG } from \"questpie/shared\";\nimport type { SimpleMessages } from \"../i18n/simple\";\nimport type {\n\tAdminBuilderState,\n\tFilterEditViews,\n\tFilterListViews,\n\tTranslationsMap,\n} from \"./admin-types\";\nimport type { BlockBuilder } from \"./block/block-builder\";\nimport { block } from \"./block/block-builder\";\nimport { collection } from \"./collection/collection\";\nimport type { CollectionBuilder } from \"./collection/collection-builder\";\nimport { global } from \"./global/global\";\nimport type { GlobalBuilder } from \"./global/global-builder\";\nimport { type PageBuilder, page } from \"./page/page\";\nimport { SidebarBuilder } from \"./sidebar/sidebar-builder\";\nimport type { MaybeLazyComponent } from \"./types/common\";\nimport type { SidebarConfig } from \"./types/ui-config\";\nimport type { DefaultViewsConfig } from \"./types/views\";\nimport { type WidgetBuilder, widget } from \"./widget/widget\";\n\n// ============================================================================\n// Translations Helpers\n// ============================================================================\n\n/**\n * Merge two translations maps\n */\nfunction mergeTranslations(\n\tbase: TranslationsMap | undefined,\n\toverride: TranslationsMap | undefined,\n): TranslationsMap {\n\tif (!base && !override) return {};\n\tif (!base) return override ?? {};\n\tif (!override) return base;\n\n\tconst result: TranslationsMap = { ...base };\n\n\tfor (const [locale, messages] of Object.entries(override)) {\n\t\tresult[locale] = {\n\t\t\t...(result[locale] ?? {}),\n\t\t\t...messages,\n\t\t};\n\t}\n\n\treturn result;\n}\n\nexport class AdminBuilder<TState extends AdminBuilderState> {\n\tconstructor(public readonly state: TState) {}\n\n\tstatic empty<TApp = any>(): AdminBuilder<{\n\t\t\"~app\": TApp;\n\t\tfields: {};\n\t\tlistViews: {};\n\t\teditViews: {};\n\t\tpages: {};\n\t\twidgets: {};\n\t\tblocks: {};\n\t\tcollections: {};\n\t\tglobals: {};\n\t\tdashboard: { layout: \"grid\"; widgets: [] };\n\t\tsidebar: { sections: [] };\n\t\tbranding: {};\n\t\tlocale: { default: string; supported: string[] };\n\t\tdefaultViews: {};\n\t\ttranslations: {};\n\t}> {\n\t\treturn new AdminBuilder({\n\t\t\t\"~app\": undefined as TApp,\n\t\t\tfields: {},\n\t\t\tlistViews: {},\n\t\t\teditViews: {},\n\t\t\tpages: {},\n\t\t\twidgets: {},\n\t\t\tblocks: {},\n\t\t\tcollections: {},\n\t\t\tglobals: {},\n\t\t\tdashboard: { layout: \"grid\", widgets: [] },\n\t\t\tsidebar: { sections: [] },\n\t\t\tbranding: {},\n\t\t\tlocale: DEFAULT_LOCALE_CONFIG,\n\t\t\tdefaultViews: {},\n\t\t\ttranslations: {},\n\t\t});\n\t}\n\n\t/**\n\t * Register field definitions\n\t */\n\tfields<TNewFields extends Record<string, any>>(\n\t\tfields: TNewFields,\n\t): AdminBuilder<\n\t\tOmit<TState, \"fields\"> & {\n\t\t\tfields: TState[\"fields\"] & TNewFields;\n\t\t}\n\t> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tfields: {\n\t\t\t\t...this.state.fields,\n\t\t\t\t...fields,\n\t\t\t},\n\t\t} as any);\n\t}\n\n\t/**\n\t * Register view definitions (auto-sorted by kind)\n\t */\n\tviews<TNewViews extends Record<string, any>>(\n\t\tviews: TNewViews,\n\t): AdminBuilder<\n\t\tOmit<TState, \"listViews\" | \"editViews\"> & {\n\t\t\tlistViews: TState[\"listViews\"] & FilterListViews<TNewViews>;\n\t\t\teditViews: TState[\"editViews\"] & FilterEditViews<TNewViews>;\n\t\t}\n\t> {\n\t\tconst listViews: Record<string, any> = {};\n\t\tconst editViews: Record<string, any> = {};\n\n\t\tfor (const [name, def] of Object.entries(views)) {\n\t\t\t// ViewBuilders now implement Definition interface, so kind is directly accessible\n\t\t\tconst kind = (def as any).kind;\n\t\t\tif (kind === \"list\") {\n\t\t\t\tlistViews[name] = def;\n\t\t\t} else if (kind === \"edit\") {\n\t\t\t\teditViews[name] = def;\n\t\t\t}\n\t\t}\n\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tlistViews: { ...this.state.listViews, ...listViews },\n\t\t\teditViews: { ...this.state.editViews, ...editViews },\n\t\t} as any);\n\t}\n\n\t/**\n\t * Register widget definitions\n\t */\n\twidgets<TNewWidgets extends Record<string, any>>(\n\t\twidgets: TNewWidgets,\n\t): AdminBuilder<\n\t\tOmit<TState, \"widgets\"> & {\n\t\t\twidgets: TState[\"widgets\"] & TNewWidgets;\n\t\t}\n\t> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\twidgets: {\n\t\t\t\t...this.state.widgets,\n\t\t\t\t...widgets,\n\t\t\t},\n\t\t} as any);\n\t}\n\n\t/**\n\t * Register page definitions\n\t */\n\tpages<TNewPages extends Record<string, any>>(\n\t\tpages: TNewPages,\n\t): AdminBuilder<\n\t\tOmit<TState, \"pages\"> & {\n\t\t\tpages: TState[\"pages\"] & TNewPages;\n\t\t}\n\t> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tpages: {\n\t\t\t\t...this.state.pages,\n\t\t\t\t...pages,\n\t\t\t},\n\t\t} as any);\n\t}\n\n\t/**\n\t * Register block definitions for the visual page builder.\n\t *\n\t * Blocks are UI-only concepts - the server stores them as JSONB with $i18n markers.\n\t * Each block has a name, fields, and a renderer component.\n\t *\n\t * @example\n\t * ```ts\n\t * const builder = qa<AppCMS>().use(adminModule);\n\t * const heroBlock = builder.block(\"hero\")\n\t * .label({ en: \"Hero Section\" })\n\t * .icon(\"Image\")\n\t * .category(\"sections\")\n\t * .fields(({ r }) => ({\n\t * title: r.text({ label: \"Title\", localized: true }),\n\t * }))\n\t * .renderer(HeroRenderer)\n\t * .build();\n\t *\n\t * const admin = builder\n\t * .blocks({ hero: heroBlock })\n\t * .sidebar({ ... });\n\t * ```\n\t */\n\tblocks<TNewBlocks extends Record<string, any>>(\n\t\tblocks: TNewBlocks,\n\t): AdminBuilder<\n\t\tOmit<TState, \"blocks\"> & {\n\t\t\tblocks: TState[\"blocks\"] & TNewBlocks;\n\t\t}\n\t> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tblocks: {\n\t\t\t\t...this.state.blocks,\n\t\t\t\t...blocks,\n\t\t\t},\n\t\t} as any);\n\t}\n\n\t/**\n\t * Register translations for i18n\n\t *\n\t * Merges new translations with existing translations from modules.\n\t *\n\t * @example\n\t * ```ts\n\t * // Add translations for multiple locales\n\t * .translations({\n\t * en: { \"myModule.label\": \"My Label\" },\n\t * sk: { \"myModule.label\": \"Moj Label\" },\n\t * })\n\t * ```\n\t */\n\ttranslations<TNewTranslations extends TranslationsMap>(\n\t\ttranslations: TNewTranslations,\n\t): AdminBuilder<\n\t\tOmit<TState, \"translations\"> & {\n\t\t\ttranslations: TState[\"translations\"] & TNewTranslations;\n\t\t}\n\t> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\ttranslations: mergeTranslations(\n\t\t\t\tthis.state.translations as TranslationsMap,\n\t\t\t\ttranslations,\n\t\t\t),\n\t\t} as any);\n\t}\n\n\t/**\n\t * Add translated messages for admin UI (simple API)\n\t *\n\t * Messages are merged with default admin messages.\n\t * Custom messages override defaults with same key.\n\t * This is an alias for .translations() with simpler naming.\n\t *\n\t * @example\n\t * ```ts\n\t * const customMessages = {\n\t * en: {\n\t * \"myApp.welcome\": \"Welcome to Barbershop Admin\",\n\t * \"myApp.bookNow\": \"Book Now\",\n\t * },\n\t * sk: {\n\t * \"myApp.welcome\": \"Vitajte v Barbershop Admin\",\n\t * \"myApp.bookNow\": \"Rezervovať\",\n\t * // Override default admin message\n\t * \"common.save\": \"Uložiť\",\n\t * },\n\t * } as const;\n\t *\n\t * const admin = qa<AppCMS>()\n\t * .use(coreAdminModule)\n\t * .messages(customMessages)\n\t * .sidebar({ ... });\n\t *\n\t * // In components, t() has full autocomplete\n\t * ```\n\t */\n\tmessages<TNewMessages extends TranslationsMap>(\n\t\tmessages: TNewMessages,\n\t): AdminBuilder<\n\t\tOmit<TState, \"translations\"> & {\n\t\t\ttranslations: TState[\"translations\"] & TNewMessages;\n\t\t}\n\t> {\n\t\treturn this.translations(messages);\n\t}\n\n\t/**\n\t * Compose another builder (merge modules)\n\t */\n\tuse<TOther extends AdminBuilder<any>>(\n\t\tother: TOther,\n\t): AdminBuilder<\n\t\tOmit<\n\t\t\tTState,\n\t\t\t| \"fields\"\n\t\t\t| \"listViews\"\n\t\t\t| \"editViews\"\n\t\t\t| \"widgets\"\n\t\t\t| \"pages\"\n\t\t\t| \"blocks\"\n\t\t\t| \"collections\"\n\t\t\t| \"globals\"\n\t\t\t| \"sidebar\"\n\t\t\t| \"translations\"\n\t\t> & {\n\t\t\tfields: TState[\"fields\"] & TOther[\"state\"][\"fields\"];\n\t\t\tlistViews: TState[\"listViews\"] & TOther[\"state\"][\"listViews\"];\n\t\t\teditViews: TState[\"editViews\"] & TOther[\"state\"][\"editViews\"];\n\t\t\twidgets: TState[\"widgets\"] & TOther[\"state\"][\"widgets\"];\n\t\t\tpages: TState[\"pages\"] & TOther[\"state\"][\"pages\"];\n\t\t\tblocks: TState[\"blocks\"] & TOther[\"state\"][\"blocks\"];\n\t\t\tcollections: TState[\"collections\"] & TOther[\"state\"][\"collections\"];\n\t\t\tglobals: TState[\"globals\"] & TOther[\"state\"][\"globals\"];\n\t\t\tsidebar: TOther[\"state\"][\"sidebar\"] extends { sections: any[] }\n\t\t\t\t? {\n\t\t\t\t\t\tsections: [\n\t\t\t\t\t\t\t...(TState[\"sidebar\"] extends { sections: infer S }\n\t\t\t\t\t\t\t\t? S extends any[]\n\t\t\t\t\t\t\t\t\t? S\n\t\t\t\t\t\t\t\t\t: []\n\t\t\t\t\t\t\t\t: []),\n\t\t\t\t\t\t\t...(TOther[\"state\"][\"sidebar\"] extends { sections: infer S }\n\t\t\t\t\t\t\t\t? S extends any[]\n\t\t\t\t\t\t\t\t\t? S\n\t\t\t\t\t\t\t\t\t: []\n\t\t\t\t\t\t\t\t: []),\n\t\t\t\t\t\t];\n\t\t\t\t\t}\n\t\t\t\t: TState[\"sidebar\"];\n\t\t\ttranslations: TState[\"translations\"] & TOther[\"state\"][\"translations\"];\n\t\t}\n\t> {\n\t\tconst otherState = (other as any).state;\n\n\t\t// Merge sidebar sections\n\t\tconst currentSections = (this.state.sidebar as any)?.sections ?? [];\n\t\tconst otherSections = otherState.sidebar?.sections ?? [];\n\t\tconst mergedSidebar = {\n\t\t\t...this.state.sidebar,\n\t\t\t...otherState.sidebar,\n\t\t\tsections: [...currentSections, ...otherSections],\n\t\t};\n\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tfields: { ...this.state.fields, ...otherState.fields },\n\t\t\tlistViews: { ...this.state.listViews, ...otherState.listViews },\n\t\t\teditViews: { ...this.state.editViews, ...otherState.editViews },\n\t\t\twidgets: { ...this.state.widgets, ...otherState.widgets },\n\t\t\tpages: { ...this.state.pages, ...otherState.pages },\n\t\t\tblocks: { ...this.state.blocks, ...otherState.blocks },\n\t\t\tcollections: { ...this.state.collections, ...otherState.collections },\n\t\t\tglobals: { ...this.state.globals, ...otherState.globals },\n\t\t\tsidebar: mergedSidebar,\n\t\t\ttranslations: mergeTranslations(\n\t\t\t\tthis.state.translations as TranslationsMap,\n\t\t\t\totherState.translations,\n\t\t\t),\n\t\t} as any);\n\t}\n\n\t/**\n\t * Register collection configs\n\t */\n\tcollections<TNewCollections extends Record<string, any>>(\n\t\tcollections: TNewCollections,\n\t): AdminBuilder<\n\t\tOmit<TState, \"collections\"> & {\n\t\t\tcollections: TState[\"collections\"] & TNewCollections;\n\t\t}\n\t> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tcollections: {\n\t\t\t\t...this.state.collections,\n\t\t\t\t...collections,\n\t\t\t},\n\t\t} as any);\n\t}\n\n\t/**\n\t * Register global configs\n\t */\n\tglobals<TNewGlobals extends Record<string, any>>(\n\t\tglobals: TNewGlobals,\n\t): AdminBuilder<\n\t\tOmit<TState, \"globals\"> & {\n\t\t\tglobals: TState[\"globals\"] & TNewGlobals;\n\t\t}\n\t> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tglobals: {\n\t\t\t\t...this.state.globals,\n\t\t\t\t...globals,\n\t\t\t},\n\t\t} as any);\n\t}\n\n\t/**\n\t * Set dashboard config\n\t */\n\tdashboard(config: any): AdminBuilder<TState> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tdashboard: config,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Set sidebar config\n\t *\n\t * Merges new sections with existing sections from modules.\n\t * Sections with the same ID will be replaced, new sections are appended.\n\t * Accepts either a SidebarConfig object or a SidebarBuilder.\n\t *\n\t * @example\n\t * ```ts\n\t * // Using config object - merges with existing sections\n\t * .sidebar({ sections: [...] })\n\t *\n\t * // Using builder - merges with existing sections\n\t * .sidebar(\n\t * qa.sidebar()\n\t * .section(\"content\", s => s.title(\"Content\").items([...]))\n\t * )\n\t * ```\n\t */\n\tsidebar<TSectionIds extends string>(\n\t\tconfig: SidebarConfig<TSectionIds> | SidebarBuilder<TSectionIds>,\n\t): AdminBuilder<\n\t\tOmit<TState, \"sidebar\"> & {\n\t\t\tsidebar: SidebarConfig<\n\t\t\t\t| (TState[\"sidebar\"] extends SidebarConfig<infer TIds> ? TIds : never)\n\t\t\t\t| TSectionIds\n\t\t\t>;\n\t\t}\n\t> {\n\t\tconst newSidebarConfig =\n\t\t\tconfig instanceof SidebarBuilder ? config.build() : config;\n\n\t\t// Merge sections: existing sections + new sections (new replaces existing with same id)\n\t\tconst currentSections =\n\t\t\t(this.state.sidebar as SidebarConfig<string>)?.sections ?? [];\n\t\tconst newSections = newSidebarConfig.sections ?? [];\n\n\t\t// Build a map of new sections by id for quick lookup\n\t\tconst newSectionsMap = new Map<string, (typeof newSections)[number]>(\n\t\t\tnewSections.map((section) => [section.id, section]),\n\t\t);\n\n\t\t// Keep existing sections that are not being replaced\n\t\tconst mergedSections = currentSections.filter(\n\t\t\t(section) => !newSectionsMap.has(section.id as string),\n\t\t);\n\n\t\t// Append all new sections\n\t\tmergedSections.push(...newSections);\n\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tsidebar: { ...newSidebarConfig, sections: mergedSections },\n\t\t} as any);\n\t}\n\n\t/**\n\t * Extend existing sidebar configuration\n\t *\n\t * Allows modifying the current sidebar by extending sections,\n\t * adding new sections, or reordering.\n\t *\n\t * @example\n\t * ```ts\n\t * // After using a module with sidebar\n\t * .use(coreAdminModule)\n\t * .extendSidebar(s => s\n\t * // Add section at the beginning\n\t * .prepend(\"dashboard\", sec => sec\n\t * .title(\"Dashboard\")\n\t * .items([{ type: \"link\", label: \"Home\", href: \"/\" }])\n\t * )\n\t * // Extend existing section from coreModule\n\t * .extend(\"content\", sec => sec\n\t * .addItems([{ type: \"collection\", collection: \"posts\" }])\n\t * )\n\t * // Add section at the end\n\t * .append(\"settings\", sec => sec\n\t * .title(\"Settings\")\n\t * .items([{ type: \"global\", global: \"siteSettings\" }])\n\t * )\n\t * )\n\t * ```\n\t */\n\textendSidebar<TNewSectionIds extends string>(\n\t\tconfigure: (\n\t\t\tbuilder: SidebarBuilder<\n\t\t\t\tTState[\"sidebar\"] extends SidebarConfig<infer TIds> ? TIds : never\n\t\t\t>,\n\t\t) => SidebarBuilder<TNewSectionIds>,\n\t): AdminBuilder<\n\t\tOmit<TState, \"sidebar\"> & {\n\t\t\tsidebar: SidebarConfig<\n\t\t\t\t| (TState[\"sidebar\"] extends SidebarConfig<infer TIds> ? TIds : never)\n\t\t\t\t| TNewSectionIds\n\t\t\t>;\n\t\t}\n\t> {\n\t\tconst currentSidebar = this.state.sidebar as SidebarConfig<string>;\n\t\tconst builder = SidebarBuilder.from(currentSidebar);\n\t\tconst configured = configure(builder as any);\n\t\tconst newSidebar = configured.build();\n\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tsidebar: newSidebar,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Set branding config\n\t */\n\tbranding(config: any): AdminBuilder<TState> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tbranding: config,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Set locale config\n\t */\n\tlocale(config: any): AdminBuilder<TState> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tlocale: { ...this.state.locale, ...config },\n\t\t} as any);\n\t}\n\n\t/**\n\t * Set default views config\n\t */\n\tdefaultViews<TDefaultViews extends DefaultViewsConfig>(\n\t\tconfig: TDefaultViews,\n\t): AdminBuilder<\n\t\tOmit<TState, \"defaultViews\"> & {\n\t\t\tdefaultViews: TState[\"defaultViews\"] & TDefaultViews;\n\t\t}\n\t> {\n\t\treturn new AdminBuilder({\n\t\t\t...this.state,\n\t\t\tdefaultViews: {\n\t\t\t\t...(this.state.defaultViews || {}),\n\t\t\t\t...config,\n\t\t\t},\n\t\t} as any);\n\t}\n\n\t// ============================================================================\n\t// Entity Creation Methods\n\t// ============================================================================\n\n\t/**\n\t * Create a collection builder bound to this admin\n\t *\n\t * Creates a CollectionBuilder with full access to registered fields,\n\t * views, and backend type inference.\n\t *\n\t * @example\n\t * ```ts\n\t * const builder = qa<AppCMS>().use(adminModule);\n\t *\n\t * const barbers = builder.collection(\"barbers\")\n\t * .fields(({ r }) => ({\n\t * name: r.text(), // ✅ autocomplete from module fields\n\t * }))\n\t * ```\n\t */\n\tcollection<TName extends string, TSelf extends AdminBuilder<TState>>(\n\t\tthis: TSelf,\n\t\tname: TName,\n\t): CollectionBuilder<{\n\t\tname: TName;\n\t\t\"~adminApp\": TSelf;\n\t}> {\n\t\treturn collection(name).use(this) as any;\n\t}\n\n\t/**\n\t * Create a block builder bound to this admin\n\t *\n\t * This gives block field definitions access to the admin field registry\n\t * defined by the builder chain.\n\t *\n\t * @example\n\t * ```ts\n\t * const builder = qa<AppCMS>().use(adminModule);\n\t *\n\t * const heroBlock = builder.block(\"hero\")\n\t * .fields(({ r }) => ({\n\t * title: r.text({ label: \"Title\" }),\n\t * }))\n\t * .renderer(HeroRenderer)\n\t * .build();\n\t * ```\n\t */\n\tblock<TName extends string, TSelf extends AdminBuilder<TState>>(\n\t\tthis: TSelf,\n\t\tname: TName,\n\t): BlockBuilder<{\n\t\tname: TName;\n\t\t\"~adminApp\": TSelf;\n\t}> {\n\t\treturn block(name).use(this) as any;\n\t}\n\n\t/**\n\t * Create a global builder bound to this admin\n\t *\n\t * Creates a GlobalBuilder with full access to registered fields,\n\t * views, and backend type inference.\n\t *\n\t * @example\n\t * ```ts\n\t * const builder = qa<AppCMS>().use(adminModule);\n\t *\n\t * const settings = builder.global(\"settings\")\n\t * .fields(({ r }) => ({\n\t * siteName: r.text(), // ✅ autocomplete from module fields\n\t * }))\n\t * ```\n\t */\n\tglobal<TName extends string, TSelf extends AdminBuilder<TState>>(\n\t\tthis: TSelf,\n\t\tname: TName,\n\t): GlobalBuilder<{\n\t\tname: TName;\n\t\t\"~adminApp\": TSelf;\n\t}> {\n\t\treturn global(name).use(this) as any;\n\t}\n\n\t/**\n\t * Create a page definition\n\t *\n\t * Creates a custom admin page outside of collections/globals.\n\t *\n\t * @example\n\t * ```ts\n\t * const builder = qa<AppCMS>().use(adminModule);\n\t *\n\t * const analyticsPage = builder.page(\"analytics\", {\n\t * component: AnalyticsPage,\n\t * })\n\t * ```\n\t */\n\tpage<TName extends string, TComponent extends MaybeLazyComponent>(\n\t\tname: TName,\n\t\tconfig: { component: TComponent },\n\t): PageBuilder<{\n\t\tname: TName;\n\t\tcomponent: TComponent;\n\t\tpath: undefined;\n\t}> {\n\t\treturn page(name, config);\n\t}\n\n\t/**\n\t * Create a widget definition\n\t *\n\t * Creates a dashboard widget.\n\t *\n\t * @example\n\t * ```ts\n\t * const builder = qa<AppCMS>().use(adminModule);\n\t *\n\t * const statsWidget = builder.widget(\"stats\", {\n\t * component: StatsWidget,\n\t * })\n\t * ```\n\t */\n\twidget<TName extends string, TComponent extends MaybeLazyComponent>(\n\t\tname: TName,\n\t\tconfig: { component: TComponent },\n\t): WidgetBuilder<{\n\t\tname: TName;\n\t\t\"~config\": any;\n\t\tcomponent: TComponent;\n\t}> {\n\t\treturn widget(name, config);\n\t}\n}\n","\"use client\";\n\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\";\nimport { CaretDownIcon, CaretUpIcon, CheckIcon } from \"@phosphor-icons/react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\n\nconst Select = SelectPrimitive.Root;\n\nfunction SelectGroup({ className, ...props }: SelectPrimitive.Group.Props) {\n return (\n <SelectPrimitive.Group\n data-slot=\"select-group\"\n className={cn(\"scroll-my-1 p-1\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {\n return (\n <SelectPrimitive.Value\n data-slot=\"select-value\"\n className={cn(\"flex flex-1 text-left\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectTrigger({\n className,\n size = \"default\",\n children,\n ...props\n}: SelectPrimitive.Trigger.Props & {\n size?: \"sm\" | \"default\";\n}) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"border-input/80 data-[placeholder]:text-muted-foreground bg-input/20 backdrop-blur-sm focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-2 border px-3 py-2 text-sm transition-all focus-visible:ring-[2px] aria-invalid:ring-[2px] data-[size=default]:h-9 data-[size=sm]:h-7 data-[size=sm]:px-2.5 data-[size=sm]:text-xs *:data-[slot=select-value]:flex *:data-[slot=select-value]:gap-2 [&_svg:not([class*='size-'])]:size-4 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon\n render={\n <CaretDownIcon className=\"text-muted-foreground size-4 pointer-events-none\" />\n }\n />\n </SelectPrimitive.Trigger>\n );\n}\n\nfunction SelectContent({\n className,\n children,\n side = \"bottom\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 0,\n alignItemWithTrigger = true,\n ...props\n}: SelectPrimitive.Popup.Props &\n Pick<\n SelectPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\" | \"alignItemWithTrigger\"\n >) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Positioner\n side={side}\n sideOffset={sideOffset}\n align={align}\n alignOffset={alignOffset}\n alignItemWithTrigger={alignItemWithTrigger}\n className=\"isolate z-50\"\n >\n <SelectPrimitive.Popup\n data-slot=\"select-content\"\n className={cn(\n \"bg-popover/20 backdrop-blur-xl text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border border-border/60 min-w-32 shadow-lg duration-100 relative isolate z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto\",\n className,\n )}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.List>{children}</SelectPrimitive.List>\n <SelectScrollDownButton />\n </SelectPrimitive.Popup>\n </SelectPrimitive.Positioner>\n </SelectPrimitive.Portal>\n );\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: SelectPrimitive.GroupLabel.Props) {\n return (\n <SelectPrimitive.GroupLabel\n data-slot=\"select-label\"\n className={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: SelectPrimitive.Item.Props) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-9 gap-2 px-3 py-2 text-sm [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n >\n <SelectPrimitive.ItemText className=\"flex flex-1 gap-2 shrink-0 whitespace-nowrap\">\n {children}\n </SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator\n render={\n <span className=\"pointer-events-none absolute right-3 flex items-center justify-center\" />\n }\n >\n <CheckIcon className=\"pointer-events-none\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n );\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: SelectPrimitive.Separator.Props) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\n \"bg-border/50 -mx-1 my-1 h-px pointer-events-none\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>) {\n return (\n <SelectPrimitive.ScrollUpArrow\n data-slot=\"select-scroll-up-button\"\n className={cn(\n \"bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-3.5 top-0 w-full\",\n className,\n )}\n {...props}\n >\n <CaretUpIcon />\n </SelectPrimitive.ScrollUpArrow>\n );\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>) {\n return (\n <SelectPrimitive.ScrollDownArrow\n data-slot=\"select-scroll-down-button\"\n className={cn(\n \"bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-3.5 bottom-0 w-full\",\n className,\n )}\n {...props}\n >\n <CaretDownIcon />\n </SelectPrimitive.ScrollDownArrow>\n );\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n","import type * as React from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\nfunction Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n \"border-input/80 bg-input/20 backdrop-blur-sm focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 resize-none border px-3 py-2.5 text-sm transition-all focus-visible:ring-[2px] aria-invalid:ring-[2px] placeholder:text-muted-foreground flex field-sizing-content min-h-24 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Textarea };\n","import * as React from \"react\";\nimport { Badge } from \"../ui/badge\";\n\ntype LocaleBadgeProps = {\n locale?: string;\n};\n\nexport function LocaleBadge({ locale }: LocaleBadgeProps) {\n if (!locale) return null;\n return (\n <Badge variant=\"secondary\" className=\"uppercase text-[10px] tracking-wide\">\n {locale}\n </Badge>\n );\n}\n","import { Checkbox as CheckboxPrimitive } from \"@base-ui/react/checkbox\";\nimport { CheckIcon, MinusIcon } from \"@phosphor-icons/react\";\nimport { cn } from \"../../lib/utils\";\n\nfunction Checkbox({\n\tclassName,\n\tindeterminate,\n\t...props\n}: CheckboxPrimitive.Root.Props & { indeterminate?: boolean }) {\n\t// Determine which icon to show based on state\n\tconst showIndeterminate = indeterminate && !props.checked;\n\n\treturn (\n\t\t<CheckboxPrimitive.Root\n\t\t\tdata-slot=\"checkbox\"\n\t\t\tindeterminate={indeterminate}\n\t\t\tclassName={cn(\n\t\t\t\t\"border-input data-checked:bg-primary data-checked:text-primary-foreground data-indeterminate:bg-primary data-indeterminate:text-primary-foreground dark:data-checked:bg-primary dark:data-indeterminate:bg-primary data-checked:border-primary data-indeterminate:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center border transition-shadow group-has-disabled/field:opacity-50 focus-visible:ring-[2px] aria-invalid:ring-[2px] peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{/* Indicator for checked state */}\n\t\t\t<CheckboxPrimitive.Indicator\n\t\t\t\tdata-slot=\"checkbox-indicator\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"[&>svg]:size-3.5 grid place-content-center text-current transition-none\",\n\t\t\t\t\tshowIndeterminate && \"hidden\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<CheckIcon weight=\"bold\" />\n\t\t\t</CheckboxPrimitive.Indicator>\n\t\t\t{/* Manual indicator for indeterminate state */}\n\t\t\t{showIndeterminate && (\n\t\t\t\t<span className=\"[&>svg]:size-3.5 grid place-content-center text-current\">\n\t\t\t\t\t<MinusIcon weight=\"bold\" />\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</CheckboxPrimitive.Root>\n\t);\n}\n\nexport { Checkbox };\n","\"use client\";\n\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { Checkbox } from \"../ui/checkbox\";\nimport type {\n\tCheckboxGroupProps,\n\tCheckboxInputProps,\n\tRadioGroupProps,\n} from \"./types\";\n\n/**\n * Checkbox Input Primitive\n *\n * A single checkbox with value/onChange pattern.\n *\n * @example\n * ```tsx\n * <CheckboxInput\n * value={isAccepted}\n * onChange={setIsAccepted}\n * />\n * ```\n */\nexport function CheckboxInput({\n\tvalue,\n\tonChange,\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: CheckboxInputProps) {\n\treturn (\n\t\t<Checkbox\n\t\t\tid={id}\n\t\t\tchecked={value}\n\t\t\tonCheckedChange={(checked) => onChange(checked === true)}\n\t\t\tdisabled={disabled}\n\t\t\taria-invalid={ariaInvalid}\n\t\t\tclassName={className}\n\t\t/>\n\t);\n}\n\n/**\n * Checkbox Group Primitive\n *\n * A group of checkboxes for multi-selection.\n * Returns an array of selected values.\n *\n * @example\n * ```tsx\n * <CheckboxGroup\n * value={selectedCategories}\n * onChange={setSelectedCategories}\n * options={[\n * { value: \"news\", label: \"News\" },\n * { value: \"blog\", label: \"Blog\" },\n * { value: \"tutorial\", label: \"Tutorial\" },\n * ]}\n * orientation=\"vertical\"\n * />\n * ```\n */\nexport function CheckboxGroup<TValue extends string = string>({\n\tvalue,\n\tonChange,\n\toptions,\n\torientation = \"vertical\",\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: CheckboxGroupProps<TValue>) {\n\tconst resolveText = useResolveText();\n\tconst handleChange = (optionValue: TValue, checked: boolean) => {\n\t\tif (checked) {\n\t\t\tonChange([...value, optionValue]);\n\t\t} else {\n\t\t\tonChange(value.filter((v) => v !== optionValue));\n\t\t}\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tid={id}\n\t\t\trole=\"group\"\n\t\t\taria-invalid={ariaInvalid}\n\t\t\tclassName={cn(\n\t\t\t\t\"flex gap-3\",\n\t\t\t\torientation === \"vertical\" ? \"flex-col\" : \"flex-row flex-wrap\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{options.map((option) => {\n\t\t\t\tconst optionId = `${id}-${String(option.value)}`;\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tkey={String(option.value)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"flex items-center gap-2\",\n\t\t\t\t\t\t\toption.disabled || disabled\n\t\t\t\t\t\t\t\t? \"opacity-50 cursor-not-allowed\"\n\t\t\t\t\t\t\t\t: \"cursor-pointer\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<CheckboxInput\n\t\t\t\t\t\t\tid={optionId}\n\t\t\t\t\t\t\tvalue={value.includes(option.value)}\n\t\t\t\t\t\t\tonChange={(checked) => handleChange(option.value, checked)}\n\t\t\t\t\t\t\tdisabled={option.disabled || disabled}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<label htmlFor={optionId} className=\"text-sm cursor-pointer\">\n\t\t\t\t\t\t\t{resolveText(option.label)}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t})}\n\t\t</div>\n\t);\n}\n\n/**\n * Radio Group Primitive\n *\n * A group of radio buttons for single selection.\n * Returns the selected value or null.\n *\n * @example\n * ```tsx\n * <RadioGroup\n * value={selectedPriority}\n * onChange={setSelectedPriority}\n * options={[\n * { value: \"low\", label: \"Low\" },\n * { value: \"medium\", label: \"Medium\" },\n * { value: \"high\", label: \"High\" },\n * ]}\n * />\n * ```\n */\nexport function RadioGroup<TValue extends string = string>({\n\tvalue,\n\tonChange,\n\toptions,\n\torientation = \"vertical\",\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: RadioGroupProps<TValue>) {\n\tconst resolveText = useResolveText();\n\treturn (\n\t\t<div\n\t\t\tid={id}\n\t\t\trole=\"radiogroup\"\n\t\t\taria-invalid={ariaInvalid}\n\t\t\tclassName={cn(\n\t\t\t\t\"flex gap-3\",\n\t\t\t\torientation === \"vertical\" ? \"flex-col\" : \"flex-row flex-wrap\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{options.map((option) => {\n\t\t\t\tconst optionId = `${id}-${String(option.value)}`;\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tkey={String(option.value)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"flex items-center gap-2\",\n\t\t\t\t\t\t\toption.disabled || disabled\n\t\t\t\t\t\t\t\t? \"opacity-50 cursor-not-allowed\"\n\t\t\t\t\t\t\t\t: \"cursor-pointer\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\tid={optionId}\n\t\t\t\t\t\t\tname={id}\n\t\t\t\t\t\t\tchecked={value === option.value}\n\t\t\t\t\t\t\tonChange={() => onChange(option.value)}\n\t\t\t\t\t\t\tdisabled={option.disabled || disabled}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"size-4 shrink-0 accent-primary\",\n\t\t\t\t\t\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<label htmlFor={optionId} className=\"text-sm cursor-pointer\">\n\t\t\t\t\t\t\t{resolveText(option.label)}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t})}\n\t\t</div>\n\t);\n}\n","import { type Control, useFormContext } from \"react-hook-form\";\n\nexport function useResolvedControl(control?: Control<any>) {\n\tconst form = useFormContext();\n\treturn control ?? form.control;\n}\n\n/**\n * Sanitize filename for safe storage.\n * Removes special characters, replaces spaces with hyphens.\n */\nexport function sanitizeFilename(filename: string): string {\n\t// Get extension\n\tconst lastDot = filename.lastIndexOf(\".\");\n\tconst ext = lastDot > 0 ? filename.slice(lastDot) : \"\";\n\tconst name = lastDot > 0 ? filename.slice(0, lastDot) : filename;\n\n\t// Normalize unicode, remove diacritics, replace spaces, remove invalid chars\n\tconst sanitized = name\n\t\t.normalize(\"NFD\")\n\t\t.replace(/[\\u0300-\\u036f]/g, \"\") // Remove diacritics\n\t\t.replace(/\\s+/g, \"-\") // Replace spaces with hyphens\n\t\t.replace(/[^a-zA-Z0-9._-]/g, \"\") // Remove invalid chars\n\t\t.replace(/-+/g, \"-\") // Collapse multiple hyphens\n\t\t.replace(/^-|-$/g, \"\") // Remove leading/trailing hyphens\n\t\t.toLowerCase();\n\n\treturn (sanitized || \"file\") + ext.toLowerCase();\n}\n\n/**\n * Extract columns from collection list config.\n * Used by relation fields to auto-detect display columns.\n */\nexport function getAutoColumns(collectionConfig: any): string[] {\n\tif (!collectionConfig?.list?.columns) return [\"_title\"];\n\n\t// List columns can be field references (f.fieldName) or strings\n\tconst columns = collectionConfig.list.columns;\n\tif (Array.isArray(columns)) {\n\t\treturn columns\n\t\t\t.map((col: any) => {\n\t\t\t\t// Handle field proxy objects\n\t\t\t\tif (col && typeof col === \"object\" && col[\"~fieldName\"]) {\n\t\t\t\t\treturn col[\"~fieldName\"];\n\t\t\t\t}\n\t\t\t\t// Handle string field names\n\t\t\t\tif (typeof col === \"string\") {\n\t\t\t\t\treturn col;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t})\n\t\t\t.filter(Boolean)\n\t\t\t.slice(0, 4); // Limit to 4 columns for relation display\n\t}\n\n\treturn [\"_title\"];\n}\n\n/**\n * Grid column classes for responsive layouts.\n * Uses standard responsive breakpoints (sm:, lg:, etc.)\n */\nexport const gridColumnClasses: Record<number, string> = {\n\t1: \"grid-cols-1\",\n\t2: \"grid-cols-1 sm:grid-cols-2\",\n\t3: \"grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\",\n\t4: \"grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4\",\n};\n\n/**\n * Grid column classes using container queries.\n * Parent must have @container class for these to work.\n */\nexport const containerGridColumnClasses: Record<number, string> = {\n\t1: \"grid-cols-1\",\n\t2: \"grid-cols-1 @sm:grid-cols-2\",\n\t3: \"grid-cols-1 @sm:grid-cols-2 @lg:grid-cols-3\",\n\t4: \"grid-cols-1 @sm:grid-cols-2 @md:grid-cols-3 @xl:grid-cols-4\",\n\t5: \"grid-cols-1 @xs:grid-cols-2 @sm:grid-cols-3 @lg:grid-cols-4 @xl:grid-cols-5\",\n\t6: \"grid-cols-1 @xs:grid-cols-2 @sm:grid-cols-3 @md:grid-cols-4 @lg:grid-cols-5 @xl:grid-cols-6\",\n};\n\n/**\n * Get grid columns class for a given column count.\n * @param columns Number of columns\n * @param useContainerQueries Use container query classes instead of viewport breakpoints\n */\nexport function getGridColumnsClass(\n\tcolumns?: number,\n\tuseContainerQueries = false,\n): string {\n\tif (!columns) return \"\";\n\tconst classes = useContainerQueries\n\t\t? containerGridColumnClasses\n\t\t: gridColumnClasses;\n\treturn classes[columns] || \"\";\n}\n","/**\n * Locale to Flag Utility\n *\n * Converts locale codes to country codes for flag display.\n * Uses flagcdn.com for PNG flags via CDN (no dependencies).\n *\n * ## Features\n *\n * - **Smart mapping**: Automatically maps locale codes to country codes (sk → SK, en → GB, en-US → US)\n * - **Custom overrides**: Support for custom country codes via `flagCountryCode` in locale config\n * - **Lightweight**: No dependencies, uses CDN for flags\n * - **Fallback support**: Gracefully handles unknown locale codes\n *\n * ## Usage\n *\n * ### Basic Usage\n *\n * ```tsx\n * import { getFlagUrl } from \"@questpie/admin/client\";\n *\n * function LocaleBadge({ locale }: { locale: string }) {\n * return (\n * <div>\n * <img src={getFlagUrl(locale, 20)} alt={locale} />\n * {locale}\n * </div>\n * );\n * }\n * ```\n *\n * ### Custom Country Code Mapping\n *\n * If the default mapping doesn't fit your needs, you can provide custom mapping:\n *\n * ```tsx\n * // Show US flag for English instead of UK\n * const flagUrl = getFlagUrl(\"en\", 20, { en: \"us\" });\n * ```\n *\n * ### In CMS Configuration\n *\n * The best way to customize flag mapping is in your CMS locale config:\n *\n * ```ts\n * // questpie/server/cms.ts\n * q().locale({\n * locales: [\n * {\n * code: \"en\",\n * label: \"English\",\n * flagCountryCode: \"us\", // Show US flag instead of UK\n * },\n * { code: \"sk\", label: \"Slovenčina\" },\n * ],\n * defaultLocale: \"en\",\n * })\n * ```\n *\n * The `flagCountryCode` will be automatically used by `LocaleSwitcher` and other locale UI components.\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FlagConfig {\n\t/** Country code (ISO 3166-1 alpha-2) */\n\tcountryCode: string;\n\t/** Alt text for accessibility */\n\talt: string;\n}\n\n// ============================================================================\n// Locale to Country Code Mapping\n// ============================================================================\n\n/**\n * Maps locale codes to country codes.\n * Handles both simple codes (en, sk) and region-specific (en-US, en-GB).\n */\nconst LOCALE_TO_COUNTRY: Record<string, string> = {\n\t// English variants\n\ten: \"gb\", // Default English → Great Britain\n\t\"en-US\": \"us\",\n\t\"en-GB\": \"gb\",\n\t\"en-CA\": \"ca\",\n\t\"en-AU\": \"au\",\n\t\"en-NZ\": \"nz\",\n\t\"en-IE\": \"ie\",\n\n\t// European languages\n\tsk: \"sk\", // Slovak\n\tcs: \"cz\", // Czech\n\tde: \"de\", // German\n\t\"de-AT\": \"at\",\n\t\"de-CH\": \"ch\",\n\tfr: \"fr\", // French\n\t\"fr-CA\": \"ca\",\n\t\"fr-CH\": \"ch\",\n\tes: \"es\", // Spanish\n\t\"es-MX\": \"mx\",\n\t\"es-AR\": \"ar\",\n\tit: \"it\", // Italian\n\tpt: \"pt\", // Portuguese\n\t\"pt-BR\": \"br\",\n\tnl: \"nl\", // Dutch\n\tpl: \"pl\", // Polish\n\tru: \"ru\", // Russian\n\tuk: \"ua\", // Ukrainian\n\ttr: \"tr\", // Turkish\n\tsv: \"se\", // Swedish\n\tno: \"no\", // Norwegian\n\tda: \"dk\", // Danish\n\tfi: \"fi\", // Finnish\n\thu: \"hu\", // Hungarian\n\tro: \"ro\", // Romanian\n\tbg: \"bg\", // Bulgarian\n\thr: \"hr\", // Croatian\n\tsr: \"rs\", // Serbian\n\tsl: \"si\", // Slovenian\n\tet: \"ee\", // Estonian\n\tlv: \"lv\", // Latvian\n\tlt: \"lt\", // Lithuanian\n\n\t// Asian languages\n\tzh: \"cn\", // Chinese\n\t\"zh-CN\": \"cn\",\n\t\"zh-TW\": \"tw\",\n\t\"zh-HK\": \"hk\",\n\tja: \"jp\", // Japanese\n\tko: \"kr\", // Korean\n\tth: \"th\", // Thai\n\tvi: \"vn\", // Vietnamese\n\tid: \"id\", // Indonesian\n\tms: \"my\", // Malay\n\thi: \"in\", // Hindi\n\tar: \"sa\", // Arabic (Saudi Arabia as default)\n\the: \"il\", // Hebrew\n\n\t// Other\n\tel: \"gr\", // Greek\n\tfa: \"ir\", // Persian\n\tur: \"pk\", // Urdu\n};\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Get country code from locale code.\n *\n * @param locale - Locale code (e.g., \"en\", \"sk\", \"en-US\")\n * @param customMapping - Optional custom locale-to-country mapping (overrides defaults)\n * @returns Country code (lowercase, e.g., \"gb\", \"sk\", \"us\")\n *\n * @example\n * ```ts\n * getCountryCode(\"en\") // \"gb\" (default)\n * getCountryCode(\"en-US\") // \"us\"\n * getCountryCode(\"sk\") // \"sk\"\n * getCountryCode(\"en\", { en: \"us\" }) // \"us\" (custom mapping)\n * getCountryCode(\"unknown\") // \"unknown\" (fallback to input)\n * ```\n */\nexport function getCountryCode(\n\tlocale: string,\n\tcustomMapping?: Record<string, string>,\n): string {\n\tconst normalized = locale.toLowerCase();\n\n\t// Try custom mapping first (highest priority)\n\tif (customMapping?.[normalized]) {\n\t\treturn customMapping[normalized].toLowerCase();\n\t}\n\n\t// Try exact match in default mapping\n\tif (LOCALE_TO_COUNTRY[normalized]) {\n\t\treturn LOCALE_TO_COUNTRY[normalized];\n\t}\n\n\t// Try base language code (e.g., \"en-US\" → \"en\")\n\tconst baseCode = normalized.split(\"-\")[0];\n\tif (baseCode && customMapping?.[baseCode]) {\n\t\treturn customMapping[baseCode].toLowerCase();\n\t}\n\tif (baseCode && LOCALE_TO_COUNTRY[baseCode]) {\n\t\treturn LOCALE_TO_COUNTRY[baseCode];\n\t}\n\n\t// Fallback to input (useful for direct country codes)\n\treturn normalized;\n}\n\n/**\n * Get flag configuration for a locale.\n *\n * @param locale - Locale code\n * @param customMapping - Optional custom locale-to-country mapping\n * @returns Flag configuration with country code and alt text\n *\n * @example\n * ```ts\n * getFlagConfig(\"sk\") // { countryCode: \"sk\", alt: \"Slovakia\" }\n * getFlagConfig(\"en-US\") // { countryCode: \"us\", alt: \"United States\" }\n * getFlagConfig(\"en\", { en: \"us\" }) // { countryCode: \"us\", alt: \"EN\" }\n * ```\n */\nexport function getFlagConfig(\n\tlocale: string,\n\tcustomMapping?: Record<string, string>,\n): FlagConfig {\n\tconst countryCode = getCountryCode(locale, customMapping);\n\treturn {\n\t\tcountryCode,\n\t\talt: locale.toUpperCase(),\n\t};\n}\n\n/**\n * Get flag image URL from flagcdn.com.\n *\n * @param locale - Locale code\n * @param size - Width in pixels (default: 20)\n * @param customMapping - Optional custom locale-to-country mapping\n * @returns URL to flag PNG\n *\n * @example\n * ```tsx\n * <img src={getFlagUrl(\"sk\")} alt=\"SK\" />\n * <img src={getFlagUrl(\"en-US\", 40)} alt=\"EN-US\" />\n * <img src={getFlagUrl(\"en\", 20, { en: \"us\" })} alt=\"EN\" />\n * ```\n */\nexport function getFlagUrl(\n\tlocale: string,\n\tsize = 24,\n\tcustomMapping?: Record<string, string>,\n): string {\n\tconst { countryCode } = getFlagConfig(locale, customMapping);\n\treturn `https://flagcdn.com/h${size}/${countryCode}.png`;\n}\n","\"use client\";\n\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\";\nimport { CaretRightIcon, CheckIcon } from \"@phosphor-icons/react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\n\nfunction DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {\n\treturn <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nfunction DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\n\treturn <MenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />;\n}\n\nfunction DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\n\treturn <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nfunction DropdownMenuContent({\n\talign = \"start\",\n\talignOffset = 0,\n\tside = \"bottom\",\n\tsideOffset = 4,\n\tclassName,\n\t...props\n}: MenuPrimitive.Popup.Props &\n\tPick<\n\t\tMenuPrimitive.Positioner.Props,\n\t\t\"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n\t>) {\n\treturn (\n\t\t<MenuPrimitive.Portal>\n\t\t\t<MenuPrimitive.Positioner\n\t\t\t\tclassName=\"isolate z-50 outline-none\"\n\t\t\t\talign={align}\n\t\t\t\talignOffset={alignOffset}\n\t\t\t\tside={side}\n\t\t\t\tsideOffset={sideOffset}\n\t\t\t>\n\t\t\t\t<MenuPrimitive.Popup\n\t\t\t\t\tdata-slot=\"dropdown-menu-content\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border border-border/60 bg-popover/95 backdrop-blur-xl text-popover-foreground min-w-48 p-1.5 shadow-lg duration-100 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden\",\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\n\t\t\t\t\t{...props}\n\t\t\t\t/>\n\t\t\t</MenuPrimitive.Positioner>\n\t\t</MenuPrimitive.Portal>\n\t);\n}\n\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n\treturn <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nfunction DropdownMenuLabel({\n\tclassName,\n\tinset,\n\t...props\n}: MenuPrimitive.GroupLabel.Props & {\n\tinset?: boolean;\n}) {\n\treturn (\n\t\t<MenuPrimitive.GroupLabel\n\t\t\tdata-slot=\"dropdown-menu-label\"\n\t\t\tdata-inset={inset}\n\t\t\tclassName={cn(\n\t\t\t\t\"text-muted-foreground px-2 py-1.5 text-xs data-[inset]:pl-8\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DropdownMenuItem({\n\tclassName,\n\tinset,\n\tvariant = \"default\",\n\t...props\n}: MenuPrimitive.Item.Props & {\n\tinset?: boolean;\n\tvariant?: \"default\" | \"destructive\";\n}) {\n\treturn (\n\t\t<MenuPrimitive.Item\n\t\t\tdata-slot=\"dropdown-menu-item\"\n\t\t\tdata-inset={inset}\n\t\t\tdata-variant={variant}\n\t\t\tclassName={cn(\n\t\t\t\t\"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-9 gap-2.5 px-3 py-2 text-sm [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-9 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\n\treturn <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n\tclassName,\n\tinset,\n\tchildren,\n\t...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n\tinset?: boolean;\n}) {\n\treturn (\n\t\t<MenuPrimitive.SubmenuTrigger\n\t\t\tdata-slot=\"dropdown-menu-sub-trigger\"\n\t\t\tdata-inset={inset}\n\t\t\tclassName={cn(\n\t\t\t\t\"focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-9 gap-2.5 px-3 py-2 text-sm [&_svg:not([class*='size-'])]:size-4 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-9 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t<CaretRightIcon className=\"ml-auto size-4\" />\n\t\t</MenuPrimitive.SubmenuTrigger>\n\t);\n}\n\nfunction DropdownMenuSubContent({\n\talign = \"start\",\n\talignOffset = -3,\n\tside = \"right\",\n\tsideOffset = 0,\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof DropdownMenuContent>) {\n\treturn (\n\t\t<DropdownMenuContent\n\t\t\tdata-slot=\"dropdown-menu-sub-content\"\n\t\t\tclassName={cn(\n\t\t\t\t\"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-32 p-1 shadow-md ring-1 duration-100 w-auto\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\talign={align}\n\t\t\talignOffset={alignOffset}\n\t\t\tside={side}\n\t\t\tsideOffset={sideOffset}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DropdownMenuCheckboxItem({\n\tclassName,\n\tchildren,\n\tchecked,\n\t...props\n}: MenuPrimitive.CheckboxItem.Props) {\n\treturn (\n\t\t<MenuPrimitive.CheckboxItem\n\t\t\tdata-slot=\"dropdown-menu-checkbox-item\"\n\t\t\tclassName={cn(\n\t\t\t\t\"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tchecked={checked}\n\t\t\t{...props}\n\t\t>\n\t\t\t<span\n\t\t\t\tclassName=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\"\n\t\t\t\tdata-slot=\"dropdown-menu-checkbox-item-indicator\"\n\t\t\t>\n\t\t\t\t<MenuPrimitive.CheckboxItemIndicator>\n\t\t\t\t\t<CheckIcon />\n\t\t\t\t</MenuPrimitive.CheckboxItemIndicator>\n\t\t\t</span>\n\t\t\t{children}\n\t\t</MenuPrimitive.CheckboxItem>\n\t);\n}\n\nfunction DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {\n\treturn (\n\t\t<MenuPrimitive.RadioGroup\n\t\t\tdata-slot=\"dropdown-menu-radio-group\"\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DropdownMenuRadioItem({\n\tclassName,\n\tchildren,\n\t...props\n}: MenuPrimitive.RadioItem.Props) {\n\treturn (\n\t\t<MenuPrimitive.RadioItem\n\t\t\tdata-slot=\"dropdown-menu-radio-item\"\n\t\t\tclassName={cn(\n\t\t\t\t\"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<span\n\t\t\t\tclassName=\"pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none\"\n\t\t\t\tdata-slot=\"dropdown-menu-radio-item-indicator\"\n\t\t\t>\n\t\t\t\t<MenuPrimitive.RadioItemIndicator>\n\t\t\t\t\t<CheckIcon />\n\t\t\t\t</MenuPrimitive.RadioItemIndicator>\n\t\t\t</span>\n\t\t\t{children}\n\t\t</MenuPrimitive.RadioItem>\n\t);\n}\n\nfunction DropdownMenuSeparator({\n\tclassName,\n\t...props\n}: MenuPrimitive.Separator.Props) {\n\treturn (\n\t\t<MenuPrimitive.Separator\n\t\t\tdata-slot=\"dropdown-menu-separator\"\n\t\t\tclassName={cn(\"bg-border/50 -mx-1 my-1 h-px\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction DropdownMenuShortcut({\n\tclassName,\n\t...props\n}: React.ComponentProps<\"span\">) {\n\treturn (\n\t\t<span\n\t\t\tdata-slot=\"dropdown-menu-shortcut\"\n\t\t\tclassName={cn(\n\t\t\t\t\"text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-[0.625rem] tracking-widest\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport {\n\tDropdownMenu,\n\tDropdownMenuPortal,\n\tDropdownMenuTrigger,\n\tDropdownMenuContent,\n\tDropdownMenuGroup,\n\tDropdownMenuLabel,\n\tDropdownMenuItem,\n\tDropdownMenuCheckboxItem,\n\tDropdownMenuRadioGroup,\n\tDropdownMenuRadioItem,\n\tDropdownMenuSeparator,\n\tDropdownMenuShortcut,\n\tDropdownMenuSub,\n\tDropdownMenuSubTrigger,\n\tDropdownMenuSubContent,\n};\n","import { CaretDown, Check } from \"@phosphor-icons/react\";\nimport type * as React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { useResolveText } from \"../i18n/hooks\";\nimport type { I18nText } from \"../i18n/types\";\nimport { cn } from \"../lib/utils\";\nimport { getFlagUrl } from \"../utils/locale-to-flag\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuTrigger,\n} from \"./ui/dropdown-menu\";\n\nexport type LocaleOption = {\n\tcode: string;\n\tlabel?: I18nText;\n\tflagCountryCode?: string;\n};\n\nexport type LocaleSwitcherLabelMode = \"code\" | \"name\" | \"both\" | \"none\";\n\nexport interface LocaleSwitcherProps {\n\tlocales: LocaleOption[];\n\tvalue?: string;\n\tonChange?: (locale: string) => void;\n\tshowFlag?: boolean;\n\tlabelMode?: LocaleSwitcherLabelMode;\n\tclassName?: string;\n}\n\nconst DROPDOWN_THRESHOLD = 4;\n\nexport function LocaleSwitcher({\n\tlocales,\n\tvalue,\n\tonChange,\n\tshowFlag = true,\n\tlabelMode = \"code\",\n\tclassName,\n}: LocaleSwitcherProps): React.ReactElement | null {\n\tconst resolveText = useResolveText();\n\tconst [imgError, setImgError] = useState(false);\n\tconst resolvedValue = value ?? locales[0]?.code ?? \"\";\n\tconst hasResolvedValue = resolvedValue.length > 0;\n\tconst localeOptions = locales.length\n\t\t? locales\n\t\t: hasResolvedValue\n\t\t\t? [{ code: resolvedValue } satisfies LocaleOption]\n\t\t\t: [];\n\tconst currentLocale =\n\t\tlocaleOptions.find((locale) => locale.code === resolvedValue) ??\n\t\t({ code: resolvedValue } satisfies LocaleOption);\n\tconst canSwitch = !!onChange && localeOptions.length > 1;\n\tconst useDropdown = localeOptions.length >= DROPDOWN_THRESHOLD;\n\n\tconst flagMapping = useMemo(() => {\n\t\tconst mapping: Record<string, string> = {};\n\t\tfor (const locale of localeOptions) {\n\t\t\tif (locale.flagCountryCode) {\n\t\t\t\tmapping[locale.code.toLowerCase()] = locale.flagCountryCode;\n\t\t\t}\n\t\t}\n\t\treturn mapping;\n\t}, [localeOptions]);\n\tconst hasCustomMapping = Object.keys(flagMapping).length > 0;\n\n\tconst getLocaleFlagUrl = (code: string, size = 24) =>\n\t\tgetFlagUrl(code, size, hasCustomMapping ? flagMapping : undefined);\n\n\tif (!hasResolvedValue) return null;\n\n\tconst codeLabel = currentLocale.code.toUpperCase();\n\tconst nameLabel = currentLocale.label\n\t\t? resolveText(currentLocale.label)\n\t\t: codeLabel;\n\tconst renderLabel = () => {\n\t\tswitch (labelMode) {\n\t\t\tcase \"none\":\n\t\t\t\treturn null;\n\t\t\tcase \"name\":\n\t\t\t\treturn <span className=\"font-medium\">{nameLabel}</span>;\n\t\t\tcase \"both\":\n\t\t\t\treturn (\n\t\t\t\t\t<span className=\"flex items-center gap-1\">\n\t\t\t\t\t\t<span className=\"uppercase tracking-wide\">{codeLabel}</span>\n\t\t\t\t\t\t{currentLocale.label && (\n\t\t\t\t\t\t\t<span className=\"font-normal text-muted-foreground\">\n\t\t\t\t\t\t\t\t{resolveText(currentLocale.label)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t);\n\t\t\tcase \"code\":\n\t\t\tdefault:\n\t\t\t\treturn <span className=\"uppercase tracking-wide\">{codeLabel}</span>;\n\t\t}\n\t};\n\n\tconst baseClassName = cn(\n\t\t\"inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground\",\n\t\tclassName,\n\t);\n\tconst interactiveClassName = cn(\n\t\tbaseClassName,\n\t\t\"cursor-pointer transition-colors hover:bg-muted/80 focus:outline-none focus:ring-1 focus:ring-ring\",\n\t);\n\tconst ariaLabel = `Switch locale (current: ${nameLabel})`;\n\n\tconst content = (\n\t\t<>\n\t\t\t{showFlag && !imgError && (\n\t\t\t\t<img\n\t\t\t\t\tsrc={getLocaleFlagUrl(resolvedValue)}\n\t\t\t\t\talt={resolvedValue}\n\t\t\t\t\tclassName=\"h-2.5 w-3.5 rounded-[1px] object-cover\"\n\t\t\t\t\tonError={() => setImgError(true)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{renderLabel()}\n\t\t</>\n\t);\n\n\tif (!canSwitch) {\n\t\treturn <span className={baseClassName}>{content}</span>;\n\t}\n\n\tif (!useDropdown) {\n\t\tconst handleCycle = (e: React.MouseEvent) => {\n\t\t\te.stopPropagation();\n\t\t\tconst currentIndex = localeOptions.findIndex(\n\t\t\t\t(locale) => locale.code === resolvedValue,\n\t\t\t);\n\t\t\tconst nextIndex = (currentIndex + 1) % localeOptions.length;\n\t\t\tconst nextLocale = localeOptions[nextIndex]?.code;\n\t\t\tif (nextLocale) onChange(nextLocale);\n\t\t};\n\n\t\treturn (\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={handleCycle}\n\t\t\t\tclassName={interactiveClassName}\n\t\t\t\taria-label={ariaLabel}\n\t\t\t\ttitle={ariaLabel}\n\t\t\t>\n\t\t\t\t{content}\n\t\t\t</button>\n\t\t);\n\t}\n\n\treturn (\n\t\t<DropdownMenu>\n\t\t\t<DropdownMenuTrigger\n\t\t\t\tclassName={interactiveClassName}\n\t\t\t\taria-label={ariaLabel}\n\t\t\t\ttitle={ariaLabel}\n\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t>\n\t\t\t\t{content}\n\t\t\t\t<CaretDown className=\"size-2.5\" />\n\t\t\t</DropdownMenuTrigger>\n\t\t\t<DropdownMenuContent align=\"start\" className=\"min-w-[140px]\">\n\t\t\t\t{localeOptions.map((locale) => (\n\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\tkey={locale.code}\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\tonChange(locale.code);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"gap-2 text-xs\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{showFlag && (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tsrc={getLocaleFlagUrl(locale.code)}\n\t\t\t\t\t\t\t\talt={locale.code}\n\t\t\t\t\t\t\t\tclassName=\"h-2.5 w-3.5 rounded-[1px] object-cover\"\n\t\t\t\t\t\t\t\tonError={(event) => {\n\t\t\t\t\t\t\t\t\tevent.currentTarget.style.display = \"none\";\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span className=\"uppercase font-medium\">{locale.code}</span>\n\t\t\t\t\t\t{locale.label && (\n\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t\t{resolveText(locale.label)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{locale.code === resolvedValue && (\n\t\t\t\t\t\t\t<Check className=\"ml-auto size-3\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t))}\n\t\t\t</DropdownMenuContent>\n\t\t</DropdownMenu>\n\t);\n}\n","import type * as React from \"react\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport type { I18nText } from \"../../i18n/types\";\nimport { useSafeContentLocales, useScopedLocale } from \"../../runtime\";\nimport { LocaleSwitcher } from \"../locale-switcher\";\nimport {\n\tField,\n\tFieldContent,\n\tFieldDescription,\n\tFieldError,\n\tFieldLabel,\n} from \"../ui/field\";\n\ntype FieldWrapperProps = {\n\tname: string;\n\tlabel?: I18nText;\n\tdescription?: I18nText;\n\trequired?: boolean;\n\tdisabled?: boolean;\n\terror?: string;\n\tlocalized?: boolean;\n\tlocale?: string;\n\tchildren: React.ReactNode;\n\t/** Field path for preview click-to-focus */\n\tfieldPath?: string;\n};\n\nexport function FieldWrapper({\n\tname,\n\tlabel,\n\tdescription,\n\trequired,\n\tdisabled,\n\terror,\n\tlocalized,\n\tlocale,\n\tchildren,\n\tfieldPath,\n}: FieldWrapperProps) {\n\tconst resolveText = useResolveText();\n\tconst { locale: scopedLocale } = useScopedLocale();\n\tconst contentLocales = useSafeContentLocales();\n\tconst resolvedLocale = locale ?? scopedLocale;\n\tconst localeOptions = contentLocales?.locales?.length\n\t\t? contentLocales.locales\n\t\t: resolvedLocale\n\t\t\t? [{ code: resolvedLocale }]\n\t\t\t: [];\n\n\tconst resolvedLabel = label ? resolveText(label) : undefined;\n\tconst resolvedDescription = description\n\t\t? resolveText(description)\n\t\t: undefined;\n\n\treturn (\n\t\t<Field\n\t\t\tdata-disabled={disabled}\n\t\t\tdata-invalid={!!error}\n\t\t\tdata-field-path={fieldPath ?? name}\n\t\t>\n\t\t\t<div className=\"space-y-2\">\n\t\t\t\t{resolvedLabel && (\n\t\t\t\t\t<FieldLabel htmlFor={name} className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<span className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t{resolvedLabel}\n\t\t\t\t\t\t\t{required && <span className=\"text-destructive\">*</span>}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{localized && (\n\t\t\t\t\t\t\t<LocaleSwitcher\n\t\t\t\t\t\t\t\tlocales={localeOptions}\n\t\t\t\t\t\t\t\tvalue={resolvedLocale}\n\t\t\t\t\t\t\t\tshowFlag={false}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</FieldLabel>\n\t\t\t\t)}\n\t\t\t\t<FieldContent>{children}</FieldContent>\n\t\t\t\t{resolvedDescription && (\n\t\t\t\t\t<FieldDescription>{resolvedDescription}</FieldDescription>\n\t\t\t\t)}\n\t\t\t\t{error && <FieldError errors={[{ message: error }]} />}\n\t\t\t</div>\n\t\t</Field>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { CheckboxInput } from \"../primitives/checkbox-input\";\nimport type { BooleanFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function CheckboxField({\n\tname,\n\tlabel,\n\tdescription,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n}: BooleanFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t<CheckboxInput\n\t\t\t\t\t\tid={name}\n\t\t\t\t\t\tvalue={!!field.value}\n\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t/>\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import type * as React from \"react\";\nimport { Controller } from \"react-hook-form\";\nimport type { BaseFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\ntype CustomFieldProps = BaseFieldProps & {\n\tcomponent: React.ComponentType<any>;\n};\n\nexport function CustomField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tcomponent: Component,\n}: CustomFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t<Component\n\t\t\t\t\t\t{...field}\n\t\t\t\t\t\tid={name}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t/>\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import { Popover as PopoverPrimitive } from \"@base-ui/react/popover\";\nimport type * as React from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\nfunction Popover({ ...props }: PopoverPrimitive.Root.Props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nfunction PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n ...props\n}: PopoverPrimitive.Popup.Props &\n Pick<\n PopoverPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <PopoverPrimitive.Popup\n data-slot=\"popover-content\"\n className={cn(\n \"bg-popover/95 backdrop-blur-xl text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 border border-border flex flex-col gap-4 p-2.5 text-xs shadow-lg duration-100 z-50 min-w-48 origin-(--transform-origin) outline-hidden\",\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Positioner>\n </PopoverPrimitive.Portal>\n );\n}\n\nfunction PopoverHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\"flex flex-col gap-1 text-xs\", className)}\n {...props}\n />\n );\n}\n\nfunction PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {\n return (\n <PopoverPrimitive.Title\n data-slot=\"popover-title\"\n className={cn(\"text-sm font-medium\", className)}\n {...props}\n />\n );\n}\n\nfunction PopoverDescription({\n className,\n ...props\n}: PopoverPrimitive.Description.Props) {\n return (\n <PopoverPrimitive.Description\n data-slot=\"popover-description\"\n className={cn(\"text-muted-foreground\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Popover,\n PopoverContent,\n PopoverDescription,\n PopoverHeader,\n PopoverTitle,\n PopoverTrigger,\n};\n","\"use client\";\n\nimport { CalendarBlank, X } from \"@phosphor-icons/react\";\nimport { format } from \"date-fns\";\nimport { useState } from \"react\";\nimport { DayPicker } from \"react-day-picker\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/popover\";\nimport type {\n\tDateInputProps,\n\tDateRangeInputProps,\n\tDateTimeInputProps,\n} from \"./types\";\n\n/**\n * Date Input Primitive\n *\n * A date picker with popover calendar.\n * Uses react-day-picker under the hood.\n *\n * @example\n * ```tsx\n * <DateInput\n * value={selectedDate}\n * onChange={setSelectedDate}\n * placeholder=\"Select date\"\n * />\n * ```\n */\nexport function DateInput({\n\tvalue,\n\tonChange,\n\tminDate,\n\tmaxDate,\n\tformat: dateFormat = \"PP\",\n\tplaceholder = \"Select date\",\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: DateInputProps) {\n\tconst resolveText = useResolveText();\n\tconst [open, setOpen] = useState(false);\n\n\tconst handleSelect = (date: Date | undefined) => {\n\t\tonChange(date ?? null);\n\t\tsetOpen(false);\n\t};\n\n\tconst handleClear = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tonChange(null);\n\t};\n\n\treturn (\n\t\t<Popover open={open} onOpenChange={setOpen}>\n\t\t\t<PopoverTrigger\n\t\t\t\tid={id}\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex h-9 w-full items-center justify-start gap-2 border border-input/80 bg-input/20 backdrop-blur-sm px-3 py-2 text-sm\",\n\t\t\t\t\t\"hover:bg-accent hover:text-accent-foreground\",\n\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\t!value && \"text-muted-foreground\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<CalendarBlank className=\"size-4\" />\n\t\t\t\t<span className=\"flex-1 text-left\">\n\t\t\t\t\t{value ? format(value, dateFormat) : resolveText(placeholder)}\n\t\t\t\t</span>\n\t\t\t\t{value && !disabled && (\n\t\t\t\t\t<X\n\t\t\t\t\t\tclassName=\"size-4 opacity-50 hover:opacity-100\"\n\t\t\t\t\t\tonClick={handleClear}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</PopoverTrigger>\n\t\t\t<PopoverContent className=\"w-auto p-0\" align=\"start\">\n\t\t\t\t<DayPicker\n\t\t\t\t\tmode=\"single\"\n\t\t\t\t\tselected={value ?? undefined}\n\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\tdisabled={(date) => {\n\t\t\t\t\t\tif (minDate && date < minDate) return true;\n\t\t\t\t\t\tif (maxDate && date > maxDate) return true;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}}\n\t\t\t\t\tclassName=\"p-3\"\n\t\t\t\t\tclassNames={{\n\t\t\t\t\t\tmonths: \"flex flex-col sm:flex-row gap-2\",\n\t\t\t\t\t\tmonth: \"flex flex-col gap-4\",\n\t\t\t\t\t\tmonth_caption: \"flex justify-center pt-1 relative items-center h-9\",\n\t\t\t\t\t\tcaption_label: \"text-sm font-medium\",\n\t\t\t\t\t\tnav: \"absolute inset-x-0 top-0 flex items-center justify-between px-1\",\n\t\t\t\t\t\tbutton_previous: cn(\n\t\t\t\t\t\t\t\"size-8 flex items-center justify-center rounded-md\",\n\t\t\t\t\t\t\t\"bg-transparent p-0 opacity-50 hover:opacity-100 hover:bg-accent\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tbutton_next: cn(\n\t\t\t\t\t\t\t\"size-8 flex items-center justify-center rounded-md\",\n\t\t\t\t\t\t\t\"bg-transparent p-0 opacity-50 hover:opacity-100 hover:bg-accent\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tmonth_grid: \"w-full border-collapse\",\n\t\t\t\t\t\tweekdays: \"flex\",\n\t\t\t\t\t\tweekday:\n\t\t\t\t\t\t\t\"text-muted-foreground w-9 font-normal text-[0.8rem] text-center\",\n\t\t\t\t\t\tweek: \"flex w-full mt-2\",\n\t\t\t\t\t\tday: \"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50\",\n\t\t\t\t\t\tday_button: cn(\n\t\t\t\t\t\t\t\"size-9 p-0 font-normal rounded-md\",\n\t\t\t\t\t\t\t\"hover:bg-accent hover:text-accent-foreground\",\n\t\t\t\t\t\t\t\"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tselected:\n\t\t\t\t\t\t\t\"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground rounded-md\",\n\t\t\t\t\t\ttoday: \"bg-accent text-accent-foreground\",\n\t\t\t\t\t\toutside: \"text-muted-foreground opacity-50\",\n\t\t\t\t\t\tdisabled: \"text-muted-foreground opacity-50\",\n\t\t\t\t\t\thidden: \"invisible\",\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n\n/**\n * DateTime Input Primitive\n *\n * A date and time picker.\n *\n * @example\n * ```tsx\n * <DateTimeInput\n * value={scheduledAt}\n * onChange={setScheduledAt}\n * precision=\"minute\"\n * />\n * ```\n */\nexport function DateTimeInput({\n\tvalue,\n\tonChange,\n\tminDate,\n\tmaxDate,\n\tformat: dateFormat = \"PPp\",\n\tprecision = \"minute\",\n\tplaceholder = \"Select date and time\",\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: DateTimeInputProps) {\n\tconst resolveText = useResolveText();\n\tconst [open, setOpen] = useState(false);\n\tconst [timeValue, setTimeValue] = useState(() => {\n\t\tif (!value) return \"\";\n\t\treturn precision === \"second\"\n\t\t\t? format(value, \"HH:mm:ss\")\n\t\t\t: format(value, \"HH:mm\");\n\t});\n\n\tconst handleDateSelect = (date: Date | undefined) => {\n\t\tif (!date) {\n\t\t\tonChange(null);\n\t\t\treturn;\n\t\t}\n\n\t\t// Preserve existing time if available\n\t\tif (timeValue) {\n\t\t\tconst [hours, minutes, seconds] = timeValue.split(\":\").map(Number);\n\t\t\tdate.setHours(hours || 0, minutes || 0, seconds || 0);\n\t\t}\n\t\tonChange(date);\n\t};\n\n\tconst handleTimeChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst time = e.target.value;\n\t\tsetTimeValue(time);\n\n\t\tif (value && time) {\n\t\t\tconst [hours, minutes, seconds] = time.split(\":\").map(Number);\n\t\t\tconst newDate = new Date(value);\n\t\t\tnewDate.setHours(hours || 0, minutes || 0, seconds || 0);\n\t\t\tonChange(newDate);\n\t\t}\n\t};\n\n\tconst handleClear = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tonChange(null);\n\t\tsetTimeValue(\"\");\n\t};\n\n\treturn (\n\t\t<Popover open={open} onOpenChange={setOpen}>\n\t\t\t<PopoverTrigger\n\t\t\t\tid={id}\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex h-9 w-full items-center justify-start gap-2 border border-input/80 bg-input/20 backdrop-blur-sm px-3 py-2 text-sm\",\n\t\t\t\t\t\"hover:bg-accent hover:text-accent-foreground\",\n\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\t!value && \"text-muted-foreground\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<CalendarBlank className=\"size-4\" />\n\t\t\t\t<span className=\"flex-1 text-left\">\n\t\t\t\t\t{value ? format(value, dateFormat) : resolveText(placeholder)}\n\t\t\t\t</span>\n\t\t\t\t{value && !disabled && (\n\t\t\t\t\t<X\n\t\t\t\t\t\tclassName=\"size-4 opacity-50 hover:opacity-100\"\n\t\t\t\t\t\tonClick={handleClear}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</PopoverTrigger>\n\t\t\t<PopoverContent className=\"w-auto p-0\" align=\"start\">\n\t\t\t\t<DayPicker\n\t\t\t\t\tmode=\"single\"\n\t\t\t\t\tselected={value ?? undefined}\n\t\t\t\t\tonSelect={handleDateSelect}\n\t\t\t\t\tdisabled={(date) => {\n\t\t\t\t\t\tif (minDate && date < minDate) return true;\n\t\t\t\t\t\tif (maxDate && date > maxDate) return true;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}}\n\t\t\t\t\tclassName=\"p-3\"\n\t\t\t\t\tclassNames={{\n\t\t\t\t\t\tmonths: \"flex flex-col sm:flex-row gap-2\",\n\t\t\t\t\t\tmonth: \"flex flex-col gap-4\",\n\t\t\t\t\t\tmonth_caption: \"flex justify-center pt-1 relative items-center h-9\",\n\t\t\t\t\t\tcaption_label: \"text-sm font-medium\",\n\t\t\t\t\t\tnav: \"absolute inset-x-0 top-0 flex items-center justify-between px-1\",\n\t\t\t\t\t\tbutton_previous: cn(\n\t\t\t\t\t\t\t\"size-8 flex items-center justify-center rounded-md\",\n\t\t\t\t\t\t\t\"bg-transparent p-0 opacity-50 hover:opacity-100 hover:bg-accent\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tbutton_next: cn(\n\t\t\t\t\t\t\t\"size-8 flex items-center justify-center rounded-md\",\n\t\t\t\t\t\t\t\"bg-transparent p-0 opacity-50 hover:opacity-100 hover:bg-accent\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tmonth_grid: \"w-full border-collapse\",\n\t\t\t\t\t\tweekdays: \"flex\",\n\t\t\t\t\t\tweekday:\n\t\t\t\t\t\t\t\"text-muted-foreground w-9 font-normal text-[0.8rem] text-center\",\n\t\t\t\t\t\tweek: \"flex w-full mt-2\",\n\t\t\t\t\t\tday: \"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50\",\n\t\t\t\t\t\tday_button: cn(\n\t\t\t\t\t\t\t\"size-9 p-0 font-normal rounded-md\",\n\t\t\t\t\t\t\t\"hover:bg-accent hover:text-accent-foreground\",\n\t\t\t\t\t\t\t\"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tselected:\n\t\t\t\t\t\t\t\"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground rounded-md\",\n\t\t\t\t\t\ttoday: \"bg-accent text-accent-foreground\",\n\t\t\t\t\t\toutside: \"text-muted-foreground opacity-50\",\n\t\t\t\t\t\tdisabled: \"text-muted-foreground opacity-50\",\n\t\t\t\t\t\thidden: \"invisible\",\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<div className=\"border-t border-border p-3\">\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"time\"\n\t\t\t\t\t\tstep={precision === \"second\" ? 1 : 60}\n\t\t\t\t\t\tvalue={timeValue}\n\t\t\t\t\t\tonChange={handleTimeChange}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"flex h-9 w-full border border-input/80 bg-input/20 backdrop-blur-sm px-3 py-2 text-sm\",\n\t\t\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n\n/**\n * Date Range Input Primitive\n *\n * A date range picker for selecting start and end dates.\n *\n * @example\n * ```tsx\n * <DateRangeInput\n * value={{ start: startDate, end: endDate }}\n * onChange={setDateRange}\n * />\n * ```\n */\nexport function DateRangeInput({\n\tvalue,\n\tonChange,\n\tminDate,\n\tmaxDate,\n\tplaceholder = \"Select date range\",\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: DateRangeInputProps) {\n\tconst resolveText = useResolveText();\n\tconst [open, setOpen] = useState(false);\n\n\tconst handleSelect = (range: { from?: Date; to?: Date } | undefined) => {\n\t\tonChange({\n\t\t\tstart: range?.from ?? null,\n\t\t\tend: range?.to ?? null,\n\t\t});\n\t};\n\n\tconst handleClear = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tonChange({ start: null, end: null });\n\t};\n\n\tconst displayValue = () => {\n\t\tif (!value.start && !value.end) return resolveText(placeholder);\n\t\tif (value.start && value.end) {\n\t\t\treturn `${format(value.start, \"PP\")} - ${format(value.end, \"PP\")}`;\n\t\t}\n\t\tif (value.start) return `${format(value.start, \"PP\")} - ...`;\n\t\treturn resolveText(placeholder);\n\t};\n\n\treturn (\n\t\t<Popover open={open} onOpenChange={setOpen}>\n\t\t\t<PopoverTrigger\n\t\t\t\tid={id}\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex h-9 w-full items-center justify-start gap-2 border border-input/80 bg-input/20 backdrop-blur-sm px-3 py-2 text-sm\",\n\t\t\t\t\t\"hover:bg-accent hover:text-accent-foreground\",\n\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\t!value.start && !value.end && \"text-muted-foreground\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<CalendarBlank className=\"size-4\" />\n\t\t\t\t<span className=\"flex-1 text-left\">{displayValue()}</span>\n\t\t\t\t{(value.start || value.end) && !disabled && (\n\t\t\t\t\t<X\n\t\t\t\t\t\tclassName=\"size-4 opacity-50 hover:opacity-100\"\n\t\t\t\t\t\tonClick={handleClear}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</PopoverTrigger>\n\t\t\t<PopoverContent className=\"w-auto p-0\" align=\"start\">\n\t\t\t\t<DayPicker\n\t\t\t\t\tmode=\"range\"\n\t\t\t\t\tselected={\n\t\t\t\t\t\tvalue.start || value.end\n\t\t\t\t\t\t\t? { from: value.start ?? undefined, to: value.end ?? undefined }\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\tnumberOfMonths={2}\n\t\t\t\t\tdisabled={(date) => {\n\t\t\t\t\t\tif (minDate && date < minDate) return true;\n\t\t\t\t\t\tif (maxDate && date > maxDate) return true;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}}\n\t\t\t\t\tclassName=\"p-3\"\n\t\t\t\t\tclassNames={{\n\t\t\t\t\t\tmonths: \"flex flex-col sm:flex-row gap-4\",\n\t\t\t\t\t\tmonth: \"flex flex-col gap-4\",\n\t\t\t\t\t\tmonth_caption: \"flex justify-center pt-1 relative items-center h-9\",\n\t\t\t\t\t\tcaption_label: \"text-sm font-medium\",\n\t\t\t\t\t\tnav: \"absolute inset-x-0 top-0 flex items-center justify-between px-1\",\n\t\t\t\t\t\tbutton_previous: cn(\n\t\t\t\t\t\t\t\"size-8 flex items-center justify-center rounded-md\",\n\t\t\t\t\t\t\t\"bg-transparent p-0 opacity-50 hover:opacity-100 hover:bg-accent\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tbutton_next: cn(\n\t\t\t\t\t\t\t\"size-8 flex items-center justify-center rounded-md\",\n\t\t\t\t\t\t\t\"bg-transparent p-0 opacity-50 hover:opacity-100 hover:bg-accent\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tmonth_grid: \"w-full border-collapse\",\n\t\t\t\t\t\tweekdays: \"flex\",\n\t\t\t\t\t\tweekday:\n\t\t\t\t\t\t\t\"text-muted-foreground w-9 font-normal text-[0.8rem] text-center\",\n\t\t\t\t\t\tweek: \"flex w-full mt-2\",\n\t\t\t\t\t\tday: \"relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50\",\n\t\t\t\t\t\tday_button: cn(\n\t\t\t\t\t\t\t\"size-9 p-0 font-normal rounded-md\",\n\t\t\t\t\t\t\t\"hover:bg-accent hover:text-accent-foreground\",\n\t\t\t\t\t\t\t\"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tselected:\n\t\t\t\t\t\t\t\"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground rounded-md\",\n\t\t\t\t\t\trange_start: \"rounded-l-md\",\n\t\t\t\t\t\trange_end: \"rounded-r-md\",\n\t\t\t\t\t\trange_middle: \"bg-accent\",\n\t\t\t\t\t\ttoday: \"bg-accent text-accent-foreground\",\n\t\t\t\t\t\toutside: \"text-muted-foreground opacity-50\",\n\t\t\t\t\t\tdisabled: \"text-muted-foreground opacity-50\",\n\t\t\t\t\t\thidden: \"invisible\",\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { DateInput } from \"../primitives/date-input\";\nimport type { DateFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function DateField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n\tminDate,\n\tmaxDate,\n\tformat,\n}: DateFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => {\n\t\t\t\t// Handle string dates from form (convert to Date object)\n\t\t\t\tconst dateValue =\n\t\t\t\t\tfield.value instanceof Date\n\t\t\t\t\t\t? field.value\n\t\t\t\t\t\t: field.value\n\t\t\t\t\t\t\t? new Date(field.value)\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\treturn (\n\t\t\t\t\t<FieldWrapper\n\t\t\t\t\t\tname={name}\n\t\t\t\t\t\tlabel={label}\n\t\t\t\t\t\tdescription={description}\n\t\t\t\t\t\trequired={required}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tlocalized={localized}\n\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t\t>\n\t\t\t\t\t\t<DateInput\n\t\t\t\t\t\t\tid={name}\n\t\t\t\t\t\t\tvalue={dateValue}\n\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\tminDate={minDate}\n\t\t\t\t\t\t\tmaxDate={maxDate}\n\t\t\t\t\t\t\tformat={format}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FieldWrapper>\n\t\t\t\t);\n\t\t\t}}\n\t\t/>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { DateTimeInput } from \"../primitives/date-input\";\nimport type { DateTimeFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function DatetimeField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n\tminDate,\n\tmaxDate,\n\tformat,\n\tprecision,\n}: DateTimeFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => {\n\t\t\t\t// Handle string dates from form (convert to Date object)\n\t\t\t\tconst dateValue =\n\t\t\t\t\tfield.value instanceof Date\n\t\t\t\t\t\t? field.value\n\t\t\t\t\t\t: field.value\n\t\t\t\t\t\t\t? new Date(field.value)\n\t\t\t\t\t\t\t: null;\n\n\t\t\t\treturn (\n\t\t\t\t\t<FieldWrapper\n\t\t\t\t\t\tname={name}\n\t\t\t\t\t\tlabel={label}\n\t\t\t\t\t\tdescription={description}\n\t\t\t\t\t\trequired={required}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tlocalized={localized}\n\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t\t>\n\t\t\t\t\t\t<DateTimeInput\n\t\t\t\t\t\t\tid={name}\n\t\t\t\t\t\t\tvalue={dateValue}\n\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\tminDate={minDate}\n\t\t\t\t\t\t\tmaxDate={maxDate}\n\t\t\t\t\t\t\tformat={format}\n\t\t\t\t\t\t\tprecision={precision}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FieldWrapper>\n\t\t\t\t);\n\t\t\t}}\n\t\t/>\n\t);\n}\n","import { useResolveText } from \"../../i18n/hooks\";\nimport { Input } from \"../ui/input\";\nimport type { TextInputProps } from \"./types\";\n\n/**\n * Text Input Primitive\n *\n * A basic text input with value/onChange pattern.\n * Supports different input types: text, email, password, url, tel, search.\n *\n * @example\n * ```tsx\n * <TextInput\n * value={email}\n * onChange={setEmail}\n * type=\"email\"\n * placeholder=\"Enter email\"\n * />\n * ```\n */\nexport function TextInput({\n\tvalue,\n\tonChange,\n\ttype = \"text\",\n\tplaceholder,\n\tdisabled,\n\treadOnly,\n\tmaxLength,\n\tautoComplete,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: TextInputProps) {\n\tconst resolveText = useResolveText();\n\n\treturn (\n\t\t<Input\n\t\t\tid={id}\n\t\t\ttype={type}\n\t\t\tvalue={value}\n\t\t\tonChange={(e) => onChange(e.target.value)}\n\t\t\tplaceholder={resolveText(placeholder)}\n\t\t\tdisabled={disabled}\n\t\t\treadOnly={readOnly}\n\t\t\tmaxLength={maxLength}\n\t\t\tautoComplete={autoComplete}\n\t\t\taria-invalid={ariaInvalid}\n\t\t\tclassName={className}\n\t\t/>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { TextInput } from \"../primitives/text-input\";\nimport type { BaseFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function EmailField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n}: BaseFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t<TextInput\n\t\t\t\t\t\tid={name}\n\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t/>\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","/**\n * JsonField Component\n *\n * JSON field with two editing modes:\n * - \"code\" - Raw JSON editing with syntax highlighting\n * - \"form\" - Structured form editing (if schema provided)\n *\n * Integrates with react-hook-form via Controller.\n */\n\nimport { Code, ListBullets, WarningCircle } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { Controller, useFormContext } from \"react-hook-form\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../ui/button\";\nimport {\n\tField,\n\tFieldContent,\n\tFieldDescription,\n\tFieldError,\n\tFieldLabel,\n} from \"../ui/field\";\nimport { Textarea } from \"../ui/textarea\";\nimport type { BaseFieldProps } from \"./field-types\";\n\nexport type JsonFieldMode = \"code\" | \"form\";\n\nexport type JsonFieldProps = BaseFieldProps & {\n\t/**\n\t * Is the field readonly\n\t */\n\treadOnly?: boolean;\n\n\t/**\n\t * Initial editing mode\n\t * @default \"code\"\n\t */\n\tdefaultMode?: JsonFieldMode;\n\n\t/**\n\t * Allow switching between modes\n\t * @default true\n\t */\n\tallowModeSwitch?: boolean;\n\n\t/**\n\t * Minimum height for the editor\n\t * @default 200\n\t */\n\tminHeight?: number;\n\n\t/**\n\t * Maximum height for the editor (0 = no limit)\n\t * @default 400\n\t */\n\tmaxHeight?: number;\n\n\t/**\n\t * Custom render function for form mode\n\t * Receives current value and onChange handler\n\t */\n\trenderForm?: (props: {\n\t\tvalue: any;\n\t\tonChange: (value: any) => void;\n\t\tdisabled?: boolean;\n\t\treadOnly?: boolean;\n\t}) => React.ReactNode;\n};\n\n/**\n * JSON field with code editor and optional form mode.\n *\n * @example\n * ```tsx\n * // Basic JSON editor\n * <JsonField\n * name=\"metadata\"\n * label=\"Metadata\"\n * description=\"Additional metadata as JSON\"\n * />\n *\n * // With custom form mode\n * <JsonField\n * name=\"settings\"\n * label=\"Settings\"\n * renderForm={({ value, onChange }) => (\n * <SettingsForm value={value} onChange={onChange} />\n * )}\n * />\n * ```\n */\nexport function JsonField({\n\tname,\n\tlabel,\n\tdescription,\n\trequired,\n\tdisabled,\n\treadOnly,\n\tplaceholder = '{\\n \"key\": \"value\"\\n}',\n\tdefaultMode = \"code\",\n\tallowModeSwitch = true,\n\tminHeight = 200,\n\tmaxHeight = 400,\n\trenderForm,\n\tcontrol: controlProp,\n\tclassName,\n}: JsonFieldProps) {\n\tconst resolveText = useResolveText();\n\tconst resolvedLabel = label ? resolveText(label) : undefined;\n\tconst resolvedDescription = description\n\t\t? resolveText(description)\n\t\t: undefined;\n\tconst formContext = useFormContext();\n\tconst control = controlProp ?? formContext?.control;\n\tconst [mode, setMode] = React.useState<JsonFieldMode>(defaultMode);\n\n\tif (!control) {\n\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\tconsole.warn(\n\t\t\t\t\"JsonField: No form control found. Make sure to use within FormProvider or pass control prop.\",\n\t\t\t);\n\t\t}\n\t\treturn null;\n\t}\n\n\t// Only show mode switch if form rendering is available\n\tconst showModeSwitch = allowModeSwitch && renderForm;\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={control}\n\t\t\trules={{\n\t\t\t\trequired: required ? `${resolvedLabel || name} is required` : undefined,\n\t\t\t\tvalidate: (value) => {\n\t\t\t\t\tif (!value) return true;\n\t\t\t\t\t// In code mode, validate JSON\n\t\t\t\t\tif (mode === \"code\" && typeof value === \"string\") {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tJSON.parse(value);\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn \"Invalid JSON format\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\t\t\t}}\n\t\t\trender={({ field, fieldState }) => {\n\t\t\t\tconst error = fieldState.error?.message;\n\n\t\t\t\treturn (\n\t\t\t\t\t<Field data-invalid={!!error} className={className}>\n\t\t\t\t\t\t{/* Header with label and mode switch */}\n\t\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t\t{resolvedLabel && (\n\t\t\t\t\t\t\t\t<FieldLabel htmlFor={name}>\n\t\t\t\t\t\t\t\t\t{resolvedLabel}\n\t\t\t\t\t\t\t\t\t{required && <span className=\"text-destructive ml-1\">*</span>}\n\t\t\t\t\t\t\t\t</FieldLabel>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{showModeSwitch && (\n\t\t\t\t\t\t\t\t<div className=\"flex gap-1\">\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tvariant={mode === \"code\" ? \"secondary\" : \"ghost\"}\n\t\t\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => setMode(\"code\")}\n\t\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\t\ttitle=\"Code editor\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Code weight=\"bold\" />\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tvariant={mode === \"form\" ? \"secondary\" : \"ghost\"}\n\t\t\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => setMode(\"form\")}\n\t\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\t\ttitle=\"Form editor\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ListBullets weight=\"bold\" />\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<FieldContent>\n\t\t\t\t\t\t\t{mode === \"code\" ? (\n\t\t\t\t\t\t\t\t<JsonCodeEditor\n\t\t\t\t\t\t\t\t\tvalue={field.value}\n\t\t\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\t\t\tminHeight={minHeight}\n\t\t\t\t\t\t\t\t\tmaxHeight={maxHeight}\n\t\t\t\t\t\t\t\t\terror={!!error}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t) : renderForm ? (\n\t\t\t\t\t\t\t\t<JsonFormEditor\n\t\t\t\t\t\t\t\t\tvalue={field.value}\n\t\t\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\t\t\t\t\trenderForm={renderForm}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<JsonCodeEditor\n\t\t\t\t\t\t\t\t\tvalue={field.value}\n\t\t\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\t\t\tminHeight={minHeight}\n\t\t\t\t\t\t\t\t\tmaxHeight={maxHeight}\n\t\t\t\t\t\t\t\t\terror={!!error}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{resolvedDescription && !error && (\n\t\t\t\t\t\t\t\t<FieldDescription>{resolvedDescription}</FieldDescription>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<FieldError>{error}</FieldError>\n\t\t\t\t\t\t</FieldContent>\n\t\t\t\t\t</Field>\n\t\t\t\t);\n\t\t\t}}\n\t\t/>\n\t);\n}\n\n/**\n * Code editor for JSON (using Textarea for simplicity)\n * Can be replaced with Monaco/CodeMirror in the future\n */\nfunction JsonCodeEditor({\n\tvalue,\n\tonChange,\n\tdisabled,\n\treadOnly,\n\tplaceholder,\n\tminHeight,\n\tmaxHeight,\n\terror,\n}: {\n\tvalue: any;\n\tonChange: (value: any) => void;\n\tdisabled?: boolean;\n\treadOnly?: boolean;\n\tplaceholder?: string;\n\tminHeight?: number;\n\tmaxHeight?: number;\n\terror?: boolean;\n}) {\n\tconst [localValue, setLocalValue] = React.useState<string>(() => {\n\t\tif (typeof value === \"string\") return value;\n\t\tif (value === null || value === undefined) return \"\";\n\t\ttry {\n\t\t\treturn JSON.stringify(value, null, 2);\n\t\t} catch {\n\t\t\treturn \"\";\n\t\t}\n\t});\n\tconst [parseError, setParseError] = React.useState<string | null>(null);\n\n\t// Sync local value when external value changes\n\tReact.useEffect(() => {\n\t\tif (typeof value === \"string\") {\n\t\t\tsetLocalValue(value);\n\t\t} else if (value !== null && value !== undefined) {\n\t\t\ttry {\n\t\t\t\tsetLocalValue(JSON.stringify(value, null, 2));\n\t\t\t} catch {\n\t\t\t\t// Keep current local value if stringification fails\n\t\t\t}\n\t\t} else {\n\t\t\tsetLocalValue(\"\");\n\t\t}\n\t}, [value]);\n\n\tconst handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\tconst newValue = e.target.value;\n\t\tsetLocalValue(newValue);\n\n\t\t// Try to parse and update form value\n\t\tif (!newValue.trim()) {\n\t\t\tsetParseError(null);\n\t\t\tonChange(null);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(newValue);\n\t\t\tsetParseError(null);\n\t\t\tonChange(parsed);\n\t\t} catch (err) {\n\t\t\tsetParseError(\"Invalid JSON\");\n\t\t\t// Still update with raw string so validation can catch it\n\t\t\tonChange(newValue);\n\t\t}\n\t};\n\n\tconst handleFormat = () => {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(localValue);\n\t\t\tconst formatted = JSON.stringify(parsed, null, 2);\n\t\t\tsetLocalValue(formatted);\n\t\t\tsetParseError(null);\n\t\t\tonChange(parsed);\n\t\t} catch {\n\t\t\t// Can't format invalid JSON\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className=\"space-y-2\">\n\t\t\t<div className=\"relative\">\n\t\t\t\t<Textarea\n\t\t\t\t\tvalue={localValue}\n\t\t\t\t\tonChange={handleChange}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"font-mono text-xs\",\n\t\t\t\t\t\terror || parseError ? \"border-destructive\" : \"\",\n\t\t\t\t\t)}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tminHeight: `${minHeight}px`,\n\t\t\t\t\t\tmaxHeight: maxHeight ? `${maxHeight}px` : undefined,\n\t\t\t\t\t\tresize: maxHeight ? \"none\" : \"vertical\",\n\t\t\t\t\t}}\n\t\t\t\t\taria-invalid={!!error || !!parseError}\n\t\t\t\t/>\n\n\t\t\t\t{/* Parse error indicator */}\n\t\t\t\t{parseError && (\n\t\t\t\t\t<div className=\"text-destructive absolute right-2 top-2 flex items-center gap-1 text-xs\">\n\t\t\t\t\t\t<WarningCircle weight=\"fill\" className=\"size-3\" />\n\t\t\t\t\t\t{parseError}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Format button */}\n\t\t\t{!readOnly && !disabled && localValue && (\n\t\t\t\t<div className=\"flex justify-end\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tonClick={handleFormat}\n\t\t\t\t\t\tdisabled={!!parseError}\n\t\t\t\t\t>\n\t\t\t\t\t\tFormat JSON\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n/**\n * Form-based editor wrapper\n */\nfunction JsonFormEditor({\n\tvalue,\n\tonChange,\n\tdisabled,\n\treadOnly,\n\trenderForm,\n}: {\n\tvalue: any;\n\tonChange: (value: any) => void;\n\tdisabled?: boolean;\n\treadOnly?: boolean;\n\trenderForm: JsonFieldProps[\"renderForm\"];\n}) {\n\t// Ensure value is an object for form mode\n\tconst safeValue = React.useMemo(() => {\n\t\tif (typeof value === \"object\" && value !== null) {\n\t\t\treturn value;\n\t\t}\n\t\tif (typeof value === \"string\") {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(value);\n\t\t\t} catch {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t}\n\t\treturn {};\n\t}, [value]);\n\n\tif (!renderForm) return null;\n\n\treturn (\n\t\t<div className=\"rounded-lg border p-4\">\n\t\t\t{renderForm({\n\t\t\t\tvalue: safeValue,\n\t\t\t\tonChange,\n\t\t\t\tdisabled,\n\t\t\t\treadOnly,\n\t\t\t})}\n\t\t</div>\n\t);\n}\n","import { Minus, Plus } from \"@phosphor-icons/react\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport type { NumberInputProps } from \"./types\";\n\n/**\n * Number Input Primitive\n *\n * A number input with optional increment/decrement buttons.\n *\n * @example\n * ```tsx\n * <NumberInput\n * value={count}\n * onChange={setCount}\n * min={0}\n * max={100}\n * step={1}\n * showButtons\n * />\n * ```\n */\nexport function NumberInput({\n\tvalue,\n\tonChange,\n\tmin,\n\tmax,\n\tstep = 1,\n\tshowButtons = false,\n\tplaceholder,\n\tdisabled,\n\treadOnly,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: NumberInputProps) {\n\tconst resolveText = useResolveText();\n\n\tconst handleChange = (newValue: number | null) => {\n\t\tif (newValue === null) {\n\t\t\tonChange(null);\n\t\t\treturn;\n\t\t}\n\n\t\tlet clampedValue = newValue;\n\t\tif (min !== undefined && clampedValue < min) clampedValue = min;\n\t\tif (max !== undefined && clampedValue > max) clampedValue = max;\n\n\t\tonChange(clampedValue);\n\t};\n\n\tconst increment = () => {\n\t\tconst current = value ?? 0;\n\t\thandleChange(current + step);\n\t};\n\n\tconst decrement = () => {\n\t\tconst current = value ?? 0;\n\t\thandleChange(current - step);\n\t};\n\n\tif (showButtons) {\n\t\treturn (\n\t\t\t<div className={cn(\"flex items-center gap-1\", className)}>\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tsize=\"icon-sm\"\n\t\t\t\t\tonClick={decrement}\n\t\t\t\t\tdisabled={disabled || (min !== undefined && (value ?? 0) <= min)}\n\t\t\t\t\ttabIndex={-1}\n\t\t\t\t>\n\t\t\t\t\t<Minus className=\"size-3\" />\n\t\t\t\t</Button>\n\t\t\t\t<Input\n\t\t\t\t\tid={id}\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\tvalue={value ?? \"\"}\n\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\tconst val = e.target.value;\n\t\t\t\t\t\tif (val === \"\") {\n\t\t\t\t\t\t\thandleChange(null);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thandleChange(Number(val));\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t\tplaceholder={resolveText(placeholder)}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\tmin={min}\n\t\t\t\t\tmax={max}\n\t\t\t\t\tstep={step}\n\t\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\t\tclassName=\"text-center [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none\"\n\t\t\t\t/>\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tsize=\"icon-sm\"\n\t\t\t\t\tonClick={increment}\n\t\t\t\t\tdisabled={disabled || (max !== undefined && (value ?? 0) >= max)}\n\t\t\t\t\ttabIndex={-1}\n\t\t\t\t>\n\t\t\t\t\t<Plus className=\"size-3\" />\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Input\n\t\t\tid={id}\n\t\t\ttype=\"number\"\n\t\t\tvalue={value ?? \"\"}\n\t\t\tonChange={(e) => {\n\t\t\t\tconst val = e.target.value;\n\t\t\t\tif (val === \"\") {\n\t\t\t\t\thandleChange(null);\n\t\t\t\t} else {\n\t\t\t\t\thandleChange(Number(val));\n\t\t\t\t}\n\t\t\t}}\n\t\t\tplaceholder={resolveText(placeholder)}\n\t\t\tdisabled={disabled}\n\t\t\treadOnly={readOnly}\n\t\t\tmin={min}\n\t\t\tmax={max}\n\t\t\tstep={step}\n\t\t\taria-invalid={ariaInvalid}\n\t\t\tclassName={className}\n\t\t/>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { NumberInput } from \"../primitives/number-input\";\nimport type { NumberFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function NumberField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n\tmin,\n\tmax,\n\tstep,\n\tshowButtons,\n}: NumberFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t<NumberInput\n\t\t\t\t\t\tid={name}\n\t\t\t\t\t\tvalue={field.value ?? null}\n\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tmin={min}\n\t\t\t\t\t\tmax={max}\n\t\t\t\t\t\tstep={step}\n\t\t\t\t\t\tshowButtons={showButtons}\n\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t/>\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { TextInput } from \"../primitives/text-input\";\nimport type { BaseFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function PasswordField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n}: BaseFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t<TextInput\n\t\t\t\t\t\tid={name}\n\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tautoComplete=\"current-password\"\n\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t/>\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","\"use client\";\n\nimport type * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"./button\";\nimport { Input } from \"./input\";\nimport { Textarea } from \"./textarea\";\n\nfunction InputGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"input-group\"\n role=\"group\"\n className={cn(\n \"border-input bg-input/20 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/30 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 h-7 border transition-colors has-[[data-slot=input-group-control]:focus-visible]:ring-[2px] has-[[data-slot][aria-invalid=true]]:ring-[2px] has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 [[data-slot=combobox-content]_&]:focus-within:border-inherit [[data-slot=combobox-content]_&]:focus-within:ring-0 group/input-group relative flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto\",\n className,\n )}\n {...props}\n />\n );\n}\n\nconst inputGroupAddonVariants = cva(\n \"text-muted-foreground **:data-[slot=kbd]:bg-muted-foreground/10 h-auto gap-1 py-2 text-xs/relaxed font-medium group-data-[disabled=true]/input-group:opacity-50 **:data-[slot=kbd]:px-1 **:data-[slot=kbd]:text-[0.625rem] [&>svg:not([class*='size-'])]:size-3.5 flex cursor-text items-center justify-center select-none\",\n {\n variants: {\n align: {\n \"inline-start\":\n \"pl-2 has-[>button]:ml-[-0.275rem] has-[>kbd]:ml-[-0.275rem] order-first\",\n \"inline-end\":\n \"pr-2 has-[>button]:mr-[-0.275rem] has-[>kbd]:mr-[-0.275rem] order-last\",\n \"block-start\":\n \"px-2 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start\",\n \"block-end\":\n \"px-2 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start\",\n },\n },\n defaultVariants: {\n align: \"inline-start\",\n },\n },\n);\n\nfunction InputGroupAddon({\n className,\n align = \"inline-start\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof inputGroupAddonVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"input-group-addon\"\n data-align={align}\n className={cn(inputGroupAddonVariants({ align }), className)}\n onClick={(e) => {\n if ((e.target as HTMLElement).closest(\"button\")) {\n return;\n }\n e.currentTarget.parentElement?.querySelector(\"input\")?.focus();\n }}\n {...props}\n />\n );\n}\n\nconst inputGroupButtonVariants = cva(\n \"gap-2 text-xs/relaxed shadow-none flex items-center\",\n {\n variants: {\n size: {\n xs: \"h-5 gap-1 px-1 [&>svg:not([class*='size-'])]:size-3\",\n sm: \"\",\n \"icon-xs\": \"size-6 p-0 has-[>svg]:p-0\",\n \"icon-sm\": \"size-8 p-0 has-[>svg]:p-0\",\n },\n },\n defaultVariants: {\n size: \"xs\",\n },\n },\n);\n\nfunction InputGroupButton({\n className,\n type = \"button\",\n variant = \"ghost\",\n size = \"xs\",\n ...props\n}: Omit<React.ComponentProps<typeof Button>, \"size\" | \"type\"> &\n VariantProps<typeof inputGroupButtonVariants> & {\n type?: \"button\" | \"submit\" | \"reset\";\n }) {\n return (\n <Button\n type={type}\n data-size={size}\n variant={variant}\n className={cn(inputGroupButtonVariants({ size }), className)}\n {...props}\n />\n );\n}\n\nfunction InputGroupText({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n className={cn(\n \"text-muted-foreground gap-2 text-xs/relaxed [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction InputGroupInput({\n className,\n ...props\n}: React.ComponentProps<\"input\">) {\n return (\n <Input\n data-slot=\"input-group-control\"\n className={cn(\n \"rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 flex-1\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction InputGroupTextarea({\n className,\n ...props\n}: React.ComponentProps<\"textarea\">) {\n return (\n <Textarea\n data-slot=\"input-group-control\"\n className={cn(\n \"rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 aria-invalid:ring-0 dark:bg-transparent flex-1 resize-none\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupText,\n InputGroupInput,\n InputGroupTextarea,\n};\n","\"use client\";\n\nimport type * as React from \"react\";\nimport { Command as CommandPrimitive } from \"cmdk\";\n\nimport { cn } from \"#questpie/admin/client/lib/utils\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from \"#questpie/admin/client/components/ui/dialog\";\nimport {\n InputGroup,\n InputGroupAddon,\n} from \"#questpie/admin/client/components/ui/input-group\";\nimport { MagnifyingGlass, Check } from \"@phosphor-icons/react\";\n\nfunction Command({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive>) {\n return (\n <CommandPrimitive\n data-slot=\"command\"\n className={cn(\n \"bg-popover text-popover-foreground p-1 flex size-full flex-col overflow-hidden\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CommandDialog({\n title = \"Command Palette\",\n description = \"Search for a command to run...\",\n children,\n className,\n showCloseButton = false,\n ...props\n}: Omit<React.ComponentProps<typeof Dialog>, \"children\"> & {\n title?: string;\n description?: string;\n className?: string;\n showCloseButton?: boolean;\n children: React.ReactNode;\n}) {\n return (\n <Dialog {...props}>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription>{description}</DialogDescription>\n </DialogHeader>\n <DialogContent\n className={cn(\"p-0 overflow-hidden\", className)}\n showCloseButton={showCloseButton}\n >\n {children}\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction CommandInput({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Input>) {\n return (\n <div data-slot=\"command-input-wrapper\" className=\"p-1 pb-0\">\n <InputGroup className=\"bg-input/20 h-8!\">\n <CommandPrimitive.Input\n data-slot=\"command-input\"\n className={cn(\n \"w-full text-xs/relaxed outline-hidden disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n <InputGroupAddon>\n <MagnifyingGlass className=\"size-3.5 shrink-0 opacity-50\" />\n </InputGroupAddon>\n </InputGroup>\n </div>\n );\n}\n\nfunction CommandList({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.List>) {\n return (\n <CommandPrimitive.List\n data-slot=\"command-list\"\n className={cn(\n \"no-scrollbar max-h-72 scroll-py-1 outline-none overflow-x-hidden overflow-y-auto\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CommandEmpty({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n data-slot=\"command-empty\"\n className={cn(\"py-6 text-center text-xs/relaxed\", className)}\n {...props}\n />\n );\n}\n\nfunction CommandGroup({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n data-slot=\"command-group\"\n className={cn(\n \"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CommandSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n data-slot=\"command-separator\"\n className={cn(\"bg-border/50 -mx-1 my-1 h-px\", className)}\n {...props}\n />\n );\n}\n\nfunction CommandItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return (\n <CommandPrimitive.Item\n data-slot=\"command-item\"\n className={cn(\n \"data-selected:bg-current/5 data-selected:text-foreground data-selected:*:[svg]:text-foreground relative flex min-h-7 cursor-pointer items-center gap-2 px-2.5 py-1.5 text-xs/relaxed outline-hidden select-none [&_svg:not([class*='size-'])]:size-3.5 group/command-item data-[disabled=true]:pointer-events-none data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n >\n {children}\n <Check className=\"ml-auto opacity-0 group-has-[[data-slot=command-shortcut]]/command-item:hidden group-data-[checked=true]/command-item:opacity-100\" />\n </CommandPrimitive.Item>\n );\n}\n\nfunction CommandShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"command-shortcut\"\n className={cn(\n \"text-muted-foreground group-data-selected/command-item:text-foreground ml-auto text-[0.625rem] tracking-widest\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n};\n","import type { ReactNode } from \"react\";\nimport type { I18nText } from \"../../i18n/types\";\n\n// =============================================================================\n// Base Props (shared by all primitives)\n// =============================================================================\n\nexport interface BasePrimitiveProps {\n\t/** Unique identifier */\n\tid?: string;\n\t/** Placeholder text */\n\tplaceholder?: I18nText;\n\t/** Disabled state */\n\tdisabled?: boolean;\n\t/** Read-only state */\n\treadOnly?: boolean;\n\t/** Additional class names */\n\tclassName?: string;\n\t/** aria-invalid for error state */\n\t\"aria-invalid\"?: boolean;\n}\n\n// =============================================================================\n// Text Inputs\n// =============================================================================\n\nexport interface TextInputProps extends BasePrimitiveProps {\n\tvalue: string;\n\tonChange: (value: string) => void;\n\ttype?: \"text\" | \"email\" | \"password\" | \"url\" | \"tel\" | \"search\";\n\tmaxLength?: number;\n\tautoComplete?: string;\n}\n\nexport interface NumberInputProps extends BasePrimitiveProps {\n\tvalue: number | null;\n\tonChange: (value: number | null) => void;\n\tmin?: number;\n\tmax?: number;\n\tstep?: number;\n\t/** Show increment/decrement buttons */\n\tshowButtons?: boolean;\n}\n\nexport interface TextareaInputProps extends BasePrimitiveProps {\n\tvalue: string;\n\tonChange: (value: string) => void;\n\trows?: number;\n\tmaxLength?: number;\n\tautoResize?: boolean;\n}\n\n// =============================================================================\n// Select / Multi-Select\n// =============================================================================\n\nexport interface SelectOption<TValue = string> {\n\tvalue: TValue;\n\tlabel: I18nText;\n\tdisabled?: boolean;\n\ticon?: ReactNode;\n}\n\nexport interface SelectOptionGroup<TValue = string> {\n\tlabel: I18nText;\n\toptions: SelectOption<TValue>[];\n}\n\nexport type SelectOptions<TValue = string> =\n\t| SelectOption<TValue>[]\n\t| SelectOptionGroup<TValue>[];\n\n// =============================================================================\n// Boolean Inputs\n// =============================================================================\n// Boolean Inputs\n// =============================================================================\n\nexport interface ToggleInputProps extends BasePrimitiveProps {\n\tvalue: boolean;\n\tonChange: (value: boolean) => void;\n\t/** Size variant */\n\tsize?: \"sm\" | \"default\" | \"lg\";\n}\n\nexport interface CheckboxInputProps extends BasePrimitiveProps {\n\tvalue: boolean;\n\tonChange: (value: boolean) => void;\n\t/** Indeterminate state */\n\tindeterminate?: boolean;\n}\n\nexport interface CheckboxGroupProps<TValue = string>\n\textends BasePrimitiveProps {\n\tvalue: TValue[];\n\tonChange: (value: TValue[]) => void;\n\toptions: SelectOption<TValue>[];\n\t/** Layout direction */\n\torientation?: \"horizontal\" | \"vertical\";\n}\n\nexport interface RadioGroupProps<TValue = string> extends BasePrimitiveProps {\n\tvalue: TValue | null;\n\tonChange: (value: TValue) => void;\n\toptions: SelectOption<TValue>[];\n\torientation?: \"horizontal\" | \"vertical\";\n}\n\n// =============================================================================\n// Date/Time Inputs\n// =============================================================================\n\nexport interface DateInputProps extends BasePrimitiveProps {\n\tvalue: Date | null;\n\tonChange: (value: Date | null) => void;\n\t/** Minimum date */\n\tminDate?: Date;\n\t/** Maximum date */\n\tmaxDate?: Date;\n\t/** Date format display */\n\tformat?: string;\n}\n\nexport interface DateTimeInputProps extends DateInputProps {\n\t/** Time precision */\n\tprecision?: \"minute\" | \"second\";\n}\n\nexport interface TimeInputProps extends BasePrimitiveProps {\n\tvalue: string | null; // \"HH:mm\" or \"HH:mm:ss\"\n\tonChange: (value: string | null) => void;\n\tprecision?: \"minute\" | \"second\";\n}\n\nexport interface DateRangeInputProps extends BasePrimitiveProps {\n\tvalue: { start: Date | null; end: Date | null };\n\tonChange: (value: { start: Date | null; end: Date | null }) => void;\n\tminDate?: Date;\n\tmaxDate?: Date;\n}\n\n// =============================================================================\n// Special Inputs\n// =============================================================================\n\nexport interface TagInputProps extends BasePrimitiveProps {\n\tvalue: string[];\n\tonChange: (value: string[]) => void;\n\t/** Suggestions for autocomplete */\n\tsuggestions?: string[];\n\t/** Max tags */\n\tmaxTags?: number;\n\t/** Allow duplicates */\n\tallowDuplicates?: boolean;\n\t/** Validation pattern */\n\tpattern?: RegExp;\n}\n\nexport interface ColorInputProps extends BasePrimitiveProps {\n\tvalue: string; // hex color\n\tonChange: (value: string) => void;\n\t/** Preset colors */\n\tpresets?: string[];\n\t/** Allow alpha */\n\talpha?: boolean;\n}\n\nexport interface SliderInputProps extends BasePrimitiveProps {\n\tvalue: number | [number, number];\n\tonChange: (value: number | [number, number]) => void;\n\tmin: number;\n\tmax: number;\n\tstep?: number;\n\t/** Show value label */\n\tshowValue?: boolean;\n}\n\nexport interface JsonEditorProps extends BasePrimitiveProps {\n\tvalue: unknown;\n\tonChange: (value: unknown) => void;\n\t/** Max height */\n\tmaxHeight?: string;\n\t/** Line numbers */\n\tshowLineNumbers?: boolean;\n\t/** Schema for validation */\n\tschema?: unknown;\n}\n\n// =============================================================================\n// Utility Types\n// =============================================================================\n\n/** Check if options are grouped */\nexport function isOptionGroup<T>(\n\toption: SelectOption<T> | SelectOptionGroup<T>,\n): option is SelectOptionGroup<T> {\n\treturn \"options\" in option;\n}\n\n/** Flatten grouped options */\nexport function flattenOptions<T>(\n\toptions: SelectOptions<T>,\n): SelectOption<T>[] {\n\treturn options.flatMap((opt) => (isOptionGroup(opt) ? opt.options : [opt]));\n}\n","\"use client\";\n\nimport { Check, CircleNotch, Plus, X } from \"@phosphor-icons/react\";\nimport type * as React from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useIsMobile } from \"../../hooks/use-media-query\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { Badge } from \"../ui/badge\";\nimport {\n\tCommand,\n\tCommandEmpty,\n\tCommandGroup,\n\tCommandInput,\n\tCommandItem,\n\tCommandList,\n} from \"../ui/command\";\nimport {\n\tDrawer,\n\tDrawerContent,\n\tDrawerHeader,\n\tDrawerTitle,\n\tDrawerTrigger,\n} from \"../ui/drawer\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/popover\";\nimport type { BasePrimitiveProps, SelectOption, SelectOptions } from \"./types\";\nimport { flattenOptions } from \"./types\";\n\nexport interface SelectMultiProps<TValue extends string = string>\n\textends BasePrimitiveProps {\n\t/** Selected values */\n\tvalue: TValue[];\n\t/** Change handler */\n\tonChange: (value: TValue[]) => void;\n\t/** Static options */\n\toptions?: SelectOptions<TValue>;\n\t/** Dynamic options loader */\n\tloadOptions?: (search: string) => Promise<SelectOption<TValue>[]>;\n\t/** Max selections */\n\tmaxSelections?: number;\n\t/** Debounce delay for loadOptions (ms) */\n\tdebounceMs?: number;\n\t/** External loading state */\n\tloading?: boolean;\n\t/** Empty state message */\n\temptyMessage?: string;\n\t/** Title for mobile drawer */\n\tdrawerTitle?: string;\n\t/** Max visible chips before collapsing */\n\tmaxVisibleChips?: number;\n}\n\n/**\n * SelectMulti - Multi-select component with chips\n *\n * Features:\n * - Always searchable\n * - Responsive: Popover on desktop, Drawer on mobile\n * - Chip display with remove buttons\n * - Supports static and async options\n * - Keyboard navigation\n *\n * @example\n * ```tsx\n * <SelectMulti\n * value={selectedTags}\n * onChange={setSelectedTags}\n * options={[\n * { value: \"react\", label: \"React\" },\n * { value: \"vue\", label: \"Vue\" },\n * { value: \"angular\", label: \"Angular\" },\n * ]}\n * />\n * ```\n */\nexport function SelectMulti<TValue extends string = string>({\n\tvalue = [],\n\tonChange,\n\toptions: staticOptions = [],\n\tloadOptions,\n\tmaxSelections,\n\tdebounceMs = 300,\n\tloading: externalLoading = false,\n\temptyMessage = \"No options found\",\n\tplaceholder = \"Select...\",\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n\tdrawerTitle = \"Select options\",\n\tmaxVisibleChips = 3,\n}: SelectMultiProps<TValue>) {\n\tconst resolveText = useResolveText();\n\tconst resolvedPlaceholder = resolveText(placeholder);\n\tconst resolvedEmptyMessage = resolveText(emptyMessage);\n\tconst resolvedDrawerTitle = resolveText(drawerTitle);\n\tconst [open, setOpen] = useState(false);\n\tconst [search, setSearch] = useState(\"\");\n\tconst [dynamicOptions, setDynamicOptions] = useState<SelectOption<TValue>[]>(\n\t\t[],\n\t);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst debounceRef = useRef<ReturnType<typeof setTimeout>>(null);\n\tconst isMobile = useIsMobile();\n\n\t// Flatten static options\n\tconst flatStaticOptions = useMemo(\n\t\t() => flattenOptions(staticOptions),\n\t\t[staticOptions],\n\t);\n\n\t// Merge static and dynamic options\n\tconst allOptions = useMemo(() => {\n\t\tif (loadOptions) {\n\t\t\treturn dynamicOptions;\n\t\t}\n\t\treturn flatStaticOptions;\n\t}, [loadOptions, dynamicOptions, flatStaticOptions]);\n\n\t// Filter options by search (for static options)\n\tconst filteredOptions = useMemo(() => {\n\t\tif (loadOptions) {\n\t\t\treturn allOptions;\n\t\t}\n\t\tif (!search) {\n\t\t\treturn allOptions;\n\t\t}\n\t\treturn allOptions.filter((opt) =>\n\t\t\tresolveText(opt.label).toLowerCase().includes(search.toLowerCase()),\n\t\t);\n\t}, [allOptions, search, loadOptions, resolveText]);\n\n\t// Load dynamic options\n\tuseEffect(() => {\n\t\tif (!loadOptions) return;\n\n\t\tif (debounceRef.current) {\n\t\t\tclearTimeout(debounceRef.current);\n\t\t}\n\n\t\tdebounceRef.current = setTimeout(async () => {\n\t\t\tsetIsLoading(true);\n\t\t\ttry {\n\t\t\t\tconst results = await loadOptions(search);\n\t\t\t\tsetDynamicOptions(results);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to load options:\", error);\n\t\t\t\tsetDynamicOptions([]);\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false);\n\t\t\t}\n\t\t}, debounceMs);\n\n\t\treturn () => {\n\t\t\tif (debounceRef.current) {\n\t\t\t\tclearTimeout(debounceRef.current);\n\t\t\t}\n\t\t};\n\t}, [search, loadOptions, debounceMs]);\n\n\t// Get label for a value\n\tconst getLabel = useCallback(\n\t\t(val: TValue): string => {\n\t\t\tconst option = allOptions.find((opt) => opt.value === val);\n\t\t\treturn option?.label ? resolveText(option.label) : String(val);\n\t\t},\n\t\t[allOptions, resolveText],\n\t);\n\n\tconst handleToggle = useCallback(\n\t\t(selectedValue: string) => {\n\t\t\tconst typedValue = selectedValue as TValue;\n\t\t\tconst isSelected = value.includes(typedValue);\n\n\t\t\tif (isSelected) {\n\t\t\t\tonChange(value.filter((v) => v !== typedValue));\n\t\t\t} else {\n\t\t\t\tif (maxSelections && value.length >= maxSelections) return;\n\t\t\t\tonChange([...value, typedValue]);\n\t\t\t}\n\t\t},\n\t\t[value, onChange, maxSelections],\n\t);\n\n\tconst handleRemove = useCallback(\n\t\t(removedValue: TValue, e?: React.MouseEvent) => {\n\t\t\te?.stopPropagation();\n\t\t\tonChange(value.filter((v) => v !== removedValue));\n\t\t},\n\t\t[value, onChange],\n\t);\n\n\tconst handleClearAll = useCallback(\n\t\t(e: React.MouseEvent) => {\n\t\t\te.stopPropagation();\n\t\t\tonChange([]);\n\t\t},\n\t\t[onChange],\n\t);\n\n\tconst showLoading = isLoading || externalLoading;\n\tconst canAddMore = !maxSelections || value.length < maxSelections;\n\n\t// Visible and hidden chips\n\tconst visibleChips = value.slice(0, maxVisibleChips);\n\tconst hiddenCount = value.length - maxVisibleChips;\n\n\tconst TriggerContent = (\n\t\t<div\n\t\t\tid={id}\n\t\t\trole=\"combobox\"\n\t\t\taria-controls=\"select-multi-list\"\n\t\t\taria-haspopup=\"listbox\"\n\t\t\taria-expanded={open}\n\t\t\taria-invalid={ariaInvalid}\n\t\t\ttabIndex={0}\n\t\t\tclassName={cn(\n\t\t\t\t\"flex min-h-9 w-full flex-wrap items-center gap-1 rounded-md border border-input/80 bg-input/20 backdrop-blur-sm px-3 py-1.5 text-sm transition-colors\",\n\t\t\t\t\"focus-within:ring-2 focus-within:ring-ring focus-within:border-ring\",\n\t\t\t\tdisabled && \"cursor-not-allowed opacity-50\",\n\t\t\t\tariaInvalid && \"border-destructive ring-destructive/20\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{value.length === 0 ? (\n\t\t\t\t<span className=\"text-muted-foreground text-xs\">\n\t\t\t\t\t{resolvedPlaceholder}\n\t\t\t\t</span>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t{visibleChips.map((val) => (\n\t\t\t\t\t\t<Badge key={String(val)} variant=\"secondary\" className=\"gap-1 pr-1\">\n\t\t\t\t\t\t\t<span className=\"truncate max-w-24\">{getLabel(val)}</span>\n\t\t\t\t\t\t\t{!disabled && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={(e) => handleRemove(val, e)}\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full hover:bg-muted-foreground/20 p-0.5\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X className=\"size-2.5\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</Badge>\n\t\t\t\t\t))}\n\t\t\t\t\t{hiddenCount > 0 && (\n\t\t\t\t\t\t<Badge variant=\"outline\" className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t+{hiddenCount} more\n\t\t\t\t\t\t</Badge>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t)}\n\t\t\t<div className=\"ml-auto flex items-center gap-1 shrink-0\">\n\t\t\t\t{value.length > 0 && !disabled && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleClearAll}\n\t\t\t\t\t\tclassName=\"rounded-sm opacity-50 hover:opacity-100 hover:bg-muted p-0.5\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<X className=\"size-3\" />\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t<Plus className=\"size-3.5 opacity-50\" />\n\t\t\t</div>\n\t\t</div>\n\t);\n\n\tconst CommandContent = (\n\t\t<Command shouldFilter={!loadOptions}>\n\t\t\t<CommandInput\n\t\t\t\tplaceholder=\"Search...\"\n\t\t\t\tvalue={search}\n\t\t\t\tonValueChange={setSearch}\n\t\t\t/>\n\t\t\t<CommandList>\n\t\t\t\t{showLoading && (\n\t\t\t\t\t<div className=\"flex items-center justify-center py-6\">\n\t\t\t\t\t\t<CircleNotch className=\"size-4 animate-spin text-muted-foreground\" />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<CommandEmpty>{resolvedEmptyMessage}</CommandEmpty>\n\t\t\t\t<CommandGroup>\n\t\t\t\t\t{filteredOptions.map((option) => {\n\t\t\t\t\t\tconst isSelected = value.includes(option.value);\n\t\t\t\t\t\tconst isDisabled = option.disabled || (!isSelected && !canAddMore);\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<CommandItem\n\t\t\t\t\t\t\t\tkey={String(option.value)}\n\t\t\t\t\t\t\t\tvalue={String(option.value)}\n\t\t\t\t\t\t\t\tonSelect={handleToggle}\n\t\t\t\t\t\t\t\tdisabled={isDisabled}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"flex size-4 items-center justify-center rounded-sm border\",\n\t\t\t\t\t\t\t\t\t\tisSelected\n\t\t\t\t\t\t\t\t\t\t\t? \"bg-primary border-primary text-primary-foreground\"\n\t\t\t\t\t\t\t\t\t\t\t: \"border-muted-foreground/30\",\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isSelected && <Check className=\"size-3\" />}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{option.icon}\n\t\t\t\t\t\t\t\t<span className=\"truncate\">{resolveText(option.label)}</span>\n\t\t\t\t\t\t\t</CommandItem>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</CommandGroup>\n\t\t\t</CommandList>\n\t\t\t{maxSelections && (\n\t\t\t\t<div className=\"border-t p-2 text-center text-xs text-muted-foreground\">\n\t\t\t\t\t{value.length} / {maxSelections} selected\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</Command>\n\t);\n\n\t// Mobile: Drawer\n\tif (isMobile) {\n\t\treturn (\n\t\t\t<Drawer open={open} onOpenChange={setOpen}>\n\t\t\t\t<DrawerTrigger asChild>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tclassName=\"w-full text-left\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{TriggerContent}\n\t\t\t\t\t</button>\n\t\t\t\t</DrawerTrigger>\n\t\t\t\t<DrawerContent>\n\t\t\t\t\t<DrawerHeader>\n\t\t\t\t\t\t<DrawerTitle>{resolvedDrawerTitle}</DrawerTitle>\n\t\t\t\t\t</DrawerHeader>\n\t\t\t\t\t<div className=\"px-4 pb-6\">{CommandContent}</div>\n\t\t\t\t</DrawerContent>\n\t\t\t</Drawer>\n\t\t);\n\t}\n\n\t// Desktop: Popover\n\treturn (\n\t\t<Popover open={open} onOpenChange={setOpen}>\n\t\t\t<PopoverTrigger\n\t\t\t\trender={\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tclassName=\"w-full text-left\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{TriggerContent}\n\t\t\t\t\t</button>\n\t\t\t\t}\n\t\t\t/>\n\t\t\t<PopoverContent className=\"w-(--anchor-width) p-0\" align=\"start\">\n\t\t\t\t{CommandContent}\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n","\"use client\";\n\nimport { CaretUpDown, CircleNotch, X } from \"@phosphor-icons/react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport type * as React from \"react\";\nimport { useCallback, useDeferredValue, useId, useMemo, useState } from \"react\";\nimport { useIsMobile } from \"../../hooks/use-media-query\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../ui/button\";\nimport {\n\tCommand,\n\tCommandEmpty,\n\tCommandGroup,\n\tCommandInput,\n\tCommandItem,\n\tCommandList,\n} from \"../ui/command\";\nimport {\n\tDrawer,\n\tDrawerContent,\n\tDrawerHeader,\n\tDrawerTitle,\n\tDrawerTrigger,\n} from \"../ui/drawer\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/popover\";\nimport type { BasePrimitiveProps, SelectOption, SelectOptions } from \"./types\";\nimport { flattenOptions } from \"./types\";\n\nexport interface SelectSingleProps<TValue extends string = string>\n\textends BasePrimitiveProps {\n\t/** Selected value */\n\tvalue: TValue | null;\n\t/** Change handler */\n\tonChange: (value: TValue | null) => void;\n\t/** Static options */\n\toptions?: SelectOptions<TValue>;\n\t/** Dynamic options loader */\n\tloadOptions?: (search: string) => Promise<SelectOption<TValue>[]>;\n\t/** Query key builder for loadOptions */\n\tqueryKey?: (search: string) => readonly unknown[];\n\t/** Prefetch options on mount */\n\tprefetchOnMount?: boolean;\n\n\t/** Allow clearing selection */\n\tclearable?: boolean;\n\t/** Debounce delay for loadOptions (ms) */\n\tdebounceMs?: number;\n\t/** External loading state */\n\tloading?: boolean;\n\t/** Empty state message */\n\temptyMessage?: string;\n\t/** Title for mobile drawer */\n\tdrawerTitle?: string;\n}\n\n/**\n * SelectSingle - Single select component with search\n *\n * Features:\n * - Always searchable\n * - Responsive: Popover on desktop, Drawer on mobile\n * - Supports static and async options\n * - Keyboard navigation\n *\n * @example\n * ```tsx\n * <SelectSingle\n * value={status}\n * onChange={setStatus}\n * options={[\n * { value: \"active\", label: \"Active\" },\n * { value: \"inactive\", label: \"Inactive\" },\n * ]}\n * />\n * ```\n */\nexport function SelectSingle<TValue extends string = string>({\n\tvalue,\n\tonChange,\n\toptions: staticOptions = [],\n\tloadOptions,\n\tqueryKey,\n\tprefetchOnMount = false,\n\tclearable = true,\n\tloading: externalLoading = false,\n\temptyMessage = \"No options found\",\n\tplaceholder = \"Select...\",\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n\tdrawerTitle = \"Select option\",\n}: SelectSingleProps<TValue>) {\n\tconst resolveText = useResolveText();\n\tconst resolvedPlaceholder = resolveText(placeholder);\n\tconst resolvedEmptyMessage = resolveText(emptyMessage);\n\tconst resolvedDrawerTitle = resolveText(drawerTitle);\n\tconst [open, setOpen] = useState(false);\n\tconst [search, setSearch] = useState(\"\");\n\tconst instanceId = useId();\n\tconst deferredSearch = useDeferredValue(search);\n\tconst isMobile = useIsMobile();\n\n\t// Flatten static options\n\tconst flatStaticOptions = useMemo(\n\t\t() => flattenOptions(staticOptions),\n\t\t[staticOptions],\n\t);\n\n\tconst loadOptionsKey = useMemo(\n\t\t() =>\n\t\t\tqueryKey\n\t\t\t\t? queryKey(deferredSearch)\n\t\t\t\t: [\"select-single\", instanceId, deferredSearch],\n\t\t[queryKey, deferredSearch, instanceId],\n\t);\n\n\tconst { data: dynamicOptions = [], isFetching } = useQuery({\n\t\tqueryKey: loadOptionsKey,\n\t\tqueryFn: () => loadOptions?.(deferredSearch) ?? Promise.resolve([]),\n\t\tenabled: !!loadOptions && (open || prefetchOnMount),\n\t\tstaleTime: 30_000,\n\t\tgcTime: 5 * 60_000,\n\t});\n\n\t// Merge static and dynamic options (immutable pattern for React Compiler)\n\tconst allOptions = useMemo(() => {\n\t\tif (!loadOptions) {\n\t\t\treturn flatStaticOptions;\n\t\t}\n\t\tif (flatStaticOptions.length === 0) {\n\t\t\treturn dynamicOptions;\n\t\t}\n\t\t// Use reduce to build Map immutably - dynamic options override static\n\t\tconst mergedMap = [...flatStaticOptions, ...dynamicOptions].reduce(\n\t\t\t(map, opt) => new Map(map).set(opt.value, opt),\n\t\t\tnew Map<TValue, SelectOption<TValue>>(),\n\t\t);\n\t\treturn Array.from(mergedMap.values());\n\t}, [loadOptions, dynamicOptions, flatStaticOptions]);\n\n\t// Filter options by search (for static options)\n\tconst filteredOptions = useMemo(() => {\n\t\tif (loadOptions) {\n\t\t\treturn allOptions; // Dynamic options are already filtered by server\n\t\t}\n\t\tif (!search) {\n\t\t\treturn allOptions;\n\t\t}\n\t\treturn allOptions.filter((opt: SelectOption<TValue>) =>\n\t\t\tresolveText(opt.label).toLowerCase().includes(search.toLowerCase()),\n\t\t);\n\t}, [allOptions, search, loadOptions, resolveText]);\n\n\t// Get label for a value\n\tconst getLabel = useCallback(\n\t\t(val: TValue): string => {\n\t\t\tconst option = allOptions.find(\n\t\t\t\t(opt: SelectOption<TValue>) => opt.value === val,\n\t\t\t);\n\t\t\treturn option?.label ? resolveText(option.label) : String(val);\n\t\t},\n\t\t[allOptions, resolveText],\n\t);\n\n\tconst handleSelect = useCallback(\n\t\t(selectedValue: string) => {\n\t\t\tonChange(selectedValue as TValue);\n\t\t\tsetOpen(false);\n\t\t\tsetSearch(\"\");\n\t\t},\n\t\t[onChange],\n\t);\n\n\tconst handleClear = useCallback(\n\t\t(e: React.MouseEvent) => {\n\t\t\te.stopPropagation();\n\t\t\tonChange(null);\n\t\t},\n\t\t[onChange],\n\t);\n\n\tconst showLoading = isFetching || externalLoading;\n\n\tconst TriggerButton = (\n\t\t<Button\n\t\t\tid={id}\n\t\t\tvariant=\"outline\"\n\t\t\trole=\"combobox\"\n\t\t\taria-expanded={open}\n\t\t\taria-invalid={ariaInvalid}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={cn(\n\t\t\t\t\"w-full justify-between font-normal\",\n\t\t\t\t!value && \"text-muted-foreground\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<span className=\"truncate\">\n\t\t\t\t{value ? getLabel(value) : resolvedPlaceholder}\n\t\t\t</span>\n\t\t\t<div className=\"flex items-center gap-1 shrink-0\">\n\t\t\t\t{clearable && value && !disabled && (\n\t\t\t\t\t<span\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\t\tonClick={handleClear}\n\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\tif (event.key === \"Enter\" || event.key === \" \") {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\thandleClear(event as unknown as React.MouseEvent);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"rounded-sm opacity-50 hover:opacity-100 hover:bg-muted p-0.5 -mr-1\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<X className=\"size-3\" />\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t\t<CaretUpDown className=\"size-3.5 opacity-50\" />\n\t\t\t</div>\n\t\t</Button>\n\t);\n\n\tconst CommandContent = (\n\t\t<Command shouldFilter={!loadOptions}>\n\t\t\t<CommandInput\n\t\t\t\tplaceholder=\"Search...\"\n\t\t\t\tvalue={search}\n\t\t\t\tonValueChange={setSearch}\n\t\t\t/>\n\t\t\t<CommandList>\n\t\t\t\t{showLoading && (\n\t\t\t\t\t<div className=\"flex items-center justify-center py-6\">\n\t\t\t\t\t\t<CircleNotch className=\"size-4 animate-spin text-muted-foreground\" />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<CommandEmpty>{resolvedEmptyMessage}</CommandEmpty>\n\t\t\t\t<CommandGroup>\n\t\t\t\t\t{filteredOptions.map((option) => (\n\t\t\t\t\t\t<CommandItem\n\t\t\t\t\t\t\tkey={String(option.value)}\n\t\t\t\t\t\t\tvalue={String(option.value)}\n\t\t\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\t\t\tdisabled={option.disabled}\n\t\t\t\t\t\t\tdata-checked={value === option.value}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{option.icon}\n\t\t\t\t\t\t\t<span className=\"truncate\">{resolveText(option.label)}</span>\n\t\t\t\t\t\t</CommandItem>\n\t\t\t\t\t))}\n\t\t\t\t</CommandGroup>\n\t\t\t</CommandList>\n\t\t</Command>\n\t);\n\n\t// Mobile: Drawer\n\tif (isMobile) {\n\t\treturn (\n\t\t\t<Drawer open={open} onOpenChange={setOpen}>\n\t\t\t\t<DrawerTrigger asChild>{TriggerButton}</DrawerTrigger>\n\t\t\t\t<DrawerContent>\n\t\t\t\t\t<DrawerHeader>\n\t\t\t\t\t\t<DrawerTitle>{resolvedDrawerTitle}</DrawerTitle>\n\t\t\t\t\t</DrawerHeader>\n\t\t\t\t\t<div className=\"px-4 pb-6\">{CommandContent}</div>\n\t\t\t\t</DrawerContent>\n\t\t\t</Drawer>\n\t\t);\n\t}\n\n\t// Desktop: Popover\n\treturn (\n\t\t<Popover open={open} onOpenChange={setOpen}>\n\t\t\t<PopoverTrigger render={TriggerButton} />\n\t\t\t<PopoverContent className=\"w-(--anchor-width) p-0\" align=\"start\">\n\t\t\t\t{CommandContent}\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { SelectMulti } from \"../primitives/select-multi\";\nimport { SelectSingle } from \"../primitives/select-single\";\nimport type { SelectFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function SelectField<TValue extends string = string>({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n\toptions,\n\tloadOptions,\n\tmultiple,\n\tclearable,\n\tmaxSelections,\n\temptyMessage,\n}: SelectFieldProps<TValue>) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t{multiple ? (\n\t\t\t\t\t\t<SelectMulti<TValue>\n\t\t\t\t\t\t\tid={name}\n\t\t\t\t\t\t\tvalue={Array.isArray(field.value) ? field.value : []}\n\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\toptions={options}\n\t\t\t\t\t\t\tloadOptions={loadOptions}\n\t\t\t\t\t\t\tmaxSelections={maxSelections}\n\t\t\t\t\t\t\temptyMessage={emptyMessage}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<SelectSingle<TValue>\n\t\t\t\t\t\t\tid={name}\n\t\t\t\t\t\t\tvalue={field.value ?? null}\n\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\toptions={options}\n\t\t\t\t\t\t\tloadOptions={loadOptions}\n\t\t\t\t\t\t\tclearable={clearable}\n\t\t\t\t\t\t\temptyMessage={emptyMessage}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","\"use client\";\n\nimport { Switch as SwitchPrimitive } from \"@base-ui/react/switch\";\n\nimport { cn } from \"../../lib/utils\";\n\nfunction Switch({\n className,\n size = \"default\",\n ...props\n}: SwitchPrimitive.Root.Props & {\n size?: \"sm\" | \"default\";\n}) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n data-size={size}\n className={cn(\n \"data-checked:bg-primary data-unchecked:bg-input focus-visible:border-ring focus-visible:ring-ring/30 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 dark:data-unchecked:bg-input/80 shrink-0 rounded-full border border-transparent focus-visible:ring-[2px] aria-invalid:ring-[2px] data-[size=default]:h-[16.6px] data-[size=default]:w-[28px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] peer group/switch relative inline-flex items-center transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className=\"bg-background dark:data-unchecked:bg-foreground dark:data-checked:bg-primary-foreground rounded-full group-data-[size=default]/switch:size-3.5 group-data-[size=sm]/switch:size-3 group-data-[size=default]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=sm]/switch:data-checked:translate-x-[calc(100%-2px)] group-data-[size=default]/switch:data-unchecked:translate-x-0 group-data-[size=sm]/switch:data-unchecked:translate-x-0 pointer-events-none block ring-0 transition-transform\"\n />\n </SwitchPrimitive.Root>\n );\n}\n\nexport { Switch };\n","import { Switch } from \"../ui/switch\";\nimport type { ToggleInputProps } from \"./types\";\n\n/**\n * Toggle Input Primitive\n *\n * A switch/toggle for boolean values.\n *\n * @example\n * ```tsx\n * <ToggleInput\n * value={isActive}\n * onChange={setIsActive}\n * />\n * ```\n */\nexport function ToggleInput({\n\tvalue,\n\tonChange,\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: ToggleInputProps) {\n\treturn (\n\t\t<Switch\n\t\t\tid={id}\n\t\t\tchecked={value}\n\t\t\tonCheckedChange={onChange}\n\t\t\tdisabled={disabled}\n\t\t\taria-invalid={ariaInvalid}\n\t\t\tclassName={className}\n\t\t/>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { ToggleInput } from \"../primitives/toggle-input\";\nimport type { BooleanFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function SwitchField({\n\tname,\n\tlabel,\n\tdescription,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n}: BooleanFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t<ToggleInput\n\t\t\t\t\t\tid={name}\n\t\t\t\t\t\tvalue={!!field.value}\n\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t/>\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { TextInput } from \"../primitives/text-input\";\nimport type { TextFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function TextField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n\ttype = \"text\",\n\tmaxLength,\n\tautoComplete,\n}: TextFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t<TextInput\n\t\t\t\t\t\tid={name}\n\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\ttype={type}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tmaxLength={maxLength}\n\t\t\t\t\t\tautoComplete={autoComplete}\n\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t/>\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import { useResolveText } from \"../../i18n/hooks\";\nimport { Textarea } from \"../ui/textarea\";\nimport type { TextareaInputProps } from \"./types\";\n\n/**\n * Textarea Input Primitive\n *\n * A multi-line text input.\n *\n * @example\n * ```tsx\n * <TextareaInput\n * value={description}\n * onChange={setDescription}\n * rows={4}\n * placeholder=\"Enter description...\"\n * />\n * ```\n */\nexport function TextareaInput({\n\tvalue,\n\tonChange,\n\trows = 3,\n\tmaxLength,\n\tplaceholder,\n\tdisabled,\n\treadOnly,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: TextareaInputProps) {\n\tconst resolveText = useResolveText();\n\n\treturn (\n\t\t<Textarea\n\t\t\tid={id}\n\t\t\tvalue={value}\n\t\t\tonChange={(e) => onChange(e.target.value)}\n\t\t\trows={rows}\n\t\t\tmaxLength={maxLength}\n\t\t\tplaceholder={resolveText(placeholder)}\n\t\t\tdisabled={disabled}\n\t\t\treadOnly={readOnly}\n\t\t\taria-invalid={ariaInvalid}\n\t\t\tclassName={className}\n\t\t/>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { TextareaInput } from \"../primitives/textarea-input\";\nimport type { TextareaFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function TextareaField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n\trows,\n\tmaxLength,\n\tautoResize,\n}: TextareaFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t<TextareaInput\n\t\t\t\t\t\tid={name}\n\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\trows={rows}\n\t\t\t\t\t\tmaxLength={maxLength}\n\t\t\t\t\t\tautoResize={autoResize}\n\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t/>\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","import type * as React from \"react\";\nimport { CheckboxField } from \"../../components/fields/checkbox-field\";\nimport { CustomField } from \"../../components/fields/custom-field\";\nimport { DateField } from \"../../components/fields/date-field\";\nimport { DatetimeField } from \"../../components/fields/datetime-field\";\nimport { EmailField } from \"../../components/fields/email-field\";\nimport type { FormFieldProps } from \"../../components/fields/field-types\";\nimport { JsonField } from \"../../components/fields/json-field\";\nimport { NumberField } from \"../../components/fields/number-field\";\nimport { PasswordField } from \"../../components/fields/password-field\";\nimport { SelectField } from \"../../components/fields/select-field\";\nimport { SwitchField } from \"../../components/fields/switch-field\";\nimport { TextField } from \"../../components/fields/text-field\";\nimport { TextareaField } from \"../../components/fields/textarea-field\";\n\nexport type { FormFieldProps } from \"../../components/fields/field-types\";\n\n/**\n * FormField - Generic form field with React Hook Form integration\n */\nexport function FormField({\n\ttype = \"text\",\n\tcomponent,\n\toptions,\n\t...baseProps\n}: FormFieldProps): React.ReactElement {\n\tif (component) {\n\t\treturn <CustomField {...baseProps} component={component} />;\n\t}\n\n\tswitch (type) {\n\t\tcase \"textarea\":\n\t\t\treturn <TextareaField {...baseProps} />;\n\t\tcase \"checkbox\":\n\t\t\treturn <CheckboxField {...baseProps} />;\n\t\tcase \"switch\":\n\t\t\treturn <SwitchField {...baseProps} />;\n\t\tcase \"select\":\n\t\t\treturn <SelectField {...baseProps} options={options} />;\n\t\tcase \"number\":\n\t\t\treturn <NumberField {...baseProps} />;\n\t\tcase \"date\":\n\t\t\treturn <DateField {...baseProps} />;\n\t\tcase \"datetime\":\n\t\t\treturn <DatetimeField {...baseProps} />;\n\t\tcase \"email\":\n\t\t\treturn <EmailField {...baseProps} />;\n\t\tcase \"password\":\n\t\t\treturn <PasswordField {...baseProps} />;\n\t\tcase \"json\":\n\t\t\treturn <JsonField {...baseProps} />;\n\t\tdefault:\n\t\t\treturn <TextField {...baseProps} />;\n\t}\n}\n","import { Dialog as SheetPrimitive } from \"@base-ui/react/dialog\";\nimport { XIcon } from \"@phosphor-icons/react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"./button\";\n\nfunction Sheet({ ...props }: SheetPrimitive.Root.Props) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />;\n}\n\nfunction SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />;\n}\n\nfunction SheetClose({ ...props }: SheetPrimitive.Close.Props) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />;\n}\n\nfunction SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />;\n}\n\nfunction SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {\n return (\n <SheetPrimitive.Backdrop\n data-slot=\"sheet-overlay\"\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-background/80 backdrop-blur-sm duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0 fixed inset-0 z-50\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n showCloseButton = true,\n ...props\n}: SheetPrimitive.Popup.Props & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n showCloseButton?: boolean;\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Popup\n data-slot=\"sheet-content\"\n data-side={side}\n className={cn(\n \"bg-background border-border data-open:animate-in data-closed:animate-out data-[side=right]:data-closed:slide-out-to-right-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=top]:data-closed:slide-out-to-top-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:fade-out-0 data-open:fade-in-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=bottom]:data-open:slide-in-from-bottom-10 fixed z-50 flex flex-col bg-clip-padding text-sm shadow-xl transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-full data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-full data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-2xl data-[side=right]:sm:max-w-2xl\",\n className,\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <SheetPrimitive.Close\n data-slot=\"sheet-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-3 right-3\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n )}\n </SheetPrimitive.Popup>\n </SheetPortal>\n );\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"gap-1.5 p-6 flex flex-col\", className)}\n {...props}\n />\n );\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\"gap-2 p-6 mt-auto flex flex-col\", className)}\n {...props}\n />\n );\n}\n\nfunction SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-foreground text-sm font-medium\", className)}\n {...props}\n />\n );\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: SheetPrimitive.Description.Props) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-muted-foreground text-xs/relaxed\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n};\n","/**\n * ObjectArrayField Component\n *\n * Manages arrays of objects with inline, modal, or drawer editing.\n * Similar to EmbeddedCollectionField but with inline field definitions.\n */\n\nimport { CaretDown, CaretUp, Pencil, Plus, Trash } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useFieldArray, useFormContext, useWatch } from \"react-hook-form\";\nimport type { FieldDefinition } from \"../../builder/field/field\";\nimport { createFieldRegistryProxy } from \"../../builder/proxies\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { selectAdmin, useAdminStore } from \"../../runtime\";\nimport { FormField } from \"../../views/collection/form-field\";\nimport { Button } from \"../ui/button\";\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogHeader,\n\tDialogTitle,\n} from \"../ui/dialog\";\nimport {\n\tSheet,\n\tSheetContent,\n\tSheetDescription,\n\tSheetHeader,\n\tSheetTitle,\n} from \"../ui/sheet\";\nimport type { ArrayFieldConfig, BaseFieldProps } from \"./field-types\";\nimport { gridColumnClasses } from \"./field-utils\";\nimport { LocaleBadge } from \"./locale-badge\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ObjectArrayFieldProps\n\textends BaseFieldProps,\n\t\tPick<\n\t\t\tArrayFieldConfig,\n\t\t\t| \"item\"\n\t\t\t| \"mode\"\n\t\t\t| \"layout\"\n\t\t\t| \"columns\"\n\t\t\t| \"itemLabel\"\n\t\t\t| \"orderable\"\n\t\t\t| \"minItems\"\n\t\t\t| \"maxItems\"\n\t\t> {}\n\n// ============================================================================\n// Nested Field Renderer (for object items)\n// ============================================================================\n\ninterface ItemFieldRendererProps {\n\tfieldName: string;\n\tfieldDef: FieldDefinition;\n\tparentName: string;\n\tdisabled?: boolean;\n}\n\nfunction ItemFieldRenderer({\n\tfieldName,\n\tfieldDef,\n\tparentName,\n\tdisabled,\n}: ItemFieldRendererProps) {\n\tconst resolveText = useResolveText();\n\tconst fullName = `${parentName}.${fieldName}`;\n\tconst fieldType = fieldDef.name;\n\tconst options = fieldDef[\"~options\"] || {};\n\n\treturn (\n\t\t<FormField\n\t\t\tname={fullName}\n\t\t\tlabel={resolveText(options.label)}\n\t\t\tdescription={resolveText(options.description)}\n\t\t\tplaceholder={resolveText(options.placeholder)}\n\t\t\trequired={options.required}\n\t\t\tdisabled={disabled || options.disabled}\n\t\t\ttype={fieldType as any}\n\t\t\toptions={options.options}\n\t\t/>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function ObjectArrayField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\titem: itemProp,\n\tmode = \"inline\",\n\tlayout = \"stack\",\n\tcolumns = 2,\n\titemLabel: itemLabelProp,\n\torderable = false,\n\tminItems,\n\tmaxItems,\n}: ObjectArrayFieldProps) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst resolvedPlaceholder = placeholder\n\t\t? resolveText(placeholder)\n\t\t: undefined;\n\tconst resolvedLabel = label ? resolveText(label) : undefined;\n\tconst form = useFormContext();\n\tconst { control } = form;\n\tconst { fields, append, remove, move } = useFieldArray({ control, name });\n\tconst values = useWatch({ control, name }) as any[] | undefined;\n\n\tconst admin = useAdminStore(selectAdmin);\n\tconst [activeIndex, setActiveIndex] = React.useState<number | null>(null);\n\tconst [isOpen, setIsOpen] = React.useState(false);\n\n\t// Resolve item field definitions\n\tconst itemFields = React.useMemo(() => {\n\t\tif (!itemProp) return {};\n\n\t\tif (typeof itemProp === \"function\") {\n\t\t\tconst registeredFields = admin.getFields();\n\t\t\tconst r = createFieldRegistryProxy(registeredFields as any);\n\t\t\treturn itemProp({ r });\n\t\t}\n\n\t\treturn itemProp;\n\t}, [itemProp, admin]);\n\n\tconst fieldEntries = Object.entries(itemFields);\n\tconst canAddMore = !maxItems || fields.length < maxItems;\n\tconst canRemove = !minItems || fields.length > minItems;\n\tconst fallbackLabel = resolvedLabel || \"Item\";\n\tconst emptyLabel = t(\"array.empty\", { name: fallbackLabel });\n\tconst addLabel = t(\"array.addItem\", { name: fallbackLabel });\n\n\t// Resolve item label\n\tconst resolveItemLabel = React.useCallback(\n\t\t(item: any, index: number) => {\n\t\t\tif (typeof itemLabelProp === \"function\") {\n\t\t\t\tconst labelValue = itemLabelProp(item, index);\n\t\t\t\tif (labelValue) return labelValue;\n\t\t\t}\n\t\t\tif (typeof itemLabelProp === \"string\") {\n\t\t\t\treturn resolveText(itemLabelProp);\n\t\t\t}\n\t\t\t// Try common label fields\n\t\t\tif (item?.name) return String(item.name);\n\t\t\tif (item?.title) return String(item.title);\n\t\t\tif (item?.label) return String(item.label);\n\t\t\treturn `${fallbackLabel} ${index + 1}`;\n\t\t},\n\t\t[fallbackLabel, itemLabelProp, resolveText],\n\t);\n\n\tconst handleAdd = () => {\n\t\tif (disabled || !canAddMore) return;\n\t\t// Create empty object with keys from field definitions (immutable pattern)\n\t\tconst emptyItem = Object.fromEntries(\n\t\t\tfieldEntries.map(([key]) => [key, undefined]),\n\t\t);\n\t\tappend(emptyItem);\n\t\tif (mode !== \"inline\") {\n\t\t\tsetActiveIndex(fields.length);\n\t\t\tsetIsOpen(true);\n\t\t}\n\t};\n\n\tconst handleRemove = (index: number) => {\n\t\tif (!canRemove) return;\n\t\tremove(index);\n\t\tif (activeIndex === null) return;\n\t\tif (index === activeIndex) {\n\t\t\tsetIsOpen(false);\n\t\t\tsetActiveIndex(null);\n\t\t} else if (index < activeIndex) {\n\t\t\tsetActiveIndex(activeIndex - 1);\n\t\t}\n\t};\n\n\tconst handleMove = (from: number, to: number) => {\n\t\tif (to < 0 || to >= fields.length) return;\n\t\tmove(from, to);\n\t\tif (activeIndex === null) return;\n\t\tif (activeIndex === from) {\n\t\t\tsetActiveIndex(to);\n\t\t} else if (activeIndex === to) {\n\t\t\tsetActiveIndex(from);\n\t\t}\n\t};\n\n\tconst handleOpenChange = (open: boolean) => {\n\t\tsetIsOpen(open);\n\t\tif (!open) {\n\t\t\tsetActiveIndex(null);\n\t\t}\n\t};\n\n\t// Render fields for an item at given index\n\tconst renderItemFields = (index: number) => {\n\t\tif (fieldEntries.length === 0) {\n\t\t\treturn (\n\t\t\t\t<div className=\"rounded-lg border border-dashed p-4 text-center\">\n\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\tNo fields configured for items.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tconst fieldElements = fieldEntries.map(([fieldName, fieldDef]) => (\n\t\t\t<ItemFieldRenderer\n\t\t\t\tkey={fieldName}\n\t\t\t\tfieldName={fieldName}\n\t\t\t\tfieldDef={fieldDef as FieldDefinition}\n\t\t\t\tparentName={`${name}.${index}`}\n\t\t\t\tdisabled={disabled}\n\t\t\t/>\n\t\t));\n\n\t\tif (layout === \"inline\") {\n\t\t\treturn (\n\t\t\t\t<div className=\"flex flex-wrap items-end gap-2\">{fieldElements}</div>\n\t\t\t);\n\t\t}\n\n\t\tif (layout === \"grid\") {\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"grid gap-4\",\n\t\t\t\t\t\tgridColumnClasses[columns] || \"grid-cols-2\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{fieldElements}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\t// Default: stack\n\t\treturn <div className=\"space-y-4\">{fieldElements}</div>;\n\t};\n\n\tconst emptyState = (\n\t\t<div className=\"rounded-lg border border-dashed p-4 text-center\">\n\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t{resolvedPlaceholder || emptyLabel}\n\t\t\t</p>\n\t\t</div>\n\t);\n\n\tconst editorContent =\n\t\tactiveIndex !== null ? renderItemFields(activeIndex) : null;\n\tconst editorTitle =\n\t\tactiveIndex !== null\n\t\t\t? resolveItemLabel(values?.[activeIndex], activeIndex)\n\t\t\t: fallbackLabel;\n\n\tconst showEditor = mode === \"modal\" || mode === \"drawer\";\n\n\treturn (\n\t\t<div className=\"space-y-2\">\n\t\t\t{label && (\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<label htmlFor={name} className=\"text-sm font-medium\">\n\t\t\t\t\t\t{resolvedLabel}\n\t\t\t\t\t\t{required && <span className=\"text-destructive\">*</span>}\n\t\t\t\t\t\t{maxItems && (\n\t\t\t\t\t\t\t<span className=\"ml-2 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t({fields.length}/{maxItems})\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</label>\n\t\t\t\t\t{localized && <LocaleBadge locale={locale || \"i18n\"} />}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{description && (\n\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t{resolveText(description)}\n\t\t\t\t</p>\n\t\t\t)}\n\n\t\t\t<div className=\"space-y-3\">\n\t\t\t\t{fields.length === 0\n\t\t\t\t\t? emptyState\n\t\t\t\t\t: fields.map((field, index) => {\n\t\t\t\t\t\t\tconst itemValue = values?.[index];\n\t\t\t\t\t\t\tconst itemLabel = resolveItemLabel(itemValue, index);\n\t\t\t\t\t\t\tconst canMoveUp = orderable && index > 0;\n\t\t\t\t\t\t\tconst canMoveDown = orderable && index < fields.length - 1;\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={field.id}\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-lg border border-border/60 bg-card/30 backdrop-blur-sm\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-between border-b px-3 py-2\">\n\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t#{index + 1}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-sm font-medium\">{itemLabel}</span>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t\t\t\t\t{orderable && (\n\t\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleMove(index, index - 1)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={!canMoveUp || disabled}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Move up\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Move item up\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CaretUp className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleMove(index, index + 1)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={!canMoveDown || disabled}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Move down\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Move item down\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CaretDown className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t{mode !== \"inline\" && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetActiveIndex(index);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetIsOpen(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={t(\"common.edit\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"common.edit\")}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Pencil className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t{canRemove && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleRemove(index)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={t(\"common.remove\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"common.remove\")}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Trash className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t{mode === \"inline\" && (\n\t\t\t\t\t\t\t\t\t\t<div className=\"p-3\">{renderItemFields(index)}</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t</div>\n\n\t\t\t{canAddMore && (\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tonClick={handleAdd}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t>\n\t\t\t\t\t<Plus className=\"h-4 w-4\" />\n\t\t\t\t\t{addLabel}\n\t\t\t\t</Button>\n\t\t\t)}\n\n\t\t\t{showEditor && mode === \"modal\" && (\n\t\t\t\t<Dialog open={isOpen} onOpenChange={handleOpenChange}>\n\t\t\t\t\t<DialogContent className=\"sm:max-w-2xl\">\n\t\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t\t<DialogTitle>{editorTitle}</DialogTitle>\n\t\t\t\t\t\t\t{description && (\n\t\t\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t\t\t{resolveText(description)}\n\t\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</DialogHeader>\n\t\t\t\t\t\t<div className=\"space-y-4\">{editorContent}</div>\n\t\t\t\t\t</DialogContent>\n\t\t\t\t</Dialog>\n\t\t\t)}\n\n\t\t\t{showEditor && mode === \"drawer\" && (\n\t\t\t\t<Sheet open={isOpen} onOpenChange={handleOpenChange}>\n\t\t\t\t\t<SheetContent side=\"right\" className=\"sm:max-w-lg\">\n\t\t\t\t\t\t<SheetHeader>\n\t\t\t\t\t\t\t<SheetTitle>{editorTitle}</SheetTitle>\n\t\t\t\t\t\t\t{description && (\n\t\t\t\t\t\t\t\t<SheetDescription>{resolveText(description)}</SheetDescription>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</SheetHeader>\n\t\t\t\t\t\t<div className=\"space-y-4 p-4\">{editorContent}</div>\n\t\t\t\t\t</SheetContent>\n\t\t\t\t</Sheet>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","/**\n * ArrayField Component\n *\n * Handles arrays of primitive values or objects with optional ordering.\n * When `item` prop is provided, delegates to ObjectArrayField for object items.\n */\n\nimport { CaretDown, CaretUp, Plus, Trash } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useFieldArray, useFormContext, useWatch } from \"react-hook-form\";\nimport type { FieldComponentProps } from \"../../builder\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { Select, SelectContent, SelectItem, SelectTrigger } from \"../ui/select\";\nimport { Textarea } from \"../ui/textarea\";\nimport type { ArrayFieldConfig } from \"./field-types\";\nimport { LocaleBadge } from \"./locale-badge\";\nimport { ObjectArrayField } from \"./object-array-field\";\n\nexport type ArrayFieldItemType =\n\t| \"text\"\n\t| \"number\"\n\t| \"email\"\n\t| \"textarea\"\n\t| \"select\";\n\nexport interface ArrayFieldProps\n\textends FieldComponentProps<any[]>,\n\t\tPick<\n\t\t\tArrayFieldConfig,\n\t\t\t\"item\" | \"mode\" | \"layout\" | \"columns\" | \"itemLabel\"\n\t\t> {\n\titemType?: ArrayFieldItemType;\n\toptions?: Array<{ label: string; value: any }>;\n\torderable?: boolean;\n\tminItems?: number;\n\tmaxItems?: number;\n}\n\nexport function ArrayField({\n\tname,\n\tvalue,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\treadOnly,\n\terror,\n\tlocalized,\n\tlocale,\n\titemType = \"text\",\n\toptions,\n\torderable = false,\n\tminItems,\n\tmaxItems,\n\t// Object array props\n\titem,\n\tmode,\n\tlayout,\n\tcolumns,\n\titemLabel,\n}: ArrayFieldProps) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst resolvedPlaceholder = placeholder\n\t\t? resolveText(placeholder)\n\t\t: undefined;\n\tconst resolvedDescription = description\n\t\t? resolveText(description)\n\t\t: undefined;\n\tconst resolvedLabel = label ? resolveText(label) : undefined;\n\tconst fallbackLabel = resolvedLabel || \"item\";\n\tconst emptyLabel = t(\"array.empty\", { name: fallbackLabel });\n\tconst addLabel = t(\"array.addItem\", { name: fallbackLabel });\n\tconst form = useFormContext();\n\tconst { control } = form;\n\tconst { fields, append, remove, move } = useFieldArray({ control, name });\n\tconst values = (useWatch({ control, name }) as any[] | undefined) ?? value;\n\n\tconst canAddMore = !maxItems || fields.length < maxItems;\n\tconst canRemove = !readOnly && (!minItems || fields.length > minItems);\n\n\tconst createEmptyItem = React.useCallback(() => {\n\t\tif (itemType === \"number\") return undefined;\n\t\tif (itemType === \"select\") {\n\t\t\treturn options?.[0]?.value ?? \"\";\n\t\t}\n\t\treturn \"\";\n\t}, [itemType, options]);\n\n\t// Delegate to ObjectArrayField if item prop is provided (object array)\n\tif (item) {\n\t\treturn (\n\t\t\t<ObjectArrayField\n\t\t\t\tname={name}\n\t\t\t\tlabel={label}\n\t\t\t\tdescription={description}\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\trequired={required}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tlocalized={localized}\n\t\t\t\tlocale={locale}\n\t\t\t\titem={item}\n\t\t\t\tmode={mode}\n\t\t\t\tlayout={layout}\n\t\t\t\tcolumns={columns}\n\t\t\t\titemLabel={itemLabel}\n\t\t\t\torderable={orderable}\n\t\t\t\tminItems={minItems}\n\t\t\t\tmaxItems={maxItems}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Primitive array handling below\n\n\tconst handleAdd = () => {\n\t\tif (disabled || readOnly || !canAddMore) return;\n\t\tappend(createEmptyItem());\n\t};\n\n\tconst handleRemove = (index: number) => {\n\t\tif (!canRemove) return;\n\t\tremove(index);\n\t};\n\n\tconst handleMove = (from: number, to: number) => {\n\t\tif (to < 0 || to >= fields.length) return;\n\t\tmove(from, to);\n\t};\n\n\tconst renderItemInput = (index: number) => {\n\t\tconst itemName = `${name}.${index}`;\n\t\tconst itemValue = values?.[index];\n\t\tconst itemPlaceholder = resolvedPlaceholder || `Item ${index + 1}`;\n\n\t\tif (itemType === \"textarea\") {\n\t\t\treturn (\n\t\t\t\t<Textarea\n\t\t\t\t\tid={itemName}\n\t\t\t\t\tplaceholder={itemPlaceholder}\n\t\t\t\t\tdisabled={disabled || readOnly}\n\t\t\t\t\tdefaultValue={itemValue ?? \"\"}\n\t\t\t\t\t{...form.register(itemName)}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\tif (itemType === \"select\") {\n\t\t\treturn (\n\t\t\t\t<Select\n\t\t\t\t\tvalue={itemValue ?? \"\"}\n\t\t\t\t\tonValueChange={(value) =>\n\t\t\t\t\t\tform.setValue(itemName, value, {\n\t\t\t\t\t\t\tshouldDirty: true,\n\t\t\t\t\t\t\tshouldTouch: true,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\tdisabled={disabled || readOnly}\n\t\t\t\t>\n\t\t\t\t\t<SelectTrigger id={itemName}>\n\t\t\t\t\t\t<span className=\"truncate\">\n\t\t\t\t\t\t\t{options?.find((o) => o.value === itemValue)?.label\n\t\t\t\t\t\t\t\t? resolveText(options.find((o) => o.value === itemValue)?.label)\n\t\t\t\t\t\t\t\t: itemPlaceholder}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t{options?.map((option) => (\n\t\t\t\t\t\t\t<SelectItem key={option.value} value={option.value}>\n\t\t\t\t\t\t\t\t{resolveText(option.label)}\n\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</SelectContent>\n\t\t\t\t</Select>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<Input\n\t\t\t\tid={itemName}\n\t\t\t\ttype={itemType === \"email\" ? \"email\" : itemType}\n\t\t\t\tplaceholder={itemPlaceholder}\n\t\t\t\tdisabled={disabled || readOnly}\n\t\t\t\tdefaultValue={itemValue ?? \"\"}\n\t\t\t\t{...form.register(\n\t\t\t\t\titemName,\n\t\t\t\t\titemType === \"number\" ? { valueAsNumber: true } : undefined,\n\t\t\t\t)}\n\t\t\t/>\n\t\t);\n\t};\n\n\treturn (\n\t\t<div className=\"space-y-2\">\n\t\t\t{label && (\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<label htmlFor={name} className=\"text-sm font-medium\">\n\t\t\t\t\t\t{resolvedLabel}\n\t\t\t\t\t\t{required && <span className=\"text-destructive\">*</span>}\n\t\t\t\t\t\t{maxItems && (\n\t\t\t\t\t\t\t<span className=\"ml-2 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t({fields.length}/{maxItems})\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</label>\n\t\t\t\t\t{localized && <LocaleBadge locale={locale || \"i18n\"} />}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{resolvedDescription && (\n\t\t\t\t<p className=\"text-sm text-muted-foreground\">{resolvedDescription}</p>\n\t\t\t)}\n\n\t\t\t<div className=\"space-y-2\">\n\t\t\t\t{fields.length === 0 ? (\n\t\t\t\t\t<div className=\"rounded-lg border border-dashed p-4 text-center\">\n\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t{resolvedPlaceholder || emptyLabel}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\tfields.map((field, index) => {\n\t\t\t\t\t\tconst canMoveUp = orderable && index > 0;\n\t\t\t\t\t\tconst canMoveDown = orderable && index < fields.length - 1;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div key={field.id} className=\"flex items-start gap-2\">\n\t\t\t\t\t\t\t\t<div className=\"flex-1\">{renderItemInput(index)}</div>\n\t\t\t\t\t\t\t\t{orderable && !readOnly && (\n\t\t\t\t\t\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleMove(index, index - 1)}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={!canMoveUp || disabled}\n\t\t\t\t\t\t\t\t\t\t\ttitle=\"Move up\"\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"Move item up\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<CaretUp className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleMove(index, index + 1)}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={!canMoveDown || disabled}\n\t\t\t\t\t\t\t\t\t\t\ttitle=\"Move down\"\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"Move item down\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<CaretDown className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{!readOnly && canRemove && (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => handleRemove(index)}\n\t\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\t\ttitle=\"Remove\"\n\t\t\t\t\t\t\t\t\t\taria-label=\"Remove item\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Trash className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t\t})\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{!readOnly && canAddMore && (\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tonClick={handleAdd}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t>\n\t\t\t\t\t<Plus className=\"h-4 w-4\" />\n\t\t\t\t\t{addLabel}\n\t\t\t\t</Button>\n\t\t\t)}\n\n\t\t\t{error && <p className=\"text-sm text-destructive\">{error}</p>}\n\t\t</div>\n\t);\n}\n","/**\n * Block System Types\n *\n * Core types for the visual page building system.\n * Server stores blocks as JSONB with $i18n markers - these types\n * define the client-side structure and rendering.\n */\n\nimport type * as React from \"react\";\n\n/**\n * Block node in the tree structure.\n * Represents a single block instance with its position and children.\n */\nexport type BlockNode = {\n\t/** Unique block instance ID (UUID) */\n\tid: string;\n\t/** Block type name (e.g., \"hero\", \"columns\", \"text\") */\n\ttype: string;\n\t/** Child blocks (for layout blocks that accept children) */\n\tchildren: BlockNode[];\n};\n\n/**\n * Block content structure stored in JSONB.\n * This is the shape of data stored in the database and passed to BlockRenderer.\n */\nexport type BlockContent = {\n\t/** Block tree with hierarchy and order */\n\t_tree: BlockNode[];\n\t/** Block values indexed by block ID */\n\t_values: Record<string, Record<string, unknown>>;\n};\n\n/**\n * Block category for organization in the block picker.\n * Categories help users find blocks quickly when adding new content.\n */\nexport type BlockCategory =\n\t| \"layout\" // Columns, Grid, Container, Section\n\t| \"content\" // Text, Heading, List, Quote\n\t| \"media\" // Image, Video, Gallery, Audio\n\t| \"sections\" // Hero, Features, Testimonials, CTA\n\t| \"interactive\" // Form, Accordion, Tabs, Carousel\n\t| (string & {}); // Custom categories\n\n/**\n * Props passed to block renderer components.\n * Each block receives these props when being rendered.\n */\nexport type BlockRendererProps<TValues = Record<string, unknown>> = {\n\t/** Block instance ID */\n\tid: string;\n\t/** Block field values (merged with i18n for current locale) */\n\tvalues: TValues;\n\t/** Data from prefetch function (if defined on block) */\n\tdata?: unknown;\n\t/** Rendered child blocks (for layout blocks) */\n\tchildren?: React.ReactNode;\n\t/** Whether this block is currently selected in the editor */\n\tisSelected?: boolean;\n\t/** Whether rendering in preview mode */\n\tisPreview?: boolean;\n};\n\n/**\n * Block prefetch function type.\n * Called during SSR to fetch data needed by the block.\n * Use with prefetchBlockData() utility in route loaders.\n *\n * @see prefetchBlockData in ./prefetch.ts\n */\nexport type BlockPrefetch<TData = unknown, TCms = unknown> = (params: {\n\t/** Block instance ID */\n\tid: string;\n\t/** Block field values */\n\tvalues: Record<string, unknown>;\n\t/** CMS client for data fetching */\n\tcms: TCms;\n\t/** Current locale */\n\tlocale: string;\n\t/** Default/fallback locale */\n\tdefaultLocale: string;\n\t/** Original request (for headers, cookies, auth) */\n\trequest?: Request;\n}) => Promise<TData>;\n\n/**\n * Empty block content for initialization.\n */\nexport const EMPTY_BLOCK_CONTENT: BlockContent = {\n\t_tree: [],\n\t_values: {},\n};\n\n/**\n * Check if a value is a valid BlockContent structure.\n */\nexport function isBlockContent(value: unknown): value is BlockContent {\n\tif (value == null || typeof value !== \"object\") return false;\n\tconst obj = value as Record<string, unknown>;\n\treturn (\n\t\tArray.isArray(obj._tree) &&\n\t\ttypeof obj._values === \"object\" &&\n\t\tobj._values !== null\n\t);\n}\n\n/**\n * Create a new block node with generated ID.\n */\nexport function createBlockNode(\n\ttype: string,\n\tchildren: BlockNode[] = [],\n): BlockNode {\n\treturn {\n\t\tid: crypto.randomUUID(),\n\t\ttype,\n\t\tchildren,\n\t};\n}\n","\"use client\";\n\nimport { cn } from \"#questpie/admin/client/lib/utils.js\";\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\";\n\nfunction TooltipProvider({\n delay = 0,\n ...props\n}: TooltipPrimitive.Provider.Props) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delay={delay}\n {...props}\n />\n );\n}\n\nfunction Tooltip({ ...props }: TooltipPrimitive.Root.Props) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n );\n}\n\nfunction TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />;\n}\n\nfunction TooltipContent({\n className,\n side = \"top\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 0,\n children,\n ...props\n}: TooltipPrimitive.Popup.Props &\n Pick<\n TooltipPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <TooltipPrimitive.Popup\n data-slot=\"tooltip-content\"\n className={cn(\n \"data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 rounded-md px-3 py-1.5 text-xs bg-foreground text-background z-50 w-fit max-w-xs origin-(--transform-origin)\",\n \"bg-card/10 backdrop-blur-md border text-foreground border-border/60\",\n className,\n )}\n {...props}\n >\n {children}\n {/* <TooltipPrimitive.Arrow\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] z-50 data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5\",\n\t\t\t\t\t\t\t\"bg-card/10 fill-card/10 backdrop-blur-md border-border/60\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t/> */}\n </TooltipPrimitive.Popup>\n </TooltipPrimitive.Positioner>\n </TooltipPrimitive.Portal>\n );\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };\n","/**\n * Shared helper functions for cell rendering\n * Extracted from build-columns.tsx to reduce duplication\n */\n\nimport type { FieldDefinition } from \"../../../../builder/field/field\";\n\n/**\n * Get display label for a relation item\n * Prefers _title (backend computed), then common label fields, then id\n */\nexport function getRelationItemLabel(item: unknown): string {\n\tif (typeof item === \"object\" && item !== null) {\n\t\tconst obj = item as Record<string, unknown>;\n\t\t// Prefer _title computed field from backend\n\t\treturn String(obj._title || obj.name || obj.title || obj.id || \"-\");\n\t}\n\treturn String(item);\n}\n\n/**\n * Get ID from a relation item\n */\nexport function getRelationItemId(item: unknown): string | null {\n\tif (typeof item === \"object\" && item !== null) {\n\t\tconst obj = item as Record<string, unknown>;\n\t\treturn obj.id ? String(obj.id) : null;\n\t}\n\tif (typeof item === \"string\" || typeof item === \"number\") {\n\t\treturn String(item);\n\t}\n\treturn null;\n}\n\n/**\n * Format a field key as a readable label (camelCase -> Title Case)\n */\nexport function formatFieldLabel(key: string): string {\n\treturn key\n\t\t.replace(/([A-Z])/g, \" $1\")\n\t\t.replace(/^./, (str) => str.toUpperCase())\n\t\t.trim();\n}\n\n/**\n * Get label for a field from field definition or format from key\n */\nexport function getFieldLabel(key: string, fieldDef?: FieldDefinition): string {\n\tif (fieldDef?.[\"~options\"]?.label) {\n\t\treturn fieldDef[\"~options\"].label;\n\t}\n\treturn formatFieldLabel(key);\n}\n\n/**\n * Format a primitive value for display\n */\nexport function formatPrimitiveValue(value: unknown): string {\n\tif (value === null || value === undefined) return \"-\";\n\tif (typeof value === \"boolean\") return value ? \"Yes\" : \"No\";\n\tif (value instanceof Date) return value.toLocaleDateString();\n\tif (typeof value === \"number\") return value.toLocaleString();\n\treturn String(value);\n}\n\n/**\n * Summarize a value for inline preview\n */\nexport function summarizeValue(val: unknown): string {\n\tif (val === null || val === undefined) return \"-\";\n\tif (typeof val === \"boolean\") return val ? \"Yes\" : \"No\";\n\tif (typeof val === \"number\") return val.toLocaleString();\n\tif (typeof val === \"string\")\n\t\treturn val.length > 25 ? `${val.slice(0, 25)}…` : val;\n\tif (Array.isArray(val)) return `${val.length} items`;\n\tif (typeof val === \"object\") return `${Object.keys(val).length} fields`;\n\treturn String(val);\n}\n\n/**\n * Get item label from various sources (used in array cells)\n */\nexport function getItemLabel(\n\titem: unknown,\n\tidx: number,\n\titemLabelFn?: (item: unknown) => string,\n): string {\n\tif (itemLabelFn) {\n\t\ttry {\n\t\t\treturn itemLabelFn(item) || `Item ${idx + 1}`;\n\t\t} catch {\n\t\t\treturn `Item ${idx + 1}`;\n\t\t}\n\t}\n\tif (typeof item === \"object\" && item !== null) {\n\t\tconst obj = item as Record<string, unknown>;\n\t\treturn (\n\t\t\tString(\n\t\t\t\tobj.name || obj.title || obj.label || obj.platform || obj.type || \"\",\n\t\t\t) || `Item ${idx + 1}`\n\t\t);\n\t}\n\treturn formatPrimitiveValue(item);\n}\n","/**\n * Complex Cell Components\n *\n * Cells for displaying complex data structures:\n * - JsonCell - simple JSON display\n * - ObjectCell - nested object with hover preview\n * - ArrayCell - array items with hover preview\n * - BlocksCell - block tree summary with tooltip\n */\n\nimport * as React from \"react\";\nimport type { BlockContent, BlockNode } from \"../../../blocks/types\";\nimport { isBlockContent } from \"../../../blocks/types\";\nimport type { BlockDefinition } from \"../../../builder/block/types\";\nimport type { FieldDefinition } from \"../../../builder/field/field\";\nimport { Badge } from \"../../../components/ui/badge\";\nimport {\n\tTooltip,\n\tTooltipContent,\n\tTooltipTrigger,\n} from \"../../../components/ui/tooltip\";\nimport { useResolveText } from \"../../../i18n/hooks\";\nimport { cn } from \"../../../lib/utils\";\nimport { selectAdmin, useAdminStore } from \"../../../runtime\";\nimport {\n\tformatFieldLabel,\n\tformatPrimitiveValue,\n\tgetFieldLabel,\n\tgetItemLabel,\n\tsummarizeValue,\n} from \"./shared/cell-helpers\";\n\n// ============================================================================\n// JSON Cell\n// ============================================================================\n\n/**\n * JSON cell - compact JSON display\n */\nexport function JsonCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\tconst json =\n\t\ttypeof value === \"string\" ? value : JSON.stringify(value, null, 0);\n\tconst truncated = json.length > 50 ? `${json.slice(0, 50)}...` : json;\n\treturn (\n\t\t<span className=\"font-mono text-xs text-muted-foreground\" title={json}>\n\t\t\t{truncated}\n\t\t</span>\n\t);\n}\n\n// ============================================================================\n// Object Cell\n// ============================================================================\n\n/**\n * Object cell - displays nested object with hover tooltip preview\n */\nexport function ObjectCell({\n\tvalue,\n\tfieldDef,\n}: {\n\tvalue: unknown;\n\trow?: unknown;\n\tfieldDef?: FieldDefinition;\n}) {\n\tconst resolveText = useResolveText();\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\tif (typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn <span>{String(value)}</span>;\n\t}\n\n\tconst obj = value as Record<string, unknown>;\n\tconst entries = Object.entries(obj);\n\n\tif (entries.length === 0) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\t// Get nested field definitions for labels\n\tconst nestedFieldsOption = fieldDef?.[\"~options\"]?.fields;\n\tconst nestedFields =\n\t\ttypeof nestedFieldsOption === \"function\" ? undefined : nestedFieldsOption;\n\n\t// Build inline preview: \"Label: value, Label: value +N\"\n\tconst previewParts = entries.slice(0, 2).map(([key, val]) => {\n\t\tconst label = resolveText(getFieldLabel(key, nestedFields?.[key]));\n\t\treturn `${label}: ${summarizeValue(val)}`;\n\t});\n\tconst hasMore = entries.length > 2;\n\n\treturn (\n\t\t<Tooltip>\n\t\t\t<TooltipTrigger>\n\t\t\t\t<span\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"inline-flex items-center gap-1 text-xs\",\n\t\t\t\t\t\t\"text-muted-foreground hover:text-foreground\",\n\t\t\t\t\t\t\"transition-colors cursor-default max-w-[220px]\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"truncate\">{previewParts.join(\", \")}</span>\n\t\t\t\t\t{hasMore && (\n\t\t\t\t\t\t<span className=\"text-muted-foreground/50 shrink-0\">\n\t\t\t\t\t\t\t+{entries.length - 2}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</span>\n\t\t\t</TooltipTrigger>\n\t\t\t<TooltipContent side=\"bottom\" align=\"start\" className={\"w-72 p-0 \"}>\n\t\t\t\t<div className=\"max-h-[300px] overflow-y-auto p-3 space-y-0.5\">\n\t\t\t\t\t{entries.slice(0, 12).map(([key, val]) => {\n\t\t\t\t\t\tconst nestedDef = nestedFields?.[key];\n\t\t\t\t\t\tconst label = resolveText(getFieldLabel(key, nestedDef));\n\n\t\t\t\t\t\t// Nested objects - show with bullet and sub-items\n\t\t\t\t\t\tif (val && typeof val === \"object\" && !Array.isArray(val)) {\n\t\t\t\t\t\t\tconst nestedObj = val as Record<string, unknown>;\n\t\t\t\t\t\t\tconst nestedEntries = Object.entries(nestedObj).slice(0, 4);\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div key={key} className=\"py-1\">\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-1.5 text-xs font-medium\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"size-1 rounded-full bg-foreground/60\" />\n\t\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<div className=\"ml-2.5 pl-2 border-l border-border/50 mt-0.5 space-y-0.5\">\n\t\t\t\t\t\t\t\t\t\t{nestedEntries.map(([k, v]) => (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tkey={k}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex justify-between gap-2 text-[11px]\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{formatFieldLabel(k)}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"truncate max-w-[120px]\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{formatPrimitiveValue(v)}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Arrays - bullet with count\n\t\t\t\t\t\tif (Array.isArray(val)) {\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\t\t\t\tclassName=\"flex items-center justify-between gap-2 text-xs py-0.5\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span className=\"flex items-center gap-1.5\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"size-1 rounded-full bg-foreground/60\" />\n\t\t\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">{label}</span>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<Badge variant=\"secondary\" className=\"h-4 px-1 text-[10px]\">\n\t\t\t\t\t\t\t\t\t\t{val.length}\n\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Primitives - bullet with value\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\t\t\tclassName=\"flex items-center justify-between gap-2 text-xs py-0.5\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span className=\"flex items-center gap-1.5\">\n\t\t\t\t\t\t\t\t\t<span className=\"size-1 rounded-full bg-foreground/60\" />\n\t\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">{label}</span>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span className=\"font-medium truncate max-w-[140px]\">\n\t\t\t\t\t\t\t\t\t{formatPrimitiveValue(val)}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t\t{entries.length > 12 && (\n\t\t\t\t\t<div className=\"text-[11px] text-muted-foreground text-center py-1.5 border-t border-border/50\">\n\t\t\t\t\t\t+{entries.length - 12} more\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</TooltipContent>\n\t\t</Tooltip>\n\t);\n}\n\n// ============================================================================\n// Array Cell\n// ============================================================================\n\n/**\n * Array cell - displays array items with hover tooltip preview\n */\nexport function ArrayCell({\n\tvalue,\n\tfieldDef,\n}: {\n\tvalue: unknown;\n\trow?: unknown;\n\tfieldDef?: FieldDefinition;\n}) {\n\tconst resolveText = useResolveText();\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\tif (!Array.isArray(value)) {\n\t\treturn <span>{String(value)}</span>;\n\t}\n\n\tif (value.length === 0) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\tconst fieldOptions = fieldDef?.[\"~options\"] ?? {};\n\tconst itemLabelFn = fieldOptions.itemLabel as\n\t\t| ((item: unknown) => string)\n\t\t| undefined;\n\tconst itemFieldsOption = fieldOptions.item;\n\tconst itemFields =\n\t\ttypeof itemFieldsOption === \"function\" ? undefined : itemFieldsOption;\n\n\t// Get preview labels for first few items\n\tconst previewLabels = value\n\t\t.slice(0, 3)\n\t\t.map((item, idx) => getItemLabel(item, idx, itemLabelFn));\n\n\treturn (\n\t\t<Tooltip>\n\t\t\t<TooltipTrigger\n\t\t\t\trender={\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"inline-flex items-center gap-1.5 text-xs\",\n\t\t\t\t\t\t\t\"text-muted-foreground hover:text-foreground\",\n\t\t\t\t\t\t\t\"transition-colors cursor-default max-w-[180px]\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\tclassName=\"h-4 min-w-4 px-1 text-[10px] shrink-0\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{value.length}\n\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t<span className=\"truncate\">\n\t\t\t\t\t\t\t{previewLabels[0]}\n\t\t\t\t\t\t\t{value.length > 1 && ` +${value.length - 1}`}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</span>\n\t\t\t\t}\n\t\t\t/>\n\t\t\t<TooltipContent\n\t\t\t\tside=\"bottom\"\n\t\t\t\talign=\"start\"\n\t\t\t\tclassName=\"p-0 w-64 max-w-[90vw] bg-popover/95 backdrop-blur-xl border-border\"\n\t\t\t>\n\t\t\t\t<div className=\"max-h-[280px] overflow-y-auto p-2 space-y-0.5\">\n\t\t\t\t\t{value.slice(0, 10).map((item, idx) => {\n\t\t\t\t\t\tconst label = getItemLabel(item, idx, itemLabelFn);\n\n\t\t\t\t\t\tif (typeof item === \"object\" && item !== null) {\n\t\t\t\t\t\t\tconst obj = item as Record<string, unknown>;\n\t\t\t\t\t\t\tconst details = Object.entries(obj)\n\t\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t\t([k]) =>\n\t\t\t\t\t\t\t\t\t\t![\n\t\t\t\t\t\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\",\n\t\t\t\t\t\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\t\t\t\t\t\"title\",\n\t\t\t\t\t\t\t\t\t\t\t\"label\",\n\t\t\t\t\t\t\t\t\t\t\t\"platform\",\n\t\t\t\t\t\t\t\t\t\t\t\"type\",\n\t\t\t\t\t\t\t\t\t\t].includes(k),\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t.slice(0, 3);\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: stable array from backend\n\t\t\t\t\t\t\t\t<div key={idx} className=\"py-1\">\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-1.5 text-xs font-medium\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"size-1 rounded-full bg-foreground/60\" />\n\t\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t{details.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t<div className=\"ml-2.5 pl-2 border-l border-border/50 mt-0.5 space-y-0.5\">\n\t\t\t\t\t\t\t\t\t\t\t{details.map(([k, v]) => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst itemFieldDef = itemFields?.[k];\n\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={k}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex justify-between gap-2 text-[11px]\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{resolveText(getFieldLabel(k, itemFieldDef))}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"truncate max-w-[100px]\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{formatPrimitiveValue(v)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: stable array from backend\n\t\t\t\t\t\t\t\tkey={idx}\n\t\t\t\t\t\t\t\tclassName=\"flex items-center gap-1.5 text-xs py-0.5\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span className=\"size-1 rounded-full bg-foreground/60\" />\n\t\t\t\t\t\t\t\t{formatPrimitiveValue(item)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t\t{value.length > 10 && (\n\t\t\t\t\t<div className=\"text-[11px] text-muted-foreground text-center py-1.5 border-t border-border/50\">\n\t\t\t\t\t\t+{value.length - 10} more\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</TooltipContent>\n\t\t</Tooltip>\n\t);\n}\n\n// ============================================================================\n// Blocks Cell\n// ============================================================================\n\ntype BlockTypeStat = {\n\ttype: string;\n\tlabel: string;\n\tcount: number;\n};\n\nfunction coerceBlockContent(value: unknown): BlockContent | null {\n\tif (isBlockContent(value)) return value;\n\tif (\n\t\tvalue &&\n\t\ttypeof value === \"object\" &&\n\t\t\"$i18n\" in value &&\n\t\tisBlockContent((value as { $i18n?: unknown }).$i18n)\n\t) {\n\t\treturn (value as { $i18n?: BlockContent }).$i18n ?? null;\n\t}\n\treturn null;\n}\n\nfunction formatBlockType(type: string): string {\n\treturn type\n\t\t.replace(/[-_]/g, \" \")\n\t\t.replace(/([a-z])([A-Z])/g, \"$1 $2\")\n\t\t.replace(/\\b\\w/g, (char) => char.toUpperCase())\n\t\t.trim();\n}\n\nfunction getBlockLabel(\n\ttype: string,\n\tblockDef: BlockDefinition | undefined,\n\tresolveText: ReturnType<typeof useResolveText>,\n): string {\n\tif (!blockDef) return formatBlockType(type);\n\tconst fallback = blockDef.name || formatBlockType(type);\n\treturn resolveText(blockDef.label, fallback) || fallback;\n}\n\nfunction collectBlockStats(tree: BlockNode[]): {\n\ttotal: number;\n\tcounts: Map<string, number>;\n} {\n\tconst counts = new Map<string, number>();\n\tlet total = 0;\n\n\tconst visit = (nodes: BlockNode[]) => {\n\t\tfor (const node of nodes) {\n\t\t\ttotal += 1;\n\t\t\tcounts.set(node.type, (counts.get(node.type) ?? 0) + 1);\n\t\t\tif (node.children?.length) {\n\t\t\t\tvisit(node.children);\n\t\t\t}\n\t\t}\n\t};\n\n\tvisit(tree);\n\treturn { total, counts };\n}\n\n/**\n * Blocks cell - summarizes block tree content with type counts\n */\nexport function BlocksCell({ value }: { value: unknown }) {\n\tconst resolveText = useResolveText();\n\tconst admin = useAdminStore(selectAdmin);\n\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\tconst content = coerceBlockContent(value);\n\tif (!content) {\n\t\treturn <JsonCell value={value} />;\n\t}\n\n\tif (!content._tree.length) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\tconst blockDefs = admin?.state?.blocks as\n\t\t| Record<string, BlockDefinition>\n\t\t| undefined;\n\tconst { total, counts } = collectBlockStats(content._tree);\n\tif (total === 0) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\tconst entries: BlockTypeStat[] = Array.from(counts.entries()).map(\n\t\t([type, count]) => ({\n\t\t\ttype,\n\t\t\tcount,\n\t\t\tlabel: getBlockLabel(type, blockDefs?.[type], resolveText),\n\t\t}),\n\t);\n\n\tentries.sort((a, b) => {\n\t\tif (b.count !== a.count) return b.count - a.count;\n\t\treturn a.label.localeCompare(b.label);\n\t});\n\n\tconst preview = entries\n\t\t.slice(0, 2)\n\t\t.map((entry) =>\n\t\t\tentry.count > 1 ? `${entry.label} x${entry.count}` : entry.label,\n\t\t);\n\tconst extraTypes = entries.length - preview.length;\n\n\treturn (\n\t\t<Tooltip>\n\t\t\t<TooltipTrigger\n\t\t\t\trender={\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"inline-flex items-center gap-1.5 text-xs\",\n\t\t\t\t\t\t\t\"text-muted-foreground hover:text-foreground\",\n\t\t\t\t\t\t\t\"transition-colors cursor-default max-w-[220px]\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\tclassName=\"h-4 min-w-4 px-1 text-[10px] shrink-0\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{total}\n\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t<span className=\"truncate\">\n\t\t\t\t\t\t\t{preview.join(\", \")}\n\t\t\t\t\t\t\t{extraTypes > 0 && ` +${extraTypes}`}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</span>\n\t\t\t\t}\n\t\t\t/>\n\t\t\t<TooltipContent\n\t\t\t\tside=\"bottom\"\n\t\t\t\talign=\"start\"\n\t\t\t\tclassName=\"p-0 w-64 max-w-[90vw] bg-popover/95 backdrop-blur-xl border-border\"\n\t\t\t>\n\t\t\t\t<div className=\"flex items-center justify-between px-2 py-1.5 text-[11px] text-muted-foreground border-b border-border/50\">\n\t\t\t\t\t<span>Blocks</span>\n\t\t\t\t\t<Badge variant=\"secondary\" className=\"h-4 px-1 text-[10px]\">\n\t\t\t\t\t\t{total}\n\t\t\t\t\t</Badge>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"max-h-[280px] overflow-y-auto p-2 space-y-0.5\">\n\t\t\t\t\t{entries.slice(0, 10).map((entry) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={entry.type}\n\t\t\t\t\t\t\tclassName=\"flex items-center justify-between gap-2 text-xs py-0.5\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"truncate\">{entry.label}</span>\n\t\t\t\t\t\t\t<Badge variant=\"secondary\" className=\"h-4 px-1 text-[10px]\">\n\t\t\t\t\t\t\t\t{entry.count}\n\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{entries.length > 10 && (\n\t\t\t\t\t<div className=\"text-[11px] text-muted-foreground text-center py-1.5 border-t border-border/50\">\n\t\t\t\t\t\t+{entries.length - 10} more\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</TooltipContent>\n\t\t</Tooltip>\n\t);\n}\n","/**\n * Confirmation Dialog\n *\n * Reusable confirmation dialog for destructive or important actions.\n * Uses base-ui dialog primitives with responsive design.\n */\n\n\"use client\";\n\nimport { Warning } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"../ui/dialog\";\nimport { Button } from \"../ui/button\";\nimport type { ConfirmationConfig } from \"../../builder/collection/action-types\";\n\nexport interface ConfirmationDialogProps {\n /** Whether the dialog is open */\n open: boolean;\n /** Callback when dialog should close */\n onOpenChange: (open: boolean) => void;\n /** Confirmation configuration */\n config: ConfirmationConfig;\n /** Callback when user confirms */\n onConfirm: () => void | Promise<void>;\n /** Whether the action is currently loading */\n loading?: boolean;\n}\n\n/**\n * ConfirmationDialog - Prompts user to confirm an action\n *\n * @example\n * ```tsx\n * <ConfirmationDialog\n * open={showConfirm}\n * onOpenChange={setShowConfirm}\n * config={{\n * title: \"Delete item?\",\n * description: \"This action cannot be undone.\",\n * destructive: true,\n * }}\n * onConfirm={handleDelete}\n * />\n * ```\n */\nexport function ConfirmationDialog({\n open,\n onOpenChange,\n config,\n onConfirm,\n loading = false,\n}: ConfirmationDialogProps): React.ReactElement {\n const [isProcessing, setIsProcessing] = React.useState(false);\n\n const handleConfirm = async () => {\n setIsProcessing(true);\n try {\n await onConfirm();\n onOpenChange(false);\n } finally {\n setIsProcessing(false);\n }\n };\n\n const isLoading = loading || isProcessing;\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-[425px]\">\n <DialogHeader>\n <div className=\"flex items-start gap-3\">\n {config.destructive && (\n <div className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-destructive/10\">\n <Warning className=\"size-5 text-destructive\" />\n </div>\n )}\n <div className=\"space-y-1\">\n <DialogTitle>{config.title}</DialogTitle>\n {config.description && (\n <DialogDescription>{config.description}</DialogDescription>\n )}\n </div>\n </div>\n </DialogHeader>\n <DialogFooter className=\"mt-4\">\n <Button\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={isLoading}\n >\n {config.cancelLabel || \"Cancel\"}\n </Button>\n <Button\n variant={config.destructive ? \"destructive\" : \"default\"}\n onClick={handleConfirm}\n disabled={isLoading}\n >\n {isLoading ? \"Processing...\" : config.confirmLabel || \"Confirm\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","/**\n * Action Button\n *\n * A button component that renders an action with optional confirmation dialog.\n * Handles different action types (navigate, api, custom, dialog, form).\n */\n\n\"use client\";\n\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport type {\n\tActionContext,\n\tActionDefinition,\n\tActionHelpers,\n\tActionQueryClient,\n} from \"../../builder/collection/action-types\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { selectAuthClient, useAdminStore } from \"../../runtime/provider\";\nimport { Button } from \"../ui/button\";\nimport { ConfirmationDialog } from \"./confirmation-dialog\";\n\nexport interface ActionButtonProps<TItem = any> {\n\t/** Action definition */\n\taction: ActionDefinition<TItem>;\n\t/** Collection name */\n\tcollection: string;\n\t/** Item for row actions */\n\titem?: TItem;\n\t/** Items for bulk actions */\n\titems?: TItem[];\n\t/** Action helpers */\n\thelpers: ActionHelpers;\n\t/** Button size */\n\tsize?: \"default\" | \"sm\" | \"lg\" | \"icon\" | \"icon-sm\" | \"icon-lg\" | \"xs\";\n\t/** Additional class names */\n\tclassName?: string;\n\t/** Show icon only */\n\ticonOnly?: boolean;\n\t/** Callback when action dialog should open */\n\tonOpenDialog?: (action: ActionDefinition<TItem>) => void;\n}\n\n/**\n * ActionButton - Renders an action button with confirmation support\n *\n * @example\n * ```tsx\n * <ActionButton\n * action={deleteAction}\n * collection=\"posts\"\n * item={post}\n * helpers={actionHelpers}\n * />\n * ```\n */\nexport function ActionButton<TItem = any>({\n\taction,\n\tcollection,\n\titem,\n\titems,\n\thelpers,\n\tsize = \"default\",\n\tclassName,\n\ticonOnly = false,\n\tonOpenDialog,\n}: ActionButtonProps<TItem>): React.ReactElement | null {\n\tconst resolveText = useResolveText();\n\tconst authClient = useAdminStore(selectAuthClient);\n\tconst queryClient = useQueryClient();\n\tconst [showConfirm, setShowConfirm] = React.useState(false);\n\tconst [isLoading, setIsLoading] = React.useState(false);\n\n\t// Wrapped query client for action context\n\tconst actionQueryClient: ActionQueryClient = React.useMemo(\n\t\t() => ({\n\t\t\tinvalidateQueries: (filters) => queryClient.invalidateQueries(filters),\n\t\t\trefetchQueries: (filters) => queryClient.refetchQueries(filters),\n\t\t\tresetQueries: (filters) => queryClient.resetQueries(filters),\n\t\t}),\n\t\t[queryClient],\n\t);\n\n\t// Build action context\n\tconst ctx: ActionContext<TItem> = React.useMemo(\n\t\t() => ({\n\t\t\titem,\n\t\t\titems,\n\t\t\tcollection,\n\t\t\thelpers,\n\t\t\tqueryClient: actionQueryClient,\n\t\t\tauthClient,\n\t\t}),\n\t\t[item, items, collection, helpers, actionQueryClient, authClient],\n\t);\n\n\t// Check visibility\n\tconst isVisible = React.useMemo(() => {\n\t\tif (action.visible === undefined) return true;\n\t\tif (typeof action.visible === \"function\") {\n\t\t\treturn action.visible(ctx);\n\t\t}\n\t\treturn action.visible;\n\t}, [action.visible, ctx]);\n\n\t// Check disabled state\n\tconst isDisabled = React.useMemo(() => {\n\t\tif (action.disabled === undefined) return false;\n\t\tif (typeof action.disabled === \"function\") {\n\t\t\treturn action.disabled(ctx);\n\t\t}\n\t\treturn action.disabled;\n\t}, [action.disabled, ctx]);\n\n\tif (!isVisible) return null;\n\n\t// Handle action execution\n\tconst executeAction = async () => {\n\t\tconst { handler } = action;\n\n\t\tswitch (handler.type) {\n\t\t\tcase \"navigate\": {\n\t\t\t\tconst path =\n\t\t\t\t\ttypeof handler.path === \"function\"\n\t\t\t\t\t\t? handler.path(item!)\n\t\t\t\t\t\t: handler.path;\n\t\t\t\thelpers.navigate(\n\t\t\t\t\t`${helpers.basePath}/collections/${collection}/${path}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"api\": {\n\t\t\t\tsetIsLoading(true);\n\t\t\t\ttry {\n\t\t\t\t\t// Build endpoint - replace {id} placeholder\n\t\t\t\t\tconst endpoint = handler.endpoint.replace(\n\t\t\t\t\t\t\"{id}\",\n\t\t\t\t\t\tString((item as any)?.id || \"\"),\n\t\t\t\t\t);\n\n\t\t\t\t\t// This would need actual API implementation\n\t\t\t\t\t// For now, we'll show a placeholder\n\t\t\t\t\thelpers.toast.info(\n\t\t\t\t\t\t`API call: ${handler.method || \"POST\"} ${endpoint}`,\n\t\t\t\t\t);\n\t\t\t\t\thelpers.refresh();\n\t\t\t\t} catch (error) {\n\t\t\t\t\thelpers.toast.error(\"Action failed\");\n\t\t\t\t} finally {\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"custom\": {\n\t\t\t\tsetIsLoading(true);\n\t\t\t\ttry {\n\t\t\t\t\tawait handler.fn(ctx);\n\t\t\t\t} catch (error) {\n\t\t\t\t\thelpers.toast.error(\"Action failed\");\n\t\t\t\t} finally {\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"dialog\":\n\t\t\tcase \"form\": {\n\t\t\t\t// Open dialog through parent component\n\t\t\t\tonOpenDialog?.(action);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Handle button click\n\tconst handleClick = (e: React.MouseEvent) => {\n\t\te.stopPropagation(); // Prevent row click propagation\n\n\t\tif (action.confirmation) {\n\t\t\tsetShowConfirm(true);\n\t\t} else {\n\t\t\texecuteAction();\n\t\t}\n\t};\n\n\t// Handle confirmation\n\tconst handleConfirm = async () => {\n\t\tawait executeAction();\n\t};\n\n\t// Render icon - cast to ComponentType since we know icons are direct components\n\tconst Icon = action.icon as\n\t\t| React.ComponentType<React.SVGProps<SVGSVGElement>>\n\t\t| undefined;\n\n\treturn (\n\t\t<>\n\t\t\t<Button\n\t\t\t\tvariant={action.variant || \"default\"}\n\t\t\t\tsize={iconOnly ? \"icon-sm\" : size}\n\t\t\t\tonClick={handleClick}\n\t\t\t\tdisabled={isDisabled || isLoading}\n\t\t\t\tclassName={className}\n\t\t\t>\n\t\t\t\t{Icon && <Icon data-icon=\"inline-start\" />}\n\t\t\t\t{!iconOnly && resolveText(action.label)}\n\t\t\t</Button>\n\n\t\t\t{action.confirmation && (\n\t\t\t\t<ConfirmationDialog\n\t\t\t\t\topen={showConfirm}\n\t\t\t\t\tonOpenChange={setShowConfirm}\n\t\t\t\t\tconfig={action.confirmation}\n\t\t\t\t\tonConfirm={handleConfirm}\n\t\t\t\t\tloading={isLoading}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","/**\n * Client-side Validation Schema Builder\n *\n * Generates Zod schemas from admin field configurations.\n * Uses createZod from field definitions for automatic schema generation.\n * Supports nested fields (object, array) via recursive schema building.\n */\n\nimport { z } from \"zod\";\nimport type { FieldDefinition, ZodBuildContext } from \"./field/field\";\nimport type { FieldValidationConfig } from \"./types/field-types\";\nimport { builtInFields, createRegistryProxy } from \"./defaults/fields\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Collection fields map (from admin config)\n */\ntype FieldsMap = Record<string, FieldDefinition>;\n\n/**\n * Field registry type\n */\ntype FieldRegistry = Record<string, any>;\n\n// ============================================================================\n// Fallback Schema Builders (for fields without createZod)\n// ============================================================================\n\n/**\n * Build a string schema with validations (fallback)\n */\nfunction buildStringSchema(validation?: FieldValidationConfig): z.ZodString {\n let schema = z.string();\n\n if (validation) {\n if (validation.minLength !== undefined) {\n schema = schema.min(\n validation.minLength,\n `Must be at least ${validation.minLength} characters`,\n );\n }\n if (validation.maxLength !== undefined) {\n schema = schema.max(\n validation.maxLength,\n `Must be at most ${validation.maxLength} characters`,\n );\n }\n if (validation.email) {\n schema = schema.email(\"Invalid email address\");\n }\n if (validation.url) {\n schema = schema.url(\"Invalid URL\");\n }\n if (validation.pattern) {\n const regex =\n typeof validation.pattern === \"string\"\n ? new RegExp(validation.pattern)\n : validation.pattern;\n schema = schema.regex(\n regex,\n validation.patternMessage || \"Invalid format\",\n );\n }\n }\n\n return schema;\n}\n\n/**\n * Build a number schema with validations (fallback)\n */\nfunction buildNumberSchema(validation?: FieldValidationConfig): z.ZodNumber {\n let schema = z.number();\n\n if (validation) {\n if (validation.min !== undefined) {\n schema = schema.min(validation.min, `Must be at least ${validation.min}`);\n }\n if (validation.max !== undefined) {\n schema = schema.max(validation.max, `Must be at most ${validation.max}`);\n }\n }\n\n return schema;\n}\n\n/**\n * Fallback schema builder for fields without createZod\n */\nfunction buildFallbackSchema(\n fieldType: string,\n required?: boolean,\n validation?: FieldValidationConfig,\n): z.ZodTypeAny {\n let schema: z.ZodTypeAny;\n\n switch (fieldType) {\n case \"text\":\n case \"textarea\":\n case \"email\":\n case \"password\":\n case \"slug\":\n case \"code\":\n case \"time\":\n schema = buildStringSchema(validation);\n break;\n\n case \"number\":\n case \"currency\":\n schema = buildNumberSchema(validation);\n break;\n\n case \"switch\":\n case \"checkbox\":\n schema = z.boolean();\n break;\n\n case \"date\":\n case \"datetime\":\n schema = z.date().or(z.string());\n break;\n\n case \"select\":\n schema = z.string().or(z.number());\n break;\n\n case \"relation\":\n schema = z.string().or(z.array(z.string()));\n break;\n\n case \"upload\":\n schema = z.string();\n break;\n\n case \"uploadMany\":\n schema = z.array(z.string());\n break;\n\n case \"array\":\n schema = z.array(z.any());\n break;\n\n case \"object\":\n schema = z.record(z.string(), z.any());\n break;\n\n case \"json\":\n case \"richText\":\n schema = z.any();\n break;\n\n default:\n schema = z.any();\n }\n\n // Apply custom refinement from validation config\n if (validation?.refine) {\n schema = validation.refine(schema);\n }\n\n // Handle required/optional\n if (!required) {\n schema = schema.optional().nullable();\n }\n\n return schema;\n}\n\n// ============================================================================\n// Main Schema Builder\n// ============================================================================\n\n/**\n * Creates the ZodBuildContext for recursive schema building\n */\nfunction createBuildContext(registry: FieldRegistry): ZodBuildContext {\n const ctx: ZodBuildContext = {\n registry,\n buildSchema: (fieldDef: FieldDefinition): z.ZodTypeAny => {\n const opts = fieldDef[\"~options\"] || {};\n\n // If field has createZod, use it\n if (fieldDef.createZod) {\n return fieldDef.createZod(opts, ctx);\n }\n\n // Fallback to generic schema based on field type name\n return buildFallbackSchema(fieldDef.name, opts.required, opts.validation);\n },\n };\n\n return ctx;\n}\n\n/**\n * Build a Zod schema from admin field definitions\n *\n * Uses createZod from each field definition if available,\n * otherwise falls back to generic schema based on field type.\n *\n * @param fields - Field definitions from admin collection config\n * @param registry - Field registry (defaults to builtInFields)\n * @returns Zod object schema for the collection\n *\n * @example\n * ```ts\n * const schema = buildValidationSchema(collectionConfig.fields);\n *\n * // Use with react-hook-form\n * const form = useForm({\n * resolver: zodResolver(schema),\n * });\n * ```\n */\nexport function buildValidationSchema(\n fields: FieldsMap,\n registry: FieldRegistry = builtInFields,\n): z.ZodObject<Record<string, z.ZodTypeAny>> {\n const ctx = createBuildContext(registry);\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const [name, fieldDef] of Object.entries(fields)) {\n shape[name] = ctx.buildSchema(fieldDef);\n }\n\n return z.object(shape);\n}\n\n/**\n * Build validation schema with custom validation functions\n *\n * This version supports the `validate` callback in FieldValidationConfig\n * which receives form values for cross-field validation.\n *\n * @param fields - Field definitions from admin collection config\n * @param registry - Field registry (defaults to builtInFields)\n * @returns Zod schema with superRefine for custom validators\n */\nexport function buildValidationSchemaWithCustom(\n fields: FieldsMap,\n registry: FieldRegistry = builtInFields,\n): z.ZodTypeAny {\n const baseSchema = buildValidationSchema(fields, registry);\n\n // Collect fields with custom validate functions\n const customValidators: Array<{\n name: string;\n validate: NonNullable<FieldValidationConfig[\"validate\"]>;\n }> = [];\n\n for (const [name, fieldDef] of Object.entries(fields)) {\n const options = fieldDef[\"~options\"] || {};\n if (options.validation?.validate) {\n customValidators.push({\n name,\n validate: options.validation.validate,\n });\n }\n }\n\n // If no custom validators, return base schema\n if (customValidators.length === 0) {\n return baseSchema;\n }\n\n // Apply custom validators via superRefine\n return baseSchema.superRefine((data, ctx) => {\n for (const { name, validate } of customValidators) {\n const error = validate(data[name], data);\n if (error) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: error,\n path: [name],\n });\n }\n }\n });\n}\n\n/**\n * Create a Zod validation schema from admin field config\n *\n * Use with @hookform/resolvers/zod for react-hook-form integration.\n *\n * @param fields - Field definitions from admin collection config\n * @param registry - Field registry (defaults to builtInFields)\n * @returns Zod schema for form validation\n *\n * @example\n * ```tsx\n * import { zodResolver } from \"@hookform/resolvers/zod\";\n * import { createFormSchema } from \"@questpie/admin/builder\";\n *\n * // From collection config\n * const schema = createFormSchema(collectionConfig.fields);\n *\n * function MyForm() {\n * const form = useForm({\n * resolver: zodResolver(schema),\n * });\n * // ...\n * }\n *\n * // Or use the hook\n * import { useCollectionValidation } from \"@questpie/admin/hooks\";\n *\n * function MyCollectionForm() {\n * const schema = useCollectionValidation(\"posts\");\n * const form = useForm({\n * resolver: schema ? zodResolver(schema) : undefined,\n * });\n * }\n * ```\n */\nexport function createFormSchema(\n fields: FieldsMap,\n registry: FieldRegistry = builtInFields,\n): z.ZodTypeAny {\n return buildValidationSchemaWithCustom(fields, registry);\n}\n\n// ============================================================================\n// Re-exports for convenience\n// ============================================================================\n\nexport { createRegistryProxy } from \"./defaults/fields\";\nexport type { ZodBuildContext } from \"./field/field\";\n","/**\n * Field Component Types\n *\n * Types for field components, form views, and field configuration.\n */\n\nimport type { z } from \"zod\";\nimport type { I18nText } from \"../../i18n/types.js\";\nimport type { ActionDefinition } from \"../collection/action-types\";\nimport type {\n\tBaseFieldProps,\n\tDynamicI18nText,\n\tIconComponent,\n\tMaybeLazyComponent,\n} from \"./common\";\n\n// ============================================================================\n// Validation Configuration\n// ============================================================================\n\n/**\n * Validation configuration for fields\n *\n * These options are used to generate Zod schemas for client-side validation.\n */\nexport interface FieldValidationConfig {\n\t/**\n\t * Minimum length for strings\n\t */\n\tminLength?: number;\n\n\t/**\n\t * Maximum length for strings\n\t */\n\tmaxLength?: number;\n\n\t/**\n\t * Minimum value for numbers\n\t */\n\tmin?: number;\n\n\t/**\n\t * Maximum value for numbers\n\t */\n\tmax?: number;\n\n\t/**\n\t * Regex pattern for strings\n\t */\n\tpattern?: RegExp | string;\n\n\t/**\n\t * Custom error message for pattern validation\n\t */\n\tpatternMessage?: string;\n\n\t/**\n\t * Email validation (for text fields)\n\t */\n\temail?: boolean;\n\n\t/**\n\t * URL validation (for text fields)\n\t */\n\turl?: boolean;\n\n\t/**\n\t * Custom validation function\n\t * @returns Error message if invalid, undefined if valid\n\t */\n\tvalidate?: (\n\t\tvalue: any,\n\t\tformValues: Record<string, any>,\n\t) => string | undefined;\n\n\t/**\n\t * Custom Zod refinement\n\t */\n\trefine?: (schema: z.ZodTypeAny) => z.ZodTypeAny;\n}\n\n// ============================================================================\n// Field Component Props\n// ============================================================================\n\n/**\n * Props passed to field components\n *\n * @typeParam TValue - Type of the field value\n */\nexport interface FieldComponentProps<TValue = any> extends BaseFieldProps {\n\t/**\n\t * Field value (typed)\n\t */\n\tvalue: TValue;\n\n\t/**\n\t * Change handler (typed)\n\t * Optional to support read-only/preview modes\n\t */\n\tonChange?: (value: TValue) => void;\n\n\t/**\n\t * Field configuration options\n\t */\n\tconfig?: FieldUIConfig;\n}\n\n/**\n * Props for embedded collection fields\n */\nexport interface EmbeddedCollectionProps extends BaseFieldProps {\n\t/**\n\t * Target collection name\n\t */\n\tcollection: string;\n\n\t/**\n\t * Display mode\n\t */\n\tmode?: \"inline\" | \"modal\" | \"drawer\";\n\n\t/**\n\t * Whether items can be reordered\n\t */\n\torderable?: boolean;\n\n\t/**\n\t * Function to generate row labels\n\t */\n\trowLabel?: (item: any) => string;\n}\n\n// ============================================================================\n// Field Hooks Context\n// ============================================================================\n\n/**\n * Context provided to field hooks (onChange, etc.)\n */\nexport interface FieldHookContext {\n\t/**\n\t * Set value of any field in the form\n\t */\n\tsetValue: (name: string, value: any) => void;\n\n\t/**\n\t * Get current values of all fields\n\t */\n\tgetValues: () => Record<string, any>;\n\n\t/**\n\t * Get value of a specific field\n\t */\n\tgetValue: (name: string) => any;\n\n\t/**\n\t * Current field name\n\t */\n\tfieldName: string;\n\n\t/**\n\t * Current locale (for localized fields)\n\t */\n\tlocale?: string;\n}\n\n// ============================================================================\n// Field UI Configuration\n// ============================================================================\n\n/**\n * Field UI configuration (per-field overrides in collection config)\n */\nexport interface FieldUIConfig {\n\t/**\n\t * Display label\n\t */\n\tlabel?: DynamicI18nText;\n\n\t/**\n\t * Description text\n\t */\n\tdescription?: DynamicI18nText;\n\n\t/**\n\t * Placeholder text\n\t */\n\tplaceholder?: DynamicI18nText;\n\n\t/**\n\t * Field type override\n\t */\n\ttype?: string;\n\n\t/**\n\t * Whether field is required\n\t */\n\trequired?: boolean | ((values: Record<string, any>) => boolean);\n\n\t/**\n\t * Whether field is read-only\n\t */\n\treadOnly?: boolean | ((values: Record<string, any>) => boolean);\n\n\t/**\n\t * Whether field is disabled (grayed out, can be dynamic)\n\t */\n\tdisabled?: boolean | ((values: Record<string, any>) => boolean);\n\n\t/**\n\t * Whether field is hidden (can be dynamic based on form values).\n\t * Hidden fields are not rendered. Default is false (visible).\n\t *\n\t * Note: undefined/false = visible, true = hidden.\n\t * This follows JavaScript falsy semantics for better DX.\n\t */\n\thidden?: boolean | ((values: Record<string, any>) => boolean);\n\n\t/**\n\t * Whether field is localized\n\t */\n\tlocalized?: boolean;\n\n\t/**\n\t * Validation configuration for client-side validation\n\t */\n\tvalidation?: FieldValidationConfig;\n\n\t/**\n\t * Custom field component\n\t */\n\tcomponent?: MaybeLazyComponent<FieldComponentProps>;\n\n\t/**\n\t * Additional options for field type\n\t */\n\toptions?: SelectOption[] | ((values: Record<string, any>) => SelectOption[]);\n\n\t/**\n\t * Relation configuration\n\t */\n\trelation?: RelationFieldConfig;\n\n\t/**\n\t * Embedded collection configuration\n\t */\n\tembedded?: EmbeddedFieldConfig;\n\n\t/**\n\t * Rich text configuration\n\t */\n\trichText?: RichTextConfig;\n\n\t/**\n\t * Array field configuration\n\t */\n\tarray?: ArrayFieldConfig;\n\n\t// ========================================================================\n\t// Field Hooks\n\t// ========================================================================\n\n\t/**\n\t * Compute field value from other fields (proxy-tracked dependencies).\n\t * Makes the field read-only and virtual (not submitted to backend).\n\t *\n\t * Dependencies are automatically detected via Proxy tracking.\n\t * Works in both forms (reactive) and tables (static).\n\t *\n\t * @example\n\t * ```ts\n\t * pricePerMinute: r.number({\n\t * label: \"Price/Minute\",\n\t * compute: (values) => values.price / values.duration,\n\t * })\n\t *\n\t * fullName: r.text({\n\t * compute: (values) => `${values.firstName} ${values.lastName}`,\n\t * })\n\t * ```\n\t */\n\tcompute?: (values: Record<string, any>) => any;\n\n\t/**\n\t * Called when field value changes.\n\t * Use for side effects like updating other fields.\n\t * Can be async for API calls.\n\t *\n\t * @example\n\t * ```ts\n\t * onChange: async (value, { setValue }) => {\n\t * // Auto-generate slug from title\n\t * setValue('slug', slugify(value));\n\t * }\n\t * ```\n\t */\n\tonChange?: (value: any, ctx: FieldHookContext) => void | Promise<void>;\n\n\t/**\n\t * Dynamic default value for new records.\n\t * Can be a static value, sync function, or async function.\n\t * Only evaluated when creating new records (not on edit).\n\t *\n\t * @example\n\t * ```ts\n\t * // Static\n\t * defaultValue: \"draft\"\n\t *\n\t * // Based on other fields\n\t * defaultValue: (values) => values.type === \"post\" ? \"draft\" : \"published\"\n\t *\n\t * // Async (fetch from API)\n\t * defaultValue: async (values) => {\n\t * const settings = await fetchSettings();\n\t * return settings.defaultStatus;\n\t * }\n\t * ```\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 for select-type fields.\n\t * Dependencies are automatically detected via Proxy tracking.\n\t *\n\t * @example\n\t * ```ts\n\t * subcategory: r.select({\n\t * loadOptions: async (values) => {\n\t * // Automatically re-fetches when values.category changes\n\t * return fetchSubcategories(values.category);\n\t * },\n\t * })\n\t * ```\n\t */\n\tloadOptions?: (values: Record<string, any>) => Promise<SelectOption[]>;\n}\n\n/**\n * Select field option\n */\nexport interface SelectOption {\n\tlabel: I18nText;\n\tvalue: string | number | boolean;\n\tdisabled?: boolean;\n}\n\n/**\n * Relation field configuration\n */\nexport interface RelationFieldConfig {\n\t/**\n\t * Target collection name\n\t */\n\ttargetCollection: string;\n\n\t/**\n\t * Display mode\n\t */\n\tmode?: \"inline\" | \"picker\" | \"create\";\n\n\t/**\n\t * Whether multiple items can be selected\n\t */\n\tmultiple?: boolean;\n\n\t/**\n\t * Whether items can be reordered\n\t */\n\torderable?: boolean;\n\n\t/**\n\t * Filter for relation options\n\t */\n\tfilter?: (values: Record<string, any>) => Record<string, any>;\n}\n\n/**\n * Embedded collection configuration\n */\nexport interface EmbeddedFieldConfig {\n\t/**\n\t * Target collection name\n\t */\n\tcollection: string;\n\n\t/**\n\t * Display mode\n\t */\n\tmode?: \"inline\" | \"modal\" | \"drawer\";\n\n\t/**\n\t * Whether items can be reordered\n\t */\n\torderable?: boolean;\n\n\t/**\n\t * Function to generate row labels\n\t */\n\trowLabel?: (item: any) => string;\n}\n\n/**\n * Rich text editor configuration\n */\nexport interface RichTextConfig {\n\t/**\n\t * Output format\n\t */\n\toutputFormat?: \"html\" | \"json\" | \"markdown\";\n\n\t/**\n\t * Enable image uploads\n\t */\n\tenableImages?: boolean;\n\n\t/**\n\t * Show character count\n\t */\n\tshowCharacterCount?: boolean;\n\n\t/**\n\t * Maximum characters\n\t */\n\tmaxCharacters?: number;\n\n\t/**\n\t * Feature toggles\n\t */\n\tfeatures?: {\n\t\tslashCommands?: boolean;\n\t\ttableControls?: boolean;\n\t\tbubbleMenu?: boolean;\n\t};\n\n\t/**\n\t * Image upload handler\n\t */\n\tonImageUpload?: (file: File) => Promise<string>;\n}\n\n/**\n * Array field configuration\n */\nexport interface ArrayFieldConfig {\n\t/**\n\t * Placeholder text for items\n\t */\n\tplaceholder?: string;\n\n\t/**\n\t * Type of items in array\n\t */\n\titemType?: string;\n\n\t/**\n\t * Options for select-type items\n\t */\n\toptions?: SelectOption[];\n\n\t/**\n\t * Whether items can be reordered\n\t */\n\torderable?: boolean;\n\n\t/**\n\t * Minimum items\n\t */\n\tminItems?: number;\n\n\t/**\n\t * Maximum items\n\t */\n\tmaxItems?: number;\n}\n\n// ============================================================================\n// Field Layout Configuration - Mirrors Object Field API\n// ============================================================================\n\n/**\n * Layout mode - controls spatial arrangement of fields\n * Mirrors ObjectFieldLayout from field components\n *\n * - `\"stack\"` - Vertical layout, each field on its own line\n * - `\"inline\"` - Horizontal flexbox, fields side-by-side with wrapping\n * - `\"grid\"` - CSS Grid with configurable columns\n *\n * @see ObjectFieldLayout in field-types.ts for detailed visual examples\n */\nexport type LayoutMode = \"stack\" | \"inline\" | \"grid\";\n\n/**\n * Wrapper mode - controls container visual appearance\n * Mirrors ObjectFieldWrapper from field components\n *\n * - `\"flat\"` - No visual container, fields render directly\n * - `\"collapsible\"` - Accordion-style expandable container\n *\n * @see ObjectFieldWrapper in field-types.ts for detailed visual examples\n */\nexport type WrapperMode = \"flat\" | \"collapsible\";\n\n/**\n * Section layout - universal container for grouping fields\n *\n * Mirrors object field API exactly:\n * - wrapper: visual container style (flat | collapsible)\n * - layout: field arrangement (stack | inline | grid)\n * - columns: for grid layout\n * - defaultCollapsed: for collapsible wrapper\n *\n * @example Simple section with label\n * ```ts\n * {\n * type: 'section',\n * label: 'Contact Information',\n * fields: [f.name, f.email, f.phone]\n * }\n * ```\n *\n * @example Grid layout (acts as \"row\")\n * ```ts\n * {\n * type: 'section',\n * layout: 'grid',\n * columns: 2,\n * fields: [f.firstName, f.lastName]\n * }\n * ```\n *\n * @example Collapsible section\n * ```ts\n * {\n * type: 'section',\n * label: 'Advanced Settings',\n * wrapper: 'collapsible',\n * defaultCollapsed: true,\n * fields: [f.apiKey, f.webhookUrl]\n * }\n * ```\n *\n * @example Collapsible + Grid\n * ```ts\n * {\n * type: 'section',\n * label: 'Address',\n * wrapper: 'collapsible',\n * layout: 'grid',\n * columns: 2,\n * fields: [f.street, f.city, f.zip, f.country]\n * }\n * ```\n */\nexport interface SectionLayout {\n\ttype: \"section\";\n\n\t// Visual grouping\n\tlabel?: DynamicI18nText;\n\tdescription?: DynamicI18nText;\n\n\t// Wrapper (mirrors object field)\n\twrapper?: WrapperMode;\n\tdefaultCollapsed?: boolean;\n\n\t// Layout (mirrors object field)\n\tlayout?: LayoutMode;\n\tcolumns?: number;\n\tgap?: number;\n\n\t// Content\n\tfields: FieldLayoutItem[];\n\n\t// Conditional visibility (hidden: false/undefined = visible, true = hidden)\n\thidden?: boolean | ((values: Record<string, any>) => boolean);\n\n\t// Custom styling\n\tclassName?: string;\n}\n\n/**\n * Tab configuration for tabbed forms\n */\nexport interface TabConfig {\n\tid: string;\n\tlabel: DynamicI18nText;\n\ticon?: IconComponent;\n\tfields: FieldLayoutItem[];\n\t// Conditional visibility (hidden: false/undefined = visible, true = hidden)\n\thidden?: boolean | ((values: Record<string, any>) => boolean);\n}\n\n/**\n * Tabs layout - tabbed navigation container\n *\n * @example Simple tabs\n * ```ts\n * {\n * type: 'tabs',\n * tabs: [\n * { id: 'basic', label: 'Basic Info', fields: [f.name, f.email] },\n * { id: 'advanced', label: 'Advanced', fields: [f.settings] }\n * ]\n * }\n * ```\n *\n * @example Tabs with sections\n * ```ts\n * {\n * type: 'tabs',\n * tabs: [\n * {\n * id: 'profile',\n * label: 'Profile',\n * fields: [\n * { type: 'section', layout: 'grid', columns: 2, fields: [f.name, f.email] },\n * { type: 'section', label: 'Bio', fields: [f.bio] }\n * ]\n * }\n * ]\n * }\n * ```\n */\nexport interface TabsLayout {\n\ttype: \"tabs\";\n\ttabs: TabConfig[];\n}\n\n/**\n * Field layout item - union of field reference or layout container\n *\n * Can be:\n * - Field name string: \"name\"\n * - Field with className: { field: \"name\", className: \"...\" }\n * - Section layout: { type: 'section', ... }\n * - Tabs layout: { type: 'tabs', ... }\n *\n * @example\n * ```ts\n * fields: [\n * f.name, // string\n * { field: f.email, className: 'col-span-2' }, // with className\n * { type: 'section', layout: 'grid', columns: 2, fields: [...] }, // section\n * { type: 'tabs', tabs: [...] } // tabs\n * ]\n * ```\n */\nexport type FieldLayoutItem =\n\t| string\n\t| { field: string; className?: string }\n\t| SectionLayout\n\t| TabsLayout;\n\n/**\n * Helper to check if item is a field reference (string or object with field)\n */\nexport function isFieldReference(\n\titem: FieldLayoutItem,\n): item is string | { field: string; className?: string } {\n\treturn typeof item === \"string\" || (\"field\" in item && !(\"type\" in item));\n}\n\n/**\n * Helper to get field name from layout item\n */\nexport function getFieldName(item: FieldLayoutItem): string | null {\n\tif (typeof item === \"string\") return item;\n\tif (\"field\" in item && typeof item.field === \"string\") return item.field;\n\treturn null;\n}\n\n/**\n * Helper to get className from field layout item\n */\nexport function getFieldClassName(item: FieldLayoutItem): string | undefined {\n\treturn typeof item === \"string\"\n\t\t? undefined\n\t\t: \"className\" in item\n\t\t\t? item.className\n\t\t\t: undefined;\n}\n\n// ============================================================================\n// Form View Configuration\n// ============================================================================\n\n/**\n * Form sidebar configuration\n * Uses `fields` array (same structure as main form)\n */\nexport interface FormSidebarConfig {\n\tposition?: \"left\" | \"right\";\n\tfields: FieldLayoutItem[];\n}\n\n/**\n * Form view configuration\n * Uses `fields` array for main content\n *\n * @example\n * ```ts\n * .form(({ v, f }) => v.form({\n * sidebar: {\n * position: 'right',\n * fields: [f.status, f.publishedAt]\n * },\n * fields: [\n * { type: 'section', layout: 'grid', columns: 2, fields: [f.name, f.email] },\n * { type: 'section', label: 'Content', fields: [f.body] }\n * ]\n * }))\n * ```\n */\nexport interface FormViewConfig {\n\tfields: FieldLayoutItem[];\n\tsidebar?: FormSidebarConfig;\n\tshowVersionHistory?: boolean;\n\tactions?: FormViewActionsConfig;\n}\n\n/**\n * Actions configuration for form views\n *\n * @example\n * ```ts\n * actions: {\n * primary: [a.action({ id: \"publish\", label: \"Publish\" })], // Buttons next to Save\n * secondary: [a.action({ id: \"delete\", label: \"Delete\" })], // In dropdown menu (...)\n * }\n * ```\n */\nexport interface FormViewActionsConfig<TItem = any> {\n\t/** Actions shown as buttons (next to Save) */\n\tprimary?: ActionDefinition<TItem>[];\n\t/** Actions shown in dropdown menu (...) */\n\tsecondary?: ActionDefinition<TItem>[];\n}\n\n// ============================================================================\n// Component Registry\n// ============================================================================\n\n/**\n * Registry for custom field and widget components\n */\nexport interface ComponentRegistry {\n\t/**\n\t * Custom field components by type\n\t */\n\tfields?: Record<string, MaybeLazyComponent<FieldComponentProps>>;\n\n\t/**\n\t * Custom widget components by type\n\t */\n\twidgets?: Record<string, MaybeLazyComponent<any>>;\n\n\t/**\n\t * Custom named components (for component prop on fields)\n\t */\n\tcustom?: Record<string, MaybeLazyComponent<any>>;\n}\n","/**\n * Auto Expand Fields Utility\n *\n * Automatically detects upload and relation fields that need to be expanded\n * when fetching data from the backend (e.g., for displaying in list views).\n */\n\nimport type { FieldDefinition } from \"../builder/field/field\";\n\nexport interface AutoExpandFieldsConfig {\n\t/**\n\t * Collection fields configuration\n\t */\n\tfields?: Record<string, FieldDefinition>;\n\n\t/**\n\t * List view configuration\n\t */\n\tlist?: {\n\t\t/**\n\t\t * Explicit relations to include\n\t\t */\n\t\twith?: string[];\n\n\t\t/**\n\t\t * Columns to display\n\t\t */\n\t\tcolumns?: Array<string | { field: string }>;\n\t};\n\n\t/**\n\t * Known relation names from collection metadata\n\t */\n\trelations?: string[];\n}\n\n/**\n * Auto-detect upload and relation fields that need to be expanded.\n *\n * This analyzes the collection config to determine which fields require\n * data expansion when fetching from the backend:\n * - Upload fields need their asset data expanded\n * - Relation fields need their related record data expanded\n *\n * @param config - Collection configuration with fields and list view settings\n * @returns Object mapping field names to `true` for fields that need expansion\n *\n * @example\n * ```tsx\n * const expandedFields = autoExpandFields({\n * fields: config?.fields,\n * list: config?.list,\n * });\n *\n * // Use with query\n * const { data } = useCollectionList(collection, {\n * with: expandedFields,\n * });\n * ```\n */\nexport function autoExpandFields(\n\tconfig: AutoExpandFieldsConfig,\n): Record<string, boolean> {\n\tconst withFields: Record<string, boolean> = {};\n\n\t// Add explicitly configured relations\n\tif (config.list?.with) {\n\t\tfor (const rel of config.list.with) {\n\t\t\twithFields[rel] = true;\n\t\t}\n\t}\n\n\t// Determine which columns are displayed\n\t// TODO: this should adhere to visible columns based on adminPrefs\n\t// const columnFields = config.list?.columns || [];\n\tconst columnFields = config.fields ? Object.keys(config.fields) : [];\n\tconst fieldsToCheck: string[] = [];\n\n\tif (columnFields.length > 0) {\n\t\t// Use explicitly configured columns\n\t\tfor (const col of columnFields) {\n\t\t\t// const fieldName = typeof col === \"string\" ? col : col.field;\n\t\t\tconst fieldName = col;\n\t\t\tfieldsToCheck.push(fieldName);\n\t\t}\n\t} else if (config.fields) {\n\t\t// When columns not set, check all fields (buildColumns auto-generates from them)\n\t\tfieldsToCheck.push(...Object.keys(config.fields));\n\t}\n\n\t// Auto-detect upload and relation fields from columns\n\tfor (const fieldName of fieldsToCheck) {\n\t\tconst fieldDef = config.fields?.[fieldName] as any;\n\t\tif (fieldDef) {\n\t\t\t// fieldDef.name contains the field type (e.g., \"upload\", \"relation\")\n\t\t\tconst fieldType = fieldDef.name;\n\n\t\t\t// Auto-expand upload and uploadMany fields\n\t\t\tif (fieldType === \"upload\" || fieldType === \"uploadMany\") {\n\t\t\t\twithFields[fieldName] = true;\n\t\t\t}\n\t\t\t// For relation fields, only expand if relationName is explicitly specified\n\t\t\t// This ensures we don't try to expand relations that don't exist on the backend\n\t\t\telse if (fieldType === \"relation\") {\n\t\t\t\tconst relationName =\n\t\t\t\t\tfieldDef[\"~options\"]?.relationName ?? (fieldName as string);\n\t\t\t\tconst knownRelations = config.relations;\n\t\t\t\tif (!relationName) continue;\n\t\t\t\tif (!knownRelations || knownRelations.length === 0) {\n\t\t\t\t\twithFields[relationName] = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (knownRelations.includes(relationName)) {\n\t\t\t\t\twithFields[relationName] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn withFields;\n}\n\n/**\n * Check if there are any fields to expand\n */\nexport function hasFieldsToExpand(\n\texpandedFields: Record<string, boolean>,\n): boolean {\n\treturn Object.keys(expandedFields).length > 0;\n}\n","/**\n * Detect Relations Utility\n *\n * Automatically detects relation fields (especially M:N relations)\n * that need to be included when fetching data for forms.\n */\n\nimport type { FieldDefinition } from \"../builder/field/field\";\n\nexport interface DetectRelationsConfig {\n /**\n * Collection fields configuration\n */\n fields?: Record<string, FieldDefinition>;\n}\n\n/**\n * Auto-detect M:N relation fields from config and build `with` clause.\n *\n * M:N relations need to be explicitly loaded when fetching items for editing,\n * as they are stored in junction tables and not included by default.\n *\n * @param config - Collection configuration with fields\n * @returns Object mapping relation field names to `true` for M:N relations\n *\n * @example\n * ```tsx\n * const withRelations = detectManyToManyRelations({ fields: config?.fields });\n *\n * // Use with query\n * const { data } = useCollectionItem(collection, id, {\n * with: withRelations,\n * });\n * ```\n */\nexport function detectManyToManyRelations(\n config: DetectRelationsConfig,\n): Record<string, boolean> {\n const withRelations: Record<string, boolean> = {};\n\n if (config?.fields) {\n for (const [fieldName, fieldConfig] of Object.entries(config.fields)) {\n const fc = fieldConfig as any;\n // Detect M:N relation fields (FieldDefinition.name: \"relation\" with ~options.type: \"multiple\")\n if (fc?.name === \"relation\" && fc?.[\"~options\"]?.type === \"multiple\") {\n withRelations[fieldName] = true;\n }\n }\n }\n\n return withRelations;\n}\n\n/**\n * Check if there are any M:N relations to include\n */\nexport function hasManyToManyRelations(\n withRelations: Record<string, boolean>,\n): boolean {\n return Object.keys(withRelations).length > 0;\n}\n","/**\n * Type-Safe Admin Routes\n *\n * Utilities for building type-safe routes for admin UI navigation.\n * Accepts the admin config to provide fully type-safe routing.\n */\n\nimport type { Questpie } from \"questpie\";\nimport type { Admin } from \"../builder/admin\";\nimport type { CollectionNames, GlobalNames, PageDefinition } from \"../builder\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Collection route actions\n */\nexport type CollectionAction = \"list\" | \"create\" | \"edit\" | \"view\";\n\n/**\n * Parsed route information\n */\nexport type ParsedRoute<TApp extends Questpie<any>> =\n | { type: \"dashboard\" }\n | {\n type: \"collection\";\n collection: CollectionNames<TApp>;\n action: \"list\" | \"create\" | \"edit\";\n id?: string;\n }\n | { type: \"global\"; global: GlobalNames<TApp> }\n | {\n type: \"page\";\n pageId: string;\n path: string;\n config: PageDefinition<string>;\n }\n | { type: \"unknown\"; path: string };\n\n/**\n * Admin routes builder result\n */\nexport interface AdminRoutes<TApp extends Questpie<any>> {\n /** Base path */\n basePath: string;\n\n /** Dashboard route */\n dashboard: () => string;\n\n /** Collection routes */\n collections: {\n /** List all items in a collection */\n list: <K extends CollectionNames<TApp>>(collection: K) => string;\n /** Create new item in a collection */\n create: <K extends CollectionNames<TApp>>(collection: K) => string;\n /** Edit/view a specific item */\n edit: <K extends CollectionNames<TApp>>(\n collection: K,\n id: string,\n ) => string;\n /** Alias for edit */\n view: <K extends CollectionNames<TApp>>(\n collection: K,\n id: string,\n ) => string;\n /** Get route for any action */\n route: <K extends CollectionNames<TApp>>(\n collection: K,\n action: CollectionAction,\n id?: string,\n ) => string;\n };\n\n /** Global routes */\n globals: {\n /** Edit a global */\n edit: <K extends GlobalNames<TApp>>(global: K) => string;\n };\n\n /** Custom page routes */\n pages: {\n /** Get route for a custom page by ID */\n byId: (pageId: string) => string | null;\n /** Get all page routes as record */\n all: () => Record<string, string>;\n /** Get list of all page IDs */\n ids: () => string[];\n };\n\n /** Parse current route to determine what's being viewed */\n parse: (pathname: string) => ParsedRoute<TApp>;\n\n /** Check if a path matches a specific route */\n matches: {\n dashboard: (pathname: string) => boolean;\n collection: <K extends CollectionNames<TApp>>(\n pathname: string,\n collection?: K,\n ) => boolean;\n global: <K extends GlobalNames<TApp>>(\n pathname: string,\n global?: K,\n ) => boolean;\n page: (pathname: string, pageId?: string) => boolean;\n };\n\n /** Get URL with query params */\n withQuery: (\n path: string,\n params: Record<string, string | number | boolean | undefined | null>,\n ) => string;\n}\n\n// ============================================================================\n// Route Builder\n// ============================================================================\n\n/**\n * Create type-safe admin routes from admin config\n *\n * @example\n * ```tsx\n * import { createAdminRoutes } from '@questpie/admin/utils/routes'\n * import { barbershopAdmin } from './configs/admin'\n *\n * const routes = createAdminRoutes(barbershopAdmin)\n *\n * // Type-safe route generation\n * routes.dashboard() // \"/admin\"\n * routes.collections.list('posts') // \"/admin/collections/posts\"\n * routes.collections.create('posts') // \"/admin/collections/posts/create\"\n * routes.collections.edit('posts', '1') // \"/admin/collections/posts/1\"\n * routes.globals.edit('siteSettings') // \"/admin/globals/siteSettings\"\n * routes.pages.byId('analytics') // \"/admin/analytics\" (from page config)\n *\n * // Parse current route\n * const parsed = routes.parse('/admin/collections/posts/123')\n * // { type: 'collection', collection: 'posts', action: 'edit', id: '123' }\n * ```\n */\nexport function createAdminRoutes<TApp extends Questpie<any>>(\n admin: Admin,\n options: { basePath?: string } = {},\n): AdminRoutes<TApp> {\n const basePath = options.basePath ?? \"/admin\";\n const pagesConfig = admin.getPages();\n\n // Build page path lookup\n const pagePathById: Record<string, string> = {};\n const pageIdByPath: Record<string, string> = {};\n const pageConfigByPath: Record<string, PageDefinition<string>> = {};\n\n for (const [id, config] of Object.entries(pagesConfig)) {\n const configPath = (config as any).path ?? id;\n const pagePath = configPath.startsWith(\"/\")\n ? configPath.slice(1)\n : configPath;\n pagePathById[id] = pagePath;\n pageIdByPath[pagePath] = id;\n pageConfigByPath[pagePath] = config as PageDefinition<string>;\n }\n\n // Helper to join path segments\n const joinPath = (...segments: string[]): string => {\n return segments.filter(Boolean).join(\"/\");\n };\n\n // Collection routes\n const collections: AdminRoutes<TApp>[\"collections\"] = {\n list: (collection) => joinPath(basePath, \"collections\", collection),\n\n create: (collection) =>\n joinPath(basePath, \"collections\", collection, \"create\"),\n\n edit: (collection, id) => joinPath(basePath, \"collections\", collection, id),\n\n view: (collection, id) => joinPath(basePath, \"collections\", collection, id),\n\n route: (collection, action, id) => {\n switch (action) {\n case \"list\":\n return collections.list(collection);\n case \"create\":\n return collections.create(collection);\n case \"edit\":\n case \"view\":\n if (!id) throw new Error(`ID required for ${action} action`);\n return collections.edit(collection, id);\n default:\n return collections.list(collection);\n }\n },\n };\n\n // Global routes\n const globals: AdminRoutes<TApp>[\"globals\"] = {\n edit: (global) => joinPath(basePath, \"globals\", global),\n };\n\n // Page routes\n const pages: AdminRoutes<TApp>[\"pages\"] = {\n byId: (pageId) => {\n const pagePath = pagePathById[pageId];\n if (!pagePath) return null;\n return joinPath(basePath, pagePath);\n },\n\n all: () => {\n const result: Record<string, string> = {};\n for (const [id, path] of Object.entries(pagePathById)) {\n result[id] = joinPath(basePath, path);\n }\n return result;\n },\n\n ids: () => Object.keys(pagePathById),\n };\n\n // Parse route\n const parse = (pathname: string): ParsedRoute<TApp> => {\n // Remove trailing slash and base path\n const cleanPath = pathname.replace(/\\/$/, \"\");\n const relativePath = cleanPath.startsWith(basePath)\n ? cleanPath.slice(basePath.length)\n : cleanPath;\n\n // Dashboard\n if (relativePath === \"\" || relativePath === \"/\") {\n return { type: \"dashboard\" };\n }\n\n const segments = relativePath.split(\"/\").filter(Boolean);\n\n // Collections: /collections/:name/:action?\n if (segments[0] === \"collections\" && segments[1]) {\n const collection = segments[1] as CollectionNames<TApp>;\n\n if (!segments[2]) {\n return { type: \"collection\", collection, action: \"list\" };\n }\n\n if (segments[2] === \"create\") {\n return { type: \"collection\", collection, action: \"create\" };\n }\n\n return {\n type: \"collection\",\n collection,\n action: \"edit\",\n id: segments[2],\n };\n }\n\n // Globals: /globals/:name\n if (segments[0] === \"globals\" && segments[1]) {\n return { type: \"global\", global: segments[1] as GlobalNames<TApp> };\n }\n\n // Custom pages - check against configured pages\n const pageRelativePath = segments.join(\"/\");\n if (pageIdByPath[pageRelativePath]) {\n return {\n type: \"page\",\n pageId: pageIdByPath[pageRelativePath],\n path: pageRelativePath,\n config: pageConfigByPath[pageRelativePath],\n };\n }\n\n // Also check if first segment matches a page\n if (pageIdByPath[segments[0]]) {\n return {\n type: \"page\",\n pageId: pageIdByPath[segments[0]],\n path: segments[0],\n config: pageConfigByPath[segments[0]],\n };\n }\n\n // Unknown/custom page\n return { type: \"unknown\", path: relativePath };\n };\n\n // Matchers\n const matches: AdminRoutes<TApp>[\"matches\"] = {\n dashboard: (pathname) => {\n const parsed = parse(pathname);\n return parsed.type === \"dashboard\";\n },\n\n collection: (pathname, collection?) => {\n const parsed = parse(pathname);\n if (parsed.type !== \"collection\") return false;\n if (collection && parsed.collection !== collection) return false;\n return true;\n },\n\n global: (pathname, global?) => {\n const parsed = parse(pathname);\n if (parsed.type !== \"global\") return false;\n if (global && parsed.global !== global) return false;\n return true;\n },\n\n page: (pathname, pageId?) => {\n const parsed = parse(pathname);\n if (parsed.type !== \"page\") return false;\n if (pageId && parsed.pageId !== pageId) return false;\n return true;\n },\n };\n\n // Query string helper\n const withQuery = (\n path: string,\n params: Record<string, string | number | boolean | undefined | null>,\n ): string => {\n return path + buildQueryString(params);\n };\n\n return {\n basePath,\n dashboard: () => basePath,\n collections,\n globals,\n pages,\n parse,\n matches,\n withQuery,\n };\n}\n\n// ============================================================================\n// Standalone Route Builder (without admin config)\n// ============================================================================\n\n/**\n * Create admin routes without admin config (less type-safe, but works without context)\n *\n * @example\n * ```tsx\n * const routes = createAdminRoutesSimple({ basePath: '/admin' })\n * routes.collections.list('posts')\n * ```\n */\nexport function createAdminRoutesSimple(\n options: { basePath?: string; pages?: Record<string, { path: string }> } = {},\n) {\n const basePath = options.basePath ?? \"/admin\";\n const pagesConfig = options.pages ?? {};\n\n const joinPath = (...segments: string[]): string => {\n return segments.filter(Boolean).join(\"/\");\n };\n\n return {\n basePath,\n dashboard: () => basePath,\n\n collections: {\n list: (collection: string) =>\n joinPath(basePath, \"collections\", collection),\n create: (collection: string) =>\n joinPath(basePath, \"collections\", collection, \"create\"),\n edit: (collection: string, id: string) =>\n joinPath(basePath, \"collections\", collection, id),\n },\n\n globals: {\n edit: (global: string) => joinPath(basePath, \"globals\", global),\n },\n\n pages: {\n byId: (pageId: string) => {\n const config = pagesConfig[pageId];\n if (!config) return null;\n const path = config.path.startsWith(\"/\")\n ? config.path.slice(1)\n : config.path;\n return joinPath(basePath, path);\n },\n },\n };\n}\n\n// ============================================================================\n// Route Helpers\n// ============================================================================\n\n/**\n * Build a query string from params\n */\nexport function buildQueryString(\n params: Record<string, string | number | boolean | undefined | null>,\n): string {\n const entries = Object.entries(params)\n .filter(([, value]) => value !== undefined && value !== null)\n .map(\n ([key, value]) =>\n `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`,\n );\n\n return entries.length > 0 ? `?${entries.join(\"&\")}` : \"\";\n}\n\n/**\n * Build a route with query params\n */\nexport function withQuery(\n path: string,\n params: Record<string, string | number | boolean | undefined | null>,\n): string {\n return path + buildQueryString(params);\n}\n\n/**\n * Extract collection info from a route path\n */\nexport function parseCollectionRoute(\n pathname: string,\n basePath = \"/admin\",\n): {\n collection: string;\n action: \"list\" | \"create\" | \"edit\";\n id?: string;\n} | null {\n const cleanPath = pathname.replace(/\\/$/, \"\");\n const relativePath = cleanPath.startsWith(basePath)\n ? cleanPath.slice(basePath.length)\n : cleanPath;\n\n const match = relativePath.match(/^\\/collections\\/([^/]+)(?:\\/([^/]+))?$/);\n if (!match) return null;\n\n const [, collection, actionOrId] = match;\n\n if (!actionOrId) {\n return { collection, action: \"list\" };\n }\n\n if (actionOrId === \"create\") {\n return { collection, action: \"create\" };\n }\n\n return { collection, action: \"edit\", id: actionOrId };\n}\n\n/**\n * Extract global info from a route path\n */\nexport function parseGlobalRoute(\n pathname: string,\n basePath = \"/admin\",\n): { global: string } | null {\n const cleanPath = pathname.replace(/\\/$/, \"\");\n const relativePath = cleanPath.startsWith(basePath)\n ? cleanPath.slice(basePath.length)\n : cleanPath;\n\n const match = relativePath.match(/^\\/globals\\/([^/]+)$/);\n if (!match) return null;\n\n return { global: match[1] };\n}\n\n// ============================================================================\n// Navigation Helpers\n// ============================================================================\n\n/**\n * Create a navigation helper function\n *\n * @example\n * ```tsx\n * const routes = createAdminRoutes(admin)\n * const go = createNavigator(routes, navigate)\n *\n * // Navigate to routes\n * go.dashboard()\n * go.collection('posts')\n * go.collectionCreate('posts')\n * go.collectionEdit('posts', '123')\n * go.global('siteSettings')\n * go.page('analytics')\n * ```\n */\nexport function createNavigator<TApp extends Questpie<any>>(\n routes: AdminRoutes<TApp>,\n navigate: (path: string) => void,\n) {\n return {\n /** Navigate to dashboard */\n dashboard: () => navigate(routes.dashboard()),\n\n /** Navigate to collection list */\n collection: <K extends CollectionNames<TApp>>(collection: K) =>\n navigate(routes.collections.list(collection)),\n\n /** Navigate to collection create */\n collectionCreate: <K extends CollectionNames<TApp>>(collection: K) =>\n navigate(routes.collections.create(collection)),\n\n /** Navigate to collection edit */\n collectionEdit: <K extends CollectionNames<TApp>>(\n collection: K,\n id: string,\n ) => navigate(routes.collections.edit(collection, id)),\n\n /** Navigate to global edit */\n global: <K extends GlobalNames<TApp>>(global: K) =>\n navigate(routes.globals.edit(global)),\n\n /** Navigate to custom page */\n page: (pageId: string) => {\n const path = routes.pages.byId(pageId);\n if (path) navigate(path);\n },\n\n /** Navigate to any path */\n to: (path: string) => navigate(path),\n };\n}\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type { CollectionNames, GlobalNames } from \"../builder\";\n","/**\n * Wrap Localized Values Utility\n *\n * Transforms nested field values by wrapping localized values with $i18n marker.\n * Used before sending data to server for proper i18n storage.\n *\n * Only processes nested fields (object, array, blocks) - flat localized fields\n * are handled separately by the server based on collection schema.\n */\n\nimport type { BlockContent } from \"#questpie/admin/client/blocks/types\";\nimport type { BlockDefinition } from \"#questpie/admin/client/builder/block/types\";\nimport {\n\tbuiltInFields,\n\tcreateRegistryProxy,\n} from \"#questpie/admin/client/builder/defaults/fields\";\nimport type { FieldDefinition } from \"#questpie/admin/client/builder/field/field\";\n\n/**\n * I18n marker value wrapper\n */\ninterface I18nWrapper<T = unknown> {\n\t$i18n: T;\n}\n\n/**\n * Check if a value is already wrapped with $i18n\n */\nfunction isI18nWrapped(value: unknown): value is I18nWrapper {\n\treturn (\n\t\tvalue !== null &&\n\t\ttypeof value === \"object\" &&\n\t\t\"$i18n\" in value &&\n\t\tObject.keys(value).length === 1\n\t);\n}\n\n/**\n * Wrap a value with $i18n marker\n */\nfunction wrapI18n<T>(value: T): I18nWrapper<T> {\n\treturn { $i18n: value };\n}\n\n/**\n * Get nested field definitions from a field's options\n */\nfunction getNestedFields(\n\tfieldDef: FieldDefinition | undefined,\n): Record<string, FieldDefinition> | undefined {\n\tif (!fieldDef) return undefined;\n\n\tconst options = (fieldDef as any)[\"~options\"];\n\tif (!options) return undefined;\n\n\t// Object field - has `fields` callback\n\tif (options.fields && typeof options.fields === \"function\") {\n\t\ttry {\n\t\t\treturn options.fields({ r: createRegistryProxy(builtInFields) });\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t// Array field with object items - has `item` callback\n\tif (options.item && typeof options.item === \"function\") {\n\t\ttry {\n\t\t\treturn options.item({ r: createRegistryProxy(builtInFields) });\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Check if a field is localized\n */\nfunction isFieldLocalized(fieldDef: FieldDefinition | undefined): boolean {\n\tif (!fieldDef) return false;\n\tconst options = (fieldDef as any)[\"~options\"];\n\treturn options?.localized === true;\n}\n\n/**\n * Check if a field is computed (has compute function = UI-only, not submitted to backend)\n */\nfunction isFieldComputed(fieldDef: FieldDefinition | undefined): boolean {\n\tif (!fieldDef) return false;\n\tconst options = (fieldDef as any)[\"~options\"];\n\treturn typeof options?.compute === \"function\";\n}\n\n/**\n * Check if nested fields contain any localized fields\n */\nfunction hasLocalizedFields(\n\tnestedFields: Record<string, FieldDefinition> | undefined,\n): boolean {\n\tif (!nestedFields) return false;\n\treturn Object.values(nestedFields).some((fieldDef) => {\n\t\tif (isFieldLocalized(fieldDef)) return true;\n\t\t// Check deeper nested fields\n\t\tconst deepNested = getNestedFields(fieldDef);\n\t\tif (deepNested) return hasLocalizedFields(deepNested);\n\t\treturn false;\n\t});\n}\n\n/**\n * Check if a field is a blocks field\n */\nfunction isBlocksField(fieldDef: FieldDefinition | undefined): boolean {\n\tif (!fieldDef) return false;\n\treturn (fieldDef as any).name === \"blocks\";\n}\n\n/**\n * Check if a field is an object field\n */\nfunction isObjectField(fieldDef: FieldDefinition | undefined): boolean {\n\tif (!fieldDef) return false;\n\treturn (fieldDef as any).name === \"object\";\n}\n\n/**\n * Check if a field is an array field\n */\nfunction isArrayField(fieldDef: FieldDefinition | undefined): boolean {\n\tif (!fieldDef) return false;\n\treturn (fieldDef as any).name === \"array\";\n}\n\n/**\n * Process object value - wrap localized nested fields\n */\nfunction processObjectValue(\n\tvalue: Record<string, unknown>,\n\tnestedFields: Record<string, FieldDefinition>,\n\tblocks?: Record<string, BlockDefinition>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = {};\n\n\tfor (const [key, fieldValue] of Object.entries(value)) {\n\t\tconst nestedFieldDef = nestedFields[key];\n\n\t\tif (fieldValue === undefined || fieldValue === null) {\n\t\t\tresult[key] = fieldValue;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Already wrapped - keep as is\n\t\tif (isI18nWrapped(fieldValue)) {\n\t\t\tresult[key] = fieldValue;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check if this nested field is localized\n\t\tif (isFieldLocalized(nestedFieldDef)) {\n\t\t\tresult[key] = wrapI18n(fieldValue);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Recursively process nested object fields\n\t\tif (isObjectField(nestedFieldDef)) {\n\t\t\tconst deepNestedFields = getNestedFields(nestedFieldDef);\n\t\t\tif (\n\t\t\t\tdeepNestedFields &&\n\t\t\t\thasLocalizedFields(deepNestedFields) &&\n\t\t\t\ttypeof fieldValue === \"object\" &&\n\t\t\t\t!Array.isArray(fieldValue)\n\t\t\t) {\n\t\t\t\tresult[key] = processObjectValue(\n\t\t\t\t\tfieldValue as Record<string, unknown>,\n\t\t\t\t\tdeepNestedFields,\n\t\t\t\t\tblocks,\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// Recursively process nested array fields (only if item has localized fields)\n\t\tif (isArrayField(nestedFieldDef)) {\n\t\t\tconst itemFields = getNestedFields(nestedFieldDef);\n\t\t\tif (\n\t\t\t\titemFields &&\n\t\t\t\thasLocalizedFields(itemFields) &&\n\t\t\t\tArray.isArray(fieldValue)\n\t\t\t) {\n\t\t\t\tresult[key] = fieldValue.map((item) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof item === \"object\" &&\n\t\t\t\t\t\titem !== null &&\n\t\t\t\t\t\t!Array.isArray(item)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn processObjectValue(\n\t\t\t\t\t\t\titem as Record<string, unknown>,\n\t\t\t\t\t\t\titemFields,\n\t\t\t\t\t\t\tblocks,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn item;\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// Recursively process nested blocks fields\n\t\tif (isBlocksField(nestedFieldDef) && blocks) {\n\t\t\tresult[key] = processBlocksValue(fieldValue as BlockContent, blocks);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Not localized - keep as is\n\t\tresult[key] = fieldValue;\n\t}\n\n\treturn result;\n}\n\n/**\n * Process blocks content - wrap localized block field values\n */\nfunction processBlocksValue(\n\tcontent: BlockContent,\n\tblocks: Record<string, BlockDefinition>,\n): BlockContent {\n\tif (!content || !content._values) {\n\t\treturn content;\n\t}\n\n\tconst processedValues: Record<string, Record<string, unknown>> = {};\n\n\tfor (const [blockId, blockValues] of Object.entries(content._values)) {\n\t\t// Find block type from tree\n\t\tconst blockNode = findBlockInTree(content._tree, blockId);\n\t\tif (!blockNode) {\n\t\t\tprocessedValues[blockId] = blockValues;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst blockDef = blocks[blockNode.type];\n\t\tif (!blockDef) {\n\t\t\tprocessedValues[blockId] = blockValues;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Get block field definitions\n\t\tconst blockFields = (blockDef as any).fields as\n\t\t\t| Record<string, FieldDefinition>\n\t\t\t| undefined;\n\t\tif (!blockFields || !hasLocalizedFields(blockFields)) {\n\t\t\tprocessedValues[blockId] = blockValues;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Process block values\n\t\tprocessedValues[blockId] = processObjectValue(\n\t\t\tblockValues,\n\t\t\tblockFields,\n\t\t\tblocks,\n\t\t);\n\t}\n\n\treturn {\n\t\t...content,\n\t\t_values: processedValues,\n\t};\n}\n\n/**\n * Find a block node in the tree by ID\n */\nfunction findBlockInTree(\n\ttree: BlockContent[\"_tree\"],\n\tblockId: string,\n): BlockContent[\"_tree\"][number] | undefined {\n\tfor (const node of tree) {\n\t\tif (node.id === blockId) {\n\t\t\treturn node;\n\t\t}\n\t\tif (node.children?.length) {\n\t\t\tconst found = findBlockInTree(node.children, blockId);\n\t\t\tif (found) return found;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Options for wrapLocalizedNestedValues\n */\nexport interface WrapLocalizedOptions {\n\t/**\n\t * Field definitions from collection/global config\n\t */\n\tfields: Record<string, FieldDefinition>;\n\n\t/**\n\t * Block definitions (required if using blocks fields)\n\t */\n\tblocks?: Record<string, BlockDefinition>;\n}\n\n/**\n * Wrap localized values in nested fields with $i18n marker.\n *\n * Processes:\n * - Object fields with nested localized fields\n * - Array fields with nested localized item fields\n * - Blocks fields with localized block fields\n *\n * Only processes fields that actually have localized nested fields.\n *\n * @param data - Form data to process\n * @param options - Field and block definitions\n * @returns Transformed data with $i18n wrappers\n *\n * @example\n * ```ts\n * const transformedData = wrapLocalizedNestedValues(formData, {\n * fields: config.fields,\n * blocks: admin.state.blocks,\n * });\n * ```\n */\nexport function wrapLocalizedNestedValues(\n\tdata: Record<string, unknown>,\n\toptions: WrapLocalizedOptions,\n): Record<string, unknown> {\n\tconst { fields, blocks } = options;\n\tconst result: Record<string, unknown> = {};\n\n\tfor (const [fieldName, fieldValue] of Object.entries(data)) {\n\t\tconst fieldDef = fields[fieldName];\n\n\t\t// Skip computed fields - they are UI-only and should not be submitted\n\t\tif (isFieldComputed(fieldDef)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (fieldValue === undefined || fieldValue === null) {\n\t\t\tresult[fieldName] = fieldValue;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Process object fields (only if has localized nested fields)\n\t\tif (isObjectField(fieldDef)) {\n\t\t\tconst nestedFields = getNestedFields(fieldDef);\n\t\t\tif (\n\t\t\t\tnestedFields &&\n\t\t\t\thasLocalizedFields(nestedFields) &&\n\t\t\t\ttypeof fieldValue === \"object\" &&\n\t\t\t\t!Array.isArray(fieldValue)\n\t\t\t) {\n\t\t\t\tresult[fieldName] = processObjectValue(\n\t\t\t\t\tfieldValue as Record<string, unknown>,\n\t\t\t\t\tnestedFields,\n\t\t\t\t\tblocks,\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// Process array fields (only if item has localized fields)\n\t\tif (isArrayField(fieldDef)) {\n\t\t\tconst itemFields = getNestedFields(fieldDef);\n\t\t\tif (\n\t\t\t\titemFields &&\n\t\t\t\thasLocalizedFields(itemFields) &&\n\t\t\t\tArray.isArray(fieldValue)\n\t\t\t) {\n\t\t\t\tresult[fieldName] = fieldValue.map((item) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof item === \"object\" &&\n\t\t\t\t\t\titem !== null &&\n\t\t\t\t\t\t!Array.isArray(item)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn processObjectValue(\n\t\t\t\t\t\t\titem as Record<string, unknown>,\n\t\t\t\t\t\t\titemFields,\n\t\t\t\t\t\t\tblocks,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn item;\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\t// Process blocks fields\n\t\tif (isBlocksField(fieldDef) && blocks) {\n\t\t\tresult[fieldName] = processBlocksValue(\n\t\t\t\tfieldValue as BlockContent,\n\t\t\t\tblocks,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Not a nested field type or no localized fields - keep as is\n\t\tresult[fieldName] = fieldValue;\n\t}\n\n\treturn result;\n}\n","// Re-export cn helper from lib/utils\nexport { cn } from \"../lib/utils\";\n// Re-export field utilities\nexport {\n\ttype AutoExpandFieldsConfig,\n\tautoExpandFields,\n\thasFieldsToExpand,\n} from \"./auto-expand-fields\";\nexport {\n\ttype DetectRelationsConfig,\n\tdetectManyToManyRelations,\n\thasManyToManyRelations,\n} from \"./detect-relations\";\n// Re-export route utilities\nexport {\n\ttype AdminRoutes,\n\tbuildQueryString,\n\ttype CollectionAction,\n\tcreateAdminRoutes,\n\tcreateAdminRoutesSimple,\n\tcreateNavigator,\n\ttype ParsedRoute,\n\tparseCollectionRoute,\n\tparseGlobalRoute,\n\twithQuery,\n} from \"./routes\";\n\nexport {\n\ttype WrapLocalizedOptions,\n\twrapLocalizedNestedValues,\n} from \"./wrap-localized\";\n\n/**\n * Utility functions for admin package\n */\n","/**\n * Field Context\n *\n * Provides context and utilities for rendering form fields.\n * Extracted from auto-form-fields.tsx for better modularity.\n */\n\nimport type React from \"react\";\nimport type { FieldDefinition } from \"../../builder/field/field\";\nimport type { DynamicI18nText } from \"../../builder/types/common\";\nimport type { FormFieldProps } from \"./form-field\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Context object containing all information needed to render a field.\n * Note: label, description, placeholder can be I18nText - resolve them before passing to components.\n */\nexport type FieldContext = {\n\tfieldName: string;\n\tfullFieldName: string;\n\tcollection: string;\n\tfieldDef?: FieldDefinition;\n\tfieldValue: any;\n\t/** Can be I18nText - must be resolved before passing to component */\n\tlabel?: DynamicI18nText;\n\t/** Can be I18nText - must be resolved before passing to component */\n\tdescription?: DynamicI18nText;\n\t/** Can be I18nText - must be resolved before passing to component */\n\tplaceholder?: DynamicI18nText;\n\toptions?: Array<{ label: string; value: any }>;\n\t/** Whether field is hidden (not rendered). Default false. */\n\tisHidden: boolean;\n\t/** Whether field is read-only (normal look, not editable). Computed fields are always readonly. */\n\tisReadOnly: boolean;\n\t/** Whether field is disabled (grayed out). */\n\tisDisabled: boolean;\n\tisRequired: boolean;\n\tisLocalized: boolean;\n\t/** Whether field has a compute function */\n\tisComputed: boolean;\n\tlocale?: string;\n\tfieldError?: string;\n\tupdateValue: (nextValue: any) => void;\n\ttype?: string;\n\tcomponent?: React.ComponentType<any>;\n\t/** Compute function if field is computed */\n\tcompute?: (values: Record<string, any>) => any;\n};\n\n// ============================================================================\n// Helper Functions - Field Definition Access\n// ============================================================================\n\n/**\n * Get field type from FieldDefinition\n * FieldDefinition.name contains the type name (e.g., \"text\", \"relation\")\n */\nexport function getFieldType(\n\tfieldDef: FieldDefinition | undefined,\n): string | undefined {\n\tif (!fieldDef) return undefined;\n\t// FieldDefinition stores the field type in 'name' property\n\t// This comes from field(\"text\", ...) where \"text\" is the type\n\treturn fieldDef.name;\n}\n\n/**\n * Get field options from FieldDefinition\n * Options are stored in \"~options\" property\n */\nexport function getFieldOptions(\n\tfieldDef: FieldDefinition | undefined,\n): Record<string, any> {\n\tif (!fieldDef) return {};\n\treturn (fieldDef as any)[\"~options\"] || {};\n}\n\n/**\n * Get field component from FieldDefinition\n * Component is stored in field.component\n */\nexport function getFieldComponent(\n\tfieldDef: FieldDefinition | undefined,\n): React.ComponentType<any> | undefined {\n\tif (!fieldDef?.field?.component) return undefined;\n\treturn fieldDef.field.component as React.ComponentType<any>;\n}\n\n// ============================================================================\n// Helper Functions - Value Resolution\n// ============================================================================\n\ntype ValueResolver<T> = T | ((values: any) => T);\n\nexport function resolveValue<T>(\n\tvalue: ValueResolver<T> | undefined,\n\tformValues: any,\n\tdefaultValue: T,\n): T {\n\tif (value === undefined) return defaultValue;\n\tif (typeof value === \"function\") {\n\t\treturn (value as (values: any) => T)(formValues);\n\t}\n\treturn value;\n}\n\n/**\n * Get form values for conditional field logic.\n *\n * @deprecated This is a legacy fallback. All callers should now use useWatch()\n * hook in their component and pass the watched values to getFieldContext via\n * the `formValues` parameter. This function uses form.watch() which doesn't\n * properly integrate with React's render cycle.\n *\n * Best practice pattern:\n * ```tsx\n * const watchedValues = useWatch({ control: form.control });\n * const context = getFieldContext({ ..., formValues: watchedValues });\n * ```\n */\nexport function getFormValues(form: any, fieldPrefix?: string) {\n\tif (!form?.watch) return {};\n\tconst values = fieldPrefix ? form.watch(fieldPrefix) : form.watch();\n\treturn values ?? {};\n}\n\nexport function getFullFieldName(fieldName: string, fieldPrefix?: string) {\n\treturn fieldPrefix ? `${fieldPrefix}.${fieldName}` : fieldName;\n}\n\n// ============================================================================\n// Field Context Factory\n// ============================================================================\n\nexport interface GetFieldContextParams {\n\tfieldName: string;\n\tfieldDef?: FieldDefinition;\n\tcollection: string;\n\tform: any;\n\tfieldPrefix?: string;\n\tlocale?: string;\n\t/** Collection metadata from backend (for inferring localized fields) */\n\tcollectionMeta?: { localizedFields?: string[] };\n\t/**\n\t * Pre-watched form values from useWatch hook.\n\t * If provided, avoids calling form.watch() internally.\n\t * This is the preferred pattern for better React integration.\n\t */\n\tformValues?: Record<string, any>;\n}\n\n/**\n * Create a FieldContext object from field definition and form context.\n * Contains all information needed to render a field component.\n */\nexport function getFieldContext({\n\tfieldName,\n\tfieldDef,\n\tcollection,\n\tform,\n\tfieldPrefix,\n\tlocale,\n\tformValues: formValuesProp,\n\tcollectionMeta,\n}: GetFieldContextParams): FieldContext {\n\t// Use pre-watched values if provided (preferred), otherwise fall back to form.watch()\n\tconst formValues = formValuesProp ?? getFormValues(form, fieldPrefix);\n\tconst fullFieldName = getFullFieldName(fieldName, fieldPrefix);\n\tconst fieldState = form?.getFieldState\n\t\t? form.getFieldState(fullFieldName)\n\t\t: undefined;\n\tconst fieldError = fieldState?.error?.message;\n\tconst fieldValue = formValues[fieldName];\n\n\t// Get options from FieldDefinition\n\tconst options = getFieldOptions(fieldDef);\n\tconst type = getFieldType(fieldDef);\n\tconst component = getFieldComponent(fieldDef);\n\n\tconst label = options.label;\n\tconst description = options.description;\n\tconst placeholder = options.placeholder;\n\n\t// hidden: false/undefined = visible, true = hidden\n\tconst isHidden = resolveValue(options.hidden, formValues, false);\n\t// compute implies readonly\n\tconst isComputed = typeof options.compute === \"function\";\n\tconst isReadOnly =\n\t\tisComputed || resolveValue(options.readOnly, formValues, false);\n\tconst isDisabled = resolveValue(options.disabled, formValues, false);\n\tconst isRequired = resolveValue(options.required, formValues, false);\n\n\t// Check if field is localized: explicit config takes priority, fallback to BE metadata\n\tconst isLocalized =\n\t\toptions.localized !== undefined\n\t\t\t? !!options.localized\n\t\t\t: (collectionMeta?.localizedFields?.includes(fieldName) ?? false);\n\n\t// Resolve dynamic options for select fields\n\tconst selectOptions = options.options\n\t\t? typeof options.options === \"function\"\n\t\t\t? options.options(formValues)\n\t\t\t: options.options\n\t\t: undefined;\n\n\tconst updateValue = (nextValue: any) => {\n\t\tif (form?.setValue) {\n\t\t\tform.setValue(fullFieldName, nextValue, {\n\t\t\t\tshouldDirty: true,\n\t\t\t\tshouldTouch: true,\n\t\t\t});\n\t\t}\n\t};\n\n\treturn {\n\t\tfieldName,\n\t\tfullFieldName,\n\t\tcollection,\n\t\tfieldDef,\n\t\tfieldValue,\n\t\tlabel,\n\t\tdescription,\n\t\tplaceholder,\n\t\toptions: selectOptions,\n\t\tisHidden,\n\t\tisReadOnly,\n\t\tisDisabled,\n\t\tisRequired,\n\t\tisLocalized,\n\t\tisComputed,\n\t\tlocale,\n\t\tfieldError,\n\t\tupdateValue,\n\t\ttype,\n\t\tcomponent,\n\t\tcompute: options.compute,\n\t};\n}\n\n// ============================================================================\n// Component Props Builders\n// ============================================================================\n\n/**\n * Raw component props with I18nText (needs resolution before passing to components)\n */\nexport type RawComponentProps = {\n\tname: string;\n\tvalue: any;\n\tonChange: (value: any) => void;\n\tlabel?: DynamicI18nText;\n\tdescription?: DynamicI18nText;\n\tplaceholder?: DynamicI18nText;\n\trequired: boolean;\n\tdisabled: boolean;\n\treadOnly: boolean;\n\terror?: string;\n\tlocalized: boolean;\n\tlocale?: string;\n};\n\n/**\n * Build props for a FieldDefinition component (field.component).\n * Returns raw props with I18nText - resolve before passing to component.\n */\nexport function buildComponentProps(context: FieldContext): RawComponentProps {\n\treturn {\n\t\tname: context.fullFieldName,\n\t\tvalue: context.fieldValue,\n\t\tonChange: context.updateValue,\n\t\tlabel: context.label,\n\t\tdescription: context.description,\n\t\tplaceholder: context.placeholder,\n\t\trequired: context.isRequired,\n\t\tdisabled: context.isDisabled,\n\t\treadOnly: context.isReadOnly,\n\t\terror: context.fieldError,\n\t\tlocalized: context.isLocalized,\n\t\tlocale: context.locale,\n\t};\n}\n\n/**\n * Raw form field props with I18nText (needs resolution before passing to components)\n */\nexport type RawFormFieldProps = Omit<\n\tFormFieldProps,\n\t\"label\" | \"description\" | \"placeholder\"\n> & {\n\tlabel?: DynamicI18nText;\n\tdescription?: DynamicI18nText;\n\tplaceholder?: DynamicI18nText;\n};\n\n/**\n * Build props for FormField component (primitive field types).\n * Returns raw props with I18nText - resolve before passing to FormField.\n */\nexport function buildFormFieldProps(context: FieldContext): RawFormFieldProps {\n\treturn {\n\t\tname: context.fullFieldName,\n\t\tlabel: context.label,\n\t\tdescription: context.description,\n\t\tplaceholder: context.placeholder,\n\t\trequired: context.isRequired,\n\t\tdisabled: context.isDisabled || context.isReadOnly,\n\t\tlocalized: context.isLocalized,\n\t\tlocale: context.locale,\n\t};\n}\n","/**\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 { type UseQueryOptions, useQuery } from \"@tanstack/react-query\";\nimport type { CollectionMeta } from \"questpie/client\";\nimport type {\n RegisteredCMS,\n RegisteredCollectionNames,\n} from \"../builder/registry\";\nimport type { Questpie } from \"questpie\";\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 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 collection: K,\n queryOptions?: Omit<UseQueryOptions<CollectionMeta>, \"queryKey\" | \"queryFn\">,\n) {\n const client = useAdminStore(selectClient);\n\n return useQuery<CollectionMeta>({\n queryKey: [\"questpie\", \"collections\", collection, \"meta\"],\n queryFn: async () => {\n return (client as any).collections[collection].meta();\n },\n // Meta rarely changes, cache aggressively\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 30 * 60 * 1000, // 30 minutes (formerly cacheTime)\n ...queryOptions,\n });\n}\n\n/**\n * Query key for collection meta\n * Useful for prefetching or invalidation\n */\nexport function getCollectionMetaQueryKey(collection: string) {\n return [\"questpie\", \"collections\", collection, \"meta\"] as const;\n}\n","/**\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 * Execute a function with tracked values (for computing)\n */\nexport function computeWithTracking<T>(\n\tvalues: Record<string, any>,\n\tcomputeFn: (values: Record<string, any>) => T,\n): TrackingResult<T> {\n\treturn trackDependencies(values, computeFn);\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\tform.setValue(fullFieldName, value, {\n\t\t\t\tshouldDirty: true,\n\t\t\t\tshouldTouch: true,\n\t\t\t\tshouldValidate: true,\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","/**\n * FieldRenderer Component\n *\n * Renders a single form field using FieldDefinition.\n * Shared between AutoFormFields and BlockEditor.\n */\n\nimport * as React from \"react\";\nimport { useFormContext, useWatch } from \"react-hook-form\";\nimport type { ComponentRegistry } from \"../../builder\";\nimport type { FieldDefinition } from \"../../builder/field/field\";\nimport { useCollectionMeta } from \"../../hooks/use-collection-meta\";\nimport { useFieldHooks } from \"../../hooks/use-field-hooks\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { selectAdmin, useAdminStore, useScopedLocale } from \"../../runtime\";\nimport {\n\tbuildComponentProps,\n\tbuildFormFieldProps,\n\ttype FieldContext,\n\tgetFieldContext,\n\tgetFieldOptions,\n\tgetFullFieldName,\n} from \"./field-context\";\nimport type { FormFieldProps } from \"./form-field\";\nimport { FormField } from \"./form-field\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface FieldRendererProps {\n\tfieldName: string;\n\tfieldDef?: FieldDefinition;\n\tcollection: string;\n\tregistry?: ComponentRegistry;\n\tfieldPrefix?: string;\n\tclassName?: string;\n\t/**\n\t * Callback to render embedded collection fields.\n\t * Required for embedded fields to work (handles recursive AutoFormFields).\n\t */\n\trenderEmbeddedFields?: (params: {\n\t\tembeddedCollection: string;\n\t\tembeddedCollectionConfig: any;\n\t\tfullFieldName: string;\n\t\tindex: number;\n\t}) => React.ReactNode;\n\t/**\n\t * All collection configs (for embedded collections)\n\t */\n\tallCollectionsConfig?: Record<string, any>;\n\t/**\n\t * Collection metadata from backend (for inferring localized fields)\n\t */\n\tcollectionMeta?: { localizedFields?: string[] };\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction renderConfigError(message: string) {\n\treturn (\n\t\t<div className=\"border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive rounded\">\n\t\t\t{message}\n\t\t</div>\n\t);\n}\n\nfunction stripFieldUiOptions(options: Record<string, any>) {\n\tconst {\n\t\tlabel,\n\t\tdescription,\n\t\tplaceholder,\n\t\trequired,\n\t\tdisabled,\n\t\treadOnly,\n\t\tvisible,\n\t\tlocalized,\n\t\tlocale,\n\t\t...rest\n\t} = options;\n\n\treturn rest;\n}\n\nfunction renderFormField(\n\tformFieldProps: FormFieldProps,\n\ttype?: FormFieldProps[\"type\"],\n\textra?: Partial<FormFieldProps>,\n) {\n\treturn <FormField {...formFieldProps} type={type} {...extra} />;\n}\n\n/**\n * Render field using FieldDefinition.field.component\n *\n * This is the primary rendering method. Field components receive:\n * - Base props (name, value, onChange, label, etc.) from componentProps\n * - Field-specific options from FieldDefinition[\"~options\"]\n */\nfunction renderDefinitionComponent({\n\tcontext,\n\tcomponentProps,\n\tblocks,\n}: {\n\tcontext: FieldContext;\n\tcomponentProps: ReturnType<typeof buildComponentProps>;\n\tblocks?: Record<string, any>;\n}) {\n\tconst Component = context.component;\n\tif (!Component) return null;\n\n\t// Get field-specific options from FieldDefinition\n\tconst options = stripFieldUiOptions(getFieldOptions(context.fieldDef));\n\n\t// For blocks field, inject the blocks registry from admin state\n\tif (context.type === \"blocks\" && blocks) {\n\t\treturn <Component {...componentProps} {...options} blocks={blocks} />;\n\t}\n\n\treturn <Component {...componentProps} {...options} />;\n}\n\n/**\n * Render embedded collection field\n *\n * Embedded fields need special handling because they require:\n * 1. Access to allCollectionsConfig for the embedded collection's config\n * 2. A renderFields callback that recursively renders AutoFormFields\n */\nfunction renderEmbeddedField({\n\tcontext,\n\tregistry,\n\tallCollectionsConfig,\n\tcomponentProps,\n\trenderEmbeddedFields,\n}: {\n\tcontext: FieldContext;\n\tregistry?: ComponentRegistry;\n\tallCollectionsConfig?: Record<string, any>;\n\tcomponentProps: ReturnType<typeof buildComponentProps>;\n\trenderEmbeddedFields?: FieldRendererProps[\"renderEmbeddedFields\"];\n}) {\n\tif (context.type !== \"embedded\") return null;\n\n\tconst options = stripFieldUiOptions(getFieldOptions(context.fieldDef));\n\tconst embeddedCollection = options.collection;\n\n\tif (!embeddedCollection) {\n\t\treturn renderConfigError(\n\t\t\t`Missing collection for embedded field \"${context.fieldName}\".`,\n\t\t);\n\t}\n\n\tconst embeddedCollectionConfig = allCollectionsConfig?.[embeddedCollection];\n\n\t// Use the component from FieldDefinition, or fall back to registry/default\n\tconst EmbeddedComponent =\n\t\tcontext.component ||\n\t\t(registry?.fields?.embedded as React.ComponentType<any>);\n\n\tif (!EmbeddedComponent) {\n\t\treturn renderConfigError(\n\t\t\t`No component found for embedded field \"${context.fieldName}\".`,\n\t\t);\n\t}\n\n\treturn (\n\t\t<EmbeddedComponent\n\t\t\t{...componentProps}\n\t\t\t{...options}\n\t\t\tvalue={context.fieldValue || []}\n\t\t\tcollection={embeddedCollection}\n\t\t\trenderFields={(index: number) =>\n\t\t\t\trenderEmbeddedFields?.({\n\t\t\t\t\tembeddedCollection,\n\t\t\t\t\tembeddedCollectionConfig,\n\t\t\t\t\tfullFieldName: context.fullFieldName,\n\t\t\t\t\tindex,\n\t\t\t\t})\n\t\t\t}\n\t\t/>\n\t);\n}\n\n/**\n * Render primitive field using FormField component\n *\n * This is the fallback for fields without a FieldDefinition.field.component.\n * It maps field types to FormField types for basic form controls.\n */\nfunction renderPrimitiveField({\n\tcontext,\n\tformFieldProps,\n}: {\n\tcontext: FieldContext;\n\tformFieldProps: FormFieldProps;\n}) {\n\tif (!context.type) {\n\t\treturn renderConfigError(\n\t\t\t`Missing field type for \"${context.fieldName}\". ` +\n\t\t\t\t`Available fields: ${Object.keys(context.fieldDef || {}).join(\", \")}`,\n\t\t);\n\t}\n\n\t// Map field types to FormField types\n\tconst typeMap: Record<string, FormFieldProps[\"type\"]> = {\n\t\ttext: \"text\",\n\t\temail: \"email\",\n\t\tpassword: \"password\",\n\t\ttextarea: \"textarea\",\n\t\tnumber: \"number\",\n\t\tcheckbox: \"checkbox\",\n\t\tswitch: \"switch\",\n\t\tselect: \"select\",\n\t\tdate: \"date\",\n\t\tdatetime: \"datetime\",\n\t\tjson: \"json\",\n\t};\n\n\tconst mappedType = typeMap[context.type];\n\n\tif (context.type === \"select\" && context.options) {\n\t\treturn renderFormField(formFieldProps, \"select\", {\n\t\t\toptions: context.options,\n\t\t});\n\t}\n\n\tif (mappedType) {\n\t\treturn renderFormField(formFieldProps, mappedType);\n\t}\n\n\t// Unknown type - try to render as text\n\treturn renderFormField(formFieldProps, \"text\");\n}\n\n// ============================================================================\n// FieldRenderer Component\n// ============================================================================\n\n/**\n * Render a single field with conditional logic\n *\n * Rendering priority:\n * 1. Embedded fields (need special handling for recursive AutoFormFields)\n * 2. FieldDefinition.field.component (handles relation, array, richText, etc.)\n * 3. Primitive fields via FormField (fallback for fields without component)\n */\nexport function FieldRenderer({\n\tfieldName,\n\tfieldDef,\n\tcollection,\n\tregistry,\n\tfieldPrefix,\n\tallCollectionsConfig,\n\trenderEmbeddedFields,\n\tclassName,\n\tcollectionMeta: collectionMetaProp,\n}: FieldRendererProps) {\n\tconst form = useFormContext() as any;\n\t// Use scoped locale (from LocaleScopeProvider in ResourceSheet) or global locale\n\tconst { locale } = useScopedLocale();\n\tconst resolveText = useResolveText();\n\t// Get admin for blocks registry\n\tconst admin = useAdminStore(selectAdmin);\n\n\t// Use useWatch hook (React pattern) instead of form.getValues() method\n\t// This ensures reactive updates when form values change\n\t// Watch all form values - the fieldPrefix scoping is handled by getFieldContext\n\tconst watchedValues = useWatch({ control: form.control });\n\tconst fullFieldName = getFullFieldName(fieldName, fieldPrefix);\n\tconst watchedFieldValue = useWatch({\n\t\tcontrol: form.control,\n\t\tname: fullFieldName,\n\t} as any);\n\n\t// Extract the scoped values if fieldPrefix is provided\n\tconst formValues = React.useMemo(() => {\n\t\tif (!watchedValues) return {};\n\t\tif (!fieldPrefix) return watchedValues as Record<string, any>;\n\t\t// Navigate to the nested path\n\t\tconst parts = fieldPrefix.split(\".\");\n\t\tlet result: any = watchedValues;\n\t\tfor (const part of parts) {\n\t\t\tresult = result?.[part];\n\t\t\tif (result === undefined) return {};\n\t\t}\n\t\treturn (result ?? {}) as Record<string, any>;\n\t}, [watchedValues, fieldPrefix]);\n\n\t// Fetch collection metadata for inferring localized fields\n\t// Use prop if provided, otherwise fetch from backend\n\tconst { data: fetchedMeta } = useCollectionMeta(collection, {\n\t\tenabled: !collectionMetaProp,\n\t});\n\tconst collectionMeta = collectionMetaProp ?? fetchedMeta;\n\n\tconst context = getFieldContext({\n\t\tfieldName,\n\t\tfieldDef,\n\t\tcollection,\n\t\tform,\n\t\tfieldPrefix,\n\t\tlocale,\n\t\tcollectionMeta,\n\t\tformValues, // Pass pre-watched values to avoid calling form.watch() internally\n\t});\n\n\t// Get field options for hooks\n\tconst fieldOptions = getFieldOptions(fieldDef);\n\n\t// Use field hooks for compute, onChange, loadOptions\n\tconst {\n\t\thandleChange,\n\t\tcomputedValue,\n\t\tisComputed,\n\t\toptions: hookOptions,\n\t\toptionsLoading,\n\t} = useFieldHooks({\n\t\tfieldName,\n\t\tfullFieldName: context.fullFieldName,\n\t\tlocale,\n\t\tcompute: fieldOptions.compute,\n\t\tonChange: fieldOptions.onChange,\n\t\tdefaultValue: fieldOptions.defaultValue,\n\t\tloadOptions: fieldOptions.loadOptions,\n\t\tstaticOptions: context.options,\n\t});\n\n\t// Hidden fields are not rendered\n\tif (context.isHidden) return null;\n\n\t// Field not found in config\n\tif (!fieldDef) {\n\t\treturn renderConfigError(\n\t\t\t`Field \"${fieldName}\" not found in collection \"${collection}\" config.`,\n\t\t);\n\t}\n\n\t// Use hook options if available, otherwise use context options\n\tconst resolvedOptions = hookOptions ?? context.options;\n\n\t// Build props and resolve I18nText labels to strings\n\tconst rawComponentProps = buildComponentProps(context);\n\n\t// For computed fields, use computed value instead of form value\n\tconst fieldValue = isComputed\n\t\t? computedValue\n\t\t: watchedFieldValue === undefined\n\t\t\t? rawComponentProps.value\n\t\t\t: watchedFieldValue;\n\n\tconst componentProps = {\n\t\t...rawComponentProps,\n\t\t// Use computed value if field is computed\n\t\tvalue: fieldValue,\n\t\t// Use handleChange from hooks instead of context.updateValue\n\t\tonChange: handleChange,\n\t\t// Use resolved options\n\t\toptions: resolvedOptions,\n\t\t// Pass loading state for async options\n\t\toptionsLoading,\n\t\t// Computed fields are always readonly\n\t\treadOnly: rawComponentProps.readOnly || isComputed,\n\t\tlabel: resolveText(rawComponentProps.label, \"\", formValues),\n\t\tdescription: resolveText(rawComponentProps.description, \"\", formValues),\n\t\tplaceholder: resolveText(rawComponentProps.placeholder, \"\", formValues),\n\t};\n\n\tconst rawFormFieldProps = buildFormFieldProps(context);\n\tconst formFieldProps: FormFieldProps = {\n\t\t...rawFormFieldProps,\n\t\t// Use resolved options for select fields (cast for compatibility)\n\t\toptions: resolvedOptions as FormFieldProps[\"options\"],\n\t\tlabel: resolveText(rawFormFieldProps.label, \"\", formValues),\n\t\tdescription: resolveText(rawFormFieldProps.description, \"\", formValues),\n\t\tplaceholder: resolveText(rawFormFieldProps.placeholder, \"\", formValues),\n\t};\n\n\t// Render content based on priority\n\tlet content: React.ReactNode = null;\n\n\t// 1. Embedded fields need special handling for recursive rendering\n\tif (context.type === \"embedded\") {\n\t\tcontent = renderEmbeddedField({\n\t\t\tcontext,\n\t\t\tregistry,\n\t\t\tallCollectionsConfig,\n\t\t\tcomponentProps,\n\t\t\trenderEmbeddedFields,\n\t\t});\n\t}\n\n\t// 2. Use FieldDefinition.field.component if available\n\tif (!content && context.component) {\n\t\tcontent = renderDefinitionComponent({\n\t\t\tcontext,\n\t\t\tcomponentProps,\n\t\t\tblocks: admin.state.blocks,\n\t\t});\n\t}\n\n\t// 3. Fallback to primitive field rendering\n\tif (!content) {\n\t\tcontent = renderPrimitiveField({ context, formFieldProps });\n\t}\n\n\tif (!content) return null;\n\n\t// Wrap with className if provided\n\tif (className) {\n\t\treturn <div className={className}>{content}</div>;\n\t}\n\n\treturn <>{content}</>;\n}\n","/**\n * AutoFormFields Component\n *\n * Automatically generates form fields from CollectionBuilderState:\n * - Reads field definitions (FieldDefinition) from config.fields\n * - Reads form layout (FormViewConfig) from config.form\n * - Supports recursive tabs/sections nesting\n * - Auto-generates fields when no form config is defined\n */\n\nimport type { Questpie } from \"questpie\";\nimport * as React from \"react\";\nimport { useFormContext, useWatch } from \"react-hook-form\";\nimport type {\n\tComponentRegistry,\n\tFieldLayoutItem,\n\tFormSidebarConfig,\n\tFormViewConfig,\n\tSectionLayout,\n\tTabConfig,\n\tTabsLayout,\n} from \"../../builder\";\nimport type { FieldDefinition } from \"../../builder/field/field\";\nimport {\n\tgetFieldName,\n\tisFieldReference,\n} from \"../../builder/types/field-types\";\nimport { containerGridColumnClasses } from \"../../components/fields/field-utils\";\nimport {\n\tAccordion,\n\tAccordionContent,\n\tAccordionItem,\n\tAccordionTrigger,\n} from \"../../components/ui/accordion\";\nimport {\n\tTabs,\n\tTabsContent,\n\tTabsList,\n\tTabsTrigger,\n} from \"../../components/ui/tabs\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../utils\";\nimport { getFullFieldName, resolveValue } from \"./field-context\";\nimport { FieldRenderer } from \"./field-renderer\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Collection config as expected by AutoFormFields\n * This matches CollectionBuilderState structure\n */\ninterface CollectionConfig {\n\tname?: string;\n\tfields?: Record<string, FieldDefinition>;\n\tform?: FormViewConfig;\n}\n\nexport interface AutoFormFieldsProps<\n\tT extends Questpie<any> = Questpie<any>,\n\tK extends string = string,\n> {\n\t/**\n\t * CMS instance (for schema introspection) - optional\n\t */\n\tcms?: T;\n\n\t/**\n\t * Collection name\n\t */\n\tcollection: K;\n\n\t/**\n\t * Collection config (CollectionBuilderState)\n\t */\n\tconfig?: CollectionConfig;\n\n\t/**\n\t * Component registry for custom field types\n\t */\n\tregistry?: ComponentRegistry;\n\n\t/**\n\t * Custom field renderer (fallback)\n\t */\n\trenderField?: (\n\t\tfieldName: string,\n\t\tfieldDef?: FieldDefinition,\n\t) => React.ReactNode;\n\n\t/**\n\t * Field name prefix for nested fields\n\t */\n\tfieldPrefix?: string;\n\n\t/**\n\t * All collection configs (for embedded collections)\n\t */\n\tallCollectionsConfig?: Record<string, CollectionConfig>;\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Normalize FieldLayoutItem to field name\n * Only handles field references, returns null for layout containers\n */\nfunction normalizeFieldItem(item: FieldLayoutItem): {\n\tfield: string;\n\tclassName?: string;\n} | null {\n\tif (typeof item === \"string\") {\n\t\treturn { field: item };\n\t}\n\tif (isFieldReference(item)) {\n\t\treturn item;\n\t}\n\treturn null;\n}\n\n// ============================================================================\n// Layout Helpers\n// ============================================================================\n\nfunction getGridColumnsClass(columns?: number) {\n\tif (!columns) return \"\";\n\treturn containerGridColumnClasses[columns] || \"\";\n}\n\nfunction getGapStyle(gap?: number) {\n\tif (gap === undefined) return undefined;\n\treturn `${gap * 0.25}rem`;\n}\n\n// ============================================================================\n// Field Layout Renderers (Recursive)\n// ============================================================================\n\ninterface FieldLayoutRendererProps {\n\tfieldItems: FieldLayoutItem[];\n\tfields: Record<string, FieldDefinition>;\n\tcollection: string;\n\tregistry?: ComponentRegistry;\n\tfieldPrefix?: string;\n\tallCollectionsConfig?: Record<string, CollectionConfig>;\n\texcludedFields?: Set<string>;\n\tformValues: any;\n\tresolveText: (\n\t\ttext: any,\n\t\tfallback?: string,\n\t\tcontextValues?: Record<string, any>,\n\t) => string;\n}\n\n/**\n * Render fields list\n */\nfunction renderFields({\n\tfieldItems,\n\tfields,\n\tcollection,\n\tregistry,\n\tfieldPrefix,\n\tallCollectionsConfig,\n\texcludedFields,\n\tcolumns = 1,\n\tgap,\n\tclassName,\n}: {\n\tfieldItems: FieldLayoutItem[];\n\tfields: Record<string, FieldDefinition>;\n\tcollection: string;\n\tregistry?: ComponentRegistry;\n\tfieldPrefix?: string;\n\tallCollectionsConfig?: Record<string, CollectionConfig>;\n\texcludedFields?: Set<string>;\n\tcolumns?: number;\n\tgap?: number;\n\tclassName?: string;\n}) {\n\tconst visibleFields = fieldItems\n\t\t.map(normalizeFieldItem)\n\t\t.filter(\n\t\t\t(item): item is { field: string; className?: string } => item !== null,\n\t\t)\n\t\t.filter((item) => !excludedFields?.has(item.field));\n\n\tif (!visibleFields.length) return null;\n\n\tconst gridClass = columns > 1 ? getGridColumnsClass(columns) : \"\";\n\n\t// Calculate if last field should span full width\n\t// (when there's an odd number of fields in a multi-column grid)\n\tconst shouldLastFieldSpan =\n\t\tcolumns > 1 && visibleFields.length % columns !== 0;\n\n\tconst fieldElements = visibleFields.map((item, index) => {\n\t\tconst isLast = index === visibleFields.length - 1;\n\t\t// Use col-span-full for last item that would be alone in its row\n\t\tconst spanClass = isLast && shouldLastFieldSpan ? \"col-span-full\" : \"\";\n\n\t\treturn (\n\t\t\t<FieldRenderer\n\t\t\t\tkey={item.field}\n\t\t\t\tfieldName={item.field}\n\t\t\t\tfieldDef={fields[item.field]}\n\t\t\t\tcollection={collection}\n\t\t\t\tregistry={registry}\n\t\t\t\tfieldPrefix={fieldPrefix}\n\t\t\t\tallCollectionsConfig={allCollectionsConfig}\n\t\t\t\tclassName={cn(item.className, spanClass)}\n\t\t\t\trenderEmbeddedFields={({\n\t\t\t\t\tembeddedCollection,\n\t\t\t\t\tembeddedCollectionConfig,\n\t\t\t\t\tfullFieldName,\n\t\t\t\t\tindex: embeddedIndex,\n\t\t\t\t}) => (\n\t\t\t\t\t<AutoFormFields\n\t\t\t\t\t\tcollection={embeddedCollection}\n\t\t\t\t\t\tconfig={embeddedCollectionConfig}\n\t\t\t\t\t\tregistry={registry}\n\t\t\t\t\t\tfieldPrefix={`${fullFieldName}.${embeddedIndex}`}\n\t\t\t\t\t\tallCollectionsConfig={allCollectionsConfig}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t/>\n\t\t);\n\t});\n\n\t// Grid uses container query breakpoints (@sm:, @md:, etc.)\n\t// These respond to the nearest @container ancestor (defined in AutoFormFields wrapper)\n\tif (columns > 1) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\"grid gap-4\", gridClass, className)}\n\t\t\t\tstyle={gap ? { gap: getGapStyle(gap) } : undefined}\n\t\t\t>\n\t\t\t\t{fieldElements}\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Single column - no grid needed\n\treturn <div className={cn(\"space-y-4\", className)}>{fieldElements}</div>;\n}\n\n/**\n * Render field layout items (fields, sections, tabs)\n *\n * NEW API: fields array can contain:\n * - Field references (string or {field, className})\n * - Section layouts ({ type: 'section', ... })\n * - Tabs layouts ({ type: 'tabs', ... })\n */\nfunction getLayoutKey(item: SectionLayout | TabsLayout): string {\n\tif (item.type === \"tabs\") {\n\t\tconst tabKey = item.tabs\n\t\t\t.map((tab) => tab.id)\n\t\t\t.filter(Boolean)\n\t\t\t.join(\"-\");\n\t\treturn tabKey ? `tabs-${tabKey}` : \"tabs\";\n\t}\n\n\tconst fieldKey = item.fields\n\t\t.map((fieldItem) => {\n\t\t\tif (isFieldReference(fieldItem)) {\n\t\t\t\treturn getFieldName(fieldItem) ?? \"field\";\n\t\t\t}\n\t\t\tif (typeof fieldItem === \"object\" && \"type\" in fieldItem) {\n\t\t\t\treturn fieldItem.type;\n\t\t\t}\n\t\t\treturn \"item\";\n\t\t})\n\t\t.join(\"-\");\n\n\treturn fieldKey ? `section-${fieldKey}` : \"section\";\n}\n\nfunction renderFieldLayoutItems({\n\tfieldItems,\n\tfields,\n\tcollection,\n\tregistry,\n\tfieldPrefix,\n\tallCollectionsConfig,\n\texcludedFields,\n\tformValues,\n\tresolveText,\n}: FieldLayoutRendererProps): React.ReactNode {\n\tif (!fieldItems?.length) return null;\n\n\tconst renderedItems = fieldItems.map((item, index) => {\n\t\t// Field reference (string or {field, className})\n\t\tif (isFieldReference(item)) {\n\t\t\tconst fieldName = getFieldName(item);\n\t\t\tif (!fieldName || !fields[fieldName]) return null;\n\n\t\t\t// Check if excluded\n\t\t\tif (excludedFields?.has(fieldName)) return null;\n\n\t\t\t// Check if hidden\n\t\t\tconst fieldDef = fields[fieldName];\n\t\t\tconst fieldOptions = (fieldDef as any)[\"~options\"] || {};\n\t\t\tconst isHidden =\n\t\t\t\ttypeof fieldOptions.hidden === \"function\"\n\t\t\t\t\t? fieldOptions.hidden(formValues)\n\t\t\t\t\t: fieldOptions.hidden === true;\n\t\t\tif (isHidden) return null;\n\n\t\t\treturn (\n\t\t\t\t<FieldRenderer\n\t\t\t\t\tkey={fieldName}\n\t\t\t\t\tfieldName={fieldName}\n\t\t\t\t\tfieldDef={fieldDef}\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\tregistry={registry}\n\t\t\t\t\tfieldPrefix={fieldPrefix}\n\t\t\t\t\tallCollectionsConfig={allCollectionsConfig}\n\t\t\t\t\tclassName={\n\t\t\t\t\t\ttypeof item === \"object\" && \"className\" in item\n\t\t\t\t\t\t\t? item.className\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\trenderEmbeddedFields={({\n\t\t\t\t\t\tembeddedCollection,\n\t\t\t\t\t\tembeddedCollectionConfig,\n\t\t\t\t\t\tfullFieldName,\n\t\t\t\t\t\tindex: embeddedIndex,\n\t\t\t\t\t}) => (\n\t\t\t\t\t\t<AutoFormFields\n\t\t\t\t\t\t\tcollection={embeddedCollection}\n\t\t\t\t\t\t\tconfig={embeddedCollectionConfig}\n\t\t\t\t\t\t\tregistry={registry}\n\t\t\t\t\t\t\tfieldPrefix={`${fullFieldName}.${embeddedIndex}`}\n\t\t\t\t\t\t\tallCollectionsConfig={allCollectionsConfig}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\t// Layout containers\n\t\tif (typeof item === \"object\" && \"type\" in item) {\n\t\t\tswitch (item.type) {\n\t\t\t\tcase \"tabs\":\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<React.Fragment key={getLayoutKey(item)}>\n\t\t\t\t\t\t\t{renderTabs({\n\t\t\t\t\t\t\t\ttabsLayout: item,\n\t\t\t\t\t\t\t\tfields,\n\t\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\t\tregistry,\n\t\t\t\t\t\t\t\tfieldPrefix,\n\t\t\t\t\t\t\t\tallCollectionsConfig,\n\t\t\t\t\t\t\t\texcludedFields,\n\t\t\t\t\t\t\t\tformValues,\n\t\t\t\t\t\t\t\tresolveText,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t);\n\n\t\t\t\tcase \"section\":\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<React.Fragment key={getLayoutKey(item)}>\n\t\t\t\t\t\t\t{renderSection({\n\t\t\t\t\t\t\t\tsection: item,\n\t\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\t\tfields,\n\t\t\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\t\tregistry,\n\t\t\t\t\t\t\t\tfieldPrefix,\n\t\t\t\t\t\t\t\tallCollectionsConfig,\n\t\t\t\t\t\t\t\texcludedFields,\n\t\t\t\t\t\t\t\tformValues,\n\t\t\t\t\t\t\t\tresolveText,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t);\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t});\n\n\tconst validItems = renderedItems.filter(Boolean);\n\n\treturn validItems.length === 1 ? (\n\t\tvalidItems[0]\n\t) : (\n\t\t<div className=\"space-y-6\">{validItems}</div>\n\t);\n}\n\n/**\n * Render a section layout\n * Mirrors object field: wrapper (flat|collapsible) + layout (stack|inline|grid)\n */\nfunction renderSection({\n\tsection,\n\tindex,\n\tfields,\n\tcollection,\n\tregistry,\n\tfieldPrefix,\n\tallCollectionsConfig,\n\texcludedFields,\n\tformValues,\n\tresolveText,\n}: {\n\tsection: SectionLayout;\n\tindex: number;\n\tfields: Record<string, FieldDefinition>;\n\tcollection: string;\n\tregistry?: ComponentRegistry;\n\tfieldPrefix?: string;\n\tallCollectionsConfig?: Record<string, CollectionConfig>;\n\texcludedFields?: Set<string>;\n\tformValues: any;\n\tresolveText: (\n\t\ttext: any,\n\t\tfallback?: string,\n\t\tcontextValues?: Record<string, any>,\n\t) => string;\n}): React.ReactNode {\n\t// Check if hidden\n\tconst isHidden = resolveValue(section.hidden, formValues, false);\n\tif (isHidden) return null;\n\n\tconst wrapper = section.wrapper ?? \"flat\";\n\tconst layout = section.layout ?? \"stack\";\n\tconst columns = section.columns ?? 2;\n\tconst gap = section.gap;\n\n\t// Render section fields based on layout mode\n\tconst renderSectionFields = () => {\n\t\tif (layout === \"grid\") {\n\t\t\t// Grid layout - use renderFields with columns\n\t\t\treturn renderFields({\n\t\t\t\tfieldItems: section.fields,\n\t\t\t\tfields,\n\t\t\t\tcollection,\n\t\t\t\tregistry,\n\t\t\t\tfieldPrefix,\n\t\t\t\tallCollectionsConfig,\n\t\t\t\texcludedFields,\n\t\t\t\tcolumns,\n\t\t\t\tgap,\n\t\t\t\tclassName: section.className,\n\t\t\t});\n\t\t}\n\n\t\tif (layout === \"inline\") {\n\t\t\t// Inline layout - horizontal flexbox\n\t\t\treturn (\n\t\t\t\t<div className={cn(\"flex flex-wrap gap-4\", section.className)}>\n\t\t\t\t\t{section.fields.map((item, idx) => {\n\t\t\t\t\t\tconst fieldName = getFieldName(item);\n\t\t\t\t\t\tif (!fieldName || !fields[fieldName]) return null;\n\t\t\t\t\t\tif (excludedFields?.has(fieldName)) return null;\n\n\t\t\t\t\t\tconst fieldDef = fields[fieldName];\n\t\t\t\t\t\tconst fieldOptions = (fieldDef as any)[\"~options\"] || {};\n\t\t\t\t\t\tconst isVis =\n\t\t\t\t\t\t\ttypeof fieldOptions.visible === \"function\"\n\t\t\t\t\t\t\t\t? fieldOptions.visible(formValues)\n\t\t\t\t\t\t\t\t: fieldOptions.visible !== false;\n\t\t\t\t\t\tif (!isVis) return null;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<FieldRenderer\n\t\t\t\t\t\t\t\tkey={fieldName}\n\t\t\t\t\t\t\t\tfieldName={fieldName}\n\t\t\t\t\t\t\t\tfieldDef={fieldDef}\n\t\t\t\t\t\t\t\tcollection={collection}\n\t\t\t\t\t\t\t\tregistry={registry}\n\t\t\t\t\t\t\t\tfieldPrefix={fieldPrefix}\n\t\t\t\t\t\t\t\tallCollectionsConfig={allCollectionsConfig}\n\t\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\t\ttypeof item === \"object\" && \"className\" in item\n\t\t\t\t\t\t\t\t\t\t? item.className\n\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trenderEmbeddedFields={({\n\t\t\t\t\t\t\t\t\tembeddedCollection,\n\t\t\t\t\t\t\t\t\tembeddedCollectionConfig,\n\t\t\t\t\t\t\t\t\tfullFieldName,\n\t\t\t\t\t\t\t\t\tindex: embeddedIndex,\n\t\t\t\t\t\t\t\t}) => (\n\t\t\t\t\t\t\t\t\t<AutoFormFields\n\t\t\t\t\t\t\t\t\t\tcollection={embeddedCollection}\n\t\t\t\t\t\t\t\t\t\tconfig={embeddedCollectionConfig}\n\t\t\t\t\t\t\t\t\t\tregistry={registry}\n\t\t\t\t\t\t\t\t\t\tfieldPrefix={`${fullFieldName}.${embeddedIndex}`}\n\t\t\t\t\t\t\t\t\t\tallCollectionsConfig={allCollectionsConfig}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\t// Stack layout (default) - render using main function\n\t\treturn renderFieldLayoutItems({\n\t\t\tfieldItems: section.fields,\n\t\t\tfields,\n\t\t\tcollection,\n\t\t\tregistry,\n\t\t\tfieldPrefix,\n\t\t\tallCollectionsConfig,\n\t\t\texcludedFields,\n\t\t\tformValues,\n\t\t\tresolveText,\n\t\t});\n\t};\n\n\tconst content = renderSectionFields();\n\tif (!content) return null;\n\n\t// Section header\n\tconst header =\n\t\tsection.label || section.description ? (\n\t\t\t<div className=\"mb-4\">\n\t\t\t\t{section.label && (\n\t\t\t\t\t<h3 className=\"text-lg font-semibold\">\n\t\t\t\t\t\t{resolveText(section.label, \"\", formValues)}\n\t\t\t\t\t</h3>\n\t\t\t\t)}\n\t\t\t\t{section.description && (\n\t\t\t\t\t<p className=\"text-sm text-muted-foreground mt-1\">\n\t\t\t\t\t\t{resolveText(section.description, \"\", formValues)}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t) : null;\n\n\t// Collapsible wrapper\n\tif (wrapper === \"collapsible\") {\n\t\tconst value = `section-${index}`;\n\t\tconst defaultOpen = section.defaultCollapsed !== true;\n\n\t\treturn (\n\t\t\t<Accordion\n\t\t\t\tkey={value}\n\t\t\t\tdefaultValue={defaultOpen ? [value] : []}\n\t\t\t\tclassName=\"w-full\"\n\t\t\t>\n\t\t\t\t<AccordionItem value={value} className=\"border rounded-lg px-4\">\n\t\t\t\t\t<AccordionTrigger className=\"hover:no-underline\">\n\t\t\t\t\t\t<span className=\"font-semibold\">\n\t\t\t\t\t\t\t{resolveText(section.label, \"Section\", formValues)}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</AccordionTrigger>\n\t\t\t\t\t<AccordionContent className=\"pt-2 pb-4\">\n\t\t\t\t\t\t{section.description && (\n\t\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground mb-4\">\n\t\t\t\t\t\t\t\t{resolveText(section.description, \"\", formValues)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{content}\n\t\t\t\t\t</AccordionContent>\n\t\t\t\t</AccordionItem>\n\t\t\t</Accordion>\n\t\t);\n\t}\n\n\t// Flat wrapper (no visual container)\n\treturn (\n\t\t<div className={cn(\"space-y-4\", section.className)}>\n\t\t\t{header}\n\t\t\t{content}\n\t\t</div>\n\t);\n}\n\n/**\n * Render tabs layout\n */\nfunction renderTabs({\n\ttabsLayout,\n\tfields,\n\tcollection,\n\tregistry,\n\tfieldPrefix,\n\tallCollectionsConfig,\n\texcludedFields,\n\tformValues,\n\tresolveText,\n}: {\n\ttabsLayout: TabsLayout;\n\tfields: Record<string, FieldDefinition>;\n\tcollection: string;\n\tregistry?: ComponentRegistry;\n\tfieldPrefix?: string;\n\tallCollectionsConfig?: Record<string, CollectionConfig>;\n\texcludedFields?: Set<string>;\n\tformValues: any;\n\tresolveText: (\n\t\ttext: any,\n\t\tfallback?: string,\n\t\tcontextValues?: Record<string, any>,\n\t) => string;\n}): React.ReactNode {\n\tconst visibleTabs = tabsLayout.tabs.filter(\n\t\t(tab) => !resolveValue(tab.hidden, formValues, false),\n\t);\n\n\tif (!visibleTabs.length) return null;\n\n\tconst defaultTab = visibleTabs[0]?.id;\n\n\treturn (\n\t\t<Tabs defaultValue={defaultTab}>\n\t\t\t<TabsList variant=\"line\">\n\t\t\t\t{visibleTabs.map((tab) => (\n\t\t\t\t\t<TabsTrigger key={tab.id} value={tab.id}>\n\t\t\t\t\t\t{tab.icon && <tab.icon className=\"mr-2 size-4\" />}\n\t\t\t\t\t\t{resolveText(tab.label, tab.id, formValues)}\n\t\t\t\t\t</TabsTrigger>\n\t\t\t\t))}\n\t\t\t</TabsList>\n\t\t\t{visibleTabs.map((tab) => (\n\t\t\t\t<TabsContent key={tab.id} value={tab.id} className=\"mt-4\">\n\t\t\t\t\t{renderFieldLayoutItems({\n\t\t\t\t\t\tfieldItems: tab.fields,\n\t\t\t\t\t\tfields,\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t\tregistry,\n\t\t\t\t\t\tfieldPrefix,\n\t\t\t\t\t\tallCollectionsConfig,\n\t\t\t\t\t\texcludedFields,\n\t\t\t\t\t\tformValues,\n\t\t\t\t\t\tresolveText,\n\t\t\t\t\t})}\n\t\t\t\t</TabsContent>\n\t\t\t))}\n\t\t</Tabs>\n\t);\n}\n\n/**\n * Render sidebar content\n */\nfunction renderSidebar({\n\tsidebar,\n\tfields,\n\tcollection,\n\tregistry,\n\tfieldPrefix,\n\tallCollectionsConfig,\n\tformValues,\n\tresolveText,\n}: {\n\tsidebar: FormSidebarConfig;\n\tfields: Record<string, FieldDefinition>;\n\tcollection: string;\n\tregistry?: ComponentRegistry;\n\tfieldPrefix?: string;\n\tallCollectionsConfig?: Record<string, CollectionConfig>;\n\tformValues: any;\n\tresolveText: (\n\t\ttext: any,\n\t\tfallback?: string,\n\t\tcontextValues?: Record<string, any>,\n\t) => string;\n}): React.ReactNode {\n\treturn renderFieldLayoutItems({\n\t\tfieldItems: sidebar.fields,\n\t\tfields,\n\t\tcollection,\n\t\tregistry,\n\t\tfieldPrefix,\n\t\tallCollectionsConfig,\n\t\tformValues,\n\t\tresolveText,\n\t});\n}\n\n/**\n * Extract field names from field layout items recursively\n */\nfunction extractFieldNamesFromFieldItems(\n\tfieldItems?: FieldLayoutItem[],\n): Set<string> {\n\tconst fieldNames = new Set<string>();\n\n\tif (!fieldItems) return fieldNames;\n\n\tfor (const item of fieldItems) {\n\t\t// Field reference\n\t\tif (isFieldReference(item)) {\n\t\t\tconst fieldName = getFieldName(item);\n\t\t\tif (fieldName) fieldNames.add(fieldName);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Layout containers\n\t\tif (typeof item === \"object\" && \"type\" in item) {\n\t\t\tswitch (item.type) {\n\t\t\t\tcase \"tabs\":\n\t\t\t\t\tfor (const tab of item.tabs) {\n\t\t\t\t\t\tconst tabFields = extractFieldNamesFromFieldItems(tab.fields);\n\t\t\t\t\t\tfor (const f of tabFields) fieldNames.add(f);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"section\": {\n\t\t\t\t\tconst sectionFields = extractFieldNamesFromFieldItems(item.fields);\n\t\t\t\t\tfor (const f of sectionFields) fieldNames.add(f);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fieldNames;\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * AutoFormFields Component\n *\n * Renders form fields based on CollectionBuilderState config.\n * Supports recursive tabs/sections nesting and auto-generates\n * field list when no form config is defined.\n */\nexport function AutoFormFields<T extends Questpie<any>, K extends string>({\n\tcms: _cms,\n\tcollection,\n\tconfig,\n\tregistry,\n\trenderField,\n\tfieldPrefix,\n\tallCollectionsConfig,\n}: AutoFormFieldsProps<T, K>): React.ReactElement {\n\tconst form = useFormContext() as any;\n\t// Use useWatch hook (React pattern) instead of form.watch() method\n\t// Watch all form values - the fieldPrefix scoping is handled below\n\tconst watchedValues = useWatch({ control: form.control });\n\n\t// Extract the scoped values if fieldPrefix is provided\n\tconst formValues = React.useMemo(() => {\n\t\tif (!watchedValues) return {};\n\t\tif (!fieldPrefix) return watchedValues as Record<string, any>;\n\t\t// Navigate to the nested path\n\t\tconst parts = fieldPrefix.split(\".\");\n\t\tlet result: any = watchedValues;\n\t\tfor (const part of parts) {\n\t\t\tresult = result?.[part];\n\t\t\tif (result === undefined) return {};\n\t\t}\n\t\treturn (result ?? {}) as Record<string, any>;\n\t}, [watchedValues, fieldPrefix]);\n\n\tconst resolveText = useResolveText();\n\n\t// Get fields config\n\tconst fields = (config?.fields || {}) as Record<string, FieldDefinition>;\n\n\t// Extract form config from view builder (~config property)\n\tconst formConfig = (config?.form as any)?.[\"~config\"] ?? config?.form;\n\n\t// Get all field names for auto-generation\n\tconst allFieldNames = Object.keys(fields);\n\n\t// Collect sidebar field names to exclude from main content\n\tconst sidebarFieldNames = formConfig?.sidebar\n\t\t? extractFieldNamesFromFieldItems(formConfig.sidebar.fields)\n\t\t: new Set<string>();\n\n\t// Custom render function provided\n\tif (renderField) {\n\t\treturn (\n\t\t\t<div className=\"space-y-4\">\n\t\t\t\t{allFieldNames.map((fieldName) => {\n\t\t\t\t\tconst fullFieldName = getFullFieldName(fieldName, fieldPrefix);\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<React.Fragment key={fullFieldName}>\n\t\t\t\t\t\t\t{renderField(fullFieldName, fields[fieldName])}\n\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Render main content based on form config\n\tconst renderMainContent = () => {\n\t\t// If form config has fields, render them\n\t\tif (formConfig?.fields?.length) {\n\t\t\treturn renderFieldLayoutItems({\n\t\t\t\tfieldItems: formConfig.fields,\n\t\t\t\tfields,\n\t\t\t\tcollection,\n\t\t\t\tregistry,\n\t\t\t\tfieldPrefix,\n\t\t\t\tallCollectionsConfig,\n\t\t\t\texcludedFields: sidebarFieldNames,\n\t\t\t\tformValues,\n\t\t\t\tresolveText,\n\t\t\t});\n\t\t}\n\n\t\t// Auto-generate: render all fields not in sidebar\n\t\tconst autoFields = allFieldNames.filter((f) => !sidebarFieldNames.has(f));\n\t\tif (autoFields.length) {\n\t\t\treturn renderFields({\n\t\t\t\tfieldItems: autoFields,\n\t\t\t\tfields,\n\t\t\t\tcollection,\n\t\t\t\tregistry,\n\t\t\t\tfieldPrefix,\n\t\t\t\tallCollectionsConfig,\n\t\t\t});\n\t\t}\n\n\t\treturn null;\n\t};\n\n\tconst mainContent = renderMainContent();\n\n\t// Check if sidebar layout is needed\n\tconst hasSidebar = formConfig?.sidebar && formConfig.sidebar.fields?.length;\n\n\tif (hasSidebar && formConfig?.sidebar) {\n\t\tconst sidebarContent = renderSidebar({\n\t\t\tsidebar: formConfig.sidebar,\n\t\t\tfields,\n\t\t\tcollection,\n\t\t\tregistry,\n\t\t\tfieldPrefix,\n\t\t\tallCollectionsConfig,\n\t\t\tformValues,\n\t\t\tresolveText,\n\t\t});\n\n\t\tconst sidebarPosition = formConfig.sidebar.position || \"right\";\n\n\t\t// Single @container on outermost wrapper for all container queries\n\t\treturn (\n\t\t\t<div className=\"@container w-full\">\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex flex-col-reverse gap-6 @2xl:flex-row\",\n\t\t\t\t\t\tsidebarPosition === \"left\" && \"@2xl:flex-row-reverse\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<div className=\"min-w-0 flex-1\">{mainContent}</div>\n\t\t\t\t\t{sidebarContent && (\n\t\t\t\t\t\t<aside\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"@2xl:border-l @max-2xl:border-b @max-2xl:pb-4 w-full border-border @2xl:pl-4\",\n\t\t\t\t\t\t\t\t\"w-full @2xl:max-w-xs\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div className=\"space-y-4 @2xl:sticky @2xl:h-auto @2xl:top-4\">\n\t\t\t\t\t\t\t\t{sidebarContent}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</aside>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn <div className=\"@container\">{mainContent}</div>;\n}\n","/**\n * Action Dialog\n *\n * Renders dialog-type and form-type actions.\n * Supports lazy-loaded components and inline form definitions.\n * Form actions use AutoFormFields for full field system support.\n */\n\n\"use client\";\n\nimport { SpinnerGap } from \"@phosphor-icons/react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport {\n\ttype FieldErrors,\n\tFormProvider,\n\ttype Resolver,\n\tuseForm,\n} from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport type {\n\tActionContext,\n\tActionDefinition,\n\tActionHelpers,\n\tDialogHandler,\n\tFormHandler,\n} from \"../../builder/collection/action-types\";\nimport type { FieldDefinition } from \"../../builder/field/field\";\nimport { buildValidationSchema } from \"../../builder/validation\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { AutoFormFields } from \"../../views/collection/auto-form-fields\";\nimport { Button } from \"../ui/button\";\nimport {\n\tResponsiveDialog,\n\tResponsiveDialogContent,\n\tResponsiveDialogDescription,\n\tResponsiveDialogFooter,\n\tResponsiveDialogHeader,\n\tResponsiveDialogTitle,\n} from \"../ui/responsive-dialog\";\n\nexport interface ActionDialogProps<TItem = any> {\n\t/** Whether the dialog is open */\n\topen: boolean;\n\t/** Callback when dialog should close */\n\tonOpenChange: (open: boolean) => void;\n\t/** The action being rendered */\n\taction: ActionDefinition<TItem>;\n\t/** Collection name */\n\tcollection: string;\n\t/** Item for row actions */\n\titem?: TItem;\n\t/** Items for bulk actions */\n\titems?: TItem[];\n\t/** Action helpers */\n\thelpers: ActionHelpers;\n}\n\n/**\n * Create a custom resolver for action form validation\n * Uses buildValidationSchema and handles Zod v4 compatibility\n */\nfunction createActionFormResolver(\n\tfields: Record<string, FieldDefinition>,\n): Resolver<Record<string, any>> {\n\tconst schema = buildValidationSchema(fields);\n\n\treturn async (values) => {\n\t\tconst result = schema.safeParse(values);\n\n\t\tif (result.success) {\n\t\t\treturn {\n\t\t\t\tvalues: result.data,\n\t\t\t\terrors: {},\n\t\t\t};\n\t\t}\n\n\t\tconst errors: FieldErrors = {};\n\t\tfor (const issue of result.error.issues) {\n\t\t\tconst path = issue.path.join(\".\");\n\t\t\tif (path && !errors[path]) {\n\t\t\t\terrors[path] = {\n\t\t\t\t\ttype: issue.code,\n\t\t\t\t\tmessage: issue.message,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tvalues: {},\n\t\t\terrors,\n\t\t};\n\t};\n}\n\n/**\n * Form Dialog content - renders form fields using AutoFormFields\n *\n * Uses buildValidationSchema for automatic Zod schema generation\n * from field definitions, providing full field system support.\n */\nfunction FormDialogContent<TItem>({\n\taction,\n\tctx,\n\tonClose,\n}: {\n\taction: ActionDefinition<TItem>;\n\tctx: ActionContext<TItem>;\n\tonClose: () => void;\n}) {\n\tconst handler = action.handler as FormHandler<TItem>;\n\tconst { config } = handler;\n\tconst resolveText = useResolveText();\n\tconst { t } = useTranslation();\n\n\t// Create resolver from field definitions\n\tconst resolver = React.useMemo(\n\t\t() => createActionFormResolver(config.fields),\n\t\t[config.fields],\n\t);\n\n\tconst form = useForm({\n\t\tdefaultValues: config.defaultValues || {},\n\t\tresolver,\n\t});\n\n\tconst [isSubmitting, setIsSubmitting] = React.useState(false);\n\n\tconst handleSubmit = form.handleSubmit(async (data) => {\n\t\tsetIsSubmitting(true);\n\n\t\tconst submitPromise = async () => {\n\t\t\tawait config.onSubmit(data, ctx);\n\t\t\treturn data;\n\t\t};\n\n\t\ttoast.promise(submitPromise(), {\n\t\t\tloading: t(\"toast.processing\"),\n\t\t\tsuccess: () => {\n\t\t\t\tonClose();\n\t\t\t\treturn t(\"toast.actionSuccess\");\n\t\t\t},\n\t\t\terror: (error) => {\n\t\t\t\treturn error instanceof Error ? error.message : t(\"toast.actionFailed\");\n\t\t\t},\n\t\t\tfinally: () => {\n\t\t\t\tsetIsSubmitting(false);\n\t\t\t},\n\t\t});\n\t});\n\n\t// Build collection config for AutoFormFields\n\tconst collectionConfig = React.useMemo(\n\t\t() => ({\n\t\t\tfields: config.fields,\n\t\t}),\n\t\t[config.fields],\n\t);\n\n\treturn (\n\t\t<FormProvider {...form}>\n\t\t\t<ResponsiveDialogHeader>\n\t\t\t\t<ResponsiveDialogTitle>\n\t\t\t\t\t{resolveText(config.title)}\n\t\t\t\t</ResponsiveDialogTitle>\n\t\t\t\t{config.description && (\n\t\t\t\t\t<ResponsiveDialogDescription>\n\t\t\t\t\t\t{resolveText(config.description)}\n\t\t\t\t\t</ResponsiveDialogDescription>\n\t\t\t\t)}\n\t\t\t</ResponsiveDialogHeader>\n\n\t\t\t<form onSubmit={handleSubmit} className=\"space-y-4\">\n\t\t\t\t<AutoFormFields collection=\"__action__\" config={collectionConfig} />\n\n\t\t\t\t<ResponsiveDialogFooter className=\"mt-6\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\tdisabled={isSubmitting}\n\t\t\t\t\t>\n\t\t\t\t\t\t{resolveText(config.cancelLabel, t(\"common.cancel\"))}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button type=\"submit\" disabled={isSubmitting}>\n\t\t\t\t\t\t{isSubmitting\n\t\t\t\t\t\t\t? t(\"common.loading\")\n\t\t\t\t\t\t\t: resolveText(config.submitLabel, t(\"common.submit\"))}\n\t\t\t\t\t</Button>\n\t\t\t\t</ResponsiveDialogFooter>\n\t\t\t</form>\n\t\t</FormProvider>\n\t);\n}\n\n/**\n * Custom Dialog content - renders lazy-loaded component\n */\nfunction CustomDialogContent<TItem>({\n\taction,\n\tctx,\n\tonClose,\n}: {\n\taction: ActionDefinition<TItem>;\n\tctx: ActionContext<TItem>;\n\tonClose: () => void;\n}) {\n\tconst handler = action.handler as DialogHandler<TItem>;\n\tconst [Component, setComponent] =\n\t\tReact.useState<React.ComponentType<any> | null>(null);\n\tconst [loading, setLoading] = React.useState(true);\n\tconst [error, setError] = React.useState<Error | null>(null);\n\n\tReact.useEffect(() => {\n\t\tlet mounted = true;\n\n\t\tasync function loadComponent() {\n\t\t\ttry {\n\t\t\t\tconst comp = handler.component;\n\n\t\t\t\t// Handle lazy-loaded components\n\t\t\t\tif (typeof comp === \"function\") {\n\t\t\t\t\t// Check if it's a React.lazy component by looking for _payload\n\t\t\t\t\tconst lazyComp = comp as any;\n\t\t\t\t\tif (lazyComp._payload !== undefined) {\n\t\t\t\t\t\t// It's a lazy component, resolve it\n\t\t\t\t\t\tconst resolved = await lazyComp._payload();\n\t\t\t\t\t\tif (mounted) {\n\t\t\t\t\t\t\tsetComponent(() => resolved.default || resolved);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// It's a direct component function or import\n\t\t\t\t\t\tconst result = (comp as () => any)();\n\t\t\t\t\t\tif (result?.then) {\n\t\t\t\t\t\t\tconst mod = await result;\n\t\t\t\t\t\t\tif (mounted) {\n\t\t\t\t\t\t\t\tsetComponent(() => mod.default || mod);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Direct component\n\t\t\t\t\t\t\tif (mounted) {\n\t\t\t\t\t\t\t\tsetComponent(() => comp as React.ComponentType<any>);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Direct component\n\t\t\t\t\tif (mounted) {\n\t\t\t\t\t\tsetComponent(() => comp as React.ComponentType<any>);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tif (mounted) {\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(\"Failed to load\"));\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tif (mounted) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tloadComponent();\n\t\treturn () => {\n\t\t\tmounted = false;\n\t\t};\n\t}, [handler.component]);\n\n\tif (loading) {\n\t\treturn (\n\t\t\t<div className=\"flex h-32 items-center justify-center\">\n\t\t\t\t<SpinnerGap className=\"size-6 animate-spin text-muted-foreground\" />\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (error) {\n\t\treturn (\n\t\t\t<div className=\"p-4 text-center\">\n\t\t\t\t<p className=\"text-destructive\">{error.message}</p>\n\t\t\t\t<Button variant=\"outline\" onClick={onClose} className=\"mt-4\">\n\t\t\t\t\tClose\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!Component) {\n\t\treturn (\n\t\t\t<div className=\"p-4 text-center\">\n\t\t\t\t<p className=\"text-muted-foreground\">Component not found</p>\n\t\t\t\t<Button variant=\"outline\" onClick={onClose} className=\"mt-4\">\n\t\t\t\t\tClose\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Component\n\t\t\titem={ctx.item}\n\t\t\titems={ctx.items}\n\t\t\tcollection={ctx.collection}\n\t\t\tonClose={onClose}\n\t\t\tonSuccess={() => {\n\t\t\t\tctx.helpers.refresh();\n\t\t\t\tonClose();\n\t\t\t}}\n\t\t/>\n\t);\n}\n\n/**\n * ActionDialog - Renders dialog-type and form-type actions\n *\n * @example\n * ```tsx\n * <ActionDialog\n * open={!!activeAction}\n * onOpenChange={(open) => !open && setActiveAction(null)}\n * action={activeAction}\n * collection=\"users\"\n * item={selectedUser}\n * helpers={actionHelpers}\n * />\n * ```\n */\nexport function ActionDialog<TItem = any>({\n\topen,\n\tonOpenChange,\n\taction,\n\tcollection,\n\titem,\n\titems,\n\thelpers,\n}: ActionDialogProps<TItem>): React.ReactElement | null {\n\tconst queryClient = useQueryClient();\n\n\t// Build action context\n\tconst ctx: ActionContext<TItem> = React.useMemo(\n\t\t() => ({\n\t\t\titem,\n\t\t\titems,\n\t\t\tcollection,\n\t\t\thelpers: {\n\t\t\t\t...helpers,\n\t\t\t\tcloseDialog: () => onOpenChange(false),\n\t\t\t},\n\t\t\tqueryClient: {\n\t\t\t\tinvalidateQueries: (filters) => queryClient.invalidateQueries(filters),\n\t\t\t\tresetQueries: (filters) => queryClient.resetQueries(filters),\n\t\t\t\trefetchQueries: (filters) => queryClient.refetchQueries(filters),\n\t\t\t},\n\t\t}),\n\t\t[item, items, collection, helpers, onOpenChange, queryClient],\n\t);\n\n\tconst handleClose = () => onOpenChange(false);\n\n\t// Determine dialog size based on handler type and config\n\tconst getDialogClassName = () => {\n\t\tif (action.handler.type === \"form\") {\n\t\t\tconst width = (action.handler as FormHandler).config.width || \"md\";\n\t\t\tconst widthMap = {\n\t\t\t\tsm: \"sm:max-w-sm\",\n\t\t\t\tmd: \"sm:max-w-md\",\n\t\t\t\tlg: \"sm:max-w-lg\",\n\t\t\t\txl: \"sm:max-w-xl\",\n\t\t\t};\n\t\t\treturn widthMap[width];\n\t\t}\n\t\tif (action.handler.type === \"dialog\") {\n\t\t\treturn \"sm:max-w-lg\";\n\t\t}\n\t\treturn \"sm:max-w-md\";\n\t};\n\n\treturn (\n\t\t<ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n\t\t\t<ResponsiveDialogContent className={getDialogClassName()}>\n\t\t\t\t{action.handler.type === \"form\" && (\n\t\t\t\t\t<FormDialogContent action={action} ctx={ctx} onClose={handleClose} />\n\t\t\t\t)}\n\t\t\t\t{action.handler.type === \"dialog\" && (\n\t\t\t\t\t<CustomDialogContent\n\t\t\t\t\t\taction={action}\n\t\t\t\t\t\tctx={ctx}\n\t\t\t\t\t\tonClose={handleClose}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</ResponsiveDialogContent>\n\t\t</ResponsiveDialog>\n\t);\n}\n","/**\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\t| { type: \"idle\" }\n\t| { type: \"field\"; fieldPath: string }\n\t| { type: \"block\"; blockId: string; fieldPath?: string }\n\t| { type: \"relation\"; fieldPath: string; targetCollection?: string };\n\nexport type FocusContextValue = {\n\t/** Current focus state */\n\tstate: FocusState;\n\t/** Focus a regular field by path */\n\tfocusField: (fieldPath: string) => void;\n\t/** Focus a block, optionally a specific field within it */\n\tfocusBlock: (blockId: string, fieldPath?: string) => void;\n\t/** Focus a relation field (opens ResourceSheet) */\n\tfocusRelation: (fieldPath: string, targetCollection?: string) => void;\n\t/** Clear focus */\n\tclearFocus: () => void;\n\t/** Check if a field is focused */\n\tisFieldFocused: (fieldPath: string) => boolean;\n\t/** Check if a block is focused */\n\tisBlockFocused: (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\tchildren: React.ReactNode;\n\t/** Callback when focus changes - useful for scrolling to field */\n\tonFocusChange?: (state: FocusState) => void;\n};\n\nexport function FocusProvider({ children, onFocusChange }: FocusProviderProps) {\n\tconst [state, setState] = React.useState<FocusState>({ type: \"idle\" });\n\n\t// Use functional setState for stable callbacks (React best practice)\n\tconst focusField = React.useCallback(\n\t\t(fieldPath: string) => {\n\t\t\tconst newState: FocusState = { type: \"field\", fieldPath };\n\t\t\tsetState(newState);\n\t\t\tonFocusChange?.(newState);\n\t\t},\n\t\t[onFocusChange],\n\t);\n\n\tconst focusBlock = React.useCallback(\n\t\t(blockId: string, fieldPath?: string) => {\n\t\t\tconst newState: FocusState = { type: \"block\", blockId, fieldPath };\n\t\t\tsetState(newState);\n\t\t\tonFocusChange?.(newState);\n\t\t},\n\t\t[onFocusChange],\n\t);\n\n\tconst focusRelation = React.useCallback(\n\t\t(fieldPath: string, targetCollection?: string) => {\n\t\t\tconst newState: FocusState = {\n\t\t\t\ttype: \"relation\",\n\t\t\t\tfieldPath,\n\t\t\t\ttargetCollection,\n\t\t\t};\n\t\t\tsetState(newState);\n\t\t\tonFocusChange?.(newState);\n\t\t},\n\t\t[onFocusChange],\n\t);\n\n\tconst clearFocus = React.useCallback(() => {\n\t\tconst newState: FocusState = { type: \"idle\" };\n\t\tsetState(newState);\n\t\tonFocusChange?.(newState);\n\t}, [onFocusChange]);\n\n\t// Derive focused field/block from state for direct comparison\n\tconst focusedFieldPath = state.type === \"field\" ? state.fieldPath : undefined;\n\tconst focusedBlockId = state.type === \"block\" ? state.blockId : undefined;\n\n\tconst value = React.useMemo(\n\t\t(): FocusContextValue => ({\n\t\t\tstate,\n\t\t\tfocusField,\n\t\t\tfocusBlock,\n\t\t\tfocusRelation,\n\t\t\tclearFocus,\n\t\t\t// Simple equality checks - no callback overhead\n\t\t\tisFieldFocused: (path: string) => focusedFieldPath === path,\n\t\t\tisBlockFocused: (id: string) => focusedBlockId === id,\n\t\t}),\n\t\t[\n\t\t\tstate,\n\t\t\tfocusField,\n\t\t\tfocusBlock,\n\t\t\tfocusRelation,\n\t\t\tclearFocus,\n\t\t\tfocusedFieldPath,\n\t\t\tfocusedBlockId,\n\t\t],\n\t);\n\n\treturn (\n\t\t<FocusContext.Provider value={value}>{children}</FocusContext.Provider>\n\t);\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Use the focus context\n */\nexport function useFocus(): FocusContextValue {\n\tconst context = React.useContext(FocusContext);\n\tif (!context) {\n\t\tthrow new Error(\"useFocus must be used within a FocusProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Use focus context if available (doesn't throw)\n */\nexport function useFocusOptional(): FocusContextValue | null {\n\treturn React.useContext(FocusContext);\n}\n\n/**\n * Hook for checking if a specific field is focused\n */\nexport function useIsFieldFocused(fieldPath: string): boolean {\n\tconst context = React.useContext(FocusContext);\n\tif (!context) return false;\n\treturn context.isFieldFocused(fieldPath);\n}\n\n/**\n * Hook for checking if a specific block is focused\n */\nexport function useIsBlockFocused(blockId: string): boolean {\n\tconst context = React.useContext(FocusContext);\n\tif (!context) return false;\n\treturn 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\tpath: string,\n\tcontext?: {\n\t\tblockId?: string;\n\t\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t\ttargetCollection?: string;\n\t},\n): FocusState {\n\t// Relation field from context\n\tif (context?.fieldType === \"relation\") {\n\t\treturn {\n\t\t\ttype: \"relation\",\n\t\t\tfieldPath: path,\n\t\t\ttargetCollection: context.targetCollection,\n\t\t};\n\t}\n\n\t// Check if it's a block field path (content._values.{id}.{field})\n\tconst blockMatch = path.match(/^content\\._values\\.([^.]+)(?:\\.(.+))?$/);\n\tif (blockMatch) {\n\t\tconst [, blockId, fieldPath] = blockMatch;\n\t\treturn { type: \"block\", blockId, fieldPath };\n\t}\n\n\t// Legacy block path format (content.blocks.{id}.{field})\n\tconst legacyBlockMatch = path.match(/^content\\.blocks\\.([^.]+)(?:\\.(.+))?$/);\n\tif (legacyBlockMatch) {\n\t\tconst [, blockId, fieldPath] = legacyBlockMatch;\n\t\treturn { type: \"block\", blockId, fieldPath };\n\t}\n\n\t// Block field from context hint\n\tif (context?.blockId) {\n\t\t// Extract relative field path if present\n\t\tconst relativeField = extractRelativeField(path, context.blockId);\n\t\treturn {\n\t\t\ttype: \"block\",\n\t\t\tblockId: context.blockId,\n\t\t\tfieldPath: relativeField,\n\t\t};\n\t}\n\n\t// Regular field\n\treturn { 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\tconst prefix = `content._values.${blockId}.`;\n\tif (path.startsWith(prefix)) {\n\t\treturn path.slice(prefix.length);\n\t}\n\treturn 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\t// First try to find within the preview form scope (to avoid matching fields in other forms)\n\tconst formScope = document.querySelector<HTMLElement>(\n\t\t\"[data-preview-form-scope]\",\n\t);\n\tconst searchRoot = formScope ?? document;\n\n\tconst wrapper = searchRoot.querySelector<HTMLElement>(\n\t\t`[data-field-path=\"${fieldPath}\"]`,\n\t);\n\tif (!wrapper) return;\n\n\t// Find first focusable element inside the wrapper\n\tconst focusable = wrapper.querySelector<HTMLElement>(\n\t\t'input:not([type=\"hidden\"]), textarea, button, select, [tabindex]:not([tabindex=\"-1\"]), [contenteditable=\"true\"]',\n\t);\n\n\tconst target = focusable ?? wrapper;\n\ttarget.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n\n\tif (focusable) {\n\t\t// Use requestAnimationFrame to focus after scroll starts\n\t\trequestAnimationFrame(() => {\n\t\t\t// Pull focus from iframe back to parent window\n\t\t\twindow.focus();\n\t\t\tfocusable.focus();\n\t\t});\n\t}\n}\n","/**\n * Collection Preview Types\n *\n * PostMessage protocol and types for live preview communication\n * between admin and preview iframe.\n */\n\n// ============================================================================\n// Admin -> Preview Messages\n// ============================================================================\n\n/**\n * Signal preview to refresh (invalidate and re-run loader).\n */\nexport type PreviewRefreshMessage = {\n\ttype: \"PREVIEW_REFRESH\";\n\t/** Optional hint about which field changed */\n\tchangedField?: string;\n};\n\n/**\n * Select a block in the preview.\n */\nexport type SelectBlockMessage = {\n\ttype: \"SELECT_BLOCK\";\n\t/** Block ID to select */\n\tblockId: string;\n};\n\n/**\n * Focus a field in the preview.\n */\nexport type FocusFieldMessage = {\n\ttype: \"FOCUS_FIELD\";\n\t/** Field path to focus (supports full scoped paths) */\n\tfieldPath: string;\n};\n\n/**\n * All messages from Admin to Preview.\n */\nexport type AdminToPreviewMessage =\n\t| PreviewRefreshMessage\n\t| SelectBlockMessage\n\t| FocusFieldMessage;\n\n// ============================================================================\n// Preview -> Admin Messages\n// ============================================================================\n\n/**\n * Preview is ready to receive data.\n */\nexport type PreviewReadyMessage = {\n\ttype: \"PREVIEW_READY\";\n};\n\n/**\n * A field was clicked in the preview.\n */\nexport type FieldClickedMessage = {\n\ttype: \"FIELD_CLICKED\";\n\t/** Full scoped field path */\n\tfieldPath: string;\n\t/** Block context hint */\n\tblockId?: string;\n\t/** Field type for routing */\n\tfieldType?: \"regular\" | \"block\" | \"relation\";\n};\n\n/**\n * A block was clicked in the preview.\n */\nexport type BlockClickedMessage = {\n\ttype: \"BLOCK_CLICKED\";\n\t/** Block ID that was clicked */\n\tblockId: string;\n};\n\n/**\n * Preview refresh completed.\n * Sent after preview successfully re-runs loader.\n */\nexport type RefreshCompleteMessage = {\n\ttype: \"REFRESH_COMPLETE\";\n\t/** Timestamp of completion */\n\ttimestamp: number;\n};\n\n/**\n * All messages from Preview to Admin.\n */\nexport type PreviewToAdminMessage =\n\t| PreviewReadyMessage\n\t| FieldClickedMessage\n\t| BlockClickedMessage\n\t| RefreshCompleteMessage;\n\n// ============================================================================\n// Preview Configuration\n// ============================================================================\n\n/**\n * Preview configuration for a collection.\n */\nexport type PreviewConfig = {\n\t/**\n\t * URL builder for preview iframe.\n\t * Receives current form values and locale.\n\t */\n\turl: (values: Record<string, unknown>, locale: string) => string;\n\n\t/**\n\t * Enable/disable preview.\n\t * @default true if url is defined\n\t */\n\tenabled?: boolean;\n\n\t/**\n\t * Preview pane position.\n\t * @default \"right\"\n\t */\n\tposition?: \"right\" | \"bottom\" | \"modal\";\n\n\t/**\n\t * Default preview pane size (percentage).\n\t * @default 50\n\t */\n\tdefaultSize?: number;\n\n\t/**\n\t * Minimum pane size (percentage).\n\t * @default 30\n\t */\n\tminSize?: number;\n};\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if a message is from admin to preview.\n */\nexport function isAdminToPreviewMessage(\n\tdata: unknown,\n): data is AdminToPreviewMessage {\n\tif (!data || typeof data !== \"object\") return false;\n\tconst msg = data as { type?: string };\n\treturn (\n\t\tmsg.type === \"PREVIEW_REFRESH\" ||\n\t\tmsg.type === \"SELECT_BLOCK\" ||\n\t\tmsg.type === \"FOCUS_FIELD\"\n\t);\n}\n\n/**\n * Check if a message is from preview to admin.\n */\nexport function isPreviewToAdminMessage(\n\tdata: unknown,\n): data is PreviewToAdminMessage {\n\tif (!data || typeof data !== \"object\") return false;\n\tconst msg = data as { type?: string };\n\treturn (\n\t\tmsg.type === \"PREVIEW_READY\" ||\n\t\tmsg.type === \"FIELD_CLICKED\" ||\n\t\tmsg.type === \"BLOCK_CLICKED\" ||\n\t\tmsg.type === \"REFRESH_COMPLETE\"\n\t);\n}\n","/**\n * Preview Pane\n *\n * Admin-side component that renders the preview iframe\n * and handles postMessage communication with the preview page.\n */\n\n\"use client\";\n\nimport { Spinner } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\nimport type {\n\tAdminToPreviewMessage,\n\tPreviewToAdminMessage,\n} from \"../../preview/types.js\";\nimport { isPreviewToAdminMessage } from \"../../preview/types.js\";\nimport { selectClient, useAdminStore } from \"../../runtime/index.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type PreviewPaneRef = {\n\ttriggerRefresh: () => void;\n\tsendFocusToPreview: (fieldPath: string) => void;\n};\n\nexport type PreviewPaneProps = {\n\t/** Preview URL */\n\turl: string;\n\t/** Selected block ID (for block editor integration) */\n\tselectedBlockId?: string | null;\n\t/** Field click handler */\n\tonFieldClick?: (\n\t\tfieldPath: string,\n\t\tcontext?: {\n\t\t\tblockId?: string;\n\t\t\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t\t},\n\t) => void;\n\t/** Block click handler */\n\tonBlockClick?: (blockId: string) => void;\n\t/** Custom class name */\n\tclassName?: string;\n\t/** Allowed preview origins (for security) */\n\tallowedOrigins?: string[];\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Preview pane component for admin.\n *\n * Renders an iframe with the preview page and handles\n * bidirectional communication via postMessage.\n */\nexport const PreviewPane = React.forwardRef<PreviewPaneRef, PreviewPaneProps>(\n\t(\n\t\t{\n\t\t\turl,\n\t\t\tselectedBlockId,\n\t\t\tonFieldClick,\n\t\t\tonBlockClick,\n\t\t\tclassName,\n\t\t\tallowedOrigins,\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst client = useAdminStore(selectClient);\n\t\tconst iframeRef = React.useRef<HTMLIFrameElement>(null);\n\t\tconst [isReady, setIsReady] = React.useState(false);\n\t\tconst [isLoading, setIsLoading] = React.useState(true);\n\t\tconst [isRefreshing, setIsRefreshing] = React.useState(false);\n\t\tconst [previewUrl, setPreviewUrl] = React.useState<string | null>(null);\n\t\tconst [tokenError, setTokenError] = React.useState<string | null>(null);\n\n\t\t// Mint preview token when URL changes\n\t\tReact.useEffect(() => {\n\t\t\tconst mintToken = async () => {\n\t\t\t\tif (!url) {\n\t\t\t\t\tsetPreviewUrl(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsetIsLoading(true);\n\t\t\t\tsetTokenError(null);\n\n\t\t\t\ttry {\n\t\t\t\t\t// Use type assertion since the client type may not include mintPreviewToken\n\t\t\t\t\t// depending on which modules are used\n\t\t\t\t\tconst result = await (client as any).functions.mintPreviewToken({\n\t\t\t\t\t\tpath: url,\n\t\t\t\t\t\tttlMs: 60 * 60 * 1000, // 1 hour\n\t\t\t\t\t});\n\t\t\t\t\tsetPreviewUrl(`/api/preview?token=${result.token}`);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\"Failed to mint preview token:\", error);\n\t\t\t\t\tsetTokenError(\n\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t: \"Failed to generate preview token\",\n\t\t\t\t\t);\n\t\t\t\t\tsetPreviewUrl(null);\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tmintToken();\n\t\t}, [url, client]);\n\n\t\t// Validate origin for security\n\t\tconst isValidOrigin = React.useCallback(\n\t\t\t(origin: string): boolean => {\n\t\t\t\tif (!allowedOrigins || allowedOrigins.length === 0) {\n\t\t\t\t\t// If no origins specified, allow same origin and preview URL origin\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst previewOrigin = new URL(url).origin;\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\torigin === window.location.origin || origin === previewOrigin\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn origin === window.location.origin;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn allowedOrigins.includes(origin);\n\t\t\t},\n\t\t\t[url, allowedOrigins],\n\t\t);\n\n\t\t// Send message to preview iframe\n\t\tconst sendToPreview = React.useCallback(\n\t\t\t(message: AdminToPreviewMessage) => {\n\t\t\t\tconst iframe = iframeRef.current;\n\t\t\t\tif (!iframe?.contentWindow) return;\n\n\t\t\t\ttry {\n\t\t\t\t\tconst targetOrigin = new URL(url).origin;\n\t\t\t\t\tiframe.contentWindow.postMessage(message, targetOrigin);\n\t\t\t\t} catch {\n\t\t\t\t\t// If URL parsing fails, use wildcard (less secure)\n\t\t\t\t\tiframe.contentWindow.postMessage(message, \"*\");\n\t\t\t\t}\n\t\t\t},\n\t\t\t[url],\n\t\t);\n\n\t\t// Expose refresh and focus methods via imperative handle\n\t\tReact.useImperativeHandle(\n\t\t\tref,\n\t\t\t() => ({\n\t\t\t\ttriggerRefresh: () => {\n\t\t\t\t\tif (isReady) {\n\t\t\t\t\t\tsetIsRefreshing(true);\n\t\t\t\t\t\tsendToPreview({ type: \"PREVIEW_REFRESH\" });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsendFocusToPreview: (fieldPath: string) => {\n\t\t\t\t\tif (isReady) {\n\t\t\t\t\t\tsendToPreview({ type: \"FOCUS_FIELD\", fieldPath });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t}),\n\t\t\t[isReady, sendToPreview],\n\t\t);\n\n\t\t// Listen for messages from preview\n\t\tReact.useEffect(() => {\n\t\t\tconst handleMessage = (event: MessageEvent<PreviewToAdminMessage>) => {\n\t\t\t\t// Validate origin\n\t\t\t\tif (!isValidOrigin(event.origin)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Validate message structure\n\t\t\t\tif (!isPreviewToAdminMessage(event.data)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tswitch (event.data.type) {\n\t\t\t\t\tcase \"PREVIEW_READY\":\n\t\t\t\t\t\tsetIsReady(true);\n\t\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"REFRESH_COMPLETE\":\n\t\t\t\t\t\tsetIsRefreshing(false);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"FIELD_CLICKED\":\n\t\t\t\t\t\tonFieldClick?.(event.data.fieldPath, {\n\t\t\t\t\t\t\tblockId: event.data.blockId,\n\t\t\t\t\t\t\tfieldType: event.data.fieldType,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"BLOCK_CLICKED\":\n\t\t\t\t\t\tonBlockClick?.(event.data.blockId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\twindow.addEventListener(\"message\", handleMessage);\n\t\t\treturn () => window.removeEventListener(\"message\", handleMessage);\n\t\t}, [isValidOrigin, onFieldClick, onBlockClick]);\n\n\t\t// Send selected block updates\n\t\tReact.useEffect(() => {\n\t\t\tif (isReady && selectedBlockId) {\n\t\t\t\tsendToPreview({ type: \"SELECT_BLOCK\", blockId: selectedBlockId });\n\t\t\t}\n\t\t}, [isReady, selectedBlockId, sendToPreview]);\n\n\t\t// Handle iframe load\n\t\tconst handleLoad = () => {\n\t\t\t// Preview should signal PREVIEW_READY, but set a fallback timeout\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (!isReady) {\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t}, 3000);\n\t\t};\n\n\t\treturn (\n\t\t\t<div className={cn(\"relative h-full w-full\", className)}>\n\t\t\t\t{/* Loading overlay */}\n\t\t\t\t{isLoading && (\n\t\t\t\t\t<div className=\"absolute inset-0 z-10 flex items-center justify-center bg-muted/80\">\n\t\t\t\t\t\t<Spinner className=\"h-6 w-6 animate-spin text-muted-foreground\" />\n\t\t\t\t\t\t<span className=\"ml-2 text-sm text-muted-foreground\">\n\t\t\t\t\t\t\tLoading preview...\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Error overlay */}\n\t\t\t\t{tokenError && (\n\t\t\t\t\t<div className=\"absolute inset-0 z-10 flex items-center justify-center bg-muted/80\">\n\t\t\t\t\t\t<div className=\"rounded-md bg-destructive/10 border border-destructive px-4 py-3 text-sm text-destructive\">\n\t\t\t\t\t\t\t<p className=\"font-medium\">Preview Error</p>\n\t\t\t\t\t\t\t<p>{tokenError}</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Refreshing indicator */}\n\t\t\t\t{isRefreshing && !isLoading && (\n\t\t\t\t\t<div className=\"absolute top-4 right-4 z-10 flex items-center gap-2 rounded-md bg-background px-3 py-2 shadow-md border\">\n\t\t\t\t\t\t<Spinner className=\"h-4 w-4 animate-spin text-muted-foreground\" />\n\t\t\t\t\t\t<span className=\"text-sm text-muted-foreground\">Refreshing...</span>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Preview iframe */}\n\t\t\t\t{previewUrl && (\n\t\t\t\t\t<iframe\n\t\t\t\t\t\tref={iframeRef}\n\t\t\t\t\t\tsrc={previewUrl}\n\t\t\t\t\t\tclassName=\"h-full w-full border-0\"\n\t\t\t\t\t\ttitle=\"Preview\"\n\t\t\t\t\t\tonLoad={handleLoad}\n\t\t\t\t\t\tsandbox=\"allow-scripts allow-same-origin allow-forms\"\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t},\n);\n\nPreviewPane.displayName = \"PreviewPane\";\n\n// ============================================================================\n// Preview Toggle Button\n// ============================================================================\n\nexport type PreviewToggleButtonProps = {\n\t/** Whether preview is currently visible */\n\tisPreviewVisible: boolean;\n\t/** Toggle handler */\n\tonToggle: () => void;\n\t/** Custom class name */\n\tclassName?: string;\n};\n\n/**\n * Button to toggle preview pane visibility.\n */\nexport function PreviewToggleButton({\n\tisPreviewVisible,\n\tonToggle,\n\tclassName,\n}: PreviewToggleButtonProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={onToggle}\n\t\t\tclassName={cn(\n\t\t\t\t\"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm\",\n\t\t\t\t\"border transition-colors\",\n\t\t\t\tisPreviewVisible\n\t\t\t\t\t? \"border-primary bg-primary/10 text-primary\"\n\t\t\t\t\t: \"border-border hover:bg-muted\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{isPreviewVisible ? \"Hide Preview\" : \"Show Preview\"}\n\t\t</button>\n\t);\n}\n","/**\n * LivePreviewMode Component\n *\n * Fullscreen overlay for live preview editing.\n * Left side: Form panel (inline, not portal)\n * Right side: Preview iframe\n * Mobile: Tabs to switch between form and preview\n */\n\n\"use client\";\n\nimport { Eye, SignOut, X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport type { CollectionBuilderState } from \"../../builder/collection/types.js\";\nimport type { ComponentRegistry } from \"../../builder/types/field-types.js\";\nimport {\n\tFocusProvider,\n\ttype FocusState,\n\tparsePreviewFieldPath,\n\tscrollFieldIntoView,\n\tuseFocus,\n} from \"../../context/focus-context.js\";\nimport { useIsMobile } from \"../../hooks/use-media-query.js\";\nimport { useTranslation } from \"../../i18n/hooks.js\";\nimport { cn } from \"../../lib/utils.js\";\nimport {\n\tLocaleScopeProvider,\n\tselectAdmin,\n\tselectBasePath,\n\tselectNavigate,\n\tuseAdminStore,\n} from \"../../runtime/index.js\";\nimport FormView from \"../../views/collection/form-view.js\";\nimport { Button } from \"../ui/button.js\";\nimport { Tabs, TabsList, TabsTrigger } from \"../ui/tabs.js\";\nimport { PreviewPane, type PreviewPaneRef } from \"./preview-pane.js\";\n\n// ============================================================================\n// Context\n// ============================================================================\n\ntype LivePreviewContextValue = {\n\ttriggerPreviewRefresh: () => void;\n};\n\nconst LivePreviewContext = React.createContext<LivePreviewContextValue | null>(\n\tnull,\n);\n\nexport function useLivePreviewContext() {\n\treturn React.useContext(LivePreviewContext);\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface LivePreviewModeProps {\n\t/** Whether preview mode is open */\n\topen: boolean;\n\t/** Callback to close preview mode */\n\tonClose: () => void;\n\t/** Collection name */\n\tcollection: string;\n\t/** Item ID (for edit mode) */\n\titemId?: string;\n\t/** Collection config */\n\tconfig?: any;\n\t/** All collections config (for embedded) */\n\tallCollectionsConfig?: Record<string, any>;\n\t/** Component registry */\n\tregistry?: ComponentRegistry;\n\t/** Preview URL */\n\tpreviewUrl: string;\n\t/** Callback after successful save */\n\tonSuccess?: (data: any) => void;\n}\n\n// ============================================================================\n// Inner Component (with FocusContext access)\n// ============================================================================\n\ntype LivePreviewContentProps = LivePreviewModeProps & {\n\tpreviewRef: React.RefObject<PreviewPaneRef | null>;\n};\n\nfunction LivePreviewContent({\n\tonClose,\n\tcollection,\n\titemId,\n\tconfig,\n\tallCollectionsConfig,\n\tregistry,\n\tpreviewUrl,\n\tonSuccess,\n\tpreviewRef,\n}: LivePreviewContentProps) {\n\tconst { t } = useTranslation();\n\tconst isMobile = useIsMobile();\n\tconst navigate = useAdminStore(selectNavigate);\n\tconst basePath = useAdminStore(selectBasePath);\n\tconst admin = useAdminStore(selectAdmin);\n\tconst [activeTab, setActiveTab] = React.useState<\"form\" | \"preview\">(\"form\");\n\n\t// Access FocusContext\n\tconst focusContext = useFocus();\n\tconst focusState = focusContext.state; // Extract for effect dependency\n\n\t// Handle exit preview (clear draft mode cookie)\n\tconst handleExitPreview = React.useCallback(() => {\n\t\t// Redirect to exit preview endpoint\n\t\twindow.location.href = \"/api/preview?disable=true\";\n\t}, []);\n\n\t// Sync focus changes to preview iframe\n\tReact.useEffect(() => {\n\t\tif (!previewRef.current) return;\n\n\t\tif (focusState.type === \"field\") {\n\t\t\tpreviewRef.current.sendFocusToPreview(focusState.fieldPath);\n\t\t} else if (focusState.type === \"block\") {\n\t\t\t// Send full block field path\n\t\t\tif (focusState.fieldPath) {\n\t\t\t\tconst fullPath = `content._values.${focusState.blockId}.${focusState.fieldPath}`;\n\t\t\t\tpreviewRef.current.sendFocusToPreview(fullPath);\n\t\t\t} else {\n\t\t\t\t// Just the block itself\n\t\t\t\tconst fullPath = `content._values.${focusState.blockId}`;\n\t\t\t\tpreviewRef.current.sendFocusToPreview(fullPath);\n\t\t\t}\n\t\t}\n\t}, [focusState, previewRef]);\n\n\t// Preview click handlers - update FocusContext state\n\tconst handlePreviewFieldClick = React.useCallback(\n\t\t(fieldPath: string, context?: any) => {\n\t\t\tconst state = parsePreviewFieldPath(fieldPath, context);\n\n\t\t\tif (state.type === \"field\") {\n\t\t\t\tfocusContext.focusField(state.fieldPath);\n\t\t\t} else if (state.type === \"block\") {\n\t\t\t\tfocusContext.focusBlock(state.blockId, state.fieldPath);\n\t\t\t} else if (state.type === \"relation\") {\n\t\t\t\tfocusContext.focusRelation(state.fieldPath, state.targetCollection);\n\t\t\t}\n\t\t},\n\t\t[focusContext],\n\t);\n\n\tconst handlePreviewBlockClick = React.useCallback(\n\t\t(blockId: string) => {\n\t\t\tfocusContext.focusBlock(blockId);\n\t\t},\n\t\t[focusContext],\n\t);\n\n\t// Get config from admin if not provided\n\tconst resolvedConfig = config ?? admin?.getCollectionConfig(collection);\n\tconst resolvedAllCollections =\n\t\tallCollectionsConfig ?? admin?.getCollections();\n\n\treturn (\n\t\t<div className=\"fixed inset-0 z-50 bg-background flex flex-col\">\n\t\t\t{/* Header */}\n\t\t\t<div className=\"flex items-center justify-between border-b px-4 py-2 shrink-0\">\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<Eye className=\"h-4 w-4 text-muted-foreground\" />\n\t\t\t\t\t<span className=\"font-medium\">{t(\"preview.livePreview\")}</span>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Mobile tabs in header */}\n\t\t\t\t{isMobile && (\n\t\t\t\t\t<Tabs\n\t\t\t\t\t\tvalue={activeTab}\n\t\t\t\t\t\tonValueChange={(v) => setActiveTab(v as \"form\" | \"preview\")}\n\t\t\t\t\t\tclassName=\"mx-4\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<TabsList className=\"h-8\">\n\t\t\t\t\t\t\t<TabsTrigger value=\"form\" className=\"text-xs px-3\">\n\t\t\t\t\t\t\t\t{t(\"common.form\")}\n\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t\t<TabsTrigger value=\"preview\" className=\"text-xs px-3\">\n\t\t\t\t\t\t\t\t{t(\"preview.title\")}\n\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t</TabsList>\n\t\t\t\t\t</Tabs>\n\t\t\t\t)}\n\n\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tonClick={handleExitPreview}\n\t\t\t\t\t\tclassName=\"gap-1.5\"\n\t\t\t\t\t\ttitle=\"Exit preview mode and clear draft cookie\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<SignOut className=\"h-4 w-4\" />\n\t\t\t\t\t\t<span className=\"hidden sm:inline\">Exit Preview</span>\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button variant=\"ghost\" size=\"icon\" onClick={onClose}>\n\t\t\t\t\t\t<X className=\"h-4 w-4\" />\n\t\t\t\t\t\t<span className=\"sr-only\">{t(\"common.close\")}</span>\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Content */}\n\t\t\t{isMobile ? (\n\t\t\t\t/* Mobile: Tabs content */\n\t\t\t\t<div className=\"flex-1 min-h-0\">\n\t\t\t\t\t{activeTab === \"form\" ? (\n\t\t\t\t\t\t<div className=\"h-full overflow-y-auto p-6\" data-preview-form-scope>\n\t\t\t\t\t\t\t<LocaleScopeProvider>\n\t\t\t\t\t\t\t\t<FormView\n\t\t\t\t\t\t\t\t\tcollection={collection}\n\t\t\t\t\t\t\t\t\tid={itemId}\n\t\t\t\t\t\t\t\t\tconfig={resolvedConfig}\n\t\t\t\t\t\t\t\t\tallCollectionsConfig={resolvedAllCollections}\n\t\t\t\t\t\t\t\t\tregistry={registry}\n\t\t\t\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\t\t\t\tonSuccess={onSuccess}\n\t\t\t\t\t\t\t\t\tshowMeta={false}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</LocaleScopeProvider>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"h-full\">\n\t\t\t\t\t\t\t<PreviewPane\n\t\t\t\t\t\t\t\tref={previewRef}\n\t\t\t\t\t\t\t\turl={previewUrl}\n\t\t\t\t\t\t\t\tonFieldClick={handlePreviewFieldClick}\n\t\t\t\t\t\t\t\tonBlockClick={handlePreviewBlockClick}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t/* Desktop: Side by side */\n\t\t\t\t<div className=\"flex-1 flex min-h-0\">\n\t\t\t\t\t{/* Form panel - fixed width like sheet */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tdata-preview-form-scope\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"h-full border-r bg-background shrink-0\",\n\t\t\t\t\t\t\t\"w-full sm:max-w-2xl\",\n\t\t\t\t\t\t\t\"overflow-y-auto p-6\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<LocaleScopeProvider>\n\t\t\t\t\t\t\t<FormView\n\t\t\t\t\t\t\t\tcollection={collection}\n\t\t\t\t\t\t\t\tid={itemId}\n\t\t\t\t\t\t\t\tconfig={resolvedConfig}\n\t\t\t\t\t\t\t\tallCollectionsConfig={resolvedAllCollections}\n\t\t\t\t\t\t\t\tregistry={registry}\n\t\t\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\t\t\tonSuccess={onSuccess}\n\t\t\t\t\t\t\t\tshowMeta={false}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</LocaleScopeProvider>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Preview panel - fills remaining space */}\n\t\t\t\t\t<div className=\"flex-1 min-w-0 bg-muted/30\">\n\t\t\t\t\t\t<PreviewPane\n\t\t\t\t\t\t\tref={previewRef}\n\t\t\t\t\t\t\turl={previewUrl}\n\t\t\t\t\t\t\tonFieldClick={handlePreviewFieldClick}\n\t\t\t\t\t\t\tonBlockClick={handlePreviewBlockClick}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function LivePreviewMode({\n\topen,\n\tonClose,\n\tcollection,\n\titemId,\n\tconfig,\n\tallCollectionsConfig,\n\tregistry,\n\tpreviewUrl,\n\tonSuccess,\n}: LivePreviewModeProps) {\n\t// Create ref for PreviewPane\n\tconst previewRef = React.useRef<PreviewPaneRef>(null);\n\n\t// Create context value with refresh callback\n\tconst contextValue = React.useMemo(\n\t\t() => ({\n\t\t\ttriggerPreviewRefresh: () => {\n\t\t\t\tpreviewRef.current?.triggerRefresh();\n\t\t\t},\n\t\t}),\n\t\t[],\n\t);\n\n\t// Handle focus changes from FocusContext - scroll to and focus the field\n\tconst handleFocusChange = React.useCallback((state: FocusState) => {\n\t\tif (state.type === \"field\") {\n\t\t\tscrollFieldIntoView(state.fieldPath);\n\t\t} else if (state.type === \"block\") {\n\t\t\t// Wait for block form to render before scrolling\n\t\t\tsetTimeout(() => {\n\t\t\t\tconst fullPath = state.fieldPath\n\t\t\t\t\t? `content._values.${state.blockId}.${state.fieldPath}`\n\t\t\t\t\t: `content._values.${state.blockId}`;\n\t\t\t\tscrollFieldIntoView(fullPath);\n\t\t\t}, 150);\n\t\t}\n\t}, []);\n\n\tif (!open) return null;\n\n\treturn (\n\t\t<LivePreviewContext.Provider value={contextValue}>\n\t\t\t<FocusProvider onFocusChange={handleFocusChange}>\n\t\t\t\t<LivePreviewContent\n\t\t\t\t\topen={open}\n\t\t\t\t\tonClose={onClose}\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\titemId={itemId}\n\t\t\t\t\tconfig={config}\n\t\t\t\t\tallCollectionsConfig={allCollectionsConfig}\n\t\t\t\t\tregistry={registry}\n\t\t\t\t\tpreviewUrl={previewUrl}\n\t\t\t\t\tonSuccess={onSuccess}\n\t\t\t\t\tpreviewRef={previewRef}\n\t\t\t\t/>\n\t\t\t</FocusProvider>\n\t\t</LivePreviewContext.Provider>\n\t);\n}\n\n// ============================================================================\n// Trigger Button Component\n// ============================================================================\n\nexport interface LivePreviewButtonProps {\n\tonClick: () => void;\n\tdisabled?: boolean;\n}\n\nexport function LivePreviewButton({\n\tonClick,\n\tdisabled,\n}: LivePreviewButtonProps) {\n\treturn (\n\t\t<Button\n\t\t\ttype=\"button\"\n\t\t\tvariant=\"outline\"\n\t\t\tsize=\"icon\"\n\t\t\tclassName=\"size-9\"\n\t\t\tonClick={onClick}\n\t\t\tdisabled={disabled}\n\t\t\ttitle=\"Live Preview\"\n\t\t>\n\t\t\t<Eye className=\"size-4\" />\n\t\t\t<span className=\"sr-only\">Live Preview</span>\n\t\t</Button>\n\t);\n}\n","/**\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\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?.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\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?.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\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?.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\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: globalQueryKey,\n\t\t\t\t});\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","/**\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/collection/action-registry\";\nimport type {\n\tActionContext,\n\tActionDefinition,\n\tActionHelpers,\n\tActionQueryClient,\n\tActionsConfig,\n\tHeaderActionsConfig,\n} from \"../builder/collection/action-types\";\nimport { useTranslation } from \"../i18n/hooks\";\nimport {\n\tselectAuthClient,\n\tselectBasePath,\n\tselectClient,\n\tselectContentLocale,\n\tselectNavigate,\n\tuseAdminStore,\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\t/** Collection name */\n\tcollection: string;\n\t/** Custom refresh callback */\n\tonRefresh?: () => void;\n}\n\nexport interface UseActionHelpersReturn {\n\t/** Action helpers to pass to action components */\n\thelpers: ActionHelpers;\n}\n\nexport interface UseActionsOptions<TItem = any> {\n\t/** Collection name */\n\tcollection: string;\n\t/** Actions configuration from collection config */\n\tactionsConfig?: ActionsConfig<TItem>;\n\t/** Custom refresh callback */\n\tonRefresh?: () => void;\n}\n\nexport interface UseActionsReturn<TItem = any> {\n\t/** Action helpers */\n\thelpers: ActionHelpers;\n\t/** Resolved actions config (with defaults) */\n\tactions: Required<ActionsConfig<TItem>>;\n\t/** Currently active dialog action */\n\tdialogAction: ActionDefinition<TItem> | null;\n\t/** Set active dialog action */\n\tsetDialogAction: (action: ActionDefinition<TItem> | null) => void;\n\t/** Item for dialog action (for row actions) */\n\tdialogItem: TItem | null;\n\t/** Set item for dialog action */\n\tsetDialogItem: (item: TItem | null) => void;\n\t/** Open dialog for an action */\n\topenDialog: (action: ActionDefinition<TItem>, item?: TItem) => void;\n\t/** Close dialog */\n\tcloseDialog: () => 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\tcollection,\n\tonRefresh,\n}: UseActionHelpersOptions): UseActionHelpersReturn {\n\tconst basePath = useAdminStore(selectBasePath);\n\tconst navigate = useAdminStore(selectNavigate);\n\tconst client = useAdminStore(selectClient);\n\tconst contentLocale = useAdminStore(selectContentLocale);\n\tconst queryClient = useQueryClient();\n\tconst { t } = useTranslation();\n\n\t// Create query options proxy for key building (same as use-collection hooks)\n\tconst queryOpts = React.useMemo(\n\t\t() =>\n\t\t\tcreateQuestpieQueryOptions(client as any, {\n\t\t\t\tkeyPrefix: QUERY_KEY_PREFIX,\n\t\t\t\tlocale: contentLocale,\n\t\t\t}),\n\t\t[client, contentLocale],\n\t);\n\n\tconst helpers: ActionHelpers = React.useMemo(\n\t\t() => ({\n\t\t\tnavigate,\n\t\t\ttoast: {\n\t\t\t\tsuccess: toast.success,\n\t\t\t\terror: toast.error,\n\t\t\t\tinfo: toast.info,\n\t\t\t\twarning: toast.warning,\n\t\t\t},\n\t\t\tt,\n\t\t\tinvalidateCollection: async (targetCollection?: string) => {\n\t\t\t\tconst col = targetCollection || collection;\n\t\t\t\t// Invalidate list and count queries for the collection\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", col, \"find\", contentLocale]),\n\t\t\t\t});\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", col, \"count\", contentLocale]),\n\t\t\t\t});\n\t\t\t\t// Call custom refresh handler\n\t\t\t\tonRefresh?.();\n\t\t\t},\n\t\t\tinvalidateItem: async (itemId: string, targetCollection?: string) => {\n\t\t\t\tconst col = targetCollection || collection;\n\t\t\t\t// Invalidate findOne query for specific item\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\n\t\t\t\t\t\t\"collections\",\n\t\t\t\t\t\tcol,\n\t\t\t\t\t\t\"findOne\",\n\t\t\t\t\t\tcontentLocale,\n\t\t\t\t\t\t{ id: itemId },\n\t\t\t\t\t]),\n\t\t\t\t});\n\t\t\t\t// Also invalidate list queries since item data changed\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", col, \"find\", contentLocale]),\n\t\t\t\t});\n\t\t\t},\n\t\t\tinvalidateAll: async () => {\n\t\t\t\t// Invalidate all CMS queries\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: [...QUERY_KEY_PREFIX],\n\t\t\t\t});\n\t\t\t\t// Call custom refresh handler\n\t\t\t\tonRefresh?.();\n\t\t\t},\n\t\t\trefresh: () => {\n\t\t\t\t// Invalidate collection queries (better than page reload)\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\n\t\t\t\t\t\t\"collections\",\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\"find\",\n\t\t\t\t\t\tcontentLocale,\n\t\t\t\t\t]),\n\t\t\t\t});\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\n\t\t\t\t\t\t\"collections\",\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\"count\",\n\t\t\t\t\t\tcontentLocale,\n\t\t\t\t\t]),\n\t\t\t\t});\n\t\t\t\t// Call custom refresh handler\n\t\t\t\tonRefresh?.();\n\t\t\t},\n\t\t\tcloseDialog: () => {\n\t\t\t\t// This will be overridden by the component managing dialog state\n\t\t\t},\n\t\t\tbasePath,\n\t\t}),\n\t\t[\n\t\t\tnavigate,\n\t\t\tqueryClient,\n\t\t\tqueryOpts,\n\t\t\tcollection,\n\t\t\tcontentLocale,\n\t\t\tonRefresh,\n\t\t\tbasePath,\n\t\t\tt,\n\t\t],\n\t);\n\n\treturn { 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\tcollection,\n\tactionsConfig,\n\tonRefresh,\n}: UseActionsOptions<TItem>): UseActionsReturn<TItem> {\n\tconst [dialogAction, setDialogAction] =\n\t\tReact.useState<ActionDefinition<TItem> | null>(null);\n\tconst [dialogItem, setDialogItem] = React.useState<TItem | null>(null);\n\n\t// Get default actions if not provided\n\tconst defaultActions = React.useMemo(\n\t\t() => getDefaultActionsConfig<TItem>(),\n\t\t[],\n\t);\n\n\t// Merge provided config with defaults\n\tconst actions: Required<ActionsConfig<TItem>> = React.useMemo(\n\t\t() => ({\n\t\t\theader: actionsConfig?.header ??\n\t\t\t\tdefaultActions.header ?? { primary: [], secondary: [] },\n\t\t\tbulk: actionsConfig?.bulk ?? defaultActions.bulk ?? [],\n\t\t}),\n\t\t[actionsConfig, defaultActions],\n\t);\n\n\t// Close dialog handler\n\tconst closeDialog = React.useCallback(() => {\n\t\tsetDialogAction(null);\n\t\tsetDialogItem(null);\n\t}, []);\n\n\t// Get base helpers\n\tconst { helpers: baseHelpers } = useActionHelpers({\n\t\tcollection,\n\t\tonRefresh: () => {\n\t\t\tonRefresh?.();\n\t\t},\n\t});\n\n\t// Enhanced helpers with dialog control\n\tconst helpers: ActionHelpers = React.useMemo(\n\t\t() => ({\n\t\t\t...baseHelpers,\n\t\t\tcloseDialog,\n\t\t}),\n\t\t[baseHelpers, closeDialog],\n\t);\n\n\t// Open dialog for an action\n\tconst openDialog = React.useCallback(\n\t\t(action: ActionDefinition<TItem>, item?: TItem) => {\n\t\t\tsetDialogAction(action);\n\t\t\tsetDialogItem(item ?? null);\n\t\t},\n\t\t[],\n\t);\n\n\treturn {\n\t\thelpers,\n\t\tactions,\n\t\tdialogAction,\n\t\tsetDialogAction,\n\t\tdialogItem,\n\t\tsetDialogItem,\n\t\topenDialog,\n\t\tcloseDialog,\n\t};\n}\n\n// ============================================================================\n// useActionExecution Hook\n// ============================================================================\n\nexport interface UseActionExecutionOptions<TItem = any> {\n\t/** Collection name */\n\tcollection: string;\n\t/** Action helpers */\n\thelpers: 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\tcollection,\n\thelpers,\n}: UseActionExecutionOptions<TItem>) {\n\tconst client = useAdminStore(selectClient);\n\tconst authClient = useAdminStore(selectAuthClient);\n\tconst queryClient = useQueryClient();\n\tconst [isExecuting, setIsExecuting] = React.useState(false);\n\n\t// Wrapped query client for action context\n\tconst actionQueryClient: ActionQueryClient = React.useMemo(\n\t\t() => ({\n\t\t\tinvalidateQueries: (filters) => queryClient.invalidateQueries(filters),\n\t\t\trefetchQueries: (filters) => queryClient.refetchQueries(filters),\n\t\t\tresetQueries: (filters) => queryClient.resetQueries(filters),\n\t\t}),\n\t\t[queryClient],\n\t);\n\n\tconst executeAction = React.useCallback(\n\t\tasync (\n\t\t\taction: ActionDefinition<TItem>,\n\t\t\titem?: TItem,\n\t\t\titems?: TItem[],\n\t\t): Promise<void> => {\n\t\t\tconst ctx: ActionContext<TItem> = {\n\t\t\t\titem,\n\t\t\t\titems,\n\t\t\t\tcollection,\n\t\t\t\thelpers,\n\t\t\t\tqueryClient: actionQueryClient,\n\t\t\t\tauthClient,\n\t\t\t};\n\n\t\t\tsetIsExecuting(true);\n\t\t\ttry {\n\t\t\t\tconst { handler } = action;\n\n\t\t\t\tswitch (handler.type) {\n\t\t\t\t\tcase \"navigate\": {\n\t\t\t\t\t\tconst path =\n\t\t\t\t\t\t\ttypeof handler.path === \"function\"\n\t\t\t\t\t\t\t\t? handler.path(item!)\n\t\t\t\t\t\t\t\t: handler.path;\n\t\t\t\t\t\thelpers.navigate(\n\t\t\t\t\t\t\t`${helpers.basePath}/collections/${collection}/${path}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"api\": {\n\t\t\t\t\t\t// Replace {id} placeholder in endpoint\n\t\t\t\t\t\tconst endpoint = handler.endpoint.replace(\n\t\t\t\t\t\t\t\"{id}\",\n\t\t\t\t\t\t\tString((item as any)?.id || \"\"),\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Execute API call\n\t\t\t\t\t\tconst method = (handler.method || \"POST\").toLowerCase();\n\n\t\t\t\t\t\t// Get collection-specific client\n\t\t\t\t\t\tconst collectionClient = (client as any).collections?.[collection];\n\n\t\t\t\t\t\tif (collectionClient) {\n\t\t\t\t\t\t\tif (method === \"delete\" && collectionClient.delete) {\n\t\t\t\t\t\t\t\tawait collectionClient.delete((item as any)?.id);\n\t\t\t\t\t\t\t\thelpers.toast.success(\"Item deleted successfully\");\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// For other methods, show info (actual implementation would call the API)\n\t\t\t\t\t\t\t\thelpers.toast.info(`${handler.method || \"POST\"} ${endpoint}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thelpers.toast.info(\n\t\t\t\t\t\t\t\t`API call: ${handler.method || \"POST\"} ${endpoint}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\thelpers.refresh();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"custom\": {\n\t\t\t\t\t\tawait handler.fn(ctx);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"dialog\":\n\t\t\t\t\tcase \"form\": {\n\t\t\t\t\t\t// These are handled by the ActionDialog component\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\thelpers.toast.error(\n\t\t\t\t\terror instanceof Error ? error.message : \"Action failed\",\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tsetIsExecuting(false);\n\t\t\t}\n\t\t},\n\t\t[collection, helpers, client, authClient, actionQueryClient],\n\t);\n\n\treturn {\n\t\texecuteAction,\n\t\tisExecuting,\n\t};\n}\n","/**\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","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useAdminStore } from \"../runtime/provider.js\";\nimport { useCurrentUser } from \"./use-current-user.js\";\n\n/**\n * Admin Preference entity from the database\n */\nexport interface AdminPreference<T = unknown> {\n id: string;\n userId: string;\n key: string;\n value: T;\n createdAt: string;\n updatedAt: 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 const client = useAdminStore((s) => s.client);\n const user = useCurrentUser();\n\n return useQuery({\n queryKey: [\"admin_preferences\", user?.id, key],\n queryFn: async (): Promise<T | null> => {\n if (!user?.id) return null;\n\n const result = await client.collections.admin_preferences.findOne({\n where: { userId: user.id, key },\n });\n\n return (result?.value as T) ?? null;\n },\n enabled: !!client && !!user?.id,\n });\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 const client = useAdminStore((s) => s.client);\n const user = useCurrentUser();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (value: T) => {\n if (!user?.id) {\n throw new Error(\"User must be logged in to save preferences\");\n }\n\n const collections = client?.collections as\n | Record<string, any>\n | undefined;\n if (!collections?.admin_preferences) {\n throw new Error(\n \"admin_preferences collection not available. Make sure to use adminModule in your CMS setup.\",\n );\n }\n\n // Try to find existing preference\n const existing = await collections.admin_preferences.findOne({\n where: { userId: user.id, key },\n });\n\n if (existing) {\n // Update existing\n return collections.admin_preferences.update(existing.id, { value });\n }\n // Create new\n return collections.admin_preferences.create({\n userId: user.id,\n key,\n value,\n });\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"admin_preferences\", user?.id, key],\n });\n },\n });\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 const client = useAdminStore((s) => s.client);\n const user = useCurrentUser();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async () => {\n if (!user?.id) {\n throw new Error(\"User must be logged in to delete preferences\");\n }\n\n const collections = client?.collections as\n | Record<string, any>\n | undefined;\n if (!collections?.admin_preferences) {\n throw new Error(\n \"admin_preferences collection not available. Make sure to use adminModule in your CMS setup.\",\n );\n }\n\n // Find existing preference\n const existing = await collections.admin_preferences.findOne({\n where: { userId: user.id, key },\n });\n\n if (existing) {\n return collections.admin_preferences.delete(existing.id);\n }\n\n return null;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"admin_preferences\", user?.id, key],\n });\n },\n });\n}\n","/**\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","/**\n * useValidationErrorMap Hook\n *\n * Creates a Zod error map that uses the admin i18n system\n * for localized validation error messages.\n */\n\nimport { useMemo } from \"react\";\nimport { createZodErrorMap, type ZodErrorMapFn } from \"questpie/shared\";\nimport { useSafeI18n } from \"../i18n/hooks\";\n\n/**\n * Create a Zod error map with i18n support\n *\n * Uses the admin's i18n adapter for translations.\n * Falls back to English messages if no adapter is available.\n *\n * @returns Zod error map function\n *\n * @example\n * ```tsx\n * import { zodResolver } from \"@hookform/resolvers/zod\";\n *\n * function MyForm() {\n * const errorMap = useValidationErrorMap();\n * const schema = useCollectionValidation(\"posts\");\n *\n * const form = useForm({\n * resolver: schema\n * ? zodResolver(schema, { errorMap })\n * : undefined,\n * });\n * }\n * ```\n */\nexport function useValidationErrorMap(): ZodErrorMapFn {\n const i18n = useSafeI18n();\n\n return useMemo(() => {\n // Create translate function that uses admin i18n\n const translate = (\n key: string,\n params?: Record<string, unknown>,\n ): string => {\n if (i18n) {\n return i18n.t(key, params);\n }\n\n // Fallback: return key with interpolated params\n if (!params) return key;\n\n return key.replace(/\\{\\{(\\w+)\\}\\}/g, (_, paramKey) => {\n const value = params[paramKey];\n return value !== undefined ? String(value) : `{{${paramKey}}}`;\n });\n };\n\n return createZodErrorMap(translate);\n }, [i18n]);\n}\n\n/**\n * Create a static error map (for use outside of React components)\n *\n * @param t - Translate function\n * @returns Zod error map function\n */\nexport function createAdminZodErrorMap(\n t: (key: string, params?: Record<string, unknown>) => string,\n): ZodErrorMapFn {\n return createZodErrorMap(t);\n}\n","/**\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 { useCallback, useMemo } from \"react\";\nimport { z } from \"zod\";\nimport type { ZodErrorMapFn } from \"questpie/shared\";\nimport type { FieldErrors, FieldValues, Resolver } from \"react-hook-form\";\nimport { createFormSchema } from \"../builder/validation\";\nimport { selectAdmin, useAdminStore } from \"../runtime\";\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 schema = useMemo(() => {\n if (!admin) return undefined;\n\n const collections = admin.getCollections();\n const config = collections[collection];\n\n if (!config?.fields) return undefined;\n\n return createFormSchema(config.fields);\n }, [admin, collection]);\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}","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 { selectClient, selectContentLocale, useAdminStore } from \"../runtime\";\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): any {\n\tconst client = useAdminStore(selectClient);\n\tconst contentLocale = useAdminStore(selectContentLocale);\n\tconst keyPrefix = [\"questpie\", \"globals\"] as const;\n\tconst queryOpts = createQuestpieQueryOptions(\n\t\tclient as any,\n\t\t{\n\t\t\tkeyPrefix,\n\t\t\tlocale: contentLocale,\n\t\t} as any,\n\t);\n\n\treturn useQuery({\n\t\t...(queryOpts as any).globals[globalName as string].get({\n\t\t\t...options,\n\t\t\tlocale: contentLocale,\n\t\t} as any),\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 keyPrefix = [\"questpie\", \"globals\"] as const;\n\tconst queryOpts = createQuestpieQueryOptions(\n\t\tclient as any,\n\t\t{\n\t\t\tkeyPrefix,\n\t\t\tlocale: contentLocale,\n\t\t} as any,\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\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: globalQueryKey,\n\t\t\t});\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","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useAdminStore } from \"../runtime/provider.js\";\nimport type { SavedView } from \"../components/filter-builder/types.js\";\n\n/**\n * Hook to fetch saved views for a collection\n *\n * Note: This hook requires the adminModule to be used in your CMS setup.\n * If admin_saved_views collection is not available, returns empty array.\n */\nexport function useSavedViews(collectionName: string) {\n const client = useAdminStore((s) => s.client);\n\n return useQuery({\n queryKey: [\"admin_saved_views\", collectionName],\n queryFn: async (): Promise<{ docs: SavedView[] }> => {\n // Check if the collection exists on the client\n const collections = client?.collections as\n | Record<string, any>\n | undefined;\n if (!collections?.admin_saved_views) {\n return { docs: [] };\n }\n\n const result = await collections.admin_saved_views.find({\n where: { collectionName },\n });\n return { docs: (result?.docs ?? []) as SavedView[] };\n },\n enabled: !!client,\n });\n}\n\n/**\n * Hook to save a new view\n */\nexport function useSaveView(collectionName: string) {\n const client = useAdminStore((s) => s.client);\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (data: {\n name: string;\n configuration: SavedView[\"configuration\"];\n userId?: string;\n }) => {\n const collections = client?.collections as\n | Record<string, any>\n | undefined;\n if (!collections?.admin_saved_views) {\n throw new Error(\n \"admin_saved_views collection not available. Make sure to use adminModule in your CMS setup.\",\n );\n }\n\n return collections.admin_saved_views.create({\n data: {\n ...data,\n collectionName,\n userId: data.userId || \"anonymous\",\n isDefault: false,\n },\n });\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"admin_saved_views\", collectionName],\n });\n },\n });\n}\n\n/**\n * Hook to update an existing view\n */\nexport function useUpdateSavedView(collectionName: string) {\n const client = useAdminStore((s) => s.client);\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({\n id,\n data,\n }: {\n id: string;\n data: Partial<SavedView>;\n }) => {\n const collections = client?.collections as\n | Record<string, any>\n | undefined;\n if (!collections?.admin_saved_views) {\n throw new Error(\n \"admin_saved_views collection not available. Make sure to use adminModule in your CMS setup.\",\n );\n }\n\n return collections.admin_saved_views.update(id, data);\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"admin_saved_views\", collectionName],\n });\n },\n });\n}\n\n/**\n * Hook to delete a view\n */\nexport function useDeleteSavedView(collectionName: string) {\n const client = useAdminStore((s) => s.client);\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (viewId: string) => {\n const collections = client?.collections as\n | Record<string, any>\n | undefined;\n if (!collections?.admin_saved_views) {\n throw new Error(\n \"admin_saved_views collection not available. Make sure to use adminModule in your CMS setup.\",\n );\n }\n\n return collections.admin_saved_views.delete(viewId);\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"admin_saved_views\", collectionName],\n });\n },\n });\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type {\n FilterRule,\n SortConfig,\n ViewConfiguration,\n} from \"../components/filter-builder/types.js\";\nimport {\n useAdminPreference,\n useSetAdminPreference,\n} from \"./use-admin-preferences.js\";\n\nconst EMPTY_CONFIG: ViewConfiguration = {\n filters: [],\n sortConfig: null,\n visibleColumns: [],\n};\n\n/**\n * Get the preference key for a collection's view state\n */\nfunction getPreferenceKey(collectionName: string): string {\n return `viewState:${collectionName}`;\n}\n\n/**\n * Merge stored visible columns with default columns to include new fields\n *\n * When a new field is added to the collection, it should appear in the column picker\n * but not automatically become visible (preserving user's existing preference).\n *\n * The merge logic:\n * 1. Start with stored visible columns (in user's preferred order)\n * 2. New columns that weren't in the previous default set are NOT auto-added to visible\n * (they appear in column picker but hidden by default)\n */\nfunction mergeVisibleColumns(\n storedColumns: string[] | undefined,\n defaultColumns: string[],\n): string[] {\n // If no stored columns, use defaults\n if (!storedColumns?.length) {\n return defaultColumns;\n }\n\n // Return stored columns as-is\n // New columns are available in the column picker but not auto-visible\n return storedColumns;\n}\n\n/**\n * Hook to manage view configuration state with database persistence\n *\n * Syncs view state (filters, sort, visible columns) to the admin_preferences\n * collection in the database. Falls back to local state when:\n * - User is not logged in\n * - admin_preferences collection is not available\n * - Data is still loading\n *\n * @param defaultColumns - Default columns to show when no config is set\n * @param initialConfig - Optional initial configuration to start with\n * @param collectionName - Collection name for preference key\n *\n * @example\n * ```tsx\n * const viewState = useViewState(\n * [\"_title\", \"status\", \"createdAt\"],\n * undefined,\n * \"posts\"\n * );\n *\n * // Use view state\n * const { config, setVisibleColumns, toggleSort } = viewState;\n * ```\n */\nexport function useViewState(\n defaultColumns: string[],\n initialConfig?: Partial<ViewConfiguration>,\n collectionName?: string,\n) {\n // Preference key for this collection\n const preferenceKey = collectionName\n ? getPreferenceKey(collectionName)\n : null;\n\n // Fetch stored preference from DB\n const { data: storedConfig, isLoading: isLoadingPreference } =\n useAdminPreference<ViewConfiguration>(preferenceKey ?? \"\");\n\n // Mutation to save preference\n const { mutate: savePreference } = useSetAdminPreference<ViewConfiguration>(\n preferenceKey ?? \"\",\n );\n\n // Track if we've initialized from DB\n const [hasInitialized, setHasInitialized] = useState(false);\n\n // Local state for immediate updates\n const [config, setConfigState] = useState<ViewConfiguration>(() => {\n // Start with initial config or defaults\n return {\n filters: initialConfig?.filters ?? [],\n sortConfig: initialConfig?.sortConfig ?? null,\n visibleColumns: initialConfig?.visibleColumns?.length\n ? initialConfig.visibleColumns\n : defaultColumns,\n };\n });\n\n // Sync from DB when data loads\n useEffect(() => {\n if (\n !isLoadingPreference &&\n storedConfig &&\n preferenceKey &&\n !hasInitialized\n ) {\n setHasInitialized(true);\n setConfigState({\n filters: storedConfig.filters ?? [],\n sortConfig: storedConfig.sortConfig ?? null,\n visibleColumns: mergeVisibleColumns(\n storedConfig.visibleColumns,\n defaultColumns,\n ),\n });\n } else if (!isLoadingPreference && !storedConfig && !hasInitialized) {\n // No stored config - use defaults\n setHasInitialized(true);\n }\n }, [\n isLoadingPreference,\n storedConfig,\n preferenceKey,\n hasInitialized,\n defaultColumns,\n ]);\n\n // Debounced save to DB\n const saveTimeoutRef = useMemo(\n () => ({ current: null as NodeJS.Timeout | null }),\n [],\n );\n\n const saveToDb = useCallback(\n (newConfig: ViewConfiguration) => {\n if (!preferenceKey) return;\n\n // Clear existing timeout\n if (saveTimeoutRef.current) {\n clearTimeout(saveTimeoutRef.current);\n }\n\n // Debounce save to avoid too many requests\n saveTimeoutRef.current = setTimeout(() => {\n savePreference(newConfig);\n }, 500);\n },\n [preferenceKey, savePreference, saveTimeoutRef],\n );\n\n // Cleanup timeout on unmount\n useEffect(() => {\n return () => {\n if (saveTimeoutRef.current) {\n clearTimeout(saveTimeoutRef.current);\n }\n };\n }, [saveTimeoutRef]);\n\n // Wrapper for setConfig that also persists\n const setConfig = useCallback(\n (\n newConfig:\n | ViewConfiguration\n | ((prev: ViewConfiguration) => ViewConfiguration),\n ) => {\n setConfigState((prev) => {\n const next =\n typeof newConfig === \"function\" ? newConfig(prev) : newConfig;\n saveToDb(next);\n return next;\n });\n },\n [saveToDb],\n );\n\n // Add a filter\n const addFilter = useCallback(\n (filter: FilterRule) => {\n setConfig((prev) => ({\n ...prev,\n filters: [...prev.filters, filter],\n }));\n },\n [setConfig],\n );\n\n // Remove a filter by ID\n const removeFilter = useCallback(\n (filterId: string) => {\n setConfig((prev) => ({\n ...prev,\n filters: prev.filters.filter((f) => f.id !== filterId),\n }));\n },\n [setConfig],\n );\n\n // Update a filter by ID\n const updateFilter = useCallback(\n (filterId: string, updates: Partial<FilterRule>) => {\n setConfig((prev) => ({\n ...prev,\n filters: prev.filters.map((f) =>\n f.id === filterId ? { ...f, ...updates } : f,\n ),\n }));\n },\n [setConfig],\n );\n\n // Clear all filters\n const clearFilters = useCallback(() => {\n setConfig((prev) => ({\n ...prev,\n filters: [],\n }));\n }, [setConfig]);\n\n // Set sort configuration\n const setSort = useCallback(\n (sortConfig: SortConfig | null) => {\n setConfig((prev) => ({ ...prev, sortConfig }));\n },\n [setConfig],\n );\n\n // Toggle sort on a field\n const toggleSort = useCallback(\n (field: string) => {\n setConfig((prev) => {\n if (prev.sortConfig?.field === field) {\n if (prev.sortConfig.direction === \"asc\") {\n return { ...prev, sortConfig: { field, direction: \"desc\" } };\n }\n return { ...prev, sortConfig: null };\n }\n return { ...prev, sortConfig: { field, direction: \"asc\" } };\n });\n },\n [setConfig],\n );\n\n // Set visible columns\n const setVisibleColumns = useCallback(\n (columns: string[]) => {\n setConfig((prev) => ({ ...prev, visibleColumns: columns }));\n },\n [setConfig],\n );\n\n // Toggle column visibility\n const toggleColumn = useCallback(\n (column: string) => {\n setConfig((prev) => {\n if (prev.visibleColumns.includes(column)) {\n return {\n ...prev,\n visibleColumns: prev.visibleColumns.filter((c) => c !== column),\n };\n }\n return {\n ...prev,\n visibleColumns: [...prev.visibleColumns, column],\n };\n });\n },\n [setConfig],\n );\n\n // Load a complete configuration\n const loadConfig = useCallback(\n (newConfig: ViewConfiguration) => {\n setConfig(newConfig);\n },\n [setConfig],\n );\n\n // Reset to default configuration\n const resetConfig = useCallback(() => {\n setConfig({\n ...EMPTY_CONFIG,\n visibleColumns: defaultColumns,\n });\n }, [setConfig, defaultColumns]);\n\n // Check if config has any changes from default\n const hasChanges = useMemo(() => {\n return (\n config.filters.length > 0 ||\n config.sortConfig !== null ||\n JSON.stringify([...config.visibleColumns].sort()) !==\n JSON.stringify([...defaultColumns].sort())\n );\n }, [config, defaultColumns]);\n\n return {\n config,\n setConfig,\n addFilter,\n removeFilter,\n updateFilter,\n clearFilters,\n setSort,\n toggleSort,\n setVisibleColumns,\n toggleColumn,\n loadConfig,\n resetConfig,\n hasChanges,\n // Additional state for loading indicator\n isLoading: isLoadingPreference && !hasInitialized,\n };\n}\n","/**\n * Search Hook\n *\n * React hook for FTS-powered search using the CMS Search API.\n * Returns full records with search metadata (score, highlights, indexed title).\n */\n\nimport { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport { useState, useEffect } from \"react\";\nimport { selectClient, useAdminStore, useScopedLocale } from \"../runtime\";\n\n// ============================================================================\n// Debounce Hook\n// ============================================================================\n\n/**\n * Hook to debounce a value\n *\n * @example\n * ```tsx\n * const [searchTerm, setSearchTerm] = useState(\"\");\n * const debouncedSearch = useDebouncedValue(searchTerm, 300);\n * ```\n */\nexport function useDebouncedValue<T>(value: T, delay: number): T {\n\tconst [debouncedValue, setDebouncedValue] = useState<T>(value);\n\n\tuseEffect(() => {\n\t\tconst timer = setTimeout(() => {\n\t\t\tsetDebouncedValue(value);\n\t\t}, delay);\n\n\t\treturn () => {\n\t\t\tclearTimeout(timer);\n\t\t};\n\t}, [value, delay]);\n\n\treturn debouncedValue;\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Facet definition for search queries\n */\nexport interface SearchFacetDefinition {\n\tfield: string;\n\tlimit?: number;\n\tsortBy?: \"count\" | \"alpha\";\n}\n\n/**\n * Search options for the hook\n */\nexport interface UseSearchOptions {\n\t/**\n\t * Collection to search in (required)\n\t */\n\tcollection: string;\n\n\t/**\n\t * Search query string\n\t */\n\tquery: string;\n\n\t/**\n\t * Additional metadata filters\n\t */\n\tfilters?: Record<string, string | string[]>;\n\n\t/**\n\t * Result limit (default: 50)\n\t */\n\tlimit?: number;\n\n\t/**\n\t * Result offset (default: 0)\n\t */\n\toffset?: number;\n\n\t/**\n\t * Include highlights (default: true)\n\t */\n\thighlights?: boolean;\n\n\t/**\n\t * Facets to retrieve\n\t */\n\tfacets?: SearchFacetDefinition[];\n\n\t/**\n\t * Whether the query is enabled (default: true if query is non-empty)\n\t */\n\tenabled?: boolean;\n}\n\n/**\n * Search metadata attached to each result\n */\nexport interface SearchMeta {\n\t/** Relevance score from search */\n\tscore: number;\n\t/** Highlighted snippets with <mark> tags */\n\thighlights?: {\n\t\ttitle?: string;\n\t\tcontent?: string;\n\t};\n\t/** Title as stored in search index */\n\tindexedTitle: string;\n\t/** Content preview from search index */\n\tindexedContent?: string;\n}\n\n/**\n * Populated search result - full record with search metadata\n */\nexport interface PopulatedSearchResult<T = Record<string, any>> {\n\t/** Full record data (spread at top level) */\n\t[key: string]: any;\n\t/** Collection name */\n\t_collection: string;\n\t/** Search metadata */\n\t_search: SearchMeta;\n}\n\n/**\n * Facet value with count\n */\nexport interface SearchFacetValue {\n\tvalue: string;\n\tcount: number;\n}\n\n/**\n * Facet result\n */\nexport interface SearchFacetResult {\n\tfield: string;\n\tvalues: SearchFacetValue[];\n\tstats?: {\n\t\tmin: number;\n\t\tmax: number;\n\t};\n}\n\n/**\n * Search response with populated records\n */\nexport interface SearchResponse<T = Record<string, any>> {\n\t/** Full records with search metadata */\n\tdocs: PopulatedSearchResult<T>[];\n\t/** Total count (accurate after access filtering) */\n\ttotal: number;\n\t/** Facet results (if requested) */\n\tfacets?: SearchFacetResult[];\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook for FTS-powered collection search\n *\n * Returns full records directly with search metadata attached.\n * No need for a second CRUD fetch - records are populated server-side.\n *\n * @example\n * ```tsx\n * const [searchTerm, setSearchTerm] = useState(\"\");\n * const debouncedSearch = useDebouncedValue(searchTerm, 300);\n *\n * const { data, isLoading } = useSearch({\n * collection: \"posts\",\n * query: debouncedSearch,\n * limit: 50,\n * });\n *\n * // Use docs directly - they're full records!\n * const items = data?.docs ?? [];\n *\n * // Access search metadata\n * items.forEach(item => {\n * console.log(item.title); // Full record field\n * console.log(item._search.score); // Search score\n * console.log(item._search.highlights?.title); // Highlighted title\n * });\n * ```\n */\nexport function useSearch<T = Record<string, any>>(\n\toptions: UseSearchOptions,\n\tqueryOptions?: Omit<UseQueryOptions<SearchResponse<T>>, \"queryKey\" | \"queryFn\">,\n) {\n\tconst client = useAdminStore(selectClient);\n\tconst { locale: contentLocale } = useScopedLocale();\n\n\tconst {\n\t\tcollection,\n\t\tquery,\n\t\tfilters,\n\t\tlimit = 50,\n\t\toffset = 0,\n\t\thighlights = true,\n\t\tfacets,\n\t\tenabled,\n\t} = options;\n\n\t// Determine if search should be enabled\n\t// By default, enabled when query has content (after trimming)\n\tconst isEnabled = enabled ?? (query?.trim().length > 0);\n\n\treturn useQuery<SearchResponse<T>>({\n\t\tqueryKey: [\n\t\t\t\"questpie\",\n\t\t\t\"search\",\n\t\t\tcollection,\n\t\t\tquery,\n\t\t\tfilters,\n\t\t\tlimit,\n\t\t\toffset,\n\t\t\tcontentLocale,\n\t\t],\n\t\tqueryFn: async () => {\n\t\t\t// Use the client's search API\n\t\t\tconst response = await (client as any).search.search({\n\t\t\t\tquery,\n\t\t\t\tcollections: [collection],\n\t\t\t\tlocale: contentLocale,\n\t\t\t\tlimit,\n\t\t\t\toffset,\n\t\t\t\tfilters,\n\t\t\t\thighlights,\n\t\t\t\tfacets,\n\t\t\t});\n\t\t\treturn response;\n\t\t},\n\t\tenabled: isEnabled,\n\t\t// Keep previous data while fetching new results for smoother UX\n\t\tplaceholderData: (prev) => prev,\n\t\t// Stale time for search results (30 seconds)\n\t\tstaleTime: 30 * 1000,\n\t\t...queryOptions,\n\t});\n}\n\n/**\n * Hook for reindexing a collection\n *\n * @example\n * ```tsx\n * const { reindex } = useReindex();\n * await reindex(\"posts\");\n * ```\n */\nexport function useReindex() {\n\tconst client = useAdminStore(selectClient);\n\n\treturn {\n\t\treindex: async (collection: string) => {\n\t\t\treturn (client as any).search.reindex(collection);\n\t\t},\n\t};\n}\n\n// ============================================================================\n// Global Search Hook\n// ============================================================================\n\n/**\n * Search options for global search (across all collections)\n */\nexport interface UseGlobalSearchOptions {\n\t/**\n\t * Search query string\n\t */\n\tquery: string;\n\n\t/**\n\t * Result limit (default: 10)\n\t */\n\tlimit?: number;\n\n\t/**\n\t * Include highlights (default: true)\n\t */\n\thighlights?: boolean;\n\n\t/**\n\t * Whether the query is enabled (default: true if query length >= 2)\n\t */\n\tenabled?: boolean;\n}\n\n/**\n * Hook for FTS-powered search across ALL collections\n *\n * Used by the global search (Cmd+K) to find records across the entire CMS.\n *\n * @example\n * ```tsx\n * const [query, setQuery] = useState(\"\");\n * const debouncedQuery = useDebouncedValue(query, 300);\n *\n * const { data, isLoading } = useGlobalSearch({\n * query: debouncedQuery,\n * limit: 10,\n * });\n *\n * // Show results grouped by collection\n * data?.docs.forEach(item => {\n * console.log(`${item._collection}: ${item._search.indexedTitle}`);\n * });\n * ```\n */\nexport function useGlobalSearch<T = Record<string, any>>(\n\toptions: UseGlobalSearchOptions,\n\tqueryOptions?: Omit<UseQueryOptions<SearchResponse<T>>, \"queryKey\" | \"queryFn\">,\n) {\n\tconst client = useAdminStore(selectClient);\n\tconst { locale: contentLocale } = useScopedLocale();\n\n\tconst { query, limit = 10, highlights = true, enabled } = options;\n\n\t// Require at least 2 characters by default\n\tconst isEnabled = enabled ?? (query?.trim().length >= 2);\n\n\treturn useQuery<SearchResponse<T>>({\n\t\tqueryKey: [\n\t\t\t\"questpie\",\n\t\t\t\"global-search\",\n\t\t\tquery,\n\t\t\tlimit,\n\t\t\tcontentLocale,\n\t\t],\n\t\tqueryFn: async () => {\n\t\t\t// Search across ALL collections (no collections filter)\n\t\t\tconst response = await (client as any).search.search({\n\t\t\t\tquery,\n\t\t\t\t// collections: undefined - search all\n\t\t\t\tlocale: contentLocale,\n\t\t\t\tlimit,\n\t\t\t\thighlights,\n\t\t\t});\n\t\t\treturn response;\n\t\t},\n\t\tenabled: isEnabled,\n\t\t// Keep previous data while fetching for smoother UX\n\t\tplaceholderData: (prev) => prev,\n\t\t// Short stale time for global search\n\t\tstaleTime: 10 * 1000,\n\t\t...queryOptions,\n\t});\n}\n","/**\n * Form View - Default edit view component\n *\n * Renders collection item edit/create form with sections, tabs, validation.\n * This is the default edit view registered in the admin view registry.\n */\n\nimport {\n\tCheck,\n\tClockCounterClockwise,\n\tDotsThreeVertical,\n\tEye,\n\tSpinnerGap,\n\tWarning,\n} from \"@phosphor-icons/react\";\nimport { createQuestpieQueryOptions } from \"@questpie/tanstack-query\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { QuestpieClientError } from \"questpie/client\";\nimport * as React from \"react\";\nimport { FormProvider, useForm, useWatch } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { getDefaultFormActions } from \"../../builder/collection/action-registry\";\nimport type {\n\tActionContext,\n\tActionDefinition,\n\tActionHelpers,\n\tActionQueryClient,\n} from \"../../builder/collection/action-types\";\nimport type {\n\tCollectionBuilderState,\n\tPreviewConfig,\n} from \"../../builder/collection/types\";\nimport type {\n\tComponentRegistry,\n\tFormViewActionsConfig,\n\tFormViewConfig,\n} from \"../../builder/types/field-types\";\nimport { ActionButton } from \"../../components/actions/action-button\";\nimport { ActionDialog } from \"../../components/actions/action-dialog\";\nimport { ConfirmationDialog } from \"../../components/actions/confirmation-dialog\";\nimport { LocaleSwitcher } from \"../../components/locale-switcher\";\nimport {\n\tLivePreviewMode,\n\tuseLivePreviewContext,\n} from \"../../components/preview/live-preview-mode\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogFooter,\n\tDialogHeader,\n\tDialogTitle,\n} from \"../../components/ui/dialog\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuSeparator,\n\tDropdownMenuTrigger,\n} from \"../../components/ui/dropdown-menu\";\nimport { useCollectionValidation } from \"../../hooks\";\nimport {\n\tuseCollectionCreate,\n\tuseCollectionDelete,\n\tuseCollectionItem,\n\tuseCollectionUpdate,\n} from \"../../hooks/use-collection\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport {\n\tselectAdmin,\n\tselectBasePath,\n\tselectClient,\n\tselectNavigate,\n\tuseAdminStore,\n\tuseSafeContentLocales,\n\tuseScopedLocale,\n} from \"../../runtime\";\nimport {\n\tdetectManyToManyRelations,\n\thasManyToManyRelations,\n} from \"../../utils/detect-relations\";\nimport { wrapLocalizedNestedValues } from \"../../utils/wrap-localized\";\n\nimport { AutoFormFields } from \"./auto-form-fields\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** Query key prefix for CMS queries (used for cache invalidation) */\nconst QUERY_KEY_PREFIX = [\"questpie\", \"collections\"] as const;\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Form view configuration from registry.\n *\n * Re-exports FormViewConfig for type consistency between builder and component.\n */\nexport type FormViewRegistryConfig = FormViewConfig;\n\n/**\n * Props for FormView component\n */\nexport interface FormViewProps {\n\t/**\n\t * Collection name\n\t */\n\tcollection: string;\n\n\t/**\n\t * Item ID (undefined for create, string for edit)\n\t */\n\tid?: string;\n\n\t/**\n\t * Collection configuration from admin builder\n\t * Accepts CollectionBuilderState or any compatible config object\n\t */\n\tconfig?: Partial<CollectionBuilderState> | Record<string, any>;\n\n\t/**\n\t * View-specific configuration from registry\n\t */\n\tviewConfig?: FormViewRegistryConfig;\n\n\t/**\n\t * Navigate function for routing\n\t */\n\tnavigate: (path: string) => void;\n\n\t/**\n\t * Base path for admin routes (e.g., \"/admin\")\n\t */\n\tbasePath?: string;\n\n\t/**\n\t * Default values for create mode (from URL prefill params)\n\t */\n\tdefaultValues?: Record<string, any>;\n\n\t/**\n\t * Component registry for custom field types\n\t */\n\tregistry?: ComponentRegistry;\n\n\t/**\n\t * All collections config (for embedded collections)\n\t */\n\tallCollectionsConfig?: Record<\n\t\tstring,\n\t\tPartial<CollectionBuilderState> | Record<string, any>\n\t>;\n\n\t/**\n\t * Show metadata (ID, created/updated dates)\n\t * @default true\n\t */\n\tshowMeta?: boolean;\n\n\t/**\n\t * Custom header actions (in addition to default Save button)\n\t */\n\theaderActions?: React.ReactNode;\n\n\t/**\n\t * Callback on successful save\n\t */\n\tonSuccess?: (data: any) => void;\n\n\t/**\n\t * Callback on error\n\t */\n\tonError?: (error: Error) => void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * FormView - Default form-based edit/create view for collections\n *\n * Features:\n * - Auto-generates form fields from collection config\n * - Supports tabs, sections, and sidebar layout\n * - Auto-detects M:N relations\n * - Keyboard shortcut (Cmd+S) to save\n * - Field-level validation errors from API\n *\n * @example\n * ```tsx\n * // Used automatically via registry when navigating to /admin/collections/:name/:id\n * // Can also be used directly:\n * <FormView\n * collection=\"posts\"\n * id=\"123\"\n * config={postsConfig}\n * navigate={navigate}\n * basePath=\"/admin\"\n * />\n * ```\n */\nexport default function FormView({\n\tcollection,\n\tid,\n\tconfig,\n\tviewConfig,\n\tnavigate,\n\tbasePath = \"/admin\",\n\tdefaultValues: defaultValuesProp,\n\tregistry,\n\tallCollectionsConfig,\n\tshowMeta = true,\n\theaderActions,\n\tonSuccess,\n\tonError,\n}: FormViewProps): React.ReactElement {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst admin = useAdminStore(selectAdmin);\n\tconst isEditMode = !!id;\n\n\t// Try to get preview context (will be null if not in LivePreviewMode)\n\tconst previewContext = useLivePreviewContext();\n\n\t// Preview configuration from collection config\n\tconst previewConfig = (config as any)?.preview as PreviewConfig | undefined;\n\tconst hasPreview = !!previewConfig?.url && previewConfig?.enabled !== false;\n\n\t// Check URL for ?preview=true on mount\n\tconst [isLivePreviewOpen, setIsLivePreviewOpen] = React.useState(() => {\n\t\tif (typeof window === \"undefined\") return false;\n\t\tconst params = new URLSearchParams(window.location.search);\n\t\treturn params.get(\"preview\") === \"true\" && hasPreview;\n\t});\n\n\t// Sync preview state with URL\n\tReact.useEffect(() => {\n\t\tif (typeof window === \"undefined\") return;\n\n\t\tconst url = new URL(window.location.href);\n\t\tif (isLivePreviewOpen) {\n\t\t\turl.searchParams.set(\"preview\", \"true\");\n\t\t} else {\n\t\t\turl.searchParams.delete(\"preview\");\n\t\t}\n\n\t\t// Update URL without navigation\n\t\twindow.history.replaceState({}, \"\", url.toString());\n\t}, [isLivePreviewOpen]);\n\n\t// Auto-detect M:N relations that need to be included when fetching\n\tconst withRelations = React.useMemo(\n\t\t() => detectManyToManyRelations({ fields: config?.fields }),\n\t\t[config?.fields],\n\t);\n\n\t// Fetch item if in edit mode (include relations if specified)\n\tconst { data: item, isLoading } = useCollectionItem(\n\t\tcollection as any,\n\t\tid ?? \"\",\n\t\thasManyToManyRelations(withRelations)\n\t\t\t? { with: withRelations, localeFallback: false }\n\t\t\t: { localeFallback: false },\n\t\t{ enabled: isEditMode },\n\t);\n\n\t// Transform loaded item - convert relation arrays of objects to arrays of IDs\n\t// Backend returns: { services: [{ id: \"...\", name: \"...\" }] }\n\t// Form needs: { services: [\"id1\", \"id2\"] }\n\tconst transformedItem = React.useMemo(() => {\n\t\tif (!item || !hasManyToManyRelations(withRelations)) return item;\n\n\t\tconst result = { ...item } as any;\n\t\tfor (const key of Object.keys(withRelations)) {\n\t\t\tconst value = result[key];\n\t\t\tif (\n\t\t\t\tArray.isArray(value) &&\n\t\t\t\tvalue.length > 0 &&\n\t\t\t\ttypeof value[0] === \"object\" &&\n\t\t\t\tvalue[0]?.id\n\t\t\t) {\n\t\t\t\t// Transform array of objects to array of IDs\n\t\t\t\tresult[key] = value.map((v: any) => v.id);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}, [item, withRelations]);\n\n\t// Mutations\n\tconst createMutation = useCollectionCreate(collection as any);\n\tconst updateMutation = useCollectionUpdate(collection as any);\n\tconst deleteMutation = useCollectionDelete(collection as any);\n\n\tconst form = useForm({\n\t\tdefaultValues: (transformedItem ?? defaultValuesProp ?? {}) as any,\n\t\tresolver: useCollectionValidation(collection),\n\t});\n\n\t// Autosave state\n\tconst [isSaving, setIsSaving] = React.useState(false);\n\tconst [lastSaved, setLastSaved] = React.useState<Date | null>(null);\n\tconst autoSaveTimerRef = React.useRef<NodeJS.Timeout | null>(null);\n\n\t// Get autosave config from collection config\n\tconst autoSaveConfig = React.useMemo(() => {\n\t\tconst cfg = (config as any)?.autoSave;\n\t\tif (!cfg) return { enabled: false, debounce: 500 };\n\t\treturn {\n\t\t\tenabled: cfg.enabled !== false,\n\t\t\tdebounce: cfg.debounce ?? 500,\n\t\t\tindicator: cfg.indicator !== false,\n\t\t\tpreventNavigation: cfg.preventNavigation !== false,\n\t\t};\n\t}, [config]);\n\n\t// Track content locale changes to warn about unsaved changes\n\t// Uses scoped locale (isolated in ResourceSheet) or global locale\n\tconst {\n\t\tlocale: contentLocale,\n\t\tsetLocale: setContentLocale,\n\t\tisScoped,\n\t} = useScopedLocale();\n\tconst contentLocales = useSafeContentLocales();\n\tconst localeOptions = contentLocales?.locales ?? [];\n\tconst prevLocaleRef = React.useRef(contentLocale);\n\tconst [localeChangeDialog, setLocaleChangeDialog] = React.useState<{\n\t\topen: boolean;\n\t\tpendingLocale: string | null;\n\t}>({ open: false, pendingLocale: null });\n\tconst localeChangeSnapshotRef = React.useRef<Record<string, any> | null>(\n\t\tnull,\n\t);\n\tconst skipItemResetRef = React.useRef(false);\n\n\t// Detect locale change and show confirmation dialog if form is dirty\n\tReact.useEffect(() => {\n\t\tif (!isEditMode) {\n\t\t\tprevLocaleRef.current = contentLocale;\n\t\t\treturn;\n\t\t}\n\t\tif (prevLocaleRef.current !== contentLocale) {\n\t\t\tif (form.formState.isDirty && !localeChangeDialog.open) {\n\t\t\t\t// Store the new locale and revert to previous locale\n\t\t\t\t// The dialog will decide whether to apply or discard\n\t\t\t\tskipItemResetRef.current = true;\n\t\t\t\tlocaleChangeSnapshotRef.current = form.getValues();\n\t\t\t\tsetLocaleChangeDialog({ open: true, pendingLocale: contentLocale });\n\t\t\t\tsetContentLocale(prevLocaleRef.current);\n\t\t\t} else {\n\t\t\t\t// No dirty form, allow locale change\n\t\t\t\tprevLocaleRef.current = contentLocale;\n\t\t\t\tskipItemResetRef.current = false;\n\t\t\t}\n\t\t}\n\t}, [\n\t\tcontentLocale,\n\t\tform.formState.isDirty,\n\t\tform.getValues,\n\t\tsetContentLocale,\n\t\tlocaleChangeDialog.open,\n\t\tisEditMode,\n\t]);\n\n\t// Reset form when item loads\n\tReact.useEffect(() => {\n\t\tif (skipItemResetRef.current) return;\n\t\tif (transformedItem) {\n\t\t\tform.reset(transformedItem as any);\n\t\t} else if (defaultValuesProp) {\n\t\t\tform.reset(defaultValuesProp as any);\n\t\t}\n\t}, [form, transformedItem, defaultValuesProp]);\n\n\t// Handle locale change confirmation\n\tconst handleLocaleChangeConfirm = React.useCallback(() => {\n\t\tskipItemResetRef.current = false;\n\t\tlocaleChangeSnapshotRef.current = null;\n\t\tif (localeChangeDialog.pendingLocale) {\n\t\t\tprevLocaleRef.current = localeChangeDialog.pendingLocale;\n\t\t\tsetContentLocale(localeChangeDialog.pendingLocale);\n\t\t}\n\t\tsetLocaleChangeDialog({ open: false, pendingLocale: null });\n\t}, [localeChangeDialog.pendingLocale, setContentLocale]);\n\n\tconst handleLocaleChangeCancel = React.useCallback(() => {\n\t\tskipItemResetRef.current = false;\n\t\tif (localeChangeSnapshotRef.current) {\n\t\t\tform.reset(localeChangeSnapshotRef.current, {\n\t\t\t\tkeepDirty: true,\n\t\t\t\tkeepDirtyValues: true,\n\t\t\t\tkeepErrors: true,\n\t\t\t\tkeepTouched: true,\n\t\t\t});\n\t\t}\n\t\tlocaleChangeSnapshotRef.current = null;\n\t\tsetLocaleChangeDialog({ open: false, pendingLocale: null });\n\t}, [form]);\n\n\tconst onSubmit = React.useEffectEvent(async (data: any) => {\n\t\t// Transform nested localized values with $i18n wrappers\n\t\tconst transformedData = config?.fields\n\t\t\t? wrapLocalizedNestedValues(data, {\n\t\t\t\t\tfields: config.fields,\n\t\t\t\t\tblocks: admin.state.blocks,\n\t\t\t\t})\n\t\t\t: data;\n\n\t\tconst savePromise = async () => {\n\t\t\tif (isEditMode) {\n\t\t\t\treturn await updateMutation.mutateAsync({\n\t\t\t\t\tid: id!,\n\t\t\t\t\tdata: transformedData,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treturn await createMutation.mutateAsync(transformedData);\n\t\t\t}\n\t\t};\n\n\t\ttoast.promise(savePromise(), {\n\t\t\tloading: isEditMode ? t(\"toast.saving\") : t(\"toast.creating\"),\n\t\t\tsuccess: (result) => {\n\t\t\t\t// Call onSuccess callback if provided\n\t\t\t\tif (onSuccess) {\n\t\t\t\t\tonSuccess(result);\n\t\t\t\t} else {\n\t\t\t\t\tif (isEditMode) {\n\t\t\t\t\t\tform.reset(result as any);\n\n\t\t\t\t\t\t// Trigger preview refresh after successful save\n\t\t\t\t\t\tif (previewContext) {\n\t\t\t\t\t\t\tpreviewContext.triggerPreviewRefresh();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (result?.id) {\n\t\t\t\t\t\tnavigate(`${basePath}/collections/${collection}/${result.id}`);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnavigate(`${basePath}/collections/${collection}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn isEditMode ? t(\"toast.saveSuccess\") : t(\"toast.createSuccess\");\n\t\t\t},\n\t\t\terror: (error) => {\n\t\t\t\t// Handle field-level validation errors from the API\n\t\t\t\tif (\n\t\t\t\t\terror instanceof QuestpieClientError &&\n\t\t\t\t\terror.fieldErrors &&\n\t\t\t\t\terror.fieldErrors.length > 0\n\t\t\t\t) {\n\t\t\t\t\tfor (const fieldError of error.fieldErrors) {\n\t\t\t\t\t\tform.setError(fieldError.path as any, {\n\t\t\t\t\t\t\ttype: \"server\",\n\t\t\t\t\t\t\tmessage: fieldError.message,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn t(\"toast.validationFailed\");\n\t\t\t\t}\n\n\t\t\t\t// Handle generic errors\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : t(\"error.unknown\");\n\t\t\t\tonError?.(error instanceof Error ? error : new Error(message));\n\t\t\t\treturn `${t(\"toast.saveFailed\")}: ${message}`;\n\t\t\t},\n\t\t});\n\t});\n\n\t// Autosave logic - debounced save on form changes\n\tReact.useEffect(() => {\n\t\t// Clear existing timer\n\t\tif (autoSaveTimerRef.current) {\n\t\t\tclearTimeout(autoSaveTimerRef.current);\n\t\t}\n\n\t\t// Don't autosave if:\n\t\t// - Autosave is disabled\n\t\t// - Form is not dirty\n\t\t// - Form is already submitting\n\t\t// - Not in edit mode (don't autosave on create)\n\t\tif (\n\t\t\t!autoSaveConfig.enabled ||\n\t\t\t!form.formState.isDirty ||\n\t\t\tform.formState.isSubmitting ||\n\t\t\t!isEditMode\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Start debounce timer\n\t\tautoSaveTimerRef.current = setTimeout(async () => {\n\t\t\ttry {\n\t\t\t\tsetIsSaving(true);\n\t\t\t\tawait form.handleSubmit(async (data) => {\n\t\t\t\t\t// Transform nested localized values with $i18n wrappers\n\t\t\t\t\tconst transformedData = config?.fields\n\t\t\t\t\t\t? wrapLocalizedNestedValues(data, {\n\t\t\t\t\t\t\t\tfields: config.fields,\n\t\t\t\t\t\t\t\tblocks: admin.state.blocks,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: data;\n\n\t\t\t\t\t// Silent save (no toast)\n\t\t\t\t\tconst result = await updateMutation.mutateAsync({\n\t\t\t\t\t\tid: id!,\n\t\t\t\t\t\tdata: transformedData,\n\t\t\t\t\t});\n\n\t\t\t\t\t// Reset form to mark as not dirty\n\t\t\t\t\tform.reset(result as any);\n\n\t\t\t\t\t// Trigger preview refresh after successful save\n\t\t\t\t\tif (previewContext) {\n\t\t\t\t\t\tpreviewContext.triggerPreviewRefresh();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Update last saved timestamp\n\t\t\t\t\tsetLastSaved(new Date());\n\t\t\t\t\tsetIsSaving(false);\n\t\t\t\t})();\n\t\t\t} catch (error) {\n\t\t\t\tsetIsSaving(false);\n\t\t\t\t// Silently fail autosave (user can still manually save)\n\t\t\t\tconsole.error(\"Autosave failed:\", error);\n\t\t\t}\n\t\t}, autoSaveConfig.debounce);\n\n\t\treturn () => {\n\t\t\tif (autoSaveTimerRef.current) {\n\t\t\t\tclearTimeout(autoSaveTimerRef.current);\n\t\t\t}\n\t\t};\n\t}, [\n\t\tform.formState.isDirty,\n\t\tform.formState.isSubmitting,\n\t\tform,\n\t\tautoSaveConfig.enabled,\n\t\tautoSaveConfig.debounce,\n\t\tisEditMode,\n\t\tupdateMutation,\n\t\tconfig,\n\t\tadmin.state.blocks,\n\t\tid,\n\t\tpreviewContext,\n\t]);\n\n\t// Prevent navigation when there are unsaved changes\n\tReact.useEffect(() => {\n\t\tif (!autoSaveConfig.preventNavigation || !autoSaveConfig.enabled) return;\n\n\t\tconst handleBeforeUnload = (e: BeforeUnloadEvent) => {\n\t\t\tif (form.formState.isDirty) {\n\t\t\t\te.preventDefault();\n\t\t\t\te.returnValue = \"\";\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener(\"beforeunload\", handleBeforeUnload);\n\t\treturn () => window.removeEventListener(\"beforeunload\", handleBeforeUnload);\n\t}, [\n\t\tform.formState.isDirty,\n\t\tautoSaveConfig.preventNavigation,\n\t\tautoSaveConfig.enabled,\n\t]);\n\n\t// Keyboard shortcut: Cmd+S to save\n\tReact.useEffect(() => {\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif ((e.metaKey || e.ctrlKey) && e.key === \"s\") {\n\t\t\t\te.preventDefault();\n\t\t\t\te.stopPropagation();\n\t\t\t\tform.handleSubmit(onSubmit)();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown);\n\t\treturn () => document.removeEventListener(\"keydown\", handleKeyDown);\n\t}, [form]);\n\n\tconst isSubmitting =\n\t\tcreateMutation.isPending ||\n\t\tupdateMutation.isPending ||\n\t\tform.formState.isSubmitting;\n\n\t// ========================================================================\n\t// Form Actions\n\t// ========================================================================\n\n\t// Get form actions from config or use defaults (only for edit mode)\n\t// Form config is stored under \"~config\" by the view registry proxy\n\tconst configFormActions: FormViewActionsConfig | undefined =\n\t\t(config?.form as any)?.[\"~config\"]?.actions ||\n\t\t(config?.form as any)?.actions;\n\n\t// Use defaults if no actions defined and in edit mode\n\t// In create mode, we don't show duplicate/delete actions\n\tconst formActions: FormViewActionsConfig | undefined = React.useMemo(() => {\n\t\tif (configFormActions) return configFormActions;\n\t\tif (!isEditMode) return { primary: [], secondary: [] };\n\t\treturn getDefaultFormActions();\n\t}, [configFormActions, isEditMode]);\n\n\t// Dialog state for form actions\n\tconst [dialogAction, setDialogAction] =\n\t\tReact.useState<ActionDefinition | null>(null);\n\tconst [confirmAction, setConfirmAction] =\n\t\tReact.useState<ActionDefinition | null>(null);\n\tconst [actionLoading, setActionLoading] = React.useState(false);\n\n\t// Navigation and query client from store/hooks\n\tconst storeNavigate = useAdminStore(selectNavigate);\n\tconst storeBasePath = useAdminStore(selectBasePath);\n\tconst client = useAdminStore(selectClient);\n\tconst queryClient = useQueryClient();\n\n\t// Create query options proxy for key building (same as use-collection hooks)\n\tconst queryOpts = React.useMemo(\n\t\t() =>\n\t\t\tcreateQuestpieQueryOptions(client as any, {\n\t\t\t\tkeyPrefix: QUERY_KEY_PREFIX,\n\t\t\t\tlocale: contentLocale,\n\t\t\t}),\n\t\t[client, contentLocale],\n\t);\n\n\t// Wrapped query client for action context\n\tconst actionQueryClient: ActionQueryClient = React.useMemo(\n\t\t() => ({\n\t\t\tinvalidateQueries: (filters) => queryClient.invalidateQueries(filters),\n\t\t\trefetchQueries: (filters) => queryClient.refetchQueries(filters),\n\t\t\tresetQueries: (filters) => queryClient.resetQueries(filters),\n\t\t}),\n\t\t[queryClient],\n\t);\n\n\t// Action helpers\n\tconst actionHelpers: ActionHelpers = React.useMemo(\n\t\t() => ({\n\t\t\tnavigate: storeNavigate,\n\t\t\ttoast: {\n\t\t\t\tsuccess: toast.success,\n\t\t\t\terror: toast.error,\n\t\t\t\tinfo: toast.info,\n\t\t\t\twarning: toast.warning,\n\t\t\t},\n\t\t\tt,\n\t\t\tinvalidateCollection: async (targetCollection?: string) => {\n\t\t\t\tconst col = targetCollection || collection;\n\t\t\t\t// Invalidate list and count queries for the collection\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", col, \"find\", contentLocale]),\n\t\t\t\t});\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", col, \"count\", contentLocale]),\n\t\t\t\t});\n\t\t\t},\n\t\t\tinvalidateItem: async (itemId: string, targetCollection?: string) => {\n\t\t\t\tconst col = targetCollection || collection;\n\t\t\t\t// Invalidate findOne query for specific item\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\n\t\t\t\t\t\t\"collections\",\n\t\t\t\t\t\tcol,\n\t\t\t\t\t\t\"findOne\",\n\t\t\t\t\t\tcontentLocale,\n\t\t\t\t\t\t{ id: itemId },\n\t\t\t\t\t]),\n\t\t\t\t});\n\t\t\t\t// Also invalidate list queries since item data changed\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", col, \"find\", contentLocale]),\n\t\t\t\t});\n\t\t\t},\n\t\t\tinvalidateAll: async () => {\n\t\t\t\t// Invalidate all CMS queries\n\t\t\t\tawait queryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: [...QUERY_KEY_PREFIX],\n\t\t\t\t});\n\t\t\t},\n\t\t\trefresh: () => {\n\t\t\t\t// Invalidate current collection queries (better than page reload)\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\n\t\t\t\t\t\t\"collections\",\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\"find\",\n\t\t\t\t\t\tcontentLocale,\n\t\t\t\t\t]),\n\t\t\t\t});\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\n\t\t\t\t\t\t\"collections\",\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t\t\"count\",\n\t\t\t\t\t\tcontentLocale,\n\t\t\t\t\t]),\n\t\t\t\t});\n\t\t\t},\n\t\t\tcloseDialog: () => {\n\t\t\t\tsetDialogAction(null);\n\t\t\t\tsetConfirmAction(null);\n\t\t\t},\n\t\t\tbasePath: storeBasePath || basePath,\n\t\t}),\n\t\t[\n\t\t\tstoreNavigate,\n\t\t\tstoreBasePath,\n\t\t\tbasePath,\n\t\t\tqueryClient,\n\t\t\tqueryOpts,\n\t\t\tcollection,\n\t\t\tcontentLocale,\n\t\t\tt,\n\t\t],\n\t);\n\n\t// Action context for visibility/disabled checks\n\tconst actionContext: ActionContext = React.useMemo(\n\t\t() => ({\n\t\t\titem: transformedItem,\n\t\t\tcollection,\n\t\t\thelpers: actionHelpers,\n\t\t\tqueryClient: actionQueryClient,\n\t\t}),\n\t\t[transformedItem, collection, actionHelpers, actionQueryClient],\n\t);\n\n\t// Filter visible actions\n\tconst filterVisibleActions = React.useCallback(\n\t\t(actions: ActionDefinition[] | undefined) => {\n\t\t\tif (!actions) return [];\n\t\t\treturn actions.filter((action) => {\n\t\t\t\tif (action.visible === undefined) return true;\n\t\t\t\tif (typeof action.visible === \"function\") {\n\t\t\t\t\treturn action.visible(actionContext);\n\t\t\t\t}\n\t\t\t\treturn action.visible;\n\t\t\t});\n\t\t},\n\t\t[actionContext],\n\t);\n\n\tconst visiblePrimaryActions = React.useMemo(\n\t\t() => filterVisibleActions(formActions?.primary),\n\t\t[formActions?.primary, filterVisibleActions],\n\t);\n\n\tconst visibleSecondaryActions = React.useMemo(\n\t\t() => filterVisibleActions(formActions?.secondary),\n\t\t[formActions?.secondary, filterVisibleActions],\n\t);\n\n\t// Group secondary by variant\n\tconst regularSecondary = visibleSecondaryActions.filter(\n\t\t(a) => a.variant !== \"destructive\",\n\t);\n\tconst destructiveSecondary = visibleSecondaryActions.filter(\n\t\t(a) => a.variant === \"destructive\",\n\t);\n\n\t// Execute action\n\tconst executeAction = React.useCallback(\n\t\tasync (action: ActionDefinition) => {\n\t\t\tconst { handler } = action;\n\t\t\tconst actionLabel = resolveText(action.label, action.id);\n\n\t\t\tswitch (handler.type) {\n\t\t\t\tcase \"navigate\": {\n\t\t\t\t\tconst path =\n\t\t\t\t\t\ttypeof handler.path === \"function\"\n\t\t\t\t\t\t\t? handler.path(transformedItem)\n\t\t\t\t\t\t\t: handler.path;\n\t\t\t\t\tstoreNavigate(path);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"api\": {\n\t\t\t\t\t// For DELETE operations, use the deleteMutation hook\n\t\t\t\t\tif (handler.method === \"DELETE\") {\n\t\t\t\t\t\tconst itemId = transformedItem?.id || id;\n\t\t\t\t\t\tif (!itemId) {\n\t\t\t\t\t\t\ttoast.error(t(\"toast.deleteFailed\"));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsetActionLoading(true);\n\t\t\t\t\t\ttoast.promise(\n\t\t\t\t\t\t\tdeleteMutation.mutateAsync(itemId).finally(() => {\n\t\t\t\t\t\t\t\tsetActionLoading(false);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tloading: t(\"toast.deleting\"),\n\t\t\t\t\t\t\t\tsuccess: () => {\n\t\t\t\t\t\t\t\t\t// Navigate back to list on delete\n\t\t\t\t\t\t\t\t\tnavigate(`${basePath}/collections/${collection}`);\n\t\t\t\t\t\t\t\t\treturn t(\"toast.deleteSuccess\");\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\terror: (err) => err.message || t(\"toast.deleteFailed\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// For other API operations, make a fetch request\n\t\t\t\t\t\t// (This is a fallback - most actions should use custom handlers)\n\t\t\t\t\t\tconst endpoint = handler.endpoint.replace(\n\t\t\t\t\t\t\t\"{id}\",\n\t\t\t\t\t\t\tString(transformedItem?.id || id),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tsetActionLoading(true);\n\t\t\t\t\t\tconst apiPromise = async () => {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// Build the URL using CMS API path\n\t\t\t\t\t\t\t\tconst url = `${storeBasePath}/${collection}/${endpoint}`;\n\t\t\t\t\t\t\t\tconst response = await fetch(url, {\n\t\t\t\t\t\t\t\t\tmethod: handler.method || \"POST\",\n\t\t\t\t\t\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\t\t\t\t\t\tbody: handler.body\n\t\t\t\t\t\t\t\t\t\t? JSON.stringify(handler.body(actionContext))\n\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tif (!response.ok) {\n\t\t\t\t\t\t\t\t\tconst error = await response.json().catch(() => ({}));\n\t\t\t\t\t\t\t\t\tthrow new Error(error.message || t(\"toast.actionFailed\"));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn response.json();\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tsetActionLoading(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\ttoast.promise(apiPromise(), {\n\t\t\t\t\t\t\tloading: `${actionLabel}...`,\n\t\t\t\t\t\t\tsuccess: t(\"toast.actionSuccess\"),\n\t\t\t\t\t\t\terror: (err) => err.message || t(\"toast.actionFailed\"),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"custom\": {\n\t\t\t\t\tconst customPromise = handler.fn(actionContext);\n\t\t\t\t\t// Only use toast.promise if it returns a promise\n\t\t\t\t\tif (customPromise instanceof Promise) {\n\t\t\t\t\t\tsetActionLoading(true);\n\t\t\t\t\t\ttoast.promise(\n\t\t\t\t\t\t\tcustomPromise.finally(() => setActionLoading(false)),\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tloading: `${actionLabel}...`,\n\t\t\t\t\t\t\t\tsuccess: t(\"toast.actionSuccess\"),\n\t\t\t\t\t\t\t\terror: (err) => err.message || t(\"toast.actionFailed\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsetConfirmAction(null);\n\t\t},\n\t\t[\n\t\t\ttransformedItem,\n\t\t\tid,\n\t\t\tactionContext,\n\t\t\tstoreNavigate,\n\t\t\tstoreBasePath,\n\t\t\tdeleteMutation,\n\t\t\tcollection,\n\t\t\tbasePath,\n\t\t\tnavigate,\n\t\t\tt,\n\t\t\tresolveText,\n\t\t],\n\t);\n\n\t// Handle action click\n\tconst handleActionClick = React.useCallback(\n\t\t(action: ActionDefinition) => {\n\t\t\tif (action.confirmation) {\n\t\t\t\tsetConfirmAction(action);\n\t\t\t} else if (\n\t\t\t\taction.handler.type === \"dialog\" ||\n\t\t\t\taction.handler.type === \"form\"\n\t\t\t) {\n\t\t\t\tsetDialogAction(action);\n\t\t\t} else {\n\t\t\t\t// Execute immediately\n\t\t\t\texecuteAction(action);\n\t\t\t}\n\t\t},\n\t\t[executeAction],\n\t);\n\n\t// Handle confirmation\n\tconst handleConfirm = React.useCallback(async () => {\n\t\tif (confirmAction) {\n\t\t\tawait executeAction(confirmAction);\n\t\t}\n\t}, [confirmAction, executeAction]);\n\n\t// Format date helper\n\tconst formatDate = (date: string | Date) => {\n\t\treturn new Date(date).toLocaleDateString(undefined, {\n\t\t\tyear: \"numeric\",\n\t\t\tmonth: \"short\",\n\t\t\tday: \"numeric\",\n\t\t\thour: \"2-digit\",\n\t\t\tminute: \"2-digit\",\n\t\t});\n\t};\n\n\t// Format time ago helper\n\tconst formatTimeAgo = (date: Date) => {\n\t\tconst seconds = Math.floor((Date.now() - date.getTime()) / 1000);\n\t\tif (seconds < 10) return t(\"autosave.justNow\");\n\t\tif (seconds < 60) return t(\"autosave.secondsAgo\", { count: seconds });\n\t\tconst minutes = Math.floor(seconds / 60);\n\t\tif (minutes < 60) return t(\"autosave.minutesAgo\", { count: minutes });\n\t\tconst hours = Math.floor(minutes / 60);\n\t\treturn t(\"autosave.hoursAgo\", { count: hours });\n\t};\n\n\t// Re-render every 10 seconds to update \"time ago\" display\n\tconst [, forceUpdate] = React.useReducer((x) => x + 1, 0);\n\tReact.useEffect(() => {\n\t\tif (!lastSaved || !autoSaveConfig.indicator) return;\n\t\tconst interval = setInterval(forceUpdate, 10000);\n\t\treturn () => clearInterval(interval);\n\t}, [lastSaved, autoSaveConfig.indicator]);\n\n\t// Watch form values for preview updates\n\t// Using useWatch hook (React way) instead of form.watch() method\n\t// This is more performant as it's a proper React subscription\n\tconst watchedValues = useWatch({ control: form.control });\n\n\t// Generate preview URL (must be after useWatch for reactive updates)\n\t// Compute preview URL for LivePreviewMode\n\tconst previewUrl = React.useMemo(() => {\n\t\tif (!hasPreview || !previewConfig?.url) return null;\n\t\ttry {\n\t\t\t// Use watched values (reactive) instead of form.getValues() (non-reactive)\n\t\t\tconst formValues = (watchedValues ?? {}) as Record<string, any>;\n\t\t\treturn previewConfig.url(formValues, contentLocale);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}, [hasPreview, previewConfig, watchedValues, contentLocale]);\n\n\tif (isEditMode && isLoading) {\n\t\treturn (\n\t\t\t<div className=\"w-full\">\n\t\t\t\t<div className=\"flex h-64 items-center justify-center text-muted-foreground\">\n\t\t\t\t\t<SpinnerGap className=\"size-6 animate-spin\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst collectionLabel = resolveText(config?.label, collection);\n\t// In edit mode, show item's _title; in new mode, show \"New {collection}\"\n\tconst title = isEditMode\n\t\t? (item as any)?._title ||\n\t\t\titem?.id ||\n\t\t\tt(\"collection.edit\", { name: collectionLabel })\n\t\t: t(\"collection.new\", { name: collectionLabel });\n\n\t// Form content - extracted for reuse in both layouts\n\tconst formContent = (\n\t\t<>\n\t\t\t<FormProvider {...form}>\n\t\t\t\t<form\n\t\t\t\t\tonSubmit={(e) => {\n\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\tform.handleSubmit(onSubmit)(e);\n\t\t\t\t\t}}\n\t\t\t\t\tclassName=\"space-y-4\"\n\t\t\t\t>\n\t\t\t\t\t{/* Header - Title, Meta & Actions */}\n\t\t\t\t\t<div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n\t\t\t\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-3 flex-wrap\">\n\t\t\t\t\t\t\t\t<h1 className=\"text-2xl md:text-3xl font-extrabold tracking-tight truncate\">\n\t\t\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t\t\t</h1>\n\t\t\t\t\t\t\t\t{localeOptions.length > 0 && (\n\t\t\t\t\t\t\t\t\t<LocaleSwitcher\n\t\t\t\t\t\t\t\t\t\tlocales={localeOptions}\n\t\t\t\t\t\t\t\t\t\tvalue={contentLocale}\n\t\t\t\t\t\t\t\t\t\tonChange={setContentLocale}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{/* Autosave status indicator */}\n\t\t\t\t\t\t\t\t{autoSaveConfig.indicator &&\n\t\t\t\t\t\t\t\t\tautoSaveConfig.enabled &&\n\t\t\t\t\t\t\t\t\tisEditMode && (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t{isSaving && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Badge variant=\"secondary\" className=\"gap-1.5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<SpinnerGap className=\"size-3 animate-spin\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"autosave.saving\")}\n\t\t\t\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t{!isSaving && form.formState.isDirty && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Badge variant=\"outline\" className=\"gap-1.5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ClockCounterClockwise className=\"size-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"autosave.unsavedChanges\")}\n\t\t\t\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t{!isSaving && !form.formState.isDirty && lastSaved && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"gap-1.5 text-muted-foreground\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Check className=\"size-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"autosave.saved\")} {formatTimeAgo(lastSaved)}\n\t\t\t\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{/* Metadata - horizontal scroll on mobile */}\n\t\t\t\t\t\t\t{showMeta && item && (\n\t\t\t\t\t\t\t\t<div className=\"mt-1 overflow-x-auto no-scrollbar\">\n\t\t\t\t\t\t\t\t\t<p className=\"text-xs text-muted-foreground font-mono flex items-center gap-2 whitespace-nowrap\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"opacity-60\">{t(\"form.id\")}:</span>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"hover:text-foreground transition-colors cursor-pointer\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tnavigator.clipboard.writeText(String(item.id)).then(\n\t\t\t\t\t\t\t\t\t\t\t\t\t() => toast.success(t(\"toast.idCopied\")),\n\t\t\t\t\t\t\t\t\t\t\t\t\t() => toast.error(t(\"toast.copyFailed\")),\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\ttitle={t(\"common.copy\")}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{item.id}\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t{item.createdAt && (\n\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"opacity-40\">·</span>\n\t\t\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"opacity-60\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"form.created\")}{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{formatDate(item.createdAt)}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{item.updatedAt && (\n\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"opacity-40\">·</span>\n\t\t\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"opacity-60\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"form.updated\")}{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{formatDate(item.updatedAt)}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div className=\"flex items-center gap-2 shrink-0 w-auto\">\n\t\t\t\t\t\t\t{headerActions}\n\n\t\t\t\t\t\t\t{/* Live Preview button */}\n\t\t\t\t\t\t\t{hasPreview && (\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\tclassName=\"size-9\"\n\t\t\t\t\t\t\t\t\tonClick={() => setIsLivePreviewOpen(true)}\n\t\t\t\t\t\t\t\t\ttitle={t(\"preview.livePreview\")}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Eye className=\"size-4\" />\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">{t(\"preview.livePreview\")}</span>\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Primary form actions as buttons */}\n\t\t\t\t\t\t\t{visiblePrimaryActions.map((action) => (\n\t\t\t\t\t\t\t\t<ActionButton\n\t\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\t\taction={action}\n\t\t\t\t\t\t\t\t\tcollection={collection}\n\t\t\t\t\t\t\t\t\thelpers={actionHelpers}\n\t\t\t\t\t\t\t\t\tonOpenDialog={(a) => setDialogAction(a)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t\t{/* Save button */}\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tdisabled={isSubmitting || !form.formState.isDirty}\n\t\t\t\t\t\t\t\tclassName=\"gap-2\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isSubmitting ? (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<SpinnerGap className=\"size-4 animate-spin\" />\n\t\t\t\t\t\t\t\t\t\t{t(\"common.loading\")}\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<Check size={16} />\n\t\t\t\t\t\t\t\t\t\t{t(\"common.save\")}\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t{/* Secondary form actions in dropdown */}\n\t\t\t\t\t\t\t{visibleSecondaryActions.length > 0 && (\n\t\t\t\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t\t\t\t<DropdownMenuTrigger\n\t\t\t\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"size-9\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<DotsThreeVertical className=\"size-4\" />\n\t\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">{t(\"common.moreActions\")}</span>\n\t\t\t\t\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t\t\t\t\t<DropdownMenuContent align=\"end\">\n\t\t\t\t\t\t\t\t\t\t{regularSecondary.map((action) => {\n\t\t\t\t\t\t\t\t\t\t\tconst Icon = action.icon as\n\t\t\t\t\t\t\t\t\t\t\t\t| React.ComponentType<React.SVGProps<SVGSVGElement>>\n\t\t\t\t\t\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleActionClick(action)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={actionLoading}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{Icon && <Icon className=\"mr-2 size-4\" />}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{resolveText(action.label)}\n\t\t\t\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t})}\n\n\t\t\t\t\t\t\t\t\t\t{regularSecondary.length > 0 &&\n\t\t\t\t\t\t\t\t\t\t\tdestructiveSecondary.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{destructiveSecondary.map((action) => {\n\t\t\t\t\t\t\t\t\t\t\tconst Icon = action.icon as\n\t\t\t\t\t\t\t\t\t\t\t\t| React.ComponentType<React.SVGProps<SVGSVGElement>>\n\t\t\t\t\t\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"destructive\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleActionClick(action)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={actionLoading}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{Icon && <Icon className=\"mr-2 size-4\" />}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{resolveText(action.label)}\n\t\t\t\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t\t\t\t</DropdownMenu>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Main Content - Form Fields */}\n\t\t\t\t\t<AutoFormFields\n\t\t\t\t\t\tcollection={collection as any}\n\t\t\t\t\t\tconfig={config}\n\t\t\t\t\t\tregistry={registry}\n\t\t\t\t\t\tallCollectionsConfig={allCollectionsConfig}\n\t\t\t\t\t/>\n\t\t\t\t</form>\n\t\t\t</FormProvider>\n\n\t\t\t{/* Locale Change Confirmation Dialog */}\n\t\t\t<Dialog\n\t\t\t\topen={localeChangeDialog.open}\n\t\t\t\tonOpenChange={(open) => {\n\t\t\t\t\tif (!open) handleLocaleChangeCancel();\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<DialogContent showCloseButton={false}>\n\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t<DialogTitle className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<Warning className=\"size-5 text-amber-500\" weight=\"fill\" />\n\t\t\t\t\t\t\t{t(\"confirm.localeChange\")}\n\t\t\t\t\t\t</DialogTitle>\n\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t{t(\"confirm.localeChangeDescription\")}\n\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t</DialogHeader>\n\t\t\t\t\t<DialogFooter>\n\t\t\t\t\t\t<Button variant=\"outline\" onClick={handleLocaleChangeCancel}>\n\t\t\t\t\t\t\t{t(\"confirm.localeChangeStay\")}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t<Button variant=\"destructive\" onClick={handleLocaleChangeConfirm}>\n\t\t\t\t\t\t\t{t(\"confirm.localeChangeDiscard\")}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</DialogFooter>\n\t\t\t\t</DialogContent>\n\t\t\t</Dialog>\n\n\t\t\t{/* Action Confirmation Dialog */}\n\t\t\t{confirmAction?.confirmation && (\n\t\t\t\t<ConfirmationDialog\n\t\t\t\t\topen={!!confirmAction}\n\t\t\t\t\tonOpenChange={(open) => !open && setConfirmAction(null)}\n\t\t\t\t\tconfig={confirmAction.confirmation}\n\t\t\t\t\tonConfirm={handleConfirm}\n\t\t\t\t\tloading={actionLoading}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Action Dialog (for form/dialog handlers) */}\n\t\t\t{dialogAction && (\n\t\t\t\t<ActionDialog\n\t\t\t\t\topen={!!dialogAction}\n\t\t\t\t\tonOpenChange={(open) => !open && setDialogAction(null)}\n\t\t\t\t\taction={dialogAction}\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\titem={transformedItem}\n\t\t\t\t\thelpers={actionHelpers}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"w-full\">{formContent}</div>\n\n\t\t\t{/* Live Preview Mode */}\n\t\t\t{hasPreview && previewUrl && (\n\t\t\t\t<LivePreviewMode\n\t\t\t\t\topen={isLivePreviewOpen}\n\t\t\t\t\tonClose={() => setIsLivePreviewOpen(false)}\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\titemId={id}\n\t\t\t\t\tconfig={config}\n\t\t\t\t\tallCollectionsConfig={allCollectionsConfig}\n\t\t\t\t\tregistry={registry}\n\t\t\t\t\tpreviewUrl={previewUrl}\n\t\t\t\t\tonSuccess={onSuccess}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","/**\n * Global Form View - Default edit view component for globals\n *\n * Mirrors FormView for collections but adapted for singleton globals.\n * Renders global settings form with sections, tabs, sidebar, validation.\n */\n\nimport { Check, SpinnerGap } from \"@phosphor-icons/react\";\nimport { QuestpieClientError } from \"questpie/client\";\nimport * as React from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport type { GlobalBuilderState } from \"../../builder/global/types\";\nimport type { ComponentRegistry } from \"../../builder/types/field-types\";\nimport { LocaleSwitcher } from \"../../components/locale-switcher\";\nimport { Button } from \"../../components/ui/button\";\nimport { useGlobal, useGlobalUpdate } from \"../../hooks/use-global\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport {\n\tselectAdmin,\n\tuseAdminStore,\n\tuseSafeContentLocales,\n\tuseScopedLocale,\n} from \"../../runtime\";\nimport { wrapLocalizedNestedValues } from \"../../utils/wrap-localized\";\nimport { AutoFormFields } from \"../collection/auto-form-fields\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Props for GlobalFormView component\n */\nexport interface GlobalFormViewProps {\n\t/**\n\t * Global name\n\t */\n\tglobal: string;\n\n\t/**\n\t * Global configuration from admin builder\n\t * Accepts GlobalBuilderState or any compatible config object\n\t */\n\tconfig?: Partial<GlobalBuilderState> | Record<string, any>;\n\n\t/**\n\t * Navigate function for routing\n\t */\n\tnavigate: (path: string) => void;\n\n\t/**\n\t * Base path for admin routes (e.g., \"/admin\")\n\t */\n\tbasePath?: string;\n\n\t/**\n\t * Component registry for custom field types\n\t */\n\tregistry?: ComponentRegistry;\n\n\t/**\n\t * All globals config (for potential cross-references)\n\t */\n\tallGlobalsConfig?: Record<\n\t\tstring,\n\t\tPartial<GlobalBuilderState> | Record<string, any>\n\t>;\n\n\t/**\n\t * Show metadata (updated dates)\n\t * @default true\n\t */\n\tshowMeta?: boolean;\n\n\t/**\n\t * Custom header actions (in addition to default Save button)\n\t */\n\theaderActions?: React.ReactNode;\n\n\t/**\n\t * Callback on successful save\n\t */\n\tonSuccess?: (data: any) => void;\n\n\t/**\n\t * Callback on error\n\t */\n\tonError?: (error: Error) => void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * GlobalFormView - Default form-based edit view for globals\n *\n * Features:\n * - Auto-generates form fields from global config\n * - Supports tabs, sections, and sidebar layout\n * - Keyboard shortcut (Cmd+S) to save\n * - Field-level validation errors from API\n * - Same layout and UX as collection FormView\n *\n * @example\n * ```tsx\n * // Used automatically via router when navigating to /admin/globals/:name\n * // Can also be used directly:\n * <GlobalFormView\n * global=\"siteSettings\"\n * config={siteSettingsConfig}\n * navigate={navigate}\n * basePath=\"/admin\"\n * />\n * ```\n */\nexport default function GlobalFormView({\n\tglobal: globalName,\n\tconfig,\n\tnavigate,\n\tbasePath = \"/admin\",\n\tregistry,\n\tallGlobalsConfig,\n\tshowMeta = true,\n\theaderActions,\n\tonSuccess,\n\tonError,\n}: GlobalFormViewProps): React.ReactElement {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst admin = useAdminStore(selectAdmin);\n\tconst { locale: contentLocale, setLocale: setContentLocale } =\n\t\tuseScopedLocale();\n\tconst contentLocales = useSafeContentLocales();\n\tconst localeOptions = contentLocales?.locales ?? [];\n\n\t// Fetch global data\n\tconst {\n\t\tdata: globalData,\n\t\tisLoading,\n\t\terror: fetchError,\n\t} = useGlobal(globalName, { localeFallback: false });\n\n\t// Update mutation\n\tconst updateMutation = useGlobalUpdate(globalName, {\n\t\tonSuccess: (data) => {\n\t\t\ttoast.success(t(\"toast.saveSuccess\"));\n\t\t\tonSuccess?.(data);\n\t\t},\n\t\tonError: (error) => {\n\t\t\tonError?.(error);\n\t\t},\n\t});\n\n\tconst form = useForm({\n\t\tdefaultValues: (globalData ?? {}) as any,\n\t});\n\n\t// Reset form when data loads\n\tReact.useEffect(() => {\n\t\tif (globalData) {\n\t\t\tform.reset(globalData as any);\n\t\t}\n\t}, [form, globalData]);\n\n\tconst onSubmit = React.useCallback(\n\t\tasync (data: any) => {\n\t\t\t// Transform nested localized values with $i18n wrappers\n\t\t\tconst transformedData = config?.fields\n\t\t\t\t? wrapLocalizedNestedValues(data, {\n\t\t\t\t\t\tfields: config.fields,\n\t\t\t\t\t\tblocks: admin.state.blocks,\n\t\t\t\t\t})\n\t\t\t\t: data;\n\n\t\t\ttry {\n\t\t\t\tconst result = await updateMutation.mutateAsync({\n\t\t\t\t\tdata: transformedData,\n\t\t\t\t});\n\t\t\t\tif (result) {\n\t\t\t\t\tform.reset(result as any);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// Handle field-level validation errors from the API\n\t\t\t\tif (\n\t\t\t\t\terror instanceof QuestpieClientError &&\n\t\t\t\t\terror.fieldErrors &&\n\t\t\t\t\terror.fieldErrors.length > 0\n\t\t\t\t) {\n\t\t\t\t\tfor (const fieldError of error.fieldErrors) {\n\t\t\t\t\t\tform.setError(fieldError.path as any, {\n\t\t\t\t\t\t\ttype: \"server\",\n\t\t\t\t\t\t\tmessage: fieldError.message,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\ttoast.error(t(\"toast.validationFailed\"), {\n\t\t\t\t\t\tdescription: t(\"toast.validationDescription\"),\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Handle generic errors\n\t\t\t\tconst message =\n\t\t\t\t\terror instanceof Error ? error.message : t(\"error.unknown\");\n\t\t\t\ttoast.error(\n\t\t\t\t\tt(\"toast.settingsSaveFailed\") || \"Failed to save settings\",\n\t\t\t\t\t{\n\t\t\t\t\t\tdescription: message,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[updateMutation, form, t, config?.fields, admin.state.blocks],\n\t);\n\n\t// Keyboard shortcut: Cmd+S to save\n\tReact.useEffect(() => {\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif ((e.metaKey || e.ctrlKey) && e.key === \"s\") {\n\t\t\t\te.preventDefault();\n\t\t\t\tform.handleSubmit(onSubmit)();\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown);\n\t\treturn () => document.removeEventListener(\"keydown\", handleKeyDown);\n\t}, [form, onSubmit]);\n\n\tconst isSubmitting = updateMutation.isPending || form.formState.isSubmitting;\n\n\t// Format date helper\n\tconst formatDate = (date: string | Date) => {\n\t\treturn new Date(date).toLocaleDateString(undefined, {\n\t\t\tyear: \"numeric\",\n\t\t\tmonth: \"short\",\n\t\t\tday: \"numeric\",\n\t\t\thour: \"2-digit\",\n\t\t\tminute: \"2-digit\",\n\t\t});\n\t};\n\n\tif (isLoading) {\n\t\treturn (\n\t\t\t<div className=\"w-full\">\n\t\t\t\t<div className=\"flex h-64 items-center justify-center text-muted-foreground\">\n\t\t\t\t\t<SpinnerGap className=\"size-6 animate-spin\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (fetchError) {\n\t\treturn (\n\t\t\t<div className=\"w-full\">\n\t\t\t\t<div className=\"rounded-lg border border-destructive/20 bg-destructive/5 p-6\">\n\t\t\t\t\t<h2 className=\"text-lg font-semibold text-destructive\">\n\t\t\t\t\t\t{t(\"toast.loadFailed\")}\n\t\t\t\t\t</h2>\n\t\t\t\t\t<p className=\"mt-2 text-sm text-muted-foreground\">\n\t\t\t\t\t\t{fetchError.message}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst title = resolveText(config?.label, globalName);\n\tconst description = resolveText(config?.description);\n\n\treturn (\n\t\t<div className=\"w-full\">\n\t\t\t<FormProvider {...form}>\n\t\t\t\t<form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\n\t\t\t\t\t{/* Header - Title, Meta & Actions */}\n\t\t\t\t\t<div className=\"flex items-start justify-between\">\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-3 flex-wrap\">\n\t\t\t\t\t\t\t\t<h1 className=\"text-2xl md:text-3xl font-extrabold tracking-tight\">\n\t\t\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t\t\t</h1>\n\t\t\t\t\t\t\t\t{localeOptions.length > 0 && (\n\t\t\t\t\t\t\t\t\t<LocaleSwitcher\n\t\t\t\t\t\t\t\t\t\tlocales={localeOptions}\n\t\t\t\t\t\t\t\t\t\tvalue={contentLocale}\n\t\t\t\t\t\t\t\t\t\tonChange={setContentLocale}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{description && (\n\t\t\t\t\t\t\t\t<p className=\"mt-1 text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{/* Metadata - inline below title */}\n\t\t\t\t\t\t\t{showMeta && globalData && (\n\t\t\t\t\t\t\t\t<p className=\"mt-1 text-xs text-muted-foreground font-mono flex items-center gap-2 flex-wrap\">\n\t\t\t\t\t\t\t\t\t{(globalData as any).createdAt && (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"opacity-60\">{t(\"form.created\")} </span>\n\t\t\t\t\t\t\t\t\t\t\t<span>{formatDate((globalData as any).createdAt)}</span>\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t{(globalData as any).updatedAt && (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"opacity-40\">·</span>\n\t\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"opacity-60\">{t(\"form.updated\")} </span>\n\t\t\t\t\t\t\t\t\t\t\t\t{formatDate((globalData as any).updatedAt)}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t{headerActions}\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tdisabled={isSubmitting || !form.formState.isDirty}\n\t\t\t\t\t\t\t\tclassName=\"gap-2\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{isSubmitting ? (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<SpinnerGap className=\"size-4 animate-spin\" />\n\t\t\t\t\t\t\t\t\t\t{t(\"common.loading\")}\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<Check size={16} />\n\t\t\t\t\t\t\t\t\t\t{t(\"common.save\")}\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Main Content - Form Fields */}\n\t\t\t\t\t<AutoFormFields\n\t\t\t\t\t\tcollection={globalName as any}\n\t\t\t\t\t\tconfig={config as any}\n\t\t\t\t\t\tregistry={registry}\n\t\t\t\t\t\tallCollectionsConfig={allGlobalsConfig as any}\n\t\t\t\t\t/>\n\t\t\t\t</form>\n\t\t\t</FormProvider>\n\t\t</div>\n\t);\n}\n","/**\n * ResourceSheet Component\n *\n * Universal sheet component for viewing/editing collections and globals.\n * Uses FormView/GlobalFormView internally for consistent UI and behavior.\n * Container queries provide automatic responsive layout.\n *\n * @example\n * ```tsx\n * // Collection usage\n * <ResourceSheet\n * type=\"collection\"\n * collection=\"posts\"\n * itemId=\"123\"\n * open={isOpen}\n * onOpenChange={setIsOpen}\n * onSave={(data) => console.log('Saved:', data)}\n * />\n *\n * // Global usage\n * <ResourceSheet\n * type=\"global\"\n * global=\"siteSettings\"\n * open={isOpen}\n * onOpenChange={setIsOpen}\n * onSave={(data) => console.log('Saved:', data)}\n * />\n * ```\n */\n\nimport * as React from \"react\";\nimport {\n\tLocaleScopeProvider,\n\tselectAdmin,\n\tselectBasePath,\n\tselectNavigate,\n\tuseAdminStore,\n} from \"../../runtime\";\nimport FormView from \"../../views/collection/form-view\";\nimport GlobalFormView from \"../../views/globals/global-form-view\";\nimport { Sheet, SheetContent } from \"../ui/sheet\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Base props shared between collection and global sheets\n */\ninterface ResourceSheetBaseProps {\n\t/**\n\t * Is sheet open\n\t */\n\topen: boolean;\n\n\t/**\n\t * Callback when sheet open state changes\n\t */\n\tonOpenChange: (open: boolean) => void;\n\n\t/**\n\t * Callback after successful save\n\t * Receives the saved data\n\t */\n\tonSave?: (data: any) => void;\n\n\t/**\n\t * Side of the screen where sheet appears\n\t * @default \"right\"\n\t */\n\tside?: \"top\" | \"right\" | \"bottom\" | \"left\";\n}\n\n/**\n * Props for collection resource type\n */\ninterface CollectionSheetProps extends ResourceSheetBaseProps {\n\ttype: \"collection\";\n\n\t/**\n\t * Collection name\n\t */\n\tcollection: string;\n\n\t/**\n\t * Item ID (undefined for create, string for edit)\n\t */\n\titemId?: string;\n\n\t/**\n\t * Default values for create mode (prefill)\n\t * Useful for pre-populating relation fields when creating from a parent context\n\t */\n\tdefaultValues?: Record<string, any>;\n}\n\n/**\n * Props for global resource type\n */\ninterface GlobalSheetProps extends ResourceSheetBaseProps {\n\ttype: \"global\";\n\n\t/**\n\t * Global name\n\t */\n\tglobal: string;\n}\n\n/**\n * Discriminated union of all resource sheet props\n */\nexport type ResourceSheetProps = CollectionSheetProps | GlobalSheetProps;\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function ResourceSheet(props: ResourceSheetProps) {\n\tconst { open, onOpenChange, onSave, side = \"right\" } = props;\n\tconst navigate = useAdminStore(selectNavigate);\n\tconst basePath = useAdminStore(selectBasePath);\n\tconst admin = useAdminStore(selectAdmin);\n\n\tconst handleSuccess = React.useCallback(\n\t\t(data: any) => {\n\t\t\tonSave?.(data);\n\t\t\tonOpenChange(false);\n\t\t},\n\t\t[onSave, onOpenChange],\n\t);\n\n\treturn (\n\t\t<Sheet open={open} onOpenChange={onOpenChange}>\n\t\t\t<SheetContent side={side} className=\"overflow-y-auto p-6 pt-12\">\n\t\t\t\t{/* LocaleScopeProvider isolates locale changes in nested forms */}\n\t\t\t\t<LocaleScopeProvider>\n\t\t\t\t\t{props.type === \"collection\" ? (\n\t\t\t\t\t\t<FormView\n\t\t\t\t\t\t\tcollection={props.collection}\n\t\t\t\t\t\t\tid={props.itemId}\n\t\t\t\t\t\t\tdefaultValues={props.defaultValues}\n\t\t\t\t\t\t\tconfig={admin?.getCollectionConfig(props.collection)}\n\t\t\t\t\t\t\tallCollectionsConfig={admin?.getCollections()}\n\t\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\t\tonSuccess={handleSuccess}\n\t\t\t\t\t\t\tshowMeta={false}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<GlobalFormView\n\t\t\t\t\t\t\tglobal={props.global}\n\t\t\t\t\t\t\tconfig={admin?.getGlobalConfig(props.global)}\n\t\t\t\t\t\t\tallGlobalsConfig={admin?.getGlobals()}\n\t\t\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\t\tonSuccess={handleSuccess}\n\t\t\t\t\t\t\tshowMeta={false}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</LocaleScopeProvider>\n\t\t\t</SheetContent>\n\t\t</Sheet>\n\t);\n}\n","/**\n * RelationChip Component\n *\n * Clickable chip for displaying relation items.\n * Extracted from RelationCell to eliminate duplication.\n * Used by RelationCell and ReverseRelationCell.\n */\n\nimport type * as React from \"react\";\nimport { useResolveText } from \"../../../../i18n/hooks\";\nimport { cn } from \"../../../../lib/utils\";\nimport { getRelationItemId, getRelationItemLabel } from \"./cell-helpers\";\n\nexport interface RelationChipProps {\n\t/**\n\t * Relation item (object with id, name, title, etc.)\n\t */\n\titem: unknown;\n\n\t/**\n\t * Target collection name for navigation\n\t */\n\ttargetCollection?: string;\n\n\t/**\n\t * Click handler (if provided, prevents default navigation)\n\t * Receives item ID and collection name\n\t */\n\tonClick?: (itemId: string, collection: string) => void;\n}\n\n/**\n * Clickable relation chip component\n * Shows label and navigates to related item on click (or opens sheet if onClick provided)\n */\nexport function RelationChip({\n\titem,\n\ttargetCollection,\n\tonClick,\n}: RelationChipProps) {\n\tconst resolveText = useResolveText();\n\tconst label = resolveText(getRelationItemLabel(item));\n\tconst id = getRelationItemId(item);\n\tconst canInteract = targetCollection && id;\n\n\tconst handleClick = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tif (onClick && id && targetCollection) {\n\t\t\te.preventDefault();\n\t\t\tonClick(id, targetCollection);\n\t\t}\n\t};\n\n\tif (canInteract) {\n\t\tconst href = `/admin/collections/${targetCollection}/${id}`;\n\t\tconst chipClassName = cn(\n\t\t\t\"inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs\",\n\t\t\t\"bg-primary/10 text-primary hover:bg-primary/20\",\n\t\t\t\"transition-colors cursor-pointer\",\n\t\t\t\"border border-primary/20 hover:border-primary/40\",\n\t\t);\n\n\t\t// If onClick provided, use button-like behavior but keep href for accessibility\n\t\treturn (\n\t\t\t<a\n\t\t\t\thref={href}\n\t\t\t\tonClick={handleClick}\n\t\t\t\tonPointerDown={(e) => e.stopPropagation()}\n\t\t\t\tclassName={chipClassName}\n\t\t\t>\n\t\t\t\t{label}\n\t\t\t</a>\n\t\t);\n\t}\n\n\t// Non-clickable chip (no target collection or id)\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs\",\n\t\t\t\t\"bg-muted text-muted-foreground\",\n\t\t\t\t\"border border-border\",\n\t\t\t)}\n\t\t>\n\t\t\t{label}\n\t\t</span>\n\t);\n}\n","/**\n * Relation Cell Components\n *\n * Cells for displaying relation fields:\n * - RelationCell - forward relations (belongs-to, has-one, has-many)\n * - ReverseRelationCell - reverse relations (computed from other collections)\n */\n\nimport * as React from \"react\";\nimport type { FieldDefinition } from \"../../../builder/field/field\";\nimport { ResourceSheet } from \"../../../components/sheets\";\nimport { Badge } from \"../../../components/ui/badge\";\nimport {\n\tTooltip,\n\tTooltipContent,\n\tTooltipTrigger,\n} from \"../../../components/ui/tooltip\";\nimport { useResolveText } from \"../../../i18n/hooks\";\nimport { cn } from \"../../../lib/utils\";\nimport { getRelationItemId, getRelationItemLabel } from \"./shared/cell-helpers\";\nimport { RelationChip } from \"./shared/relation-chip\";\n\n// ============================================================================\n// Relation Cell\n// ============================================================================\n\n/**\n * Relation cell - displays relation as clickable chips\n * Supports both single relations and arrays\n * Opens detail sheet on click\n */\nexport function RelationCell({\n\tvalue,\n\tfieldDef,\n}: {\n\tvalue: unknown;\n\trow?: unknown;\n\tfieldDef?: FieldDefinition;\n}) {\n\tconst resolveText = useResolveText();\n\tconst targetCollection = fieldDef?.[\"~options\"]?.targetCollection as\n\t\t| string\n\t\t| undefined;\n\n\t// Sheet state\n\tconst [sheetOpen, setSheetOpen] = React.useState(false);\n\tconst [sheetItemId, setSheetItemId] = React.useState<string | undefined>();\n\tconst [sheetCollection, setSheetCollection] = React.useState<\n\t\tstring | undefined\n\t>();\n\n\tconst handleChipClick = React.useCallback(\n\t\t(itemId: string, collection: string) => {\n\t\t\tsetSheetItemId(itemId);\n\t\t\tsetSheetCollection(collection);\n\t\t\tsetSheetOpen(true);\n\t\t},\n\t\t[],\n\t);\n\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\t// Handle array of relations (multiple)\n\tif (Array.isArray(value)) {\n\t\tif (value.length === 0) {\n\t\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t\t}\n\n\t\tconst visibleItems = value.slice(0, 3);\n\t\tconst remainingCount = value.length - 3;\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<Tooltip>\n\t\t\t\t\t<TooltipTrigger\n\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t<span className=\"inline-flex flex-wrap items-center gap-1 max-w-[250px]\">\n\t\t\t\t\t\t\t\t{visibleItems.map((item, idx) => (\n\t\t\t\t\t\t\t\t\t<RelationChip\n\t\t\t\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: stable array from backend\n\t\t\t\t\t\t\t\t\t\tkey={idx}\n\t\t\t\t\t\t\t\t\t\titem={item}\n\t\t\t\t\t\t\t\t\t\ttargetCollection={targetCollection}\n\t\t\t\t\t\t\t\t\t\tonClick={handleChipClick}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t{remainingCount > 0 && (\n\t\t\t\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-5 px-1.5 text-[10px] shrink-0\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t+{remainingCount}\n\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t\t{value.length > 3 && (\n\t\t\t\t\t\t<TooltipContent side=\"bottom\" align=\"start\" className=\"p-0 w-56\">\n\t\t\t\t\t\t\t<div className=\"max-h-[200px] overflow-y-auto p-2 space-y-1\">\n\t\t\t\t\t\t\t\t{value.map((item, idx) => {\n\t\t\t\t\t\t\t\t\tconst label = resolveText(getRelationItemLabel(item));\n\t\t\t\t\t\t\t\t\tconst id = getRelationItemId(item);\n\t\t\t\t\t\t\t\t\tconst canNavigate = targetCollection && id;\n\t\t\t\t\t\t\t\t\tconst key = id ?? label ?? `item-${idx}`;\n\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center gap-1.5 text-xs\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"size-1 rounded-full bg-foreground/60\" />\n\t\t\t\t\t\t\t\t\t\t\t{canNavigate ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleChipClick(id, targetCollection);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-primary hover:underline text-left\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t<span>{label}</span>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t)}\n\t\t\t\t</Tooltip>\n\n\t\t\t\t{/* Detail sheet */}\n\t\t\t\t{sheetCollection && sheetItemId && (\n\t\t\t\t\t<ResourceSheet\n\t\t\t\t\t\ttype=\"collection\"\n\t\t\t\t\t\tcollection={sheetCollection}\n\t\t\t\t\t\titemId={sheetItemId}\n\t\t\t\t\t\topen={sheetOpen}\n\t\t\t\t\t\tonOpenChange={setSheetOpen}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</>\n\t\t);\n\t}\n\n\t// Handle single relation\n\treturn (\n\t\t<>\n\t\t\t<RelationChip\n\t\t\t\titem={value}\n\t\t\t\ttargetCollection={targetCollection}\n\t\t\t\tonClick={handleChipClick}\n\t\t\t/>\n\t\t\t{/* Detail sheet */}\n\t\t\t{sheetCollection && sheetItemId && (\n\t\t\t\t<ResourceSheet\n\t\t\t\t\ttype=\"collection\"\n\t\t\t\t\tcollection={sheetCollection}\n\t\t\t\t\titemId={sheetItemId}\n\t\t\t\t\topen={sheetOpen}\n\t\t\t\t\tonOpenChange={setSheetOpen}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n\n// ============================================================================\n// Reverse Relation Cell\n// ============================================================================\n\n/**\n * Reverse relation cell - displays related items as clickable chips\n * Shows count badge with tooltip listing all items for navigation\n * Opens detail sheet on click\n */\nexport function ReverseRelationCell({\n\tvalue,\n\tfieldDef,\n}: {\n\tvalue: unknown;\n\trow?: unknown;\n\tfieldDef?: FieldDefinition;\n}) {\n\tconst resolveText = useResolveText();\n\t// Get source collection from fieldDef (the collection that has the relation pointing here)\n\tconst sourceCollection = fieldDef?.[\"~options\"]?.sourceCollection as\n\t\t| string\n\t\t| undefined;\n\n\t// Sheet state\n\tconst [sheetOpen, setSheetOpen] = React.useState(false);\n\tconst [sheetItemId, setSheetItemId] = React.useState<string | undefined>();\n\tconst [sheetCollection, setSheetCollection] = React.useState<\n\t\tstring | undefined\n\t>();\n\n\tconst handleChipClick = React.useCallback(\n\t\t(itemId: string, collection: string) => {\n\t\t\tsetSheetItemId(itemId);\n\t\t\tsetSheetCollection(collection);\n\t\t\tsetSheetOpen(true);\n\t\t},\n\t\t[],\n\t);\n\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\t// Handle count-only value (when items not fetched)\n\tif (typeof value === \"number\") {\n\t\treturn (\n\t\t\t<Badge variant=\"secondary\">\n\t\t\t\t{value} item{value !== 1 ? \"s\" : \"\"}\n\t\t\t</Badge>\n\t\t);\n\t}\n\n\t// Handle array of related items\n\tif (Array.isArray(value)) {\n\t\tif (value.length === 0) {\n\t\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t\t}\n\n\t\t// For small counts, show chips inline\n\t\tif (value.length <= 2) {\n\t\t\treturn (\n\t\t\t\t<>\n\t\t\t\t\t<span className=\"inline-flex flex-wrap items-center gap-1\">\n\t\t\t\t\t\t{value.map((item, idx) => (\n\t\t\t\t\t\t\t<RelationChip\n\t\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: stable array from backend\n\t\t\t\t\t\t\t\tkey={idx}\n\t\t\t\t\t\t\t\titem={item}\n\t\t\t\t\t\t\t\ttargetCollection={sourceCollection}\n\t\t\t\t\t\t\t\tonClick={handleChipClick}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</span>\n\t\t\t\t\t{/* Detail sheet */}\n\t\t\t\t\t{sheetCollection && sheetItemId && (\n\t\t\t\t\t\t<ResourceSheet\n\t\t\t\t\t\t\ttype=\"collection\"\n\t\t\t\t\t\t\tcollection={sheetCollection}\n\t\t\t\t\t\t\titemId={sheetItemId}\n\t\t\t\t\t\t\topen={sheetOpen}\n\t\t\t\t\t\t\tonOpenChange={setSheetOpen}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t);\n\t\t}\n\n\t\t// For larger counts, show count badge with tooltip\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<Tooltip>\n\t\t\t\t\t<TooltipTrigger\n\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"inline-flex items-center gap-1.5 cursor-default\",\n\t\t\t\t\t\t\t\t\t\"text-muted-foreground hover:text-foreground transition-colors\",\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Badge variant=\"secondary\" className=\"h-5 px-1.5 text-xs\">\n\t\t\t\t\t\t\t\t\t{value.length}\n\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t<span className=\"text-xs\">\n\t\t\t\t\t\t\t\t\t{resolveText(getRelationItemLabel(value[0]))}\n\t\t\t\t\t\t\t\t\t{value.length > 1 && ` +${value.length - 1}`}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t\t<TooltipContent side=\"bottom\" align=\"start\" className=\"p-0 w-56\">\n\t\t\t\t\t\t<div className=\"max-h-[200px] overflow-y-auto p-2 space-y-1\">\n\t\t\t\t\t\t\t{value.slice(0, 15).map((item, idx) => {\n\t\t\t\t\t\t\t\tconst label = resolveText(getRelationItemLabel(item));\n\t\t\t\t\t\t\t\tconst id = getRelationItemId(item);\n\t\t\t\t\t\t\t\tconst canNavigate = sourceCollection && id;\n\t\t\t\t\t\t\t\tconst key = id ?? label ?? `item-${idx}`;\n\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div key={key} className=\"flex items-center gap-1.5 text-xs\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"size-1 rounded-full bg-foreground/60\" />\n\t\t\t\t\t\t\t\t\t\t{canNavigate ? (\n\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleChipClick(id, sourceCollection);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-primary hover:underline text-left truncate\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"truncate\">{label}</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t{value.length > 15 && (\n\t\t\t\t\t\t\t\t<div className=\"text-[11px] text-muted-foreground text-center pt-1 border-t border-border/50 mt-1\">\n\t\t\t\t\t\t\t\t\t+{value.length - 15} more\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</TooltipContent>\n\t\t\t\t</Tooltip>\n\n\t\t\t\t{/* Detail sheet */}\n\t\t\t\t{sheetCollection && sheetItemId && (\n\t\t\t\t\t<ResourceSheet\n\t\t\t\t\t\ttype=\"collection\"\n\t\t\t\t\t\tcollection={sheetCollection}\n\t\t\t\t\t\titemId={sheetItemId}\n\t\t\t\t\t\topen={sheetOpen}\n\t\t\t\t\t\tonOpenChange={setSheetOpen}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</>\n\t\t);\n\t}\n\n\treturn <span className=\"text-muted-foreground\">-</span>;\n}\n","/**\n * AssetThumbnail Component\n *\n * Unified asset display component for all contexts.\n * Replaces 3 duplicate implementations:\n * - UploadCell (32px table)\n * - AssetPreviewCell (40px preview)\n * - AssetPreviewField (400px form preview)\n */\n\nimport * as React from \"react\";\nimport {\n\tFile,\n\tFileImage,\n\tFileVideo,\n\tFileAudio,\n\tFilePdf,\n\tFileDoc,\n\tFileZip,\n\tFileCode,\n\tArrowSquareOut,\n} from \"@phosphor-icons/react\";\nimport { Button } from \"../../../../components/ui/button\";\nimport { cn } from \"../../../../lib/utils\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AssetThumbnailProps {\n\t/**\n\t * Asset object or ID\n\t */\n\tasset: unknown;\n\n\t/**\n\t * Size variant\n\t * - sm: 32px (table cells)\n\t * - md: 40px/64px (preview)\n\t * - lg: 400px (form preview with controls)\n\t */\n\tsize?: \"sm\" | \"md\" | \"lg\";\n\n\t/**\n\t * Show filename next to thumbnail (sm/md sizes only)\n\t */\n\tshowFilename?: boolean;\n\n\t/**\n\t * Show video/audio controls (lg size only)\n\t */\n\tshowControls?: boolean;\n\n\t/**\n\t * Called when the thumbnail is clicked\n\t */\n\tonClick?: (id: string) => void;\n\n\t/**\n\t * Additional className\n\t */\n\tclassName?: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getFileIcon(mimeType?: string) {\n\tif (!mimeType) return File;\n\n\tconst type = mimeType.toLowerCase();\n\n\tif (type.startsWith(\"image/\")) return FileImage;\n\tif (type.startsWith(\"video/\")) return FileVideo;\n\tif (type.startsWith(\"audio/\")) return FileAudio;\n\tif (type === \"application/pdf\") return FilePdf;\n\tif (\n\t\ttype.includes(\"zip\") ||\n\t\ttype.includes(\"compressed\") ||\n\t\ttype.includes(\"archive\")\n\t)\n\t\treturn FileZip;\n\tif (\n\t\ttype.includes(\"word\") ||\n\t\ttype.includes(\"document\") ||\n\t\ttype === \"application/rtf\"\n\t)\n\t\treturn FileDoc;\n\tif (\n\t\ttype.includes(\"json\") ||\n\t\ttype.includes(\"javascript\") ||\n\t\ttype.includes(\"typescript\") ||\n\t\ttype.includes(\"xml\") ||\n\t\ttype.includes(\"html\")\n\t)\n\t\treturn FileCode;\n\n\treturn File;\n}\n\nfunction isImage(mimeType?: string): boolean {\n\treturn !!mimeType?.toLowerCase().startsWith(\"image/\");\n}\n\nfunction isVideo(mimeType?: string): boolean {\n\treturn !!mimeType?.toLowerCase().startsWith(\"video/\");\n}\n\nfunction isAudio(mimeType?: string): boolean {\n\treturn !!mimeType?.toLowerCase().startsWith(\"audio/\");\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function AssetThumbnail({\n\tasset,\n\tsize = \"sm\",\n\tshowFilename = false,\n\tshowControls = false,\n\tonClick,\n\tclassName,\n}: AssetThumbnailProps) {\n\t// Handle null/undefined\n\tif (asset === null || asset === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\t// If asset is just an ID string\n\tif (typeof asset === \"string\") {\n\t\treturn (\n\t\t\t<span\n\t\t\t\tclassName=\"font-mono text-xs text-muted-foreground truncate max-w-[100px]\"\n\t\t\t\ttitle={asset}\n\t\t\t>\n\t\t\t\t{asset.slice(0, 8)}...\n\t\t\t</span>\n\t\t);\n\t}\n\n\t// Extract asset properties\n\tconst assetObj = asset as Record<string, unknown>;\n\tconst url = assetObj.url as string | undefined;\n\tconst filename = assetObj.filename as string | undefined;\n\tconst mimeType = assetObj.mimeType as string | undefined;\n\tconst alt = assetObj.alt as string | undefined;\n\n\tconst isImageType = isImage(mimeType);\n\tconst isVideoType = isVideo(mimeType);\n\tconst isAudioType = isAudio(mimeType);\n\tconst FileIcon = getFileIcon(mimeType);\n\n\t// No URL means no preview\n\tif (!url) {\n\t\tif (assetObj.id) {\n\t\t\treturn (\n\t\t\t\t<span className=\"font-mono text-xs text-muted-foreground\">\n\t\t\t\t\t{String(assetObj.id).slice(0, 8)}...\n\t\t\t\t</span>\n\t\t\t);\n\t\t}\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\t// ========== SM SIZE (32px) - Table cells ==========\n\tif (size === \"sm\") {\n\t\tconst assetId = assetObj.id as string | undefined;\n\t\tconst handleClick = onClick && assetId ? () => onClick(assetId) : undefined;\n\n\t\tif (isImageType) {\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex items-center gap-2\",\n\t\t\t\t\t\tonClick && \"cursor-pointer hover:opacity-80\",\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\n\t\t\t\t\tonClick={handleClick}\n\t\t\t\t>\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={url}\n\t\t\t\t\t\talt={filename || \"Asset\"}\n\t\t\t\t\t\tclassName=\"size-8 rounded object-cover border\"\n\t\t\t\t\t/>\n\t\t\t\t\t{showFilename && filename && (\n\t\t\t\t\t\t<span className=\"text-xs truncate max-w-[100px]\" title={filename}>\n\t\t\t\t\t\t\t{filename}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\t// Non-image files\n\t\tif (showFilename && filename) {\n\t\t\treturn (\n\t\t\t\t<span className=\"text-sm truncate max-w-[150px]\" title={filename}>\n\t\t\t\t\t{filename}\n\t\t\t\t</span>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<span className=\"font-mono text-xs text-muted-foreground\">\n\t\t\t\t{String(assetObj.id || \"\").slice(0, 8)}...\n\t\t\t</span>\n\t\t);\n\t}\n\n\t// ========== MD SIZE (40px) - Preview/Icon ==========\n\tif (size === \"md\") {\n\t\tconst assetId = assetObj.id as string | undefined;\n\t\tconst handleClick = onClick && assetId ? () => onClick(assetId) : undefined;\n\n\t\tif (isImageType) {\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex items-center justify-center\",\n\t\t\t\t\t\tonClick && \"cursor-pointer hover:opacity-80\",\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\n\t\t\t\t\tonClick={handleClick}\n\t\t\t\t>\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={url}\n\t\t\t\t\t\talt={filename || \"Asset\"}\n\t\t\t\t\t\tclassName=\"size-10 rounded object-cover border\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\t// Show icon for non-images\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex items-center justify-center\",\n\t\t\t\t\tonClick && \"cursor-pointer hover:opacity-80\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonClick={handleClick}\n\t\t\t>\n\t\t\t\t<div className=\"size-10 rounded border bg-muted flex items-center justify-center\">\n\t\t\t\t\t<FileIcon className=\"size-5 text-muted-foreground\" weight=\"regular\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// ========== LG SIZE (400px) - Full preview with controls ==========\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"relative overflow-hidden rounded-lg border bg-muted/30\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{/* Image Preview */}\n\t\t\t{isImageType && (\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={url}\n\t\t\t\t\t\talt={alt || filename || \"Asset preview\"}\n\t\t\t\t\t\tclassName=\"max-h-[400px] w-full object-contain\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Video Preview */}\n\t\t\t{isVideoType && (\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t{showControls ? (\n\t\t\t\t\t\t<video\n\t\t\t\t\t\t\tsrc={url}\n\t\t\t\t\t\t\tcontrols\n\t\t\t\t\t\t\tclassName=\"max-h-[400px] w-full\"\n\t\t\t\t\t\t\tpreload=\"metadata\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<track kind=\"captions\" />\n\t\t\t\t\t\t\tYour browser does not support the video tag.\n\t\t\t\t\t\t</video>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"flex flex-col items-center justify-center gap-4 p-12\">\n\t\t\t\t\t\t\t<FileIcon\n\t\t\t\t\t\t\t\tclassName=\"size-20 text-muted-foreground\"\n\t\t\t\t\t\t\t\tweight=\"regular\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t\t{filename || \"Video\"}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Audio Preview */}\n\t\t\t{isAudioType && (\n\t\t\t\t<div className=\"flex flex-col items-center justify-center gap-4 p-8\">\n\t\t\t\t\t<FileIcon\n\t\t\t\t\t\tclassName=\"size-16 text-muted-foreground\"\n\t\t\t\t\t\tweight=\"regular\"\n\t\t\t\t\t/>\n\t\t\t\t\t{showControls && (\n\t\t\t\t\t\t<audio src={url} controls className=\"w-full max-w-md\" preload=\"metadata\">\n\t\t\t\t\t\t\tYour browser does not support the audio tag.\n\t\t\t\t\t\t</audio>\n\t\t\t\t\t)}\n\t\t\t\t\t{!showControls && (\n\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t{filename || \"Audio\"}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Other File Types */}\n\t\t\t{!isImageType && !isVideoType && !isAudioType && (\n\t\t\t\t<div className=\"flex flex-col items-center justify-center gap-4 p-12\">\n\t\t\t\t\t<FileIcon className=\"size-20 text-muted-foreground\" weight=\"regular\" />\n\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">{filename || \"File\"}</p>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Open in new tab button (lg size only) */}\n\t\t\t<div className=\"absolute right-2 top-2\">\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\tsize=\"icon-sm\"\n\t\t\t\t\tnativeButton={false}\n\t\t\t\t\trender={<a href={url} target=\"_blank\" rel=\"noopener noreferrer\" />}\n\t\t\t\t>\n\t\t\t\t\t<ArrowSquareOut weight=\"bold\" />\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","/**\n * Upload Cell Components\n *\n * Cells for displaying asset/upload fields:\n * - UploadCell - single asset\n * - UploadManyCell - multiple assets\n *\n * Uses unified AssetThumbnail component\n */\n\nimport * as React from \"react\";\nimport { Badge } from \"../../../components/ui/badge\";\nimport { AssetThumbnail } from \"./shared/asset-thumbnail\";\n\n// ============================================================================\n// Upload Cell\n// ============================================================================\n\n/**\n * Upload cell - displays single asset thumbnail or file info\n * Uses AssetThumbnail with size=\"sm\"\n */\nexport function UploadCell({ value }: { value: unknown }) {\n\treturn <AssetThumbnail asset={value} size=\"sm\" showFilename />;\n}\n\n// ============================================================================\n// Upload Many Cell\n// ============================================================================\n\n/**\n * Upload many cell - displays multiple assets count or thumbnails\n */\nexport function UploadManyCell({ value }: { value: unknown }) {\n\tif (value === null || value === undefined) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\tif (!Array.isArray(value)) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\tif (value.length === 0) {\n\t\treturn <span className=\"text-muted-foreground\">-</span>;\n\t}\n\n\t// Get image assets for preview\n\tconst imageAssets = value\n\t\t.filter((item): item is Record<string, unknown> => {\n\t\t\tif (typeof item !== \"object\" || item === null) return false;\n\t\t\tconst mimeType = (item as Record<string, unknown>).mimeType;\n\t\t\treturn typeof mimeType === \"string\" && mimeType.startsWith(\"image/\");\n\t\t})\n\t\t.slice(0, 3);\n\n\t// Show mini grid of thumbnails for images\n\tif (imageAssets.length > 0) {\n\t\tconst remaining = value.length - imageAssets.length;\n\t\treturn (\n\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t<div className=\"flex -space-x-2\">\n\t\t\t\t\t{imageAssets.map((asset, index) => (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={(asset.id as string) || index}\n\t\t\t\t\t\t\tsrc={asset.url as string}\n\t\t\t\t\t\t\talt={(asset.filename as string) || \"Asset\"}\n\t\t\t\t\t\t\tclassName=\"size-6 rounded border bg-background object-cover\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{remaining > 0 && (\n\t\t\t\t\t<span className=\"text-xs text-muted-foreground ml-1\">\n\t\t\t\t\t\t+{remaining}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Show count badge for non-images\n\treturn (\n\t\t<Badge variant=\"secondary\">\n\t\t\t{value.length} file{value.length !== 1 ? \"s\" : \"\"}\n\t\t</Badge>\n\t);\n}\n","/**\n * AssetPreviewField Component\n *\n * Read-only field that displays the current asset's preview (image/video/file).\n * Used in the assets collection form to show a preview of the uploaded file.\n *\n * @example\n * ```tsx\n * <AssetPreviewField\n * name=\"url\"\n * label=\"Preview\"\n * />\n * ```\n */\n\nimport * as React from \"react\";\nimport { useFormContext, useWatch } from \"react-hook-form\";\nimport type { I18nText } from \"../../i18n/types\";\nimport { cn } from \"../../lib/utils\";\nimport { AssetThumbnail } from \"../../views/collection/cells\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AssetPreviewFieldProps {\n\t/**\n\t * Field name (not used for value, just for form integration)\n\t */\n\tname?: string;\n\n\t/**\n\t * Label for the field (supports I18nText)\n\t */\n\tlabel?: I18nText;\n\n\t/**\n\t * Description text (supports I18nText)\n\t */\n\tdescription?: I18nText;\n\n\t/**\n\t * Additional className\n\t */\n\tclassName?: string;\n\n\t/**\n\t * URL field name to watch (defaults to \"url\")\n\t */\n\turlField?: string;\n\n\t/**\n\t * MIME type field name to watch (defaults to \"mimeType\")\n\t */\n\tmimeTypeField?: string;\n\n\t/**\n\t * Filename field name to watch (defaults to \"filename\")\n\t */\n\tfilenameField?: string;\n\n\t/**\n\t * Alt text field name to watch (defaults to \"alt\")\n\t */\n\taltField?: string;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function AssetPreviewField({\n\tname = \"preview\",\n\tlabel = \"Preview\",\n\tdescription,\n\tclassName,\n\turlField = \"url\",\n\tmimeTypeField = \"mimeType\",\n\tfilenameField = \"filename\",\n\taltField = \"alt\",\n}: AssetPreviewFieldProps) {\n\tconst form = useFormContext();\n\n\t// Watch the relevant fields\n\tconst url = useWatch({ control: form?.control, name: urlField }) as\n\t\t| string\n\t\t| undefined;\n\tconst mimeType = useWatch({ control: form?.control, name: mimeTypeField }) as\n\t\t| string\n\t\t| undefined;\n\tconst filename = useWatch({ control: form?.control, name: filenameField }) as\n\t\t| string\n\t\t| undefined;\n\tconst alt = useWatch({ control: form?.control, name: altField }) as\n\t\t| string\n\t\t| undefined;\n\n\t// Build asset object for AssetThumbnail\n\tconst asset = url\n\t\t? {\n\t\t\t\turl,\n\t\t\t\tmimeType,\n\t\t\t\tfilename,\n\t\t\t\talt,\n\t\t\t}\n\t\t: null;\n\n\t// No URL means no preview available\n\tif (!asset) {\n\t\treturn (\n\t\t\t<FieldWrapper name={name} label={label} description={description}>\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex items-center justify-center rounded-lg border border-dashed p-8\",\n\t\t\t\t\t\t\"bg-muted/30 text-muted-foreground\",\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<p className=\"text-sm\">No preview available</p>\n\t\t\t\t</div>\n\t\t\t</FieldWrapper>\n\t\t);\n\t}\n\n\treturn (\n\t\t<FieldWrapper name={name} label={label} description={description}>\n\t\t\t<AssetThumbnail\n\t\t\t\tasset={asset}\n\t\t\t\tsize=\"lg\"\n\t\t\t\tshowControls\n\t\t\t\tclassName={className}\n\t\t\t/>\n\t\t</FieldWrapper>\n\t);\n}\n","import {\n\tGroup,\n\ttype GroupProps,\n\tPanel,\n\ttype PanelProps,\n\tSeparator,\n\ttype SeparatorProps,\n} from \"react-resizable-panels\";\n\nimport { cn } from \"#questpie/admin/client/lib/utils\";\n\nfunction ResizablePanelGroup({ className, ...props }: GroupProps) {\n\treturn (\n\t\t<Group\n\t\t\tdata-slot=\"resizable-panel-group\"\n\t\t\tclassName={cn(\n\t\t\t\t\"flex h-full w-full data-[orientation=vertical]:flex-col\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction ResizablePanel(props: PanelProps) {\n\treturn <Panel data-slot=\"resizable-panel\" {...props} />;\n}\n\nfunction ResizableHandle({\n\twithHandle,\n\tclassName,\n\t...props\n}: SeparatorProps & {\n\twithHandle?: boolean;\n}) {\n\treturn (\n\t\t<Separator\n\t\t\tdata-slot=\"resizable-handle\"\n\t\t\tclassName={cn(\n\t\t\t\t\"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full data-[orientation=vertical]:after:left-0 data-[orientation=vertical]:after:h-1 data-[orientation=vertical]:after:w-full data-[orientation=vertical]:after:translate-x-0 data-[orientation=vertical]:after:-translate-y-1/2 [&[data-orientation=vertical]>div]:rotate-90\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{withHandle && (\n\t\t\t\t<div className=\"bg-border h-6 w-1 rounded-lg z-10 flex shrink-0\" />\n\t\t\t)}\n\t\t</Separator>\n\t);\n}\n\nexport { ResizablePanelGroup, ResizablePanel, ResizableHandle };\n","/**\n * Block Editor Context\n *\n * Context and hooks for the block editor state management.\n */\n\n\"use client\";\n\nimport * as React from \"react\";\nimport type { BlockContent } from \"../../blocks/types.js\";\nimport type { BlockDefinition } from \"../../builder/block/types.js\";\nimport type { InsertPosition } from \"./utils/tree-utils.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Block editor state.\n */\nexport type BlockEditorState = {\n\t/** Block content (tree + values) */\n\tcontent: BlockContent;\n\t/** Currently selected block ID */\n\tselectedBlockId: string | null;\n\t/** Expanded block IDs (for nested blocks) */\n\texpandedBlockIds: Set<string>;\n\t/** Is block library open */\n\tisLibraryOpen: boolean;\n\t/** Insert position when adding new block */\n\tinsertPosition: InsertPosition | null;\n\t/** Registered block definitions */\n\tblocks: Record<string, BlockDefinition>;\n\t/** Allowed block types for this field */\n\tallowedBlocks: string[] | null;\n\t/** Current locale for editing */\n\tlocale: string;\n};\n\n/**\n * Block editor actions.\n */\nexport type BlockEditorActions = {\n\t// Selection\n\tselectBlock: (id: string | null) => void;\n\ttoggleExpanded: (id: string) => void;\n\texpandAll: () => void;\n\tcollapseAll: () => void;\n\n\t// CRUD\n\taddBlock: (type: string, position: InsertPosition) => void;\n\tremoveBlock: (id: string) => void;\n\tduplicateBlock: (id: string) => void;\n\n\t// Reorder\n\tmoveBlock: (id: string, toPosition: InsertPosition) => void;\n\n\t// Values\n\tupdateBlockValues: (id: string, values: Record<string, unknown>) => void;\n\n\t// Library\n\topenLibrary: (position: InsertPosition) => void;\n\tcloseLibrary: () => void;\n};\n\n/**\n * Block editor context value.\n */\nexport type BlockEditorContextValue = {\n\tstate: BlockEditorState;\n\tactions: BlockEditorActions;\n};\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst BlockEditorContext = React.createContext<BlockEditorContextValue | null>(\n\tnull,\n);\n\n/**\n * Hook to access block editor state and actions.\n * Must be used within BlockEditorProvider.\n */\nexport function useBlockEditor(): BlockEditorContextValue {\n\tconst ctx = React.useContext(BlockEditorContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useBlockEditor must be used within BlockEditorProvider\");\n\t}\n\treturn ctx;\n}\n\n/**\n * Hook to access only block editor state.\n */\nexport function useBlockEditorState(): BlockEditorState {\n\treturn useBlockEditor().state;\n}\n\n/**\n * Hook to access only block editor actions.\n */\nexport function useBlockEditorActions(): BlockEditorActions {\n\treturn useBlockEditor().actions;\n}\n\n/**\n * Hook to check if a block is selected.\n */\nexport function useIsBlockSelected(blockId: string): boolean {\n\tconst { state } = useBlockEditor();\n\treturn state.selectedBlockId === blockId;\n}\n\n/**\n * Hook to check if a block is expanded.\n */\nexport function useIsBlockExpanded(blockId: string): boolean {\n\tconst { state } = useBlockEditor();\n\treturn state.expandedBlockIds.has(blockId);\n}\n\n/**\n * Hook to get a block definition by type.\n */\nexport function useBlockDefinition(\n\tblockType: string,\n): BlockDefinition | undefined {\n\tconst { state } = useBlockEditor();\n\treturn state.blocks[blockType];\n}\n\n/**\n * Hook to get the selected block's definition.\n */\nexport function useSelectedBlockDefinition(): BlockDefinition | undefined {\n\tconst { state } = useBlockEditor();\n\tif (!state.selectedBlockId) return undefined;\n\n\tconst blockNode = findBlockNodeById(\n\t\tstate.content._tree,\n\t\tstate.selectedBlockId,\n\t);\n\tif (!blockNode) return undefined;\n\n\treturn state.blocks[blockNode.type];\n}\n\n/**\n * Hook to get the selected block's values.\n */\nexport function useSelectedBlockValues(): Record<string, unknown> | undefined {\n\tconst { state } = useBlockEditor();\n\tif (!state.selectedBlockId) return undefined;\n\treturn state.content._values[state.selectedBlockId];\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\nexport const BlockEditorContextProvider = BlockEditorContext.Provider;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nimport type { BlockNode } from \"../../blocks/types.js\";\n\nfunction findBlockNodeById(\n\ttree: BlockNode[],\n\tid: string,\n): BlockNode | undefined {\n\tfor (const node of tree) {\n\t\tif (node.id === id) return node;\n\t\tconst found = findBlockNodeById(node.children, id);\n\t\tif (found) return found;\n\t}\n\treturn undefined;\n}\n","/**\n * Block Type Icon\n *\n * Displays the icon for a block type using Phosphor icons.\n */\n\n\"use client\";\n\nimport * as PhosphorIcons from \"@phosphor-icons/react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\nimport { useBlockDefinition } from \"./block-editor-context.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type BlockTypeIconProps = {\n\t/** Block type name */\n\ttype: string;\n\t/** Custom class name */\n\tclassName?: string;\n\t/** Icon size */\n\tsize?: number;\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function BlockTypeIcon({\n\ttype,\n\tclassName,\n\tsize = 16,\n}: BlockTypeIconProps) {\n\tconst blockDef = useBlockDefinition(type);\n\tconst iconName = blockDef?.icon || \"Cube\";\n\n\t// Get icon component from Phosphor\n\tconst IconComponent = getPhosphorIcon(iconName);\n\n\treturn <IconComponent className={cn(\"shrink-0\", className)} size={size} />;\n}\n\n/**\n * Standalone icon component that doesn't require context.\n * Useful for rendering icons outside the editor.\n */\nexport function BlockIcon({\n\ticon,\n\tclassName,\n\tsize = 16,\n}: {\n\ticon: string;\n\tclassName?: string;\n\tsize?: number;\n}) {\n\tconst IconComponent = getPhosphorIcon(icon);\n\treturn <IconComponent className={cn(\"shrink-0\", className)} size={size} />;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Get a Phosphor icon component by name.\n * Falls back to Cube icon if not found.\n */\nfunction getPhosphorIcon(\n\tname: string,\n): React.ComponentType<{ className?: string; size?: number }> {\n\t// Try to get the icon from Phosphor\n\tconst icon = (PhosphorIcons as Record<string, unknown>)[name];\n\n\tif (typeof icon === \"function\") {\n\t\treturn icon as React.ComponentType<{ className?: string; size?: number }>;\n\t}\n\n\t// Fallback to Cube\n\treturn PhosphorIcons.Cube;\n}\n\n/**\n * Map of common block types to their default icons.\n */\nexport const DEFAULT_BLOCK_ICONS: Record<string, string> = {\n\t// Layout\n\tcolumns: \"Columns\",\n\tgrid: \"GridFour\",\n\tcontainer: \"Square\",\n\tsection: \"Rectangle\",\n\trow: \"Rows\",\n\n\t// Content\n\ttext: \"TextAa\",\n\theading: \"TextH\",\n\tparagraph: \"Paragraph\",\n\tquote: \"Quotes\",\n\tlist: \"List\",\n\tcode: \"Code\",\n\n\t// Media\n\timage: \"Image\",\n\tvideo: \"VideoCamera\",\n\tgallery: \"Images\",\n\taudio: \"SpeakerHigh\",\n\tfile: \"File\",\n\n\t// Sections\n\thero: \"Image\",\n\tfeatures: \"Star\",\n\ttestimonials: \"Quotes\",\n\tcta: \"Megaphone\",\n\tpricing: \"CurrencyDollar\",\n\tfaq: \"Question\",\n\n\t// Interactive\n\tform: \"TextBox\",\n\taccordion: \"CaretDown\",\n\ttabs: \"Tabs\",\n\tcarousel: \"Slideshow\",\n\tbutton: \"Cursor\",\n};\n","/**\n * Block Library\n *\n * Block picker component for adding new blocks.\n * Used both as standalone panel and as popover content.\n */\n\n\"use client\";\n\nimport { MagnifyingGlass, X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport type { BlockDefinition } from \"../../builder/block/types.js\";\nimport { cn } from \"../../lib/utils.js\";\nimport { Button } from \"../ui/button.js\";\nimport { Input } from \"../ui/input.js\";\nimport { useBlockEditor, useBlockEditorState } from \"./block-editor-context.js\";\nimport { BlockIcon } from \"./block-type-icon.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype BlockWithName = BlockDefinition & { name: string };\n\nexport type BlockLibraryContentProps = {\n\t/** Callback when a block is selected */\n\tonSelect: (type: string) => void;\n\t/** Show header with close button */\n\tshowHeader?: boolean;\n\t/** Close handler for header */\n\tonClose?: () => void;\n};\n\n// ============================================================================\n// BlockLibraryContent - Reusable content for popover or panel\n// ============================================================================\n\nexport function BlockLibraryContent({\n\tonSelect,\n\tshowHeader = false,\n\tonClose,\n}: BlockLibraryContentProps) {\n\tconst state = useBlockEditorState();\n\tconst [search, setSearch] = React.useState(\"\");\n\n\t// Group blocks by category\n\tconst blocksByCategory = React.useMemo(() => {\n\t\tconst result = new Map<string, BlockWithName[]>();\n\n\t\tfor (const [name, def] of Object.entries(state.blocks)) {\n\t\t\t// Filter by allowed blocks\n\t\t\tif (state.allowedBlocks && !state.allowedBlocks.includes(name)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Filter by search\n\t\t\tif (search) {\n\t\t\t\tconst label = getBlockDisplayLabel(def);\n\t\t\t\tif (!label.toLowerCase().includes(search.toLowerCase())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst category = def.category || \"other\";\n\t\t\tif (!result.has(category)) {\n\t\t\t\tresult.set(category, []);\n\t\t\t}\n\t\t\tresult.get(category)!.push({ ...def, name });\n\t\t}\n\n\t\treturn result;\n\t}, [state.blocks, state.allowedBlocks, search]);\n\n\t// Focus search on mount\n\tconst searchInputRef = React.useRef<HTMLInputElement>(null);\n\tReact.useEffect(() => {\n\t\tconst timer = setTimeout(() => searchInputRef.current?.focus(), 100);\n\t\treturn () => clearTimeout(timer);\n\t}, []);\n\n\treturn (\n\t\t<div className=\"flex flex-col\">\n\t\t\t{/* Optional Header */}\n\t\t\t{showHeader && (\n\t\t\t\t<div className=\"flex items-center justify-between border-b p-3\">\n\t\t\t\t\t<h3 className=\"font-medium text-sm\">Add Block</h3>\n\t\t\t\t\t{onClose && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\tclassName=\"h-7 w-7\"\n\t\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<X className=\"h-4 w-4\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Search */}\n\t\t\t<div className=\"p-3\">\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<MagnifyingGlass className=\"absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n\t\t\t\t\t<Input\n\t\t\t\t\t\tref={searchInputRef}\n\t\t\t\t\t\tplaceholder=\"Search blocks...\"\n\t\t\t\t\t\tvalue={search}\n\t\t\t\t\t\tonChange={(e) => setSearch(e.target.value)}\n\t\t\t\t\t\tclassName=\"pl-8 h-8 text-sm\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Block list by category */}\n\t\t\t<div className=\"max-h-64 overflow-auto px-3 pb-3\">\n\t\t\t\t{blocksByCategory.size === 0 ? (\n\t\t\t\t\t<div className=\"text-center text-sm text-muted-foreground py-4\">\n\t\t\t\t\t\tNo blocks found\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\t<div className=\"space-y-4\">\n\t\t\t\t\t\t{Array.from(blocksByCategory.entries()).map(\n\t\t\t\t\t\t\t([category, blocks]) => (\n\t\t\t\t\t\t\t\t<div key={category}>\n\t\t\t\t\t\t\t\t\t<h4 className=\"mb-1.5 text-xs font-medium uppercase text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t{getCategoryLabel(category)}\n\t\t\t\t\t\t\t\t\t</h4>\n\t\t\t\t\t\t\t\t\t<div className=\"grid grid-cols-2 gap-1.5\">\n\t\t\t\t\t\t\t\t\t\t{blocks.map((block) => (\n\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\tkey={block.name}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"flex items-center gap-2 rounded-md border p-2 text-left\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"transition-colors hover:border-primary hover:bg-accent\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"focus:outline-none focus-visible:ring-2 focus-visible:ring-primary\",\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => onSelect(block.name)}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<BlockIcon\n\t\t\t\t\t\t\t\t\t\t\t\t\ticon={block.icon || \"Cube\"}\n\t\t\t\t\t\t\t\t\t\t\t\t\tsize={16}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground flex-shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-xs truncate\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{getBlockDisplayLabel(block)}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// BlockLibrary - Standalone panel version (legacy, for sidebar use)\n// ============================================================================\n\nexport function BlockLibrary() {\n\tconst { state, actions } = useBlockEditor();\n\n\tconst handleSelect = (type: string) => {\n\t\tif (state.insertPosition) {\n\t\t\tactions.addBlock(type, state.insertPosition);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className=\"h-full\">\n\t\t\t<BlockLibraryContent\n\t\t\t\tonSelect={handleSelect}\n\t\t\t\tshowHeader\n\t\t\t\tonClose={actions.closeLibrary}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getBlockDisplayLabel(block: BlockDefinition): string {\n\tif (!block.label) {\n\t\treturn block.name;\n\t}\n\n\tconst label = block.label;\n\n\tif (typeof label === \"string\") {\n\t\treturn label;\n\t}\n\n\tif (typeof label === \"function\") {\n\t\treturn block.name;\n\t}\n\n\tif (\"key\" in label) {\n\t\treturn label.fallback || block.name;\n\t}\n\n\t// I18nLocaleMap\n\tconst localeMap = label as Record<string, string>;\n\treturn localeMap.en || Object.values(localeMap)[0] || block.name;\n}\n\nfunction getCategoryLabel(category: string): string {\n\tconst labels: Record<string, string> = {\n\t\tlayout: \"Layout\",\n\t\tcontent: \"Content\",\n\t\tmedia: \"Media\",\n\t\tsections: \"Sections\",\n\t\tinteractive: \"Interactive\",\n\t\tother: \"Other\",\n\t};\n\treturn (\n\t\tlabels[category] || category.charAt(0).toUpperCase() + category.slice(1)\n\t);\n}\n","/**\n * Block Insert Button\n *\n * Button with popover to add new blocks at a specific position.\n */\n\n\"use client\";\n\nimport { Plus } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\nimport { Button } from \"../ui/button.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/popover.js\";\nimport { useBlockEditorActions } from \"./block-editor-context.js\";\nimport { BlockLibraryContent } from \"./block-library.js\";\nimport type { InsertPosition } from \"./utils/tree-utils.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type BlockInsertButtonProps = {\n\t/** Position where the block will be inserted */\n\tposition: InsertPosition;\n\t/** Compact style (shows on hover) */\n\tcompact?: boolean;\n\t/** Custom class name */\n\tclassName?: string;\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function BlockInsertButton({\n\tposition,\n\tcompact = false,\n\tclassName,\n}: BlockInsertButtonProps) {\n\tconst [open, setOpen] = React.useState(false);\n\tconst { addBlock } = useBlockEditorActions();\n\n\tconst handleSelectBlock = (type: string) => {\n\t\taddBlock(type, position);\n\t\tsetOpen(false);\n\t};\n\n\tif (compact) {\n\t\treturn (\n\t\t\t<Popover open={open} onOpenChange={setOpen}>\n\t\t\t\t<PopoverTrigger\n\t\t\t\t\trender={\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"group relative w-full cursor-pointer -my-0.5 z-10\",\n\t\t\t\t\t\t\t\t\"h-2 sm:h-1\",\n\t\t\t\t\t\t\t\tclassName,\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\t\ttabIndex={0}\n\t\t\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\t\t\tif (e.key === \"Enter\" || e.key === \" \") {\n\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\tsetOpen(true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t{/* Hover indicator line */}\n\t\t\t\t\t<div className=\"absolute inset-x-0 top-1/2 h-0.5 -translate-y-1/2 bg-primary/40 transition-colors sm:bg-transparent sm:group-hover:bg-primary\" />\n\n\t\t\t\t\t{/* Add button that appears on hover - overlays other content */}\n\t\t\t\t\t<div className=\"pointer-events-none absolute inset-x-0 top-1/2 flex -translate-y-1/2 items-center justify-center opacity-100 transition-opacity sm:opacity-0 sm:group-hover:opacity-100\">\n\t\t\t\t\t\t<div className=\"pointer-events-auto flex items-center gap-1 rounded-full bg-primary px-2 py-0.5 text-xs text-primary-foreground shadow-sm\">\n\t\t\t\t\t\t\t<Plus size={10} weight=\"bold\" />\n\t\t\t\t\t\t\t<span>Add</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</PopoverTrigger>\n\t\t\t\t<PopoverContent className=\"w-72 p-0\" align=\"start\">\n\t\t\t\t\t<BlockLibraryContent onSelect={handleSelectBlock} />\n\t\t\t\t</PopoverContent>\n\t\t\t</Popover>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Popover open={open} onOpenChange={setOpen}>\n\t\t\t<PopoverTrigger\n\t\t\t\trender={\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tclassName={cn(\"w-full border-dashed\", className)}\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t<Plus className=\"mr-2 h-4 w-4\" />\n\t\t\t\tAdd block\n\t\t\t</PopoverTrigger>\n\t\t\t<PopoverContent className=\"w-72 p-0\" align=\"start\">\n\t\t\t\t<BlockLibraryContent onSelect={handleSelectBlock} />\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n","/**\n * Block Tree Utilities\n *\n * Functions for manipulating the block tree structure.\n * All functions are pure and return new objects.\n */\n\nimport type { BlockNode } from \"../../../blocks/types.js\";\n\n/**\n * Position where a block should be inserted.\n */\nexport type InsertPosition = {\n\t/** Parent block ID (null = root level) */\n\tparentId: string | null;\n\t/** Index within parent's children or root */\n\tindex: number;\n};\n\n/**\n * Find a block by ID in the tree.\n */\nexport function findBlockById(tree: BlockNode[], id: string): BlockNode | null {\n\tfor (const node of tree) {\n\t\tif (node.id === id) return node;\n\t\tconst found = findBlockById(node.children, id);\n\t\tif (found) return found;\n\t}\n\treturn null;\n}\n\n/**\n * Find a block's position (parent and index) in the tree.\n */\nexport function findBlockPosition(\n\ttree: BlockNode[],\n\tid: string,\n\tparentId: string | null = null,\n): InsertPosition | null {\n\tfor (let i = 0; i < tree.length; i++) {\n\t\tconst node = tree[i];\n\t\tif (node.id === id) {\n\t\t\treturn { parentId, index: i };\n\t\t}\n\t\tconst found = findBlockPosition(node.children, id, node.id);\n\t\tif (found) return found;\n\t}\n\treturn null;\n}\n\n/**\n * Insert a block at the specified position.\n */\nexport function insertBlockInTree(\n\ttree: BlockNode[],\n\tblock: BlockNode,\n\tposition: InsertPosition,\n): BlockNode[] {\n\tif (position.parentId === null) {\n\t\t// Insert at root level\n\t\tconst newTree = [...tree];\n\t\tnewTree.splice(position.index, 0, block);\n\t\treturn newTree;\n\t}\n\n\t// Insert as child of parent\n\treturn tree.map((node) => {\n\t\tif (node.id === position.parentId) {\n\t\t\tconst newChildren = [...node.children];\n\t\t\tnewChildren.splice(position.index, 0, block);\n\t\t\treturn { ...node, children: newChildren };\n\t\t}\n\t\treturn {\n\t\t\t...node,\n\t\t\tchildren: insertBlockInTree(node.children, block, position),\n\t\t};\n\t});\n}\n\n/**\n * Remove a block and all its children from the tree.\n * Returns the new tree and list of removed block IDs.\n */\nexport function removeBlockFromTree(\n\ttree: BlockNode[],\n\tid: string,\n): { newTree: BlockNode[]; removedIds: string[] } {\n\tconst removedIds: string[] = [];\n\n\tfunction collectIds(node: BlockNode) {\n\t\tremovedIds.push(node.id);\n\t\tnode.children.forEach(collectIds);\n\t}\n\n\tfunction remove(nodes: BlockNode[]): BlockNode[] {\n\t\treturn nodes\n\t\t\t.filter((node) => {\n\t\t\t\tif (node.id === id) {\n\t\t\t\t\tcollectIds(node);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t})\n\t\t\t.map((node) => ({\n\t\t\t\t...node,\n\t\t\t\tchildren: remove(node.children),\n\t\t\t}));\n\t}\n\n\treturn { newTree: remove(tree), removedIds };\n}\n\n/**\n * Move a block to a new position in the tree.\n */\nexport function moveBlockInTree(\n\ttree: BlockNode[],\n\tblockId: string,\n\ttoPosition: InsertPosition,\n): BlockNode[] {\n\t// Find and remove block\n\tconst block = findBlockById(tree, blockId);\n\tif (!block) return tree;\n\n\tconst { newTree } = removeBlockFromTree(tree, blockId);\n\n\t// Insert at new position\n\treturn insertBlockInTree(newTree, block, toPosition);\n}\n\n/**\n * Duplicate a block and all its children.\n * Returns the new tree, list of new IDs, and new values.\n */\nexport function duplicateBlockInTree(\n\ttree: BlockNode[],\n\tvalues: Record<string, Record<string, unknown>>,\n\tblockId: string,\n): {\n\tnewTree: BlockNode[];\n\tnewIds: string[];\n\tnewValues: Record<string, Record<string, unknown>>;\n} {\n\tconst block = findBlockById(tree, blockId);\n\tif (!block) {\n\t\treturn { newTree: tree, newIds: [], newValues: {} };\n\t}\n\n\tconst newIds: string[] = [];\n\tconst newValues: Record<string, Record<string, unknown>> = {};\n\n\tfunction cloneNode(node: BlockNode): BlockNode {\n\t\tconst newId = crypto.randomUUID();\n\t\tnewIds.push(newId);\n\t\tnewValues[newId] = { ...values[node.id] };\n\n\t\treturn {\n\t\t\tid: newId,\n\t\t\ttype: node.type,\n\t\t\tchildren: node.children.map(cloneNode),\n\t\t};\n\t}\n\n\tconst clonedBlock = cloneNode(block);\n\n\t// Find parent and index\n\tconst position = findBlockPosition(tree, blockId);\n\tif (!position) {\n\t\treturn { newTree: tree, newIds: [], newValues: {} };\n\t}\n\n\t// Insert after original\n\tconst newTree = insertBlockInTree(tree, clonedBlock, {\n\t\tparentId: position.parentId,\n\t\tindex: position.index + 1,\n\t});\n\n\treturn { newTree, newIds, newValues };\n}\n\n/**\n * Get all block IDs in the tree (flattened).\n */\nexport function getAllBlockIds(tree: BlockNode[]): string[] {\n\tconst ids: string[] = [];\n\n\tfunction collect(nodes: BlockNode[]) {\n\t\tfor (const node of nodes) {\n\t\t\tids.push(node.id);\n\t\t\tcollect(node.children);\n\t\t}\n\t}\n\n\tcollect(tree);\n\treturn ids;\n}\n\n/**\n * Count total blocks in the tree.\n */\nexport function countBlocks(tree: BlockNode[]): number {\n\tlet count = 0;\n\n\tfunction traverse(nodes: BlockNode[]) {\n\t\tfor (const node of nodes) {\n\t\t\tcount++;\n\t\t\ttraverse(node.children);\n\t\t}\n\t}\n\n\ttraverse(tree);\n\treturn count;\n}\n\n/**\n * Get default values for block fields.\n */\nexport function getDefaultValues(\n\tfields:\n\t\t| Record<string, { \"~options\"?: { defaultValue?: unknown } }>\n\t\t| undefined,\n): Record<string, unknown> {\n\tif (!fields) return {};\n\n\tconst values: Record<string, unknown> = {};\n\n\tfor (const [key, field] of Object.entries(fields)) {\n\t\tconst defaultValue = field[\"~options\"]?.defaultValue;\n\t\tif (defaultValue !== undefined) {\n\t\t\tvalues[key] = defaultValue;\n\t\t}\n\t}\n\n\treturn values;\n}\n","/**\n * Block Item Menu\n *\n * Shared menu items for block context menu and dropdown.\n * Provides actions like duplicate, delete, add child, etc.\n */\n\n\"use client\";\n\nimport {\n\tArrowDown,\n\tArrowUp,\n\tCopy,\n\tDotsThreeVertical,\n\tPlus,\n\tTrash,\n} from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useTranslation } from \"../../i18n/hooks.js\";\nimport { Button } from \"../ui/button.js\";\nimport {\n\tContextMenu,\n\tContextMenuContent,\n\tContextMenuItem,\n\tContextMenuSeparator,\n\tContextMenuSub,\n\tContextMenuSubContent,\n\tContextMenuSubTrigger,\n\tContextMenuTrigger,\n} from \"../ui/context-menu.js\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuSeparator,\n\tDropdownMenuSub,\n\tDropdownMenuSubContent,\n\tDropdownMenuSubTrigger,\n\tDropdownMenuTrigger,\n} from \"../ui/dropdown-menu.js\";\nimport { useBlockEditor } from \"./block-editor-context.js\";\nimport { BlockTypeIcon } from \"./block-type-icon.js\";\nimport { findBlockById, findBlockPosition } from \"./utils/tree-utils.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface BlockItemMenuProps {\n\t/** Block ID */\n\tblockId: string;\n\t/** Whether this block can have children */\n\tcanHaveChildren: boolean;\n\t/** Callback for duplicate */\n\tonDuplicate: () => void;\n\t/** Callback for remove */\n\tonRemove: () => void;\n}\n\n// ============================================================================\n// Shared Menu Content\n// ============================================================================\n\ninterface MenuItemsProps extends BlockItemMenuProps {\n\t/** Render function for menu item */\n\tMenuItem: React.ComponentType<{\n\t\tonClick?: () => void;\n\t\tvariant?: \"default\" | \"destructive\";\n\t\tchildren: React.ReactNode;\n\t}>;\n\t/** Render function for separator */\n\tSeparator: React.ComponentType;\n\t/** Render function for submenu */\n\tSubMenu: React.ComponentType<{ children: React.ReactNode }>;\n\t/** Render function for submenu trigger */\n\tSubMenuTrigger: React.ComponentType<{ children: React.ReactNode }>;\n\t/** Render function for submenu content */\n\tSubMenuContent: React.ComponentType<{ children: React.ReactNode }>;\n\t/** Close the menu */\n\tonClose?: () => void;\n}\n\nfunction MenuItems({\n\tblockId,\n\tcanHaveChildren,\n\tonDuplicate,\n\tonRemove,\n\tMenuItem,\n\tSeparator,\n\tSubMenu,\n\tSubMenuTrigger,\n\tSubMenuContent,\n\tonClose,\n}: MenuItemsProps) {\n\tconst { t } = useTranslation();\n\tconst { state, actions } = useBlockEditor();\n\n\t// Get available block types for add actions\n\tconst blockTypes = React.useMemo(() => {\n\t\treturn Object.entries(state.blocks)\n\t\t\t.filter(([type]) => {\n\t\t\t\tif (!state.allowedBlocks) return true;\n\t\t\t\treturn state.allowedBlocks.includes(type);\n\t\t\t})\n\t\t\t.map(([type, def]) => ({\n\t\t\t\ttype,\n\t\t\t\tlabel: getBlockLabel(def),\n\t\t\t}))\n\t\t\t.sort((a, b) => a.label.localeCompare(b.label));\n\t}, [state.blocks, state.allowedBlocks]);\n\n\tconst blockPosition = React.useMemo(\n\t\t() => findBlockPosition(state.content._tree, blockId),\n\t\t[state.content._tree, blockId],\n\t);\n\n\tconst handleAddChild = (blockType: string) => {\n\t\t// Find current block to get children count\n\t\tconst block = findBlockById(state.content._tree, blockId);\n\t\tconst childrenCount = block?.children?.length ?? 0;\n\n\t\tactions.addBlock(blockType, {\n\t\t\tparentId: blockId,\n\t\t\tindex: childrenCount,\n\t\t});\n\n\t\t// Make sure block is expanded\n\t\tif (!state.expandedBlockIds.has(blockId)) {\n\t\t\tactions.toggleExpanded(blockId);\n\t\t}\n\n\t\tonClose?.();\n\t};\n\n\tconst handleAddAbove = (blockType: string) => {\n\t\tif (!blockPosition) return;\n\t\tactions.addBlock(blockType, {\n\t\t\tparentId: blockPosition.parentId,\n\t\t\tindex: blockPosition.index,\n\t\t});\n\t\tonClose?.();\n\t};\n\n\tconst handleAddBelow = (blockType: string) => {\n\t\tif (!blockPosition) return;\n\t\tactions.addBlock(blockType, {\n\t\t\tparentId: blockPosition.parentId,\n\t\t\tindex: blockPosition.index + 1,\n\t\t});\n\t\tonClose?.();\n\t};\n\n\tconst handleDuplicate = () => {\n\t\tonDuplicate();\n\t\tonClose?.();\n\t};\n\n\tconst handleRemove = () => {\n\t\tonRemove();\n\t\tonClose?.();\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t{blockTypes.length > 0 && blockPosition && (\n\t\t\t\t<>\n\t\t\t\t\t<SubMenu>\n\t\t\t\t\t\t<SubMenuTrigger>\n\t\t\t\t\t\t\t<ArrowUp className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t{t(\"blocks.addAbove\")}\n\t\t\t\t\t\t</SubMenuTrigger>\n\t\t\t\t\t\t<SubMenuContent>\n\t\t\t\t\t\t\t{blockTypes.map(({ type, label }) => (\n\t\t\t\t\t\t\t\t<MenuItem key={type} onClick={() => handleAddAbove(type)}>\n\t\t\t\t\t\t\t\t\t<BlockTypeIcon type={type} className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</SubMenuContent>\n\t\t\t\t\t</SubMenu>\n\t\t\t\t\t<SubMenu>\n\t\t\t\t\t\t<SubMenuTrigger>\n\t\t\t\t\t\t\t<ArrowDown className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t{t(\"blocks.addBelow\")}\n\t\t\t\t\t\t</SubMenuTrigger>\n\t\t\t\t\t\t<SubMenuContent>\n\t\t\t\t\t\t\t{blockTypes.map(({ type, label }) => (\n\t\t\t\t\t\t\t\t<MenuItem key={type} onClick={() => handleAddBelow(type)}>\n\t\t\t\t\t\t\t\t\t<BlockTypeIcon type={type} className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</SubMenuContent>\n\t\t\t\t\t</SubMenu>\n\t\t\t\t\t{canHaveChildren && (\n\t\t\t\t\t\t<SubMenu>\n\t\t\t\t\t\t\t<SubMenuTrigger>\n\t\t\t\t\t\t\t\t<Plus className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t\t{t(\"blocks.addChild\")}\n\t\t\t\t\t\t\t</SubMenuTrigger>\n\t\t\t\t\t\t\t<SubMenuContent>\n\t\t\t\t\t\t\t\t{blockTypes.map(({ type, label }) => (\n\t\t\t\t\t\t\t\t\t<MenuItem key={type} onClick={() => handleAddChild(type)}>\n\t\t\t\t\t\t\t\t\t\t<BlockTypeIcon type={type} className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</SubMenuContent>\n\t\t\t\t\t\t</SubMenu>\n\t\t\t\t\t)}\n\t\t\t\t\t<Separator />\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t{/* Duplicate */}\n\t\t\t<MenuItem onClick={handleDuplicate}>\n\t\t\t\t<Copy className=\"h-4 w-4\" />\n\t\t\t\t{t(\"common.duplicate\")}\n\t\t\t</MenuItem>\n\n\t\t\t<Separator />\n\n\t\t\t{/* Delete */}\n\t\t\t<MenuItem variant=\"destructive\" onClick={handleRemove}>\n\t\t\t\t<Trash className=\"h-4 w-4\" />\n\t\t\t\t{t(\"common.delete\")}\n\t\t\t</MenuItem>\n\t\t</>\n\t);\n}\n\n// ============================================================================\n// Context Menu Wrapper\n// ============================================================================\n\nexport interface BlockItemContextMenuProps extends BlockItemMenuProps {\n\tchildren: React.ReactNode;\n}\n\nexport function BlockItemContextMenu({\n\tchildren,\n\t...menuProps\n}: BlockItemContextMenuProps) {\n\treturn (\n\t\t<ContextMenu>\n\t\t\t<ContextMenuTrigger className=\"block\">{children}</ContextMenuTrigger>\n\t\t\t<ContextMenuContent>\n\t\t\t\t<MenuItems\n\t\t\t\t\t{...menuProps}\n\t\t\t\t\tMenuItem={ContextMenuItem}\n\t\t\t\t\tSeparator={ContextMenuSeparator}\n\t\t\t\t\tSubMenu={ContextMenuSub}\n\t\t\t\t\tSubMenuTrigger={ContextMenuSubTrigger}\n\t\t\t\t\tSubMenuContent={ContextMenuSubContent}\n\t\t\t\t/>\n\t\t\t</ContextMenuContent>\n\t\t</ContextMenu>\n\t);\n}\n\n// ============================================================================\n// Dropdown Menu Button\n// ============================================================================\n\nexport interface BlockItemDropdownMenuProps extends BlockItemMenuProps {\n\tclassName?: string;\n}\n\nexport function BlockItemDropdownMenu({\n\tclassName,\n\t...menuProps\n}: BlockItemDropdownMenuProps) {\n\tconst [open, setOpen] = React.useState(false);\n\n\treturn (\n\t\t<DropdownMenu open={open} onOpenChange={setOpen}>\n\t\t\t<DropdownMenuTrigger\n\t\t\t\trender={\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t/>\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t<DotsThreeVertical className=\"h-4 w-4\" />\n\t\t\t\t<span className=\"sr-only\">Block actions</span>\n\t\t\t</DropdownMenuTrigger>\n\t\t\t<DropdownMenuContent align=\"end\">\n\t\t\t\t<MenuItems\n\t\t\t\t\t{...menuProps}\n\t\t\t\t\tMenuItem={DropdownMenuItem}\n\t\t\t\t\tSeparator={DropdownMenuSeparator}\n\t\t\t\t\tSubMenu={DropdownMenuSub}\n\t\t\t\t\tSubMenuTrigger={DropdownMenuSubTrigger}\n\t\t\t\t\tSubMenuContent={DropdownMenuSubContent}\n\t\t\t\t\tonClose={() => setOpen(false)}\n\t\t\t\t/>\n\t\t\t</DropdownMenuContent>\n\t\t</DropdownMenu>\n\t);\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nimport type { BlockDefinition } from \"../../builder/block/types.js\";\n\nfunction getBlockLabel(blockDef: BlockDefinition): string {\n\tif (!blockDef.label) {\n\t\treturn blockDef.name || \"Block\";\n\t}\n\n\tconst label = blockDef.label;\n\n\tif (typeof label === \"string\") {\n\t\treturn label;\n\t}\n\n\tif (typeof label === \"function\") {\n\t\treturn blockDef.name || \"Block\";\n\t}\n\n\tif (\"key\" in label) {\n\t\treturn label.fallback || blockDef.name || \"Block\";\n\t}\n\n\tconst localeMap = label as Record<string, string>;\n\treturn (\n\t\tlocaleMap.en || Object.values(localeMap)[0] || blockDef.name || \"Block\"\n\t);\n}\n","/**\n * Block Item\n *\n * Single draggable block item in the tree.\n */\n\n\"use client\";\n\nimport { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { CaretDown, CaretRight, DotsSixVertical } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport type { BlockNode } from \"../../blocks/types.js\";\nimport { useFocusOptional } from \"../../context/focus-context.js\";\nimport { cn } from \"../../lib/utils.js\";\nimport {\n\tuseBlockEditor,\n\tuseIsBlockExpanded,\n\tuseIsBlockSelected,\n} from \"./block-editor-context.js\";\nimport { BlockItemDropdownMenu } from \"./block-item-menu.js\";\nimport { BlockTree } from \"./block-tree.js\";\nimport { BlockTypeIcon } from \"./block-type-icon.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type BlockItemProps = {\n\t/** Block node data */\n\tblock: BlockNode;\n\t/** Nesting level (0 = root) */\n\tlevel: number;\n\t/** Index in parent's children */\n\tindex: number;\n\t/** Parent block ID (null = root) */\n\tparentId: string | null;\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function BlockItem({ block, level, index, parentId }: BlockItemProps) {\n\tconst { state, actions } = useBlockEditor();\n\tconst blockDef = state.blocks[block.type];\n\tconst isSelected = useIsBlockSelected(block.id);\n\tconst isExpanded = useIsBlockExpanded(block.id);\n\tconst canHaveChildren = blockDef?.allowChildren ?? false;\n\tconst focusContext = useFocusOptional();\n\n\t// Drag and drop\n\tconst {\n\t\tattributes,\n\t\tlisteners,\n\t\tsetNodeRef,\n\t\ttransform,\n\t\ttransition,\n\t\tisDragging,\n\t\tisOver,\n\t\tactive,\n\t} = useSortable({ id: block.id });\n\n\tconst style = {\n\t\ttransform: CSS.Transform.toString(transform),\n\t\ttransition,\n\t};\n\n\t// Show drop indicator when dragging over this item (but not self)\n\tconst showDropIndicator = isOver && active?.id !== block.id;\n\n\t// Get block label from values or definition\n\tconst values = state.content._values[block.id];\n\tconst blockLabel = getBlockLabel(block, blockDef, values);\n\n\t// Handlers\n\tconst handleSelect = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tfocusContext?.clearFocus();\n\t\tactions.selectBlock(block.id);\n\t};\n\n\tconst handleToggleExpand = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tactions.toggleExpanded(block.id);\n\t};\n\n\tconst handleDuplicate = React.useCallback(() => {\n\t\tactions.duplicateBlock(block.id);\n\t}, [actions, block.id]);\n\n\tconst handleRemove = React.useCallback(() => {\n\t\tactions.removeBlock(block.id);\n\t}, [actions, block.id]);\n\n\treturn (\n\t\t<div\n\t\t\tref={setNodeRef}\n\t\t\tstyle={style}\n\t\t\tclassName={cn(\"group/item relative\", isDragging && \"opacity-50\")}\n\t\t>\n\t\t\t{/* Drop indicator line */}\n\t\t\t{showDropIndicator && (\n\t\t\t\t<div className=\"absolute -top-0.5 left-0 right-0 z-10 h-0.5 bg-primary\" />\n\t\t\t)}\n\n\t\t\t{/* Block row */}\n\t\t\t<div\n\t\t\t\trole=\"button\"\n\t\t\t\ttabIndex={0}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex min-w-[200px] cursor-pointer items-center gap-1.5 rounded-md px-2 py-1.5 transition-colors\",\n\t\t\t\t\t\"hover:bg-accent focus:outline-none focus-visible:ring-2 focus-visible:ring-primary\",\n\t\t\t\t\tisSelected && \"bg-accent ring-2 ring-primary\",\n\t\t\t\t\tshowDropIndicator && \"ring-1 ring-primary/30\",\n\t\t\t\t)}\n\t\t\t\tonClick={handleSelect}\n\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\tif (e.key === \"Enter\" || e.key === \" \") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\thandleSelect(e as unknown as React.MouseEvent);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{/* Drag handle */}\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"cursor-grab opacity-0 transition-opacity group-hover/item:opacity-100 active:cursor-grabbing\"\n\t\t\t\t\t{...attributes}\n\t\t\t\t\t{...listeners}\n\t\t\t\t>\n\t\t\t\t\t<DotsSixVertical className=\"h-4 w-4 text-muted-foreground\" />\n\t\t\t\t</button>\n\n\t\t\t\t{/* Expand/collapse for layout blocks */}\n\t\t\t\t{canHaveChildren ? (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleToggleExpand}\n\t\t\t\t\t\tclassName=\"p-0.5 text-muted-foreground hover:text-foreground\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{isExpanded ? (\n\t\t\t\t\t\t\t<CaretDown className=\"h-4 w-4\" />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<CaretRight className=\"h-4 w-4\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</button>\n\t\t\t\t) : null}\n\n\t\t\t\t{/* Block icon */}\n\t\t\t\t<BlockTypeIcon\n\t\t\t\t\ttype={block.type}\n\t\t\t\t\tclassName=\"h-4 w-4 shrink-0 text-muted-foreground\"\n\t\t\t\t/>\n\n\t\t\t\t{/* Block label */}\n\t\t\t\t<span className=\"flex-1 min-w-0 truncate text-sm\">{blockLabel}</span>\n\n\t\t\t\t{/* Actions */}\n\t\t\t\t<div className=\"flex items-center\">\n\t\t\t\t\t<BlockItemDropdownMenu\n\t\t\t\t\t\tblockId={block.id}\n\t\t\t\t\t\tcanHaveChildren={canHaveChildren}\n\t\t\t\t\t\tonDuplicate={handleDuplicate}\n\t\t\t\t\t\tonRemove={handleRemove}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"h-8 w-8 sm:h-7 sm:w-7 transition-opacity\",\n\t\t\t\t\t\t\t\"opacity-100 sm:opacity-0 sm:group-hover/item:opacity-100\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Children */}\n\t\t\t{canHaveChildren && isExpanded && (\n\t\t\t\t<div className=\"ml-4 mt-1 border-l border-border/40 pl-3\">\n\t\t\t\t\t<BlockTree\n\t\t\t\t\t\tblocks={block.children}\n\t\t\t\t\t\tlevel={level + 1}\n\t\t\t\t\t\tparentId={block.id}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nimport type { BlockDefinition } from \"../../builder/block/types.js\";\n\nfunction getBlockLabel(\n\tblock: BlockNode,\n\tblockDef: BlockDefinition | undefined,\n\tvalues: Record<string, unknown> | undefined,\n): string {\n\t// Try to get meaningful label from values\n\tif (values) {\n\t\tconst title = values.title || values.name || values.label || values.heading;\n\t\tif (title && typeof title === \"string\") {\n\t\t\treturn title.slice(0, 50);\n\t\t}\n\t}\n\n\t// Fall back to block type label\n\tif (blockDef?.label) {\n\t\tconst label = blockDef.label;\n\n\t\t// Handle string directly\n\t\tif (typeof label === \"string\") {\n\t\t\treturn label;\n\t\t}\n\n\t\t// Handle function (not ideal but return type name)\n\t\tif (typeof label === \"function\") {\n\t\t\treturn block.type.charAt(0).toUpperCase() + block.type.slice(1);\n\t\t}\n\n\t\t// Handle key-based translation object\n\t\tif (\"key\" in label) {\n\t\t\treturn label.fallback || block.type;\n\t\t}\n\n\t\t// Handle I18nLocaleMap - use English or first available\n\t\tconst localeLabel = (label as Record<string, string>).en;\n\t\tif (localeLabel) {\n\t\t\treturn localeLabel;\n\t\t}\n\t\tconst firstValue = Object.values(label)[0];\n\t\tif (typeof firstValue === \"string\") {\n\t\t\treturn firstValue;\n\t\t}\n\t}\n\n\t// Fall back to type name\n\treturn block.type.charAt(0).toUpperCase() + block.type.slice(1);\n}\n","/**\n * Block Tree\n *\n * Renders a list of blocks with drag-and-drop support.\n */\n\n\"use client\";\n\nimport {\n\tSortableContext,\n\tverticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport * as React from \"react\";\nimport type { BlockNode } from \"../../blocks/types.js\";\nimport { cn } from \"../../lib/utils.js\";\nimport { BlockInsertButton } from \"./block-insert-button.js\";\nimport { BlockItem } from \"./block-item.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type BlockTreeProps = {\n\t/** Block nodes to render */\n\tblocks: BlockNode[];\n\t/** Nesting level (0 = root) */\n\tlevel: number;\n\t/** Parent block ID (null = root) */\n\tparentId: string | null;\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function BlockTree({ blocks, level, parentId }: BlockTreeProps) {\n\t// Get block IDs for sortable context\n\tconst blockIds = React.useMemo(() => blocks.map((b) => b.id), [blocks]);\n\n\treturn (\n\t\t<div className=\"min-w-fit space-y-1\">\n\t\t\t<SortableContext items={blockIds} strategy={verticalListSortingStrategy}>\n\t\t\t\t{blocks.map((block, index) => (\n\t\t\t\t\t<BlockItem\n\t\t\t\t\t\tkey={block.id}\n\t\t\t\t\t\tblock={block}\n\t\t\t\t\t\tlevel={level}\n\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\tparentId={parentId}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</SortableContext>\n\n\t\t\t{/* Single add button at the end of this level */}\n\t\t\t<BlockInsertButton\n\t\t\t\tposition={{ parentId, index: blocks.length }}\n\t\t\t\tcompact\n\t\t\t\tclassName={level > 0 ? \"mt-1\" : \"mt-2\"}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","/**\n * Block Canvas\n *\n * Main canvas area for displaying and editing the block tree.\n */\n\n\"use client\";\n\nimport {\n\tclosestCenter,\n\tDndContext,\n\ttype DragEndEvent,\n\tDragOverlay,\n\ttype DragStartEvent,\n\tKeyboardSensor,\n\tPointerSensor,\n\tuseSensor,\n\tuseSensors,\n} from \"@dnd-kit/core\";\nimport { sortableKeyboardCoordinates } from \"@dnd-kit/sortable\";\nimport { DotsSixVertical } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useBlockEditor } from \"./block-editor-context.js\";\nimport { BlockInsertButton } from \"./block-insert-button.js\";\nimport { BlockTree } from \"./block-tree.js\";\nimport { BlockTypeIcon } from \"./block-type-icon.js\";\nimport { findBlockById, findBlockPosition } from \"./utils/tree-utils.js\";\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function BlockCanvas() {\n\tconst { state, actions } = useBlockEditor();\n\tconst [activeId, setActiveId] = React.useState<string | null>(null);\n\n\t// Configure drag sensors with keyboard support\n\tconst sensors = useSensors(\n\t\tuseSensor(PointerSensor, {\n\t\t\tactivationConstraint: {\n\t\t\t\tdistance: 8, // Require 8px of movement before starting drag\n\t\t\t},\n\t\t}),\n\t\tuseSensor(KeyboardSensor, {\n\t\t\tcoordinateGetter: sortableKeyboardCoordinates,\n\t\t}),\n\t);\n\n\t// Handle drag start - track active item for overlay\n\tconst handleDragStart = (event: DragStartEvent) => {\n\t\tsetActiveId(event.active.id as string);\n\t};\n\n\t// Handle drag end\n\tconst handleDragEnd = (event: DragEndEvent) => {\n\t\tconst { active, over } = event;\n\t\tsetActiveId(null);\n\n\t\tif (!over || active.id === over.id) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst activeId = active.id as string;\n\t\tconst overId = over.id as string;\n\n\t\t// Find positions of both blocks\n\t\tconst activePosition = findBlockPosition(state.content._tree, activeId);\n\t\tconst overPosition = findBlockPosition(state.content._tree, overId);\n\n\t\tif (!activePosition || !overPosition) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Calculate new index based on relative positions\n\t\t// If moving within same parent\n\t\tif (activePosition.parentId === overPosition.parentId) {\n\t\t\t// If dragging down (active index < over index), insert at over's position\n\t\t\t// If dragging up (active index > over index), insert at over's position\n\t\t\tconst newIndex =\n\t\t\t\tactivePosition.index < overPosition.index\n\t\t\t\t\t? overPosition.index\n\t\t\t\t\t: overPosition.index;\n\n\t\t\tactions.moveBlock(activeId, {\n\t\t\t\tparentId: overPosition.parentId,\n\t\t\t\tindex: newIndex,\n\t\t\t});\n\t\t} else {\n\t\t\t// Moving to different parent - insert at over's position\n\t\t\tactions.moveBlock(activeId, {\n\t\t\t\tparentId: overPosition.parentId,\n\t\t\t\tindex: overPosition.index,\n\t\t\t});\n\t\t}\n\t};\n\n\t// Get active block for overlay\n\tconst activeBlock = activeId\n\t\t? findBlockById(state.content._tree, activeId)\n\t\t: null;\n\tconst activeBlockDef = activeBlock ? state.blocks[activeBlock.type] : null;\n\n\t// Empty state\n\tif (state.content._tree.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"flex h-full flex-col items-center justify-center p-8\">\n\t\t\t\t<div className=\"mb-4 text-center text-muted-foreground\">\n\t\t\t\t\t<p className=\"text-lg font-medium\">No blocks yet</p>\n\t\t\t\t\t<p className=\"text-sm\">Add your first block to get started</p>\n\t\t\t\t</div>\n\t\t\t\t<BlockInsertButton position={{ parentId: null, index: 0 }} />\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"\">\n\t\t\t<DndContext\n\t\t\t\tsensors={sensors}\n\t\t\t\tcollisionDetection={closestCenter}\n\t\t\t\tonDragStart={handleDragStart}\n\t\t\t\tonDragEnd={handleDragEnd}\n\t\t\t>\n\t\t\t\t<BlockTree blocks={state.content._tree} level={0} parentId={null} />\n\n\t\t\t\t{/* Drag overlay - shows what's being dragged */}\n\t\t\t\t<DragOverlay>\n\t\t\t\t\t{activeBlock && (\n\t\t\t\t\t\t<div className=\"flex items-center gap-2 rounded-md border bg-background p-2 shadow-lg\">\n\t\t\t\t\t\t\t<DotsSixVertical className=\"h-4 w-4 text-muted-foreground\" />\n\t\t\t\t\t\t\t<BlockTypeIcon\n\t\t\t\t\t\t\t\ttype={activeBlock.type}\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<span className=\"text-sm font-medium\">\n\t\t\t\t\t\t\t\t{getBlockLabel(activeBlockDef, activeBlock.type)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</DragOverlay>\n\t\t\t</DndContext>\n\n\t\t\t{/* Add block at end */}\n\t\t\t<div className=\"mt-4\">\n\t\t\t\t<BlockInsertButton\n\t\t\t\t\tposition={{ parentId: null, index: state.content._tree.length }}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// Helper to get block label\nfunction getBlockLabel(\n\tblockDef: { label?: unknown } | null | undefined,\n\ttype: string,\n): string {\n\tif (!blockDef?.label) {\n\t\treturn type.charAt(0).toUpperCase() + type.slice(1);\n\t}\n\n\tconst label = blockDef.label;\n\n\tif (typeof label === \"string\") return label;\n\tif (typeof label === \"object\" && label !== null) {\n\t\tif (\"en\" in label && typeof label.en === \"string\") return label.en;\n\t\tconst first = Object.values(label)[0];\n\t\tif (typeof first === \"string\") return first;\n\t}\n\n\treturn type.charAt(0).toUpperCase() + type.slice(1);\n}\n","/**\n * Block Form\n *\n * Form for editing the selected block's values.\n */\n\n\"use client\";\n\nimport { X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport type { BlockNode } from \"../../blocks/types.js\";\nimport type { FieldDefinition } from \"../../builder/field/field.js\";\nimport { useResolveText } from \"../../i18n/hooks.js\";\nimport { FormField } from \"../../views/collection/form-field.js\";\nimport { Button } from \"../ui/button.js\";\nimport {\n\tuseBlockEditor,\n\tuseSelectedBlockDefinition,\n} from \"./block-editor-context.js\";\nimport { BlockTypeIcon } from \"./block-type-icon.js\";\nimport { findBlockById } from \"./utils/tree-utils.js\";\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function BlockForm() {\n\tconst { state, actions } = useBlockEditor();\n\tconst blockDef = useSelectedBlockDefinition();\n\n\t// Find block node\n\tconst block = React.useMemo(() => {\n\t\tif (!state.selectedBlockId) return null;\n\t\treturn findBlockById(state.content._tree, state.selectedBlockId);\n\t}, [state.content._tree, state.selectedBlockId]);\n\n\tif (!state.selectedBlockId || !block || !blockDef) {\n\t\treturn <BlockFormEmpty />;\n\t}\n\n\t// Get block label\n\tconst blockLabel = getBlockDisplayLabel(blockDef, block);\n\n\t// Handle close (deselect block)\n\tconst handleClose = () => {\n\t\tactions.selectBlock(null);\n\t};\n\n\treturn (\n\t\t<div className=\"flex h-full flex-col\">\n\t\t\t{/* Header */}\n\t\t\t<div className=\"flex items-center gap-2 border-b px-4 py-3\">\n\t\t\t\t<BlockTypeIcon type={block.type} size={18} />\n\t\t\t\t<h3 className=\"flex-1 font-medium text-sm\">{blockLabel}</h3>\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\tclassName=\"h-6 w-6 shrink-0\"\n\t\t\t\t\tonClick={handleClose}\n\t\t\t\t\ttitle=\"Close\"\n\t\t\t\t>\n\t\t\t\t\t<X className=\"h-4 w-4\" />\n\t\t\t\t</Button>\n\t\t\t</div>\n\n\t\t\t{/* Description */}\n\t\t\t{blockDef.description && (\n\t\t\t\t<p className=\"border-b px-4 py-2 text-sm text-muted-foreground\">\n\t\t\t\t\t{getDescriptionText(blockDef.description)}\n\t\t\t\t</p>\n\t\t\t)}\n\n\t\t\t{/* Fields */}\n\t\t\t<div className=\"flex-1 overflow-auto p-4\">\n\t\t\t\t{blockDef.fields ? (\n\t\t\t\t\t// Key by blockId to force remount when switching blocks\n\t\t\t\t\t// This prevents React from reusing Controller instances\n\t\t\t\t\t// which would cause values to leak between blocks with same field names\n\t\t\t\t\t<BlockFormFields\n\t\t\t\t\t\tkey={state.selectedBlockId}\n\t\t\t\t\t\tfields={blockDef.fields}\n\t\t\t\t\t\tblockId={state.selectedBlockId!}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<div className=\"text-center text-sm text-muted-foreground\">\n\t\t\t\t\t\tThis block has no editable fields.\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Empty State\n// ============================================================================\n\nfunction BlockFormEmpty() {\n\treturn (\n\t\t<div className=\"flex h-full items-center justify-center text-center\">\n\t\t\t<div className=\"text-muted-foreground\">\n\t\t\t\t<p className=\"text-lg font-medium\">No block selected</p>\n\t\t\t\t<p className=\"text-sm\">Click a block to edit its content</p>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Block Form Fields\n// ============================================================================\n\ntype BlockFormFieldsProps = {\n\tfields: Record<string, FieldDefinition>;\n\tblockId: string;\n};\n\nfunction BlockFormFields({ fields, blockId }: BlockFormFieldsProps) {\n\treturn (\n\t\t<div className=\"space-y-4\">\n\t\t\t{Object.entries(fields).map(([fieldName, fieldDef]) => (\n\t\t\t\t<BlockFormField\n\t\t\t\t\t// Include blockId in key to ensure fresh Controller instances per block\n\t\t\t\t\tkey={`${blockId}:${fieldName}`}\n\t\t\t\t\tname={fieldName}\n\t\t\t\t\tblockId={blockId}\n\t\t\t\t\tdefinition={fieldDef}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Individual Field - Uses registered field components with scoped names\n// ============================================================================\n\ntype BlockFormFieldProps = {\n\tname: string;\n\tblockId: string;\n\tdefinition: FieldDefinition;\n};\n\nfunction BlockFormField({ name, blockId, definition }: BlockFormFieldProps) {\n\tconst resolveText = useResolveText();\n\tconst options = (definition as any)[\"~options\"] || {};\n\tconst fieldType = definition.name;\n\n\t// Resolve i18n texts\n\tconst label = resolveText(options.label, name);\n\tconst description = resolveText(options.description, \"\");\n\tconst placeholder = resolveText(options.placeholder, \"\");\n\n\t// Scope the field name to the block's values in the parent form\n\t// This ensures block fields don't conflict with collection-level fields\n\tconst scopedName = `content._values.${blockId}.${name}`;\n\n\t// Check if field has a registered component\n\tconst FieldComponent = definition.field?.component as\n\t\t| React.ComponentType<any>\n\t\t| undefined;\n\n\t// If field has a registered component, use it with scoped name\n\tif (FieldComponent) {\n\t\tconst componentProps = {\n\t\t\tname: scopedName,\n\t\t\tlabel,\n\t\t\tdescription,\n\t\t\tplaceholder,\n\t\t\trequired: options.required ?? false,\n\t\t\tdisabled: options.disabled ?? false,\n\t\t\treadOnly: options.readOnly ?? false,\n\t\t\tlocalized: options.localized ?? false, // IMPORTANT: Pass localized for LocaleBadge\n\t\t\t// Pass all field-specific options\n\t\t\t...stripUiOptions(options),\n\t\t};\n\n\t\treturn <FieldComponent {...componentProps} />;\n\t}\n\n\t// Fallback to FormField for unregistered field types\n\treturn (\n\t\t<FormField\n\t\t\tname={scopedName}\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tplaceholder={placeholder}\n\t\t\trequired={options.required}\n\t\t\tdisabled={options.disabled}\n\t\t\tlocalized={options.localized} // IMPORTANT: Pass localized for LocaleBadge\n\t\t\ttype={fieldType as any}\n\t\t\toptions={options.options}\n\t\t/>\n\t);\n}\n\n// Strip UI-specific options that shouldn't be passed to field components\nfunction stripUiOptions(options: Record<string, any>) {\n\tconst {\n\t\tlabel,\n\t\tdescription,\n\t\tplaceholder,\n\t\trequired,\n\t\tdisabled,\n\t\treadOnly,\n\t\thidden,\n\t\tvisible,\n\t\tlocalized,\n\t\tlocale,\n\t\tcompute,\n\t\tonChange: _onChange,\n\t\t...rest\n\t} = options;\n\treturn rest;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nimport type { BlockDefinition } from \"../../builder/block/types.js\";\nimport type { I18nText } from \"../../i18n/types.js\";\n\nfunction getDescriptionText(description: I18nText | undefined): string {\n\tif (!description) return \"\";\n\n\tif (typeof description === \"string\") {\n\t\treturn description;\n\t}\n\n\tif (typeof description === \"function\") {\n\t\treturn \"\";\n\t}\n\n\tif (\"key\" in description) {\n\t\treturn description.fallback || \"\";\n\t}\n\n\tconst localeMap = description as Record<string, string>;\n\treturn localeMap.en || Object.values(localeMap)[0] || \"\";\n}\n\nfunction getBlockDisplayLabel(\n\tblockDef: BlockDefinition,\n\tblock: BlockNode,\n): string {\n\tif (!blockDef.label) {\n\t\treturn block.type.charAt(0).toUpperCase() + block.type.slice(1);\n\t}\n\n\tconst label = blockDef.label;\n\n\tif (typeof label === \"string\") {\n\t\treturn label;\n\t}\n\n\tif (typeof label === \"function\") {\n\t\treturn block.type.charAt(0).toUpperCase() + block.type.slice(1);\n\t}\n\n\tif (\"key\" in label) {\n\t\treturn label.fallback || block.type;\n\t}\n\n\tconst localeMap = label as Record<string, string>;\n\treturn localeMap.en || Object.values(localeMap)[0] || block.type;\n}\n","/**\n * Block Editor Layout\n *\n * Side-by-side layout: tree on left, form on right when block selected.\n * Uses resizable panels for flexible sizing.\n */\n\n\"use client\";\n\nimport * as React from \"react\";\nimport { useFocusOptional } from \"../../context/focus-context.js\";\nimport { cn } from \"../../lib/utils.js\";\nimport {\n\tResizableHandle,\n\tResizablePanel,\n\tResizablePanelGroup,\n} from \"../ui/resizable.js\";\nimport { BlockCanvas } from \"./block-canvas.js\";\nimport { useBlockEditor } from \"./block-editor-context.js\";\nimport { BlockForm } from \"./block-form.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type BlockEditorLayoutProps = {\n\t/** Custom class name */\n\tclassName?: string;\n\t/** Minimum height for the editor */\n\tminHeight?: number;\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function BlockEditorLayout({\n\tclassName,\n\tminHeight = 500,\n}: BlockEditorLayoutProps) {\n\tconst { state, actions } = useBlockEditor();\n\tconst focusContext = useFocusOptional();\n\tconst hasSelectedBlock = !!state.selectedBlockId;\n\tconst hasBlocks = state.content._tree.length > 0;\n\n\t// Sync FocusContext block focus to BlockEditor\n\tReact.useEffect(() => {\n\t\tif (!focusContext) return;\n\n\t\tconst { state: focusState } = focusContext;\n\n\t\tif (focusState.type === \"block\") {\n\t\t\tconst blockId = focusState.blockId;\n\n\t\t\t// Select the block\n\t\t\tactions.selectBlock(blockId);\n\n\t\t\t// Expand if collapsed\n\t\t\tif (!state.expandedBlockIds.has(blockId)) {\n\t\t\t\tactions.toggleExpanded(blockId);\n\t\t\t}\n\t\t}\n\t}, [focusContext?.state, state.expandedBlockIds, actions]);\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"rounded-lg border bg-background overflow-hidden\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tstyle={{ height: minHeight }}\n\t\t>\n\t\t\t<ResizablePanelGroup orientation=\"horizontal\" className=\"h-full\">\n\t\t\t\t{/* Block Tree Panel - always visible */}\n\t\t\t\t<ResizablePanel\n\t\t\t\t\tdefaultSize={hasSelectedBlock ? 40 : 100}\n\t\t\t\t\tminSize={20}\n\t\t\t\t\tclassName=\"bg-muted/30\"\n\t\t\t\t>\n\t\t\t\t\t<div className=\"h-full overflow-x-auto overflow-y-auto p-2\">\n\t\t\t\t\t\t<div className=\"min-w-fit\">\n\t\t\t\t\t\t\t<BlockCanvas />\n\n\t\t\t\t\t\t\t{/* Empty state hint when no blocks */}\n\t\t\t\t\t\t\t{!hasBlocks && (\n\t\t\t\t\t\t\t\t<div className=\"p-4 text-center text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t\t\tClick the + button above to add your first block\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</ResizablePanel>\n\n\t\t\t\t{/* Resize handle and form panel - only when block selected */}\n\t\t\t\t{hasSelectedBlock && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<ResizableHandle withHandle />\n\t\t\t\t\t\t<ResizablePanel defaultSize={60} minSize={30}>\n\t\t\t\t\t\t\t<div className=\"h-full overflow-auto\">\n\t\t\t\t\t\t\t\t<BlockForm />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</ResizablePanel>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</ResizablePanelGroup>\n\t\t</div>\n\t);\n}\n","/**\n * Block Editor Provider\n *\n * Provides state and actions for the block editor.\n */\n\n\"use client\";\n\nimport * as React from \"react\";\nimport type { BlockContent, BlockNode } from \"../../blocks/types.js\";\nimport type { BlockDefinition } from \"../../builder/block/types.js\";\nimport {\n\ttype BlockEditorActions,\n\tBlockEditorContextProvider,\n\ttype BlockEditorState,\n} from \"./block-editor-context.js\";\nimport {\n\tduplicateBlockInTree,\n\tfindBlockById,\n\tgetAllBlockIds,\n\tgetDefaultValues,\n\ttype InsertPosition,\n\tinsertBlockInTree,\n\tmoveBlockInTree,\n\tremoveBlockFromTree,\n} from \"./utils/tree-utils.js\";\n\n// ============================================================================\n// Props\n// ============================================================================\n\nexport type BlockEditorProviderProps = {\n\t/** Initial/controlled content */\n\tvalue: BlockContent;\n\t/** Change handler */\n\tonChange: (content: BlockContent) => void;\n\t/** Registered blocks */\n\tblocks: Record<string, BlockDefinition>;\n\t/** Allowed block types (optional filter) */\n\tallowedBlocks?: string[];\n\t/** Current locale */\n\tlocale?: string;\n\t/** Children */\n\tchildren: React.ReactNode;\n};\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\nexport function BlockEditorProvider({\n\tvalue,\n\tonChange,\n\tblocks,\n\tallowedBlocks,\n\tlocale = \"en\",\n\tchildren,\n}: BlockEditorProviderProps) {\n\t// Selection state\n\tconst [selectedBlockId, setSelectedBlockId] = React.useState<string | null>(\n\t\tnull,\n\t);\n\n\t// Expanded blocks state\n\tconst [expandedBlockIds, setExpandedBlockIds] = React.useState<Set<string>>(\n\t\t() => new Set(),\n\t);\n\n\t// Library state\n\tconst [isLibraryOpen, setIsLibraryOpen] = React.useState(false);\n\tconst [insertPosition, setInsertPosition] =\n\t\tReact.useState<InsertPosition | null>(null);\n\n\t// Actions\n\tconst actions: BlockEditorActions = React.useMemo(\n\t\t() => ({\n\t\t\t// Selection\n\t\t\tselectBlock: (id) => {\n\t\t\t\tsetSelectedBlockId(id);\n\t\t\t\t// Close library when selecting a block\n\t\t\t\tif (id !== null) {\n\t\t\t\t\tsetIsLibraryOpen(false);\n\t\t\t\t\tsetInsertPosition(null);\n\t\t\t\t}\n\t\t\t},\n\n\t\t\ttoggleExpanded: (id) => {\n\t\t\t\tsetExpandedBlockIds((prev) => {\n\t\t\t\t\tconst next = new Set(prev);\n\t\t\t\t\tif (next.has(id)) {\n\t\t\t\t\t\tnext.delete(id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnext.add(id);\n\t\t\t\t\t}\n\t\t\t\t\treturn next;\n\t\t\t\t});\n\t\t\t},\n\n\t\t\texpandAll: () => {\n\t\t\t\tconst allIds = getAllBlockIds(value._tree);\n\t\t\t\tsetExpandedBlockIds(new Set(allIds));\n\t\t\t},\n\n\t\t\tcollapseAll: () => {\n\t\t\t\tsetExpandedBlockIds(new Set());\n\t\t\t},\n\n\t\t\t// CRUD\n\t\t\taddBlock: (type, position) => {\n\t\t\t\tconst blockDef = blocks[type];\n\t\t\t\tif (!blockDef) {\n\t\t\t\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\t\t\t\tconsole.warn(`Block type \"${type}\" not found`);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst newBlock: BlockNode = {\n\t\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\t\ttype,\n\t\t\t\t\tchildren: [],\n\t\t\t\t};\n\n\t\t\t\tconst newValues = getDefaultValues(blockDef.fields);\n\n\t\t\t\tonChange({\n\t\t\t\t\t_tree: insertBlockInTree(value._tree, newBlock, position),\n\t\t\t\t\t_values: { ...value._values, [newBlock.id]: newValues },\n\t\t\t\t});\n\n\t\t\t\t// Select the new block and close library\n\t\t\t\tsetSelectedBlockId(newBlock.id);\n\t\t\t\tsetIsLibraryOpen(false);\n\t\t\t\tsetInsertPosition(null);\n\n\t\t\t\t// Expand parent if inserting as child\n\t\t\t\tif (position.parentId) {\n\t\t\t\t\tsetExpandedBlockIds((prev) => new Set([...prev, position.parentId!]));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tremoveBlock: (id) => {\n\t\t\t\tconst { newTree, removedIds } = removeBlockFromTree(value._tree, id);\n\t\t\t\tconst newValues = { ...value._values };\n\t\t\t\tfor (const removedId of removedIds) {\n\t\t\t\t\tdelete newValues[removedId];\n\t\t\t\t}\n\n\t\t\t\tonChange({ _tree: newTree, _values: newValues });\n\n\t\t\t\t// Clear selection if removed block was selected\n\t\t\t\tif (selectedBlockId === id || removedIds.includes(selectedBlockId!)) {\n\t\t\t\t\tsetSelectedBlockId(null);\n\t\t\t\t}\n\n\t\t\t\t// Clear from expanded\n\t\t\t\tsetExpandedBlockIds((prev) => {\n\t\t\t\t\tconst next = new Set(prev);\n\t\t\t\t\tfor (const removedId of removedIds) {\n\t\t\t\t\t\tnext.delete(removedId);\n\t\t\t\t\t}\n\t\t\t\t\treturn next;\n\t\t\t\t});\n\t\t\t},\n\n\t\t\tduplicateBlock: (id) => {\n\t\t\t\tconst { newTree, newIds, newValues } = duplicateBlockInTree(\n\t\t\t\t\tvalue._tree,\n\t\t\t\t\tvalue._values,\n\t\t\t\t\tid,\n\t\t\t\t);\n\n\t\t\t\tonChange({\n\t\t\t\t\t_tree: newTree,\n\t\t\t\t\t_values: { ...value._values, ...newValues },\n\t\t\t\t});\n\n\t\t\t\t// Select the first duplicated block\n\t\t\t\tif (newIds.length > 0) {\n\t\t\t\t\tsetSelectedBlockId(newIds[0]);\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Reorder\n\t\t\tmoveBlock: (id, toPosition) => {\n\t\t\t\t// Don't allow moving into itself or its children\n\t\t\t\tconst block = findBlockById(value._tree, id);\n\t\t\t\tif (!block) return;\n\n\t\t\t\t// Check if target parent is a child of the block being moved\n\t\t\t\tif (toPosition.parentId) {\n\t\t\t\t\tconst isChildOfSelf = findBlockById(\n\t\t\t\t\t\tblock.children,\n\t\t\t\t\t\ttoPosition.parentId,\n\t\t\t\t\t);\n\t\t\t\t\tif (isChildOfSelf || toPosition.parentId === id) {\n\t\t\t\t\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\t\t\t\t\tconsole.warn(\"Cannot move block into itself or its children\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tonChange({\n\t\t\t\t\t...value,\n\t\t\t\t\t_tree: moveBlockInTree(value._tree, id, toPosition),\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t// Values\n\t\t\tupdateBlockValues: (id, newValues) => {\n\t\t\t\tonChange({\n\t\t\t\t\t...value,\n\t\t\t\t\t_values: {\n\t\t\t\t\t\t...value._values,\n\t\t\t\t\t\t[id]: { ...value._values[id], ...newValues },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\n\t\t\t// Library\n\t\t\topenLibrary: (position) => {\n\t\t\t\tsetInsertPosition(position);\n\t\t\t\tsetIsLibraryOpen(true);\n\t\t\t\tsetSelectedBlockId(null);\n\t\t\t},\n\n\t\t\tcloseLibrary: () => {\n\t\t\t\tsetIsLibraryOpen(false);\n\t\t\t\tsetInsertPosition(null);\n\t\t\t},\n\t\t}),\n\t\t[value, onChange, blocks, selectedBlockId],\n\t);\n\n\t// State object\n\tconst state: BlockEditorState = React.useMemo(\n\t\t() => ({\n\t\t\tcontent: value,\n\t\t\tselectedBlockId,\n\t\t\texpandedBlockIds,\n\t\t\tisLibraryOpen,\n\t\t\tinsertPosition,\n\t\t\tblocks,\n\t\t\tallowedBlocks: allowedBlocks || null,\n\t\t\tlocale,\n\t\t}),\n\t\t[\n\t\t\tvalue,\n\t\t\tselectedBlockId,\n\t\t\texpandedBlockIds,\n\t\t\tisLibraryOpen,\n\t\t\tinsertPosition,\n\t\t\tblocks,\n\t\t\tallowedBlocks,\n\t\t\tlocale,\n\t\t],\n\t);\n\n\t// Context value\n\tconst contextValue = React.useMemo(\n\t\t() => ({ state, actions }),\n\t\t[state, actions],\n\t);\n\n\treturn (\n\t\t<BlockEditorContextProvider value={contextValue}>\n\t\t\t{children}\n\t\t</BlockEditorContextProvider>\n\t);\n}\n","/**\n * Blocks Field Component\n *\n * Form field for editing block content using the visual block editor.\n */\n\n\"use client\";\n\nimport * as React from \"react\";\nimport { useFormContext, useWatch } from \"react-hook-form\";\nimport type { BlockContent } from \"../../../blocks/types.js\";\nimport { EMPTY_BLOCK_CONTENT, isBlockContent } from \"../../../blocks/types.js\";\nimport type { BlockDefinition } from \"../../../builder/block/types.js\";\nimport type { BaseFieldProps } from \"../../../builder/types/common.js\";\nimport {\n\tCard,\n\tCardContent,\n\tCardHeader,\n\tCardTitle,\n} from \"../../../components/ui/card.js\";\nimport { BlockEditorLayout } from \"../../blocks/block-editor-layout.js\";\nimport { BlockEditorProvider } from \"../../blocks/block-editor-provider.js\";\nimport { countBlocks } from \"../../blocks/utils/tree-utils.js\";\nimport { FieldWrapper } from \"../field-wrapper.js\";\n\n/**\n * Blocks field configuration.\n *\n * @typeParam TAllowed - Union of allowed block type names (inferred from admin registry)\n */\nexport type BlocksFieldConfig<TAllowed extends string = string> = {\n\t/** Allowed block types (if not set, all registered blocks are allowed) */\n\tallowedBlocks?: TAllowed[];\n\t/** Minimum number of blocks */\n\tminBlocks?: number;\n\t/** Maximum number of blocks */\n\tmaxBlocks?: number;\n};\n\nexport type BlocksFieldProps = BaseFieldProps &\n\tBlocksFieldConfig & {\n\t\t/** Registered block definitions (passed from admin context) */\n\t\tblocks?: Record<string, BlockDefinition>;\n\t};\n\n/**\n * Blocks field component.\n *\n * Renders the visual block editor for editing block content.\n */\nexport function BlocksField({\n\tname,\n\tvalue,\n\tonChange,\n\tlabel,\n\tdescription,\n\terror,\n\trequired,\n\tdisabled,\n\treadOnly,\n\tallowedBlocks,\n\tminBlocks,\n\tmaxBlocks,\n\tblocks = {},\n}: BlocksFieldProps) {\n\tconst form = useFormContext();\n\tconst watchedContent = useWatch({ control: form.control, name });\n\n\t// Ensure we have valid block content\n\tconst content: BlockContent = isBlockContent(watchedContent)\n\t\t? watchedContent\n\t\t: isBlockContent(value)\n\t\t\t? value\n\t\t\t: EMPTY_BLOCK_CONTENT;\n\n\t// Filter blocks by allowed list\n\tconst filteredBlocks = React.useMemo(() => {\n\t\tif (!allowedBlocks || allowedBlocks.length === 0) {\n\t\t\treturn blocks;\n\t\t}\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries(blocks).filter(([name]) => allowedBlocks.includes(name)),\n\t\t);\n\t}, [blocks, allowedBlocks]);\n\n\t// Handle content changes (validation happens on form submit)\n\tconst handleChange = React.useCallback(\n\t\t(newContent: BlockContent) => {\n\t\t\tonChange?.(newContent);\n\t\t},\n\t\t[onChange],\n\t);\n\n\tconst blockCount = countBlocks(content._tree);\n\tconst hasBlocks = Object.keys(filteredBlocks).length > 0;\n\n\treturn (\n\t\t<FieldWrapper\n\t\t\tname={name}\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\terror={error}\n\t\t\trequired={required}\n\t\t\tdisabled={disabled}\n\t\t>\n\t\t\t{hasBlocks ? (\n\t\t\t\t<BlockEditorProvider\n\t\t\t\t\tvalue={content}\n\t\t\t\t\tonChange={handleChange}\n\t\t\t\t\tblocks={filteredBlocks}\n\t\t\t\t\tallowedBlocks={allowedBlocks}\n\t\t\t\t>\n\t\t\t\t\t<BlockEditorLayout />\n\t\t\t\t</BlockEditorProvider>\n\t\t\t) : (\n\t\t\t\t<Card className=\"border-dashed\">\n\t\t\t\t\t<CardHeader className=\"pb-2\">\n\t\t\t\t\t\t<CardTitle className=\"flex items-center justify-between text-sm font-medium\">\n\t\t\t\t\t\t\t<span>Blocks ({blockCount})</span>\n\t\t\t\t\t\t</CardTitle>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<CardContent>\n\t\t\t\t\t\t<div className=\"py-8 text-center text-muted-foreground\">\n\t\t\t\t\t\t\t<p className=\"text-sm\">No block definitions registered</p>\n\t\t\t\t\t\t\t<p className=\"mt-1 text-xs\">\n\t\t\t\t\t\t\t\tRegister blocks with .blocks() in your admin configuration\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardContent>\n\t\t\t\t</Card>\n\t\t\t)}\n\n\t\t\t{/* Constraints info */}\n\t\t\t{(minBlocks || maxBlocks) && (\n\t\t\t\t<div className=\"mt-2 text-xs text-muted-foreground\">\n\t\t\t\t\t{minBlocks && <span>Min: {minBlocks} blocks </span>}\n\t\t\t\t\t{maxBlocks && <span>Max: {maxBlocks} blocks</span>}\n\t\t\t\t\t<span className=\"ml-2\">Current: {blockCount}</span>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</FieldWrapper>\n\t);\n}\n\nexport default BlocksField;\n","/**\n * EmbeddedCollectionField Component\n *\n * Manages embedded collections with inline, modal, or drawer editing.\n */\n\nimport { CaretDown, CaretUp, Pencil, Plus, Trash } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useFieldArray, useFormContext, useWatch } from \"react-hook-form\";\nimport type { EmbeddedCollectionProps } from \"../../builder\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { Button } from \"../ui/button\";\nimport {\n\tDialog,\n\tDialogContent,\n\tDialogDescription,\n\tDialogHeader,\n\tDialogTitle,\n} from \"../ui/dialog\";\nimport {\n\tSheet,\n\tSheetContent,\n\tSheetDescription,\n\tSheetHeader,\n\tSheetTitle,\n} from \"../ui/sheet\";\nimport { LocaleBadge } from \"./locale-badge\";\n\ntype RowLabel = ((item: any) => string) | string;\n\nexport interface EmbeddedCollectionFieldProps\n\textends Omit<EmbeddedCollectionProps, \"rowLabel\"> {\n\trowLabel?: RowLabel;\n\trenderFields?: (index: number) => React.ReactNode;\n\tminItems?: number;\n\tmaxItems?: number;\n}\n\nexport function EmbeddedCollectionField({\n\tname,\n\tvalue,\n\tcollection,\n\tmode = \"inline\",\n\torderable = false,\n\trowLabel,\n\tlabel,\n\tdescription,\n\trequired,\n\tdisabled,\n\treadOnly,\n\terror,\n\tplaceholder,\n\tlocalized,\n\tlocale,\n\trenderFields,\n\tminItems,\n\tmaxItems,\n}: EmbeddedCollectionFieldProps) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst form = useFormContext();\n\tconst { control } = form;\n\tconst { fields, append, remove, move } = useFieldArray({ control, name });\n\tconst values = (useWatch({ control, name }) as any[] | undefined) ?? value;\n\tconst resolvedLabel = label ? resolveText(label) : undefined;\n\tconst resolvedPlaceholder = placeholder\n\t\t? resolveText(placeholder)\n\t\t: undefined;\n\n\tconst [activeIndex, setActiveIndex] = React.useState<number | null>(null);\n\tconst [isOpen, setIsOpen] = React.useState(false);\n\n\tconst canAddMore = !maxItems || fields.length < maxItems;\n\tconst canRemove = !readOnly && (!minItems || fields.length > minItems);\n\tconst fallbackLabel = resolvedLabel || collection || \"Item\";\n\tconst emptyLabel = t(\"array.empty\", { name: fallbackLabel });\n\tconst addLabel = t(\"array.addItem\", { name: fallbackLabel });\n\n\tconst resolveRowLabel = React.useCallback(\n\t\t(item: any, index: number) => {\n\t\t\tif (typeof rowLabel === \"function\") {\n\t\t\t\tconst labelValue = rowLabel(item);\n\t\t\t\tif (labelValue) return labelValue;\n\t\t\t}\n\t\t\tif (typeof rowLabel === \"string\") {\n\t\t\t\tconst labelValue = item?.[rowLabel];\n\t\t\t\tif (labelValue) return String(labelValue);\n\t\t\t}\n\t\t\t// Prefer _title computed field from backend\n\t\t\tif (item?._title) return String(item._title);\n\t\t\tif (item?.title) return String(item.title);\n\t\t\tif (item?.name) return String(item.name);\n\t\t\treturn `${fallbackLabel} ${index + 1}`;\n\t\t},\n\t\t[fallbackLabel, rowLabel],\n\t);\n\n\tconst handleAdd = () => {\n\t\tif (disabled || readOnly || !canAddMore) return;\n\t\tappend({});\n\t\tif (mode !== \"inline\") {\n\t\t\tconst nextIndex = fields.length;\n\t\t\tsetActiveIndex(nextIndex);\n\t\t\tsetIsOpen(true);\n\t\t}\n\t};\n\n\tconst handleRemove = (index: number) => {\n\t\tif (!canRemove) return;\n\t\tremove(index);\n\t\tif (activeIndex === null) return;\n\t\tif (index === activeIndex) {\n\t\t\tsetIsOpen(false);\n\t\t\tsetActiveIndex(null);\n\t\t} else if (index < activeIndex) {\n\t\t\tsetActiveIndex(activeIndex - 1);\n\t\t}\n\t};\n\n\tconst handleMove = (from: number, to: number) => {\n\t\tif (to < 0 || to >= fields.length) return;\n\t\tmove(from, to);\n\t\tif (activeIndex === null) return;\n\t\tif (activeIndex === from) {\n\t\t\tsetActiveIndex(to);\n\t\t} else if (activeIndex === to) {\n\t\t\tsetActiveIndex(from);\n\t\t}\n\t};\n\n\tconst handleOpenChange = (open: boolean) => {\n\t\tsetIsOpen(open);\n\t\tif (!open) {\n\t\t\tsetActiveIndex(null);\n\t\t}\n\t};\n\n\tconst renderItemFields = (index: number) => {\n\t\tif (!renderFields) {\n\t\t\treturn (\n\t\t\t\t<div className=\"rounded-lg border border-dashed p-4 text-center\">\n\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\tForm fields not configured.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\t\treturn renderFields(index);\n\t};\n\n\tconst emptyState = (\n\t\t<div className=\"rounded-lg border border-dashed p-4 text-center\">\n\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t{resolvedPlaceholder || emptyLabel}\n\t\t\t</p>\n\t\t</div>\n\t);\n\n\tconst editorContent =\n\t\tactiveIndex !== null ? renderItemFields(activeIndex) : null;\n\tconst editorTitle =\n\t\tactiveIndex !== null\n\t\t\t? resolveRowLabel(values?.[activeIndex], activeIndex)\n\t\t\t: fallbackLabel;\n\n\tconst showEditor = mode === \"modal\" || mode === \"drawer\";\n\n\treturn (\n\t\t<div className=\"space-y-2\">\n\t\t\t{label && (\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<label htmlFor={name} className=\"text-sm font-medium\">\n\t\t\t\t\t\t{resolvedLabel}\n\t\t\t\t\t\t{required && <span className=\"text-destructive\">*</span>}\n\t\t\t\t\t\t{maxItems && (\n\t\t\t\t\t\t\t<span className=\"ml-2 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t({fields.length}/{maxItems})\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</label>\n\t\t\t\t\t{localized && <LocaleBadge locale={locale || \"i18n\"} />}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{description && (\n\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t{resolveText(description)}\n\t\t\t\t</p>\n\t\t\t)}\n\n\t\t\t<div className=\"space-y-3\">\n\t\t\t\t{fields.length === 0\n\t\t\t\t\t? emptyState\n\t\t\t\t\t: fields.map((field, index) => {\n\t\t\t\t\t\t\tconst itemValue = values?.[index];\n\t\t\t\t\t\t\tconst itemLabel = resolveRowLabel(itemValue, index);\n\t\t\t\t\t\t\tconst canMoveUp = orderable && index > 0;\n\t\t\t\t\t\t\tconst canMoveDown = orderable && index < fields.length - 1;\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tkey={field.id}\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-lg border border-border/60 bg-card/30 backdrop-blur-sm\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-between border-b px-3 py-2\">\n\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t#{index + 1}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-sm font-medium\">{itemLabel}</span>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t\t\t\t\t{orderable && !readOnly && (\n\t\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleMove(index, index - 1)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={!canMoveUp || disabled}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Move up\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Move item up\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CaretUp className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleMove(index, index + 1)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={!canMoveDown || disabled}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Move down\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Move item down\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CaretDown className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t{mode !== \"inline\" && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetActiveIndex(index);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetIsOpen(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={disabled || !renderFields}\n\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={readOnly ? \"View\" : \"Edit\"}\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={readOnly ? \"View item\" : \"Edit item\"}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Pencil className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t{!readOnly && canRemove && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleRemove(index)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Remove\"\n\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Remove item\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Trash className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t{mode === \"inline\" && (\n\t\t\t\t\t\t\t\t\t\t<div className=\"space-y-3 p-3\">\n\t\t\t\t\t\t\t\t\t\t\t{renderItemFields(index)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t</div>\n\n\t\t\t{!readOnly && canAddMore && (\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tonClick={handleAdd}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t>\n\t\t\t\t\t<Plus className=\"h-4 w-4\" />\n\t\t\t\t\t{addLabel}\n\t\t\t\t</Button>\n\t\t\t)}\n\n\t\t\t{error && <p className=\"text-sm text-destructive\">{error}</p>}\n\n\t\t\t{showEditor && mode === \"modal\" && (\n\t\t\t\t<Dialog open={isOpen} onOpenChange={handleOpenChange}>\n\t\t\t\t\t<DialogContent className=\"sm:max-w-2xl\">\n\t\t\t\t\t\t<DialogHeader>\n\t\t\t\t\t\t\t<DialogTitle>{editorTitle}</DialogTitle>\n\t\t\t\t\t\t\t{description && (\n\t\t\t\t\t\t\t\t<DialogDescription>\n\t\t\t\t\t\t\t\t\t{resolveText(description)}\n\t\t\t\t\t\t\t\t</DialogDescription>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</DialogHeader>\n\t\t\t\t\t\t<div className=\"space-y-4\">{editorContent}</div>\n\t\t\t\t\t</DialogContent>\n\t\t\t\t</Dialog>\n\t\t\t)}\n\n\t\t\t{showEditor && mode === \"drawer\" && (\n\t\t\t\t<Sheet open={isOpen} onOpenChange={handleOpenChange}>\n\t\t\t\t\t<SheetContent side=\"right\" className=\"sm:max-w-lg\">\n\t\t\t\t\t\t<SheetHeader>\n\t\t\t\t\t\t\t<SheetTitle>{editorTitle}</SheetTitle>\n\t\t\t\t\t\t\t{description && (\n\t\t\t\t\t\t\t\t<SheetDescription>{resolveText(description)}</SheetDescription>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</SheetHeader>\n\t\t\t\t\t\t<div className=\"px-4 pb-4\">{editorContent}</div>\n\t\t\t\t\t\t<div className=\"px-4 pb-4\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\tonClick={() => handleOpenChange(false)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tClose\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</SheetContent>\n\t\t\t\t</Sheet>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","/**\n * ObjectField Component\n *\n * Renders nested fields for JSON object structures.\n * Supports wrapper modes (flat, collapsible) and layout modes (stack, inline, grid).\n */\n\nimport { CaretDown, CaretRight } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\n\nimport type { FieldDefinition } from \"../../builder/field/field\";\nimport { createFieldRegistryProxy } from \"../../builder/proxies\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { selectAdmin, useAdminStore } from \"../../runtime\";\nimport { FormField } from \"../../views/collection/form-field\";\nimport type { BaseFieldProps, ObjectFieldConfig } from \"./field-types\";\nimport { gridColumnClasses } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ObjectFieldProps\n\textends BaseFieldProps,\n\t\tOmit<ObjectFieldConfig, \"fields\"> {\n\t/**\n\t * Nested field definitions.\n\t * Can be a callback (evaluated at render time) or pre-evaluated record.\n\t */\n\tfields?: ((ctx: { r: any }) => Record<string, any>) | Record<string, any>;\n}\n\n// ============================================================================\n// Nested Field Renderer\n// ============================================================================\n\ninterface NestedFieldRendererProps {\n\tfieldName: string;\n\tfieldDef: FieldDefinition;\n\tparentName: string;\n\tdisabled?: boolean;\n}\n\nfunction NestedFieldRenderer({\n\tfieldName,\n\tfieldDef,\n\tparentName,\n\tdisabled,\n}: NestedFieldRendererProps) {\n\tconst resolveText = useResolveText();\n\tconst fullName = `${parentName}.${fieldName}`;\n\tconst fieldType = fieldDef.name;\n\tconst options = fieldDef[\"~options\"] || {};\n\n\t// For nested object fields, render recursively\n\tif (fieldType === \"object\" && options.fields) {\n\t\treturn (\n\t\t\t<ObjectField\n\t\t\t\tname={fullName}\n\t\t\t\tlabel={resolveText(options.label)}\n\t\t\t\tdescription={resolveText(options.description)}\n\t\t\t\tfields={options.fields}\n\t\t\t\twrapper={options.wrapper}\n\t\t\t\tlayout={options.layout}\n\t\t\t\tcolumns={options.columns}\n\t\t\t\tdefaultCollapsed={options.defaultCollapsed}\n\t\t\t\tdisabled={disabled}\n\t\t\t\trequired={options.required}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// For other fields, use FormField\n\treturn (\n\t\t<FormField\n\t\t\tname={fullName}\n\t\t\tlabel={resolveText(options.label)}\n\t\t\tdescription={resolveText(options.description)}\n\t\t\tplaceholder={resolveText(options.placeholder)}\n\t\t\trequired={options.required}\n\t\t\tdisabled={disabled || options.disabled}\n\t\t\ttype={fieldType as any}\n\t\t\toptions={options.options}\n\t\t/>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function ObjectField({\n\tname,\n\tlabel,\n\tdescription,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tclassName,\n\tfields: fieldsProp,\n\twrapper = \"flat\",\n\tlayout = \"stack\",\n\tcolumns = 2,\n\tdefaultCollapsed = true,\n}: ObjectFieldProps) {\n\tconst resolveText = useResolveText();\n\tconst admin = useAdminStore(selectAdmin);\n\tconst [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed);\n\n\t// Resolve nested field definitions\n\tconst nestedFields = React.useMemo(() => {\n\t\tif (!fieldsProp) return {};\n\n\t\t// If it's a callback, evaluate it with field registry\n\t\tif (typeof fieldsProp === \"function\") {\n\t\t\tconst registeredFields = admin.getFields();\n\t\t\tconst r = createFieldRegistryProxy(registeredFields as any);\n\t\t\treturn fieldsProp({ r });\n\t\t}\n\n\t\t// Otherwise it's already evaluated\n\t\treturn fieldsProp;\n\t}, [fieldsProp, admin]);\n\n\tconst fieldEntries = Object.entries(nestedFields);\n\n\tif (fieldEntries.length === 0) {\n\t\treturn null;\n\t}\n\n\t// Render nested fields based on layout\n\tconst renderFields = () => {\n\t\tconst fieldElements = fieldEntries.map(([fieldName, fieldDef]) => (\n\t\t\t<NestedFieldRenderer\n\t\t\t\tkey={fieldName}\n\t\t\t\tfieldName={fieldName}\n\t\t\t\tfieldDef={fieldDef as FieldDefinition}\n\t\t\t\tparentName={name}\n\t\t\t\tdisabled={disabled}\n\t\t\t/>\n\t\t));\n\n\t\tif (layout === \"inline\") {\n\t\t\treturn (\n\t\t\t\t<div className=\"flex flex-wrap items-end gap-2\">{fieldElements}</div>\n\t\t\t);\n\t\t}\n\n\t\tif (layout === \"grid\") {\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"grid gap-4\",\n\t\t\t\t\t\tgridColumnClasses[columns] || \"grid-cols-2\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{fieldElements}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\t// Default: stack\n\t\treturn <div className=\"space-y-4\">{fieldElements}</div>;\n\t};\n\n\t// Collapsible wrapper (also support legacy layout=\"collapsible\" for backwards compatibility)\n\tif (wrapper === \"collapsible\" || (layout as string) === \"collapsible\") {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"rounded-lg border border-border/60 bg-card/30 backdrop-blur-sm\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => setIsCollapsed(!isCollapsed)}\n\t\t\t\t\tclassName=\"flex w-full items-center justify-between p-3 text-left hover:bg-muted/50\"\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t>\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t{isCollapsed ? (\n\t\t\t\t\t\t\t<CaretRight className=\"h-4 w-4\" />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<CaretDown className=\"h-4 w-4\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span className=\"font-medium\">{resolveText(label ?? name)}</span>\n\t\t\t\t\t\t{required && <span className=\"text-destructive\">*</span>}\n\t\t\t\t\t</div>\n\t\t\t\t</button>\n\t\t\t\t{!isCollapsed && (\n\t\t\t\t\t<div className=\"border-t p-4\">\n\t\t\t\t\t\t{description && (\n\t\t\t\t\t\t\t<p className=\"mb-4 text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t\t{resolveText(description)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{renderFields()}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Flat wrapper with optional label\n\tif (label) {\n\t\treturn (\n\t\t\t<FieldWrapper\n\t\t\t\tname={name}\n\t\t\t\tlabel={resolveText(label)}\n\t\t\t\tdescription={description}\n\t\t\t\trequired={required}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tlocalized={localized}\n\t\t\t\tlocale={locale}\n\t\t\t>\n\t\t\t\t<div className={cn(\"pt-1\", className)}>{renderFields()}</div>\n\t\t\t</FieldWrapper>\n\t\t);\n\t}\n\n\t// No label - just render fields\n\treturn <div className={className}>{renderFields()}</div>;\n}\n","/**\n * Shared types for relation display components\n */\n\nimport type * as React from \"react\";\nimport type { FieldDefinition } from \"../../../../builder/field/field\";\nimport { DefaultCell } from \"../../../../views/collection/cells\";\n\n/**\n * Display mode for relation items\n */\nexport type RelationDisplayMode = \"chips\" | \"list\" | \"table\" | \"cards\" | \"grid\";\n\n/**\n * Action handlers for relation items\n */\nexport interface RelationItemActions {\n\tonEdit?: (item: any) => void;\n\tonRemove?: (item: any) => void;\n\tonNavigate?: (item: any) => void;\n}\n\n/**\n * Field mapping for cards/grid display\n */\nexport interface RelationDisplayFields {\n\ttitle?: string;\n\tsubtitle?: string;\n\timage?: string;\n\tmeta?: string[];\n}\n\n/**\n * Collection field definitions for cell rendering\n */\nexport interface CollectionFieldsConfig {\n\tfields?: Record<string, FieldDefinition>;\n}\n\n/**\n * Common props for all display components\n */\nexport interface RelationDisplayProps {\n\t/**\n\t * Items to display\n\t */\n\titems: any[];\n\n\t/**\n\t * Collection name for navigation links\n\t */\n\tcollection: string;\n\n\t/**\n\t * Collection icon component\n\t */\n\tcollectionIcon?: React.ComponentType<{ className?: string }>;\n\n\t/**\n\t * Action handlers\n\t */\n\tactions?: RelationItemActions;\n\n\t/**\n\t * Whether items are editable (shows edit/remove buttons)\n\t */\n\teditable?: boolean;\n\n\t/**\n\t * Whether items are orderable (shows drag handle)\n\t */\n\torderable?: boolean;\n\n\t/**\n\t * Columns to show in table display\n\t */\n\tcolumns?: string[];\n\n\t/**\n\t * Field mapping for cards/grid display\n\t */\n\tfields?: RelationDisplayFields;\n\n\t/**\n\t * Number of columns for grid/cards layout\n\t */\n\tgridColumns?: 1 | 2 | 3 | 4;\n\n\t/**\n\t * Whether to show navigation link to detail page\n\t */\n\tlinkToDetail?: boolean;\n\n\t/**\n\t * Custom render function for items\n\t */\n\trenderItem?: (item: any, index: number) => React.ReactNode;\n\n\t/**\n\t * Collection config for cell rendering (enables proper cell components)\n\t */\n\tcollectionConfig?: CollectionFieldsConfig;\n}\n\n/**\n * Get display value from item (_title fallback chain)\n */\nexport function getItemDisplayValue(item: any): string {\n\treturn item?._title || item?.name || item?.title || item?.id || \"\";\n}\n\n/**\n * Format column header (camelCase to Title Case)\n */\nexport function formatColumnHeader(column: string): string {\n\tif (column === \"_title\") return \"Name\";\n\treturn column\n\t\t.replace(/([A-Z])/g, \" $1\")\n\t\t.replace(/^./, (str) => str.toUpperCase())\n\t\t.trim();\n}\n\n/**\n * Format cell value for display\n */\nexport function formatCellValue(value: unknown): string {\n\tif (value === null || value === undefined) return \"-\";\n\tif (typeof value === \"boolean\") return value ? \"Yes\" : \"No\";\n\tif (value instanceof Date) return value.toLocaleDateString();\n\tif (typeof value === \"object\") return JSON.stringify(value);\n\treturn String(value);\n}\n\n/**\n * Get image URL from item field\n */\nexport function getImageUrl(item: any, imageField?: string): string | null {\n\tif (!imageField) return null;\n\tconst imageValue = item[imageField];\n\tif (typeof imageValue === \"string\") return imageValue;\n\tif (imageValue?.url) return imageValue.url;\n\tif (imageValue?.key) return imageValue.key;\n\treturn null;\n}\n\n/**\n * Field types that need fieldDef passed to their cell component\n */\nconst FIELD_TYPES_NEEDING_FIELD_DEF = new Set([\n\t\"object\",\n\t\"array\",\n\t\"relation\",\n\t\"reverseRelation\",\n]);\n\n/**\n * Resolved cell info for rendering\n */\nexport interface ResolvedCell {\n\tcomponent: React.ComponentType<{\n\t\tvalue: unknown;\n\t\trow?: unknown;\n\t\tfieldDef?: FieldDefinition;\n\t}>;\n\tfieldDef?: FieldDefinition;\n\tneedsFieldDef: boolean;\n\taccessorKey: string;\n}\n\n/**\n * Resolve cell component for a column based on field config\n * Uses the same priority as buildColumns:\n * 1. Cell from field registry (fieldDef.cell.component)\n * 2. DefaultCell fallback\n */\nexport function resolveCellForColumn(\n\tcolumn: string,\n\tcollectionConfig?: CollectionFieldsConfig,\n): ResolvedCell {\n\tconst fieldDef = collectionConfig?.fields?.[column];\n\tconst fieldType = fieldDef?.name ?? \"text\";\n\tconst fieldOptions = (fieldDef as any)?.[\"~options\"] ?? {};\n\n\t// Resolve cell component\n\tlet component: React.ComponentType<{\n\t\tvalue: unknown;\n\t\trow?: unknown;\n\t\tfieldDef?: FieldDefinition;\n\t}>;\n\n\tif (fieldDef?.cell?.component) {\n\t\t// Cell from field registry\n\t\tcomponent = fieldDef.cell.component as React.ComponentType<{\n\t\t\tvalue: unknown;\n\t\t\trow?: unknown;\n\t\t\tfieldDef?: FieldDefinition;\n\t\t}>;\n\t} else {\n\t\t// DefaultCell fallback\n\t\tcomponent = DefaultCell;\n\t}\n\n\tconst needsFieldDef = FIELD_TYPES_NEEDING_FIELD_DEF.has(fieldType);\n\n\t// For relation fields, use relationName as accessor if specified\n\tconst accessorKey: string =\n\t\tfieldType === \"relation\" && fieldOptions.relationName\n\t\t\t? fieldOptions.relationName\n\t\t\t: column;\n\n\treturn {\n\t\tcomponent,\n\t\tfieldDef,\n\t\tneedsFieldDef,\n\t\taccessorKey,\n\t};\n}\n","/**\n * AdminLink Component\n *\n * A type-safe link component for navigating within the admin UI.\n * Automatically generates correct URLs based on collection, global, or page targets.\n */\n\nimport * as React from \"react\";\nimport type { Questpie } from \"questpie\";\nimport {\n useAdminRoutes,\n getAdminLinkHref,\n type AdminLinkProps as AdminLinkTargetProps,\n} from \"../hooks/use-admin-routes\";\nimport type { CollectionNames, GlobalNames } from \"../builder\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AdminLinkProps<TApp extends Questpie<any>> extends Omit<\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\n \"href\"\n> {\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 /** Custom href (overrides other props) */\n href?: string;\n /** Whether to use the navigate function instead of native anchor */\n useNavigate?: boolean;\n /** Children */\n children: React.ReactNode;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Type-safe link component for admin navigation\n *\n * @example\n * ```tsx\n * // Link to dashboard\n * <AdminLink to=\"dashboard\">Dashboard</AdminLink>\n *\n * // Link to collection list\n * <AdminLink collection=\"posts\">View Posts</AdminLink>\n *\n * // Link to create new item\n * <AdminLink collection=\"posts\" action=\"create\">New Post</AdminLink>\n *\n * // Link to edit item\n * <AdminLink collection=\"posts\" action=\"edit\" id=\"123\">Edit Post</AdminLink>\n *\n * // Link to global\n * <AdminLink global=\"siteSettings\">Site Settings</AdminLink>\n *\n * // Link to custom page\n * <AdminLink pageId=\"analytics\">Analytics</AdminLink>\n * ```\n */\nexport function AdminLink<TApp extends Questpie<any>>({\n to,\n collection,\n action,\n id,\n global,\n pageId,\n href: customHref,\n useNavigate = false,\n children,\n onClick,\n ...rest\n}: AdminLinkProps<TApp>) {\n const { routes } = useAdminRoutes<TApp>();\n\n // Determine the href\n const href = React.useMemo(() => {\n if (customHref) return customHref;\n\n const targetProps: AdminLinkTargetProps<TApp> = {\n to,\n collection,\n action,\n id,\n global,\n pageId,\n };\n\n return getAdminLinkHref(routes, targetProps);\n }, [customHref, to, collection, action, id, global, pageId, routes]);\n\n // Handle click for navigate mode\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLAnchorElement>) => {\n if (onClick) {\n onClick(e);\n }\n\n if (useNavigate && !e.defaultPrevented) {\n e.preventDefault();\n // Navigate will be called via routes context\n if (typeof window !== \"undefined\") {\n window.history.pushState({}, \"\", href);\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n }\n }\n },\n [onClick, useNavigate, href],\n );\n\n return (\n <a href={href} onClick={handleClick} {...rest}>\n {children}\n </a>\n );\n}\n\n// ============================================================================\n// Convenience Components\n// ============================================================================\n\n/**\n * Link to a collection list\n */\nexport function CollectionLink<TApp extends Questpie<any>>({\n collection,\n ...rest\n}: Omit<AdminLinkProps<TApp>, \"to\" | \"global\" | \"pageId\" | \"action\" | \"id\"> & {\n collection: CollectionNames<TApp>;\n}) {\n return <AdminLink<TApp> collection={collection} action=\"list\" {...rest} />;\n}\n\n/**\n * Link to create a new item in a collection\n */\nexport function CollectionCreateLink<TApp extends Questpie<any>>({\n collection,\n ...rest\n}: Omit<AdminLinkProps<TApp>, \"to\" | \"global\" | \"pageId\" | \"action\" | \"id\"> & {\n collection: CollectionNames<TApp>;\n}) {\n return <AdminLink<TApp> collection={collection} action=\"create\" {...rest} />;\n}\n\n/**\n * Link to edit an item in a collection\n */\nexport function CollectionEditLink<TApp extends Questpie<any>>({\n collection,\n id,\n ...rest\n}: Omit<AdminLinkProps<TApp>, \"to\" | \"global\" | \"pageId\" | \"action\"> & {\n collection: CollectionNames<TApp>;\n id: string;\n}) {\n return (\n <AdminLink<TApp> collection={collection} action=\"edit\" id={id} {...rest} />\n );\n}\n\n/**\n * Link to a global settings page\n */\nexport function GlobalLink<TApp extends Questpie<any>>({\n global,\n ...rest\n}: Omit<\n AdminLinkProps<TApp>,\n \"to\" | \"collection\" | \"pageId\" | \"action\" | \"id\"\n> & {\n global: GlobalNames<TApp>;\n}) {\n return <AdminLink<TApp> global={global} {...rest} />;\n}\n\n/**\n * Link to dashboard\n */\nexport function DashboardLink<TApp extends Questpie<any>>(\n props: Omit<\n AdminLinkProps<TApp>,\n \"to\" | \"collection\" | \"global\" | \"pageId\" | \"action\" | \"id\"\n >,\n) {\n return <AdminLink<TApp> to=\"dashboard\" {...props} />;\n}\n\nexport default AdminLink;\n","/**\n * Chips Display - compact badge/tag style\n */\n\nimport { Pencil, X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { CollectionEditLink } from \"../../../admin-link\";\nimport { Badge } from \"../../../ui/badge\";\nimport { Button } from \"../../../ui/button\";\nimport { type RelationDisplayProps, getItemDisplayValue } from \"./types\";\n\nexport function ChipsDisplay({\n items,\n collection,\n collectionIcon: CollectionIcon,\n actions,\n editable = false,\n linkToDetail = false,\n}: RelationDisplayProps) {\n return (\n <div className=\"flex flex-wrap gap-2\">\n {items.map((item) => {\n const displayText = getItemDisplayValue(item);\n\n // Editable mode - show edit/remove buttons\n if (editable && (actions?.onEdit || actions?.onRemove)) {\n return (\n <div\n key={item.id}\n className=\"inline-flex items-center gap-1 rounded-md border bg-secondary/50 pl-2 pr-1 py-1\"\n >\n {CollectionIcon && (\n <CollectionIcon className=\"size-3 text-muted-foreground\" />\n )}\n <span className=\"text-sm\">{displayText}</span>\n {actions?.onEdit && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-5 w-5\"\n onClick={() => actions.onEdit?.(item)}\n aria-label=\"Edit item\"\n >\n <Pencil className=\"size-3\" />\n </Button>\n )}\n {actions?.onRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-5 w-5\"\n onClick={() => actions.onRemove?.(item)}\n aria-label=\"Remove item\"\n >\n <X className=\"size-3\" />\n </Button>\n )}\n </div>\n );\n }\n\n // Clickable for edit in sheet\n if (actions?.onEdit) {\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => actions.onEdit?.(item)}\n className=\"inline-flex\"\n >\n <Badge\n variant=\"secondary\"\n className=\"hover:bg-secondary/80 cursor-pointer gap-1\"\n >\n {CollectionIcon && (\n <CollectionIcon className=\"size-3 text-muted-foreground\" />\n )}\n {displayText}\n <Pencil className=\"size-3\" />\n </Badge>\n </button>\n );\n }\n\n // Link to detail page\n if (linkToDetail && actions?.onNavigate) {\n return (\n <CollectionEditLink\n key={item.id}\n collection={collection as any}\n id={item.id}\n className=\"inline-flex\"\n >\n <Badge\n variant=\"secondary\"\n className=\"hover:bg-secondary/80 cursor-pointer gap-1\"\n >\n {CollectionIcon && (\n <CollectionIcon className=\"size-3 text-muted-foreground\" />\n )}\n {displayText}\n </Badge>\n </CollectionEditLink>\n );\n }\n\n // Read-only badge\n return (\n <Badge key={item.id} variant=\"secondary\" className=\"gap-1\">\n {CollectionIcon && (\n <CollectionIcon className=\"size-3 text-muted-foreground\" />\n )}\n {displayText}\n </Badge>\n );\n })}\n </div>\n );\n}\n","/**\n * List Display - vertical list with action buttons\n */\n\nimport { ArrowRight, DotsSixVertical, Pencil, X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { CollectionEditLink } from \"../../../admin-link\";\nimport { Button } from \"../../../ui/button\";\nimport { type RelationDisplayProps, getItemDisplayValue } from \"./types\";\n\nexport function ListDisplay({\n items,\n collection,\n collectionIcon: CollectionIcon,\n actions,\n editable = false,\n orderable = false,\n linkToDetail = false,\n renderItem,\n}: RelationDisplayProps) {\n // Editable list with cards\n if (editable) {\n return (\n <div className=\"space-y-2 rounded-lg border border-border/60 bg-card/30 backdrop-blur-sm p-3\">\n {items.map((item, index) => (\n <div\n key={item.id}\n className=\"flex items-center gap-2 rounded-md border border-border/60 bg-card/30 backdrop-blur-sm p-2\"\n >\n {/* Drag Handle */}\n {orderable && (\n <button\n type=\"button\"\n className=\"cursor-grab text-muted-foreground hover:text-foreground\"\n aria-label=\"Drag to reorder\"\n >\n <DotsSixVertical className=\"h-4 w-4\" />\n </button>\n )}\n\n {/* Item Display */}\n <div className=\"flex-1 flex items-center gap-2 min-w-0\">\n {CollectionIcon && (\n <CollectionIcon className=\"size-3.5 text-muted-foreground shrink-0\" />\n )}\n {renderItem ? (\n renderItem(item, index)\n ) : (\n <span className=\"text-sm truncate\">\n {getItemDisplayValue(item)}\n </span>\n )}\n </div>\n\n {/* Edit Button */}\n {actions?.onEdit && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 shrink-0\"\n onClick={() => actions.onEdit?.(item)}\n title=\"Edit\"\n aria-label=\"Edit item\"\n >\n <Pencil className=\"h-3 w-3\" />\n </Button>\n )}\n\n {/* Remove Button */}\n {actions?.onRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 shrink-0\"\n onClick={() => actions.onRemove?.(item)}\n title=\"Remove\"\n aria-label=\"Remove item\"\n >\n <X className=\"h-3 w-3\" />\n </Button>\n )}\n </div>\n ))}\n </div>\n );\n }\n\n // Read-only list\n return (\n <ul className=\"space-y-1\">\n {items.map((item, index) => {\n const displayText = renderItem\n ? renderItem(item, index)\n : getItemDisplayValue(item);\n\n // Clickable for sheet edit\n if (actions?.onEdit) {\n return (\n <li key={item.id}>\n <button\n type=\"button\"\n onClick={() => actions.onEdit?.(item)}\n className=\"text-sm text-primary hover:underline inline-flex items-center gap-1\"\n >\n {CollectionIcon && (\n <CollectionIcon className=\"size-3 text-muted-foreground\" />\n )}\n {displayText}\n <Pencil className=\"size-3\" />\n </button>\n </li>\n );\n }\n\n // Link to detail page\n if (linkToDetail) {\n return (\n <li key={item.id}>\n <CollectionEditLink\n collection={collection as any}\n id={item.id}\n className=\"text-sm text-primary hover:underline inline-flex items-center gap-1\"\n >\n {CollectionIcon && (\n <CollectionIcon className=\"size-3 text-muted-foreground\" />\n )}\n {displayText}\n <ArrowRight className=\"size-3\" />\n </CollectionEditLink>\n </li>\n );\n }\n\n // Read-only\n return (\n <li key={item.id} className=\"text-sm flex items-center gap-1\">\n {CollectionIcon && (\n <CollectionIcon className=\"size-3 text-muted-foreground\" />\n )}\n {displayText}\n </li>\n );\n })}\n </ul>\n );\n}\n","/**\n * Table Display - table with columns\n *\n * Uses the same cell components as TableView for consistent rendering.\n */\n\nimport { ArrowRight, Pencil, X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { CollectionEditLink } from \"../../../admin-link\";\nimport { Button } from \"../../../ui/button\";\nimport {\n\tformatColumnHeader,\n\ttype RelationDisplayProps,\n\tresolveCellForColumn,\n} from \"./types\";\n\n/**\n * Cell renderer that uses resolved cell components from field registry\n */\nfunction CellRenderer({\n\titem,\n\tcolumn,\n\tcollectionConfig,\n}: {\n\titem: any;\n\tcolumn: string;\n\tcollectionConfig?: RelationDisplayProps[\"collectionConfig\"];\n}) {\n\tconst resolved = React.useMemo(\n\t\t() => resolveCellForColumn(column, collectionConfig),\n\t\t[column, collectionConfig],\n\t);\n\n\tconst value = item[resolved.accessorKey];\n\tconst { component: CellComponent, fieldDef, needsFieldDef } = resolved;\n\n\tif (needsFieldDef) {\n\t\treturn <CellComponent value={value} row={item} fieldDef={fieldDef} />;\n\t}\n\n\treturn <CellComponent value={value} row={item} />;\n}\n\nexport function TableDisplay({\n\titems,\n\tcollection,\n\tactions,\n\teditable = false,\n\tcolumns = [\"_title\"],\n\tlinkToDetail = false,\n\tcollectionConfig,\n}: RelationDisplayProps) {\n\tconst hasActions = editable || linkToDetail || actions?.onEdit;\n\n\treturn (\n\t\t<div className=\"rounded-md border\">\n\t\t\t<table className=\"w-full text-sm\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr className=\"border-b border-border/40 bg-card/10 backdrop-blur-sm\">\n\t\t\t\t\t\t{columns.map((col) => (\n\t\t\t\t\t\t\t<th key={col} className=\"px-3 py-2 text-left font-medium\">\n\t\t\t\t\t\t\t\t{formatColumnHeader(col)}\n\t\t\t\t\t\t\t</th>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t{hasActions && <th className=\"px-3 py-2 w-20\" />}\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t{items.map((item) => (\n\t\t\t\t\t\t<tr key={item.id} className=\"border-b last:border-0\">\n\t\t\t\t\t\t\t{columns.map((col) => (\n\t\t\t\t\t\t\t\t<td key={col} className=\"px-3 py-2\">\n\t\t\t\t\t\t\t\t\t<CellRenderer\n\t\t\t\t\t\t\t\t\t\titem={item}\n\t\t\t\t\t\t\t\t\t\tcolumn={col}\n\t\t\t\t\t\t\t\t\t\tcollectionConfig={collectionConfig}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t{hasActions && (\n\t\t\t\t\t\t\t\t<td className=\"px-3 py-2\">\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-end gap-1\">\n\t\t\t\t\t\t\t\t\t\t{/* Edit button */}\n\t\t\t\t\t\t\t\t\t\t{actions?.onEdit && (\n\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-7 w-7\"\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => actions.onEdit?.(item)}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Edit item\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<Pencil className=\"size-4\" />\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{/* Remove button (editable mode) */}\n\t\t\t\t\t\t\t\t\t\t{editable && actions?.onRemove && (\n\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-7 w-7\"\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => actions.onRemove?.(item)}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Remove item\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<X className=\"size-4\" />\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{/* Link to detail (non-editable mode) */}\n\t\t\t\t\t\t\t\t\t\t{!editable && linkToDetail && !actions?.onEdit && (\n\t\t\t\t\t\t\t\t\t\t\t<CollectionEditLink\n\t\t\t\t\t\t\t\t\t\t\t\tcollection={collection as any}\n\t\t\t\t\t\t\t\t\t\t\t\tid={item.id}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-primary hover:underline\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<ArrowRight className=\"size-4\" />\n\t\t\t\t\t\t\t\t\t\t\t</CollectionEditLink>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t))}\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</div>\n\t);\n}\n","/**\n * Cards Display - card grid with image, title, subtitle, meta\n */\n\nimport { Pencil, X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useResolveText } from \"../../../../i18n/hooks\";\nimport { CollectionEditLink } from \"../../../admin-link\";\nimport { Button } from \"../../../ui/button\";\nimport {\n\tformatCellValue,\n\tformatColumnHeader,\n\tgetImageUrl,\n\tgetItemDisplayValue,\n\ttype RelationDisplayProps,\n} from \"./types\";\n\nexport function CardsDisplay({\n\titems,\n\tcollection,\n\tactions,\n\teditable = false,\n\tfields,\n\tgridColumns = 2,\n\tlinkToDetail = false,\n}: RelationDisplayProps) {\n\tconst resolveText = useResolveText();\n\tconst getTitle = (item: any) =>\n\t\titem[fields?.title || \"_title\"] || getItemDisplayValue(item);\n\tconst getSubtitle = (item: any) =>\n\t\tfields?.subtitle ? item[fields.subtitle] : null;\n\tconst getImage = (item: any) => getImageUrl(item, fields?.image);\n\tconst getMeta = (item: any) => {\n\t\tif (!fields?.meta?.length) return [];\n\t\treturn fields.meta\n\t\t\t.map((field) => ({\n\t\t\t\tlabel: formatColumnHeader(field),\n\t\t\t\tvalue: formatCellValue(item[field]),\n\t\t\t}))\n\t\t\t.filter((m) => m.value !== \"-\");\n\t};\n\n\tconst gridCols = {\n\t\t1: \"grid-cols-1\",\n\t\t2: \"grid-cols-1 sm:grid-cols-2\",\n\t\t3: \"grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\",\n\t\t4: \"grid-cols-1 sm:grid-cols-2 lg:grid-cols-4\",\n\t};\n\n\treturn (\n\t\t<div className={`grid gap-4 ${gridCols[gridColumns]}`}>\n\t\t\t{items.map((item) => {\n\t\t\t\tconst image = getImage(item);\n\t\t\t\tconst subtitle = getSubtitle(item);\n\t\t\t\tconst meta = getMeta(item);\n\n\t\t\t\tconst cardContent = (\n\t\t\t\t\t<div className=\"rounded-lg border border-border/60 bg-card/30 backdrop-blur-sm hover:bg-card/50 transition-colors overflow-hidden h-full\">\n\t\t\t\t\t\t{image && (\n\t\t\t\t\t\t\t<div className=\"aspect-video bg-muted\">\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tsrc={image}\n\t\t\t\t\t\t\t\t\talt={getTitle(item)}\n\t\t\t\t\t\t\t\t\tclassName=\"w-full h-full object-cover\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<div className=\"p-3\">\n\t\t\t\t\t\t\t<div className=\"flex items-start justify-between gap-2\">\n\t\t\t\t\t\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t\t\t\t\t\t<div className=\"font-medium truncate\">{getTitle(item)}</div>\n\t\t\t\t\t\t\t\t\t{subtitle && (\n\t\t\t\t\t\t\t\t\t\t<div className=\"text-sm text-muted-foreground truncate mt-0.5\">\n\t\t\t\t\t\t\t\t\t\t\t{subtitle}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{/* Action buttons for editable mode */}\n\t\t\t\t\t\t\t\t{editable && (actions?.onEdit || actions?.onRemove) && (\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-1 shrink-0\">\n\t\t\t\t\t\t\t\t\t\t{actions?.onEdit && (\n\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-7 w-7\"\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\tactions.onEdit?.(item);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Edit item\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<Pencil className=\"size-3\" />\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{actions?.onRemove && (\n\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-7 w-7\"\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\tactions.onRemove?.(item);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Remove item\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<X className=\"size-3\" />\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{meta.length > 0 && (\n\t\t\t\t\t\t\t\t<div className=\"flex flex-wrap gap-x-3 gap-y-1 mt-2 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{meta.map((m) => (\n\t\t\t\t\t\t\t\t\t\t<span key={String(m.label)}>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"font-medium\">\n\t\t\t\t\t\t\t\t\t\t\t\t{resolveText(m.label)}:\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t{m.value}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\n\t\t\t\t// Non-editable with sheet edit\n\t\t\t\tif (!editable && actions?.onEdit) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => actions.onEdit?.(item)}\n\t\t\t\t\t\t\tclassName=\"text-left w-full\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{cardContent}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Non-editable with link to detail\n\t\t\t\tif (!editable && linkToDetail) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<CollectionEditLink\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\tcollection={collection as any}\n\t\t\t\t\t\t\tid={item.id}\n\t\t\t\t\t\t\tclassName=\"block\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{cardContent}\n\t\t\t\t\t\t</CollectionEditLink>\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Editable or read-only\n\t\t\t\treturn <div key={item.id}>{cardContent}</div>;\n\t\t\t})}\n\t\t</div>\n\t);\n}\n","/**\n * Grid Display - compact grid with thumbnails\n */\n\nimport { Pencil, X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { CollectionEditLink } from \"../../../admin-link\";\nimport { Button } from \"../../../ui/button\";\nimport {\n type RelationDisplayProps,\n getImageUrl,\n getItemDisplayValue,\n} from \"./types\";\n\nexport function GridDisplay({\n items,\n collection,\n collectionIcon: CollectionIcon,\n actions,\n editable = false,\n fields,\n gridColumns = 3,\n linkToDetail = false,\n}: RelationDisplayProps) {\n const getTitle = (item: any) =>\n item[fields?.title || \"_title\"] || getItemDisplayValue(item);\n const getImage = (item: any) => getImageUrl(item, fields?.image);\n\n const gridCols = {\n 1: \"grid-cols-1\",\n 2: \"grid-cols-2\",\n 3: \"grid-cols-2 sm:grid-cols-3\",\n 4: \"grid-cols-2 sm:grid-cols-3 lg:grid-cols-4\",\n };\n\n return (\n <div className={`grid gap-2 ${gridCols[gridColumns]}`}>\n {items.map((item) => {\n const image = getImage(item);\n\n const gridContent = (\n <div className=\"flex items-center gap-2 rounded-md border border-border/60 bg-card/30 backdrop-blur-sm p-2 hover:bg-card/50 transition-colors h-full\">\n {image ? (\n <div className=\"size-8 rounded bg-muted shrink-0 overflow-hidden\">\n <img\n src={image}\n alt={getTitle(item)}\n className=\"w-full h-full object-cover\"\n />\n </div>\n ) : CollectionIcon ? (\n <div className=\"size-8 rounded bg-muted shrink-0 flex items-center justify-center\">\n <CollectionIcon className=\"size-4 text-muted-foreground\" />\n </div>\n ) : null}\n <span className=\"text-sm truncate flex-1\">{getTitle(item)}</span>\n {/* Action buttons for editable mode */}\n {editable && (actions?.onEdit || actions?.onRemove) && (\n <div className=\"flex items-center gap-0.5 shrink-0\">\n {actions?.onEdit && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n actions.onEdit?.(item);\n }}\n aria-label=\"Edit item\"\n >\n <Pencil className=\"size-3\" />\n </Button>\n )}\n {actions?.onRemove && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n actions.onRemove?.(item);\n }}\n aria-label=\"Remove item\"\n >\n <X className=\"size-3\" />\n </Button>\n )}\n </div>\n )}\n </div>\n );\n\n // Non-editable with sheet edit\n if (!editable && actions?.onEdit) {\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => actions.onEdit?.(item)}\n className=\"text-left w-full\"\n >\n {gridContent}\n </button>\n );\n }\n\n // Non-editable with link to detail\n if (!editable && linkToDetail) {\n return (\n <CollectionEditLink\n key={item.id}\n collection={collection as any}\n id={item.id}\n className=\"block\"\n >\n {gridContent}\n </CollectionEditLink>\n );\n }\n\n // Editable or read-only\n return <div key={item.id}>{gridContent}</div>;\n })}\n </div>\n );\n}\n","/**\n * RelationItemsDisplay Component\n *\n * Unified display component for relation items.\n * Renders items using the specified display mode.\n *\n * Used by:\n * - RelationPicker (editable M:N relations)\n * - ReverseRelationField (read-only reverse relations)\n */\n\nimport type * as React from \"react\";\nimport { useResolveText } from \"../../../i18n/hooks\";\nimport type { I18nText } from \"../../../i18n/types\";\nimport type {\n\tCollectionFieldsConfig,\n\tRelationDisplayFields,\n\tRelationDisplayMode,\n\tRelationDisplayProps,\n\tRelationItemActions,\n} from \"./displays\";\nimport { CardsDisplay } from \"./displays/cards-display\";\nimport { ChipsDisplay } from \"./displays/chips-display\";\nimport { GridDisplay } from \"./displays/grid-display\";\nimport { ListDisplay } from \"./displays/list-display\";\nimport { TableDisplay } from \"./displays/table-display\";\n\nexport interface RelationItemsDisplayProps {\n\t/**\n\t * Display mode\n\t */\n\tdisplay?: RelationDisplayMode;\n\n\t/**\n\t * Items to display\n\t */\n\titems: any[];\n\n\t/**\n\t * Collection name\n\t */\n\tcollection: string;\n\n\t/**\n\t * Collection icon component\n\t */\n\tcollectionIcon?: React.ComponentType<{ className?: string }>;\n\n\t/**\n\t * Action handlers\n\t */\n\tactions?: RelationItemActions;\n\n\t/**\n\t * Whether items are editable (shows edit/remove buttons inline)\n\t */\n\teditable?: boolean;\n\n\t/**\n\t * Whether items can be reordered (shows drag handle)\n\t */\n\torderable?: boolean;\n\n\t/**\n\t * Columns for table display\n\t */\n\tcolumns?: string[];\n\n\t/**\n\t * Field mapping for cards/grid display\n\t */\n\tfields?: RelationDisplayFields;\n\n\t/**\n\t * Number of columns for grid/cards layout\n\t */\n\tgridColumns?: 1 | 2 | 3 | 4;\n\n\t/**\n\t * Show link to detail page (for read-only displays)\n\t */\n\tlinkToDetail?: boolean;\n\n\t/**\n\t * Custom render function for list items\n\t */\n\trenderItem?: (item: any, index: number) => React.ReactNode;\n\n\t/**\n\t * Message to show when no items\n\t */\n\temptyMessage?: I18nText;\n\n\t/**\n\t * Collection config for cell rendering (enables proper cell components in table mode)\n\t */\n\tcollectionConfig?: CollectionFieldsConfig;\n}\n\nexport function RelationItemsDisplay({\n\tdisplay = \"list\",\n\titems,\n\tcollection,\n\tcollectionIcon,\n\tactions,\n\teditable = false,\n\torderable = false,\n\tcolumns,\n\tfields,\n\tgridColumns,\n\tlinkToDetail = false,\n\trenderItem,\n\temptyMessage = \"No items\",\n\tcollectionConfig,\n}: RelationItemsDisplayProps) {\n\tconst resolveText = useResolveText();\n\tconst resolvedEmptyMessage = resolveText(emptyMessage ?? \"No items\");\n\t// Empty state\n\tif (!items || items.length === 0) {\n\t\treturn (\n\t\t\t<div className=\"rounded-lg border border-dashed p-4 text-center\">\n\t\t\t\t<p className=\"text-sm text-muted-foreground\">{resolvedEmptyMessage}</p>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst displayProps: RelationDisplayProps = {\n\t\titems,\n\t\tcollection,\n\t\tcollectionIcon,\n\t\tactions,\n\t\teditable,\n\t\torderable,\n\t\tcolumns: columns || [\"_title\"],\n\t\tfields,\n\t\tgridColumns,\n\t\tlinkToDetail,\n\t\trenderItem,\n\t\tcollectionConfig,\n\t};\n\n\tswitch (display) {\n\t\tcase \"chips\":\n\t\t\treturn <ChipsDisplay {...displayProps} />;\n\t\tcase \"table\":\n\t\t\treturn <TableDisplay {...displayProps} />;\n\t\tcase \"cards\":\n\t\t\treturn <CardsDisplay {...displayProps} />;\n\t\tcase \"grid\":\n\t\t\treturn <GridDisplay {...displayProps} />;\n\t\tcase \"list\":\n\t\tdefault:\n\t\t\treturn <ListDisplay {...displayProps} />;\n\t}\n}\n\n// Re-export types for convenience\nexport type {\n\tCollectionFieldsConfig,\n\tRelationDisplayFields,\n\tRelationDisplayMode,\n\tRelationDisplayProps,\n\tRelationItemActions,\n} from \"./displays\";\n","/**\n * RelationPicker Component\n *\n * Multiple relation field (one-to-many, many-to-many) with:\n * - Searchable select to add existing items\n * - Plus button to create new related item (opens side sheet)\n * - Edit button on each selected item (opens side sheet)\n * - Remove button on each selected item\n * - Optional drag-and-drop reordering\n * - Multiple display modes (list, chips, table, cards, grid)\n * - Responsive: Popover on desktop, Drawer on mobile\n */\n\nimport { Plus } from \"@phosphor-icons/react\";\nimport { createQuestpieQueryOptions } from \"@questpie/tanstack-query\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport * as React from \"react\";\nimport { toast } from \"sonner\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { selectAdmin, selectClient, useAdminStore } from \"../../runtime\";\nimport { SelectSingle } from \"../primitives/select-single\";\nimport type { SelectOption } from \"../primitives/types\";\nimport { ResourceSheet } from \"../sheets/resource-sheet\";\nimport { Button } from \"../ui/button\";\nimport { getAutoColumns } from \"./field-utils\";\nimport { LocaleBadge } from \"./locale-badge\";\nimport {\n\ttype RelationDisplayFields,\n\ttype RelationDisplayMode,\n\tRelationItemsDisplay,\n} from \"./relation\";\n\nexport interface RelationPickerProps<_T extends Questpie<any>> {\n\t/**\n\t * Field name\n\t */\n\tname: string;\n\n\t/**\n\t * Current value (array of IDs of related items)\n\t */\n\tvalue?: string[] | null;\n\n\t/**\n\t * Change handler\n\t */\n\tonChange: (value: string[]) => void;\n\n\t/**\n\t * Target collection name\n\t */\n\ttargetCollection: string;\n\n\t/**\n\t * Label for the field\n\t */\n\tlabel?: string;\n\n\t/**\n\t * Localized field\n\t */\n\tlocalized?: boolean;\n\n\t/**\n\t * Active locale\n\t */\n\tlocale?: string;\n\n\t/**\n\t * Filter options based on form values\n\t */\n\tfilter?: (formValues: any) => any;\n\n\t/**\n\t * Is the field required\n\t */\n\trequired?: boolean;\n\n\t/**\n\t * Is the field disabled\n\t */\n\tdisabled?: boolean;\n\n\t/**\n\t * Is the field readonly\n\t */\n\treadOnly?: boolean;\n\n\t/**\n\t * Placeholder text\n\t */\n\tplaceholder?: string;\n\n\t/**\n\t * Error message\n\t */\n\terror?: string;\n\n\t/**\n\t * Enable drag-and-drop reordering\n\t */\n\torderable?: boolean;\n\n\t/**\n\t * Maximum number of items\n\t */\n\tmaxItems?: number;\n\n\t/**\n\t * Display mode for selected items\n\t * @default \"list\"\n\t */\n\tdisplay?: RelationDisplayMode;\n\n\t/**\n\t * Columns to show in table display mode\n\t */\n\tcolumns?: string[];\n\n\t/**\n\t * Field mapping for cards/grid display modes\n\t */\n\tfields?: RelationDisplayFields;\n\n\t/**\n\t * Number of columns for grid/cards layout\n\t */\n\tgridColumns?: 1 | 2 | 3 | 4;\n\n\t/**\n\t * Custom render function for selected items (only used in list mode)\n\t */\n\trenderItem?: (item: any, index: number) => React.ReactNode;\n\n\t/**\n\t * Custom render function for dropdown options\n\t */\n\trenderOption?: (item: any) => React.ReactNode;\n}\n\nexport function RelationPicker<T extends Questpie<any>>({\n\tname,\n\tvalue = [],\n\tonChange,\n\ttargetCollection,\n\tlabel,\n\tfilter,\n\trequired,\n\tdisabled,\n\treadOnly,\n\tplaceholder,\n\terror,\n\tlocalized,\n\tlocale: localeProp,\n\torderable = false,\n\tmaxItems,\n\tdisplay = \"list\",\n\tcolumns,\n\tfields,\n\tgridColumns,\n\trenderItem,\n\trenderOption,\n}: RelationPickerProps<T>) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst resolvedLabel = label ? resolveText(label) : undefined;\n\tconst resolvedPlaceholder = placeholder\n\t\t? resolveText(placeholder)\n\t\t: undefined;\n\tconst labelText = resolvedLabel || targetCollection;\n\tconst addLabel = t(\"relation.addItem\", { name: labelText });\n\tconst noResultsLabel = t(\"relation.noResults\", { name: labelText });\n\tconst emptyLabel = t(\"relation.noneSelected\", { name: labelText });\n\tconst createLabel = t(\"relation.createNew\", { name: labelText });\n\tconst locale = localeProp;\n\tconst [isSheetOpen, setIsSheetOpen] = React.useState(false);\n\tconst [editingItemId, setEditingItemId] = React.useState<\n\t\tstring | undefined\n\t>();\n\n\t// Get admin config for target collection\n\tconst admin = useAdminStore(selectAdmin);\n\tconst collections = admin?.getCollections() ?? {};\n\tconst targetConfig = collections[targetCollection];\n\tconst CollectionIcon = (targetConfig as any)?.icon as\n\t\t| React.ComponentType<{ className?: string }>\n\t\t| undefined;\n\tconst displayColumns = React.useMemo(() => {\n\t\tif (columns && columns.length > 0) return columns;\n\t\tif (display === \"table\" && targetConfig) {\n\t\t\treturn getAutoColumns(targetConfig);\n\t\t}\n\t\treturn [\"_title\"];\n\t}, [columns, display, targetConfig]);\n\n\t// Normalize value to array (handles prefill with single string ID)\n\tconst selectedIds = React.useMemo(() => {\n\t\tif (!value) return [];\n\t\tif (Array.isArray(value)) return value;\n\t\t// Single string ID (from prefill) - convert to array\n\t\treturn [value];\n\t}, [value]);\n\tconst client = useAdminStore(selectClient);\n\n\t// Keep track of fetched items for display\n\t// Using lazy init to avoid creating new Map on every render\n\tconst [fetchedItems, setFetchedItems] = React.useState<Map<string, any>>(\n\t\t() => new Map(),\n\t);\n\n\t// Load options from server with search\n\tconst loadOptions = React.useCallback(\n\t\tasync (search: string): Promise<SelectOption<string>[]> => {\n\t\t\tif (!client) return [];\n\n\t\t\ttry {\n\t\t\t\tconst options: any = {\n\t\t\t\t\tlimit: 50,\n\t\t\t\t};\n\n\t\t\t\t// Add search filter for _title\n\t\t\t\tif (search) {\n\t\t\t\t\toptions.search = search;\n\t\t\t\t}\n\n\t\t\t\t// Add custom filter if provided\n\t\t\t\tif (filter) {\n\t\t\t\t\toptions.where = filter({});\n\t\t\t\t}\n\n\t\t\t\tconst response = await (client as any).collections[\n\t\t\t\t\ttargetCollection\n\t\t\t\t].find(options);\n\t\t\t\tconst docs = response?.docs || [];\n\n\t\t\t\t// Immutable update - create new Map with spread to avoid mutations\n\t\t\t\tsetFetchedItems(\n\t\t\t\t\t(prev) =>\n\t\t\t\t\t\tnew Map([\n\t\t\t\t\t\t\t...prev,\n\t\t\t\t\t\t\t...docs.map((doc: any) => [doc.id, doc] as const),\n\t\t\t\t\t\t]),\n\t\t\t\t);\n\n\t\t\t\t// Filter out already selected items and transform to SelectOption format\n\t\t\t\treturn docs\n\t\t\t\t\t.filter((opt: any) => !selectedIds.includes(opt.id))\n\t\t\t\t\t.map((item: any) => ({\n\t\t\t\t\t\tvalue: item.id,\n\t\t\t\t\t\tlabel: renderOption\n\t\t\t\t\t\t\t? String(renderOption(item))\n\t\t\t\t\t\t\t: item._title || item.id || \"\",\n\t\t\t\t\t\ticon: CollectionIcon ? (\n\t\t\t\t\t\t\t<CollectionIcon className=\"size-3.5 text-muted-foreground\" />\n\t\t\t\t\t\t) : undefined,\n\t\t\t\t\t}));\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to load relation options:\", error);\n\t\t\t\ttoast.error(\"Failed to load options\");\n\t\t\t\treturn [];\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tclient,\n\t\t\ttargetCollection,\n\t\t\tfilter,\n\t\t\tselectedIds,\n\t\t\trenderOption,\n\t\t\tCollectionIcon,\n\t\t],\n\t);\n\n\t// Refetch for mutations (after create/update)\n\tconst queryClient = useQueryClient();\n\tconst queryOpts = React.useMemo(\n\t\t() =>\n\t\t\tcreateQuestpieQueryOptions(\n\t\t\t\t(client ?? {}) as any,\n\t\t\t\t{\n\t\t\t\t\tkeyPrefix: [\"questpie\", \"collections\"],\n\t\t\t\t} as any,\n\t\t\t),\n\t\t[client],\n\t);\n\n\tconst refetch = React.useCallback(async () => {\n\t\t// Clear cached items to force refresh\n\t\tsetFetchedItems(new Map());\n\t\tqueryClient.invalidateQueries({\n\t\t\tqueryKey: queryOpts.key([\"collections\", targetCollection, \"find\"]),\n\t\t});\n\t\tselectedIds.forEach((id) => {\n\t\t\tqueryClient.invalidateQueries({\n\t\t\t\tqueryKey: queryOpts.key([\n\t\t\t\t\t\"collections\",\n\t\t\t\t\ttargetCollection,\n\t\t\t\t\t\"findOne\",\n\t\t\t\t\t{ where: { id } },\n\t\t\t\t]),\n\t\t\t});\n\t\t});\n\t}, [queryClient, queryOpts, selectedIds, targetCollection]);\n\n\t// Fetch selected items on mount for display\n\tReact.useEffect(() => {\n\t\tif (!client || !selectedIds.length) return;\n\n\t\t// Fetch any selected items that we don't have in cache\n\t\tconst missingIds = selectedIds.filter((id) => !fetchedItems.has(id));\n\t\tif (missingIds.length === 0) return;\n\n\t\t(async () => {\n\t\t\ttry {\n\t\t\t\tfor (const id of missingIds) {\n\t\t\t\t\tconst response = await (client as any).collections[\n\t\t\t\t\t\ttargetCollection\n\t\t\t\t\t].findOne({ where: { id } });\n\t\t\t\t\tif (response) {\n\t\t\t\t\t\t// Immutable update - spread prev and add new entry\n\t\t\t\t\t\tsetFetchedItems((prev) => new Map([...prev, [id, response]]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to fetch selected items:\", error);\n\t\t\t\ttoast.error(\"Failed to load selected items\");\n\t\t\t}\n\t\t})();\n\t}, [client, targetCollection, selectedIds, fetchedItems]);\n\n\t// Get selected items from cache\n\tconst selectedItems = React.useMemo(() => {\n\t\treturn selectedIds\n\t\t\t.map((id: string) => fetchedItems.get(id))\n\t\t\t.filter(Boolean);\n\t}, [selectedIds, fetchedItems]);\n\n\tconst handleAdd = React.useCallback(\n\t\t(itemId: string | null) => {\n\t\t\tif (!itemId) return;\n\t\t\tif (selectedIds.includes(itemId)) return;\n\t\t\tif (maxItems && selectedIds.length >= maxItems) return;\n\t\t\tonChange([...selectedIds, itemId]);\n\t\t},\n\t\t[selectedIds, maxItems, onChange],\n\t);\n\n\tconst handleRemove = React.useCallback(\n\t\t(itemId: string) => {\n\t\t\tonChange(selectedIds.filter((id) => id !== itemId));\n\t\t},\n\t\t[selectedIds, onChange],\n\t);\n\n\tconst handleOpenCreate = React.useCallback(() => {\n\t\tsetEditingItemId(undefined);\n\t\tsetIsSheetOpen(true);\n\t}, []);\n\n\tconst handleOpenEdit = React.useCallback((itemId: string) => {\n\t\tsetEditingItemId(itemId);\n\t\tsetIsSheetOpen(true);\n\t}, []);\n\n\t// Handle save from ResourceSheet\n\tconst handleSheetSave = React.useCallback(\n\t\tasync (result: any) => {\n\t\t\t// Add newly created item to selection (create mode = no editingItemId)\n\t\t\tif (!editingItemId && result?.id) {\n\t\t\t\tonChange([...selectedIds, result.id]);\n\t\t\t}\n\t\t\tawait refetch();\n\t\t},\n\t\t[editingItemId, selectedIds, onChange, refetch],\n\t);\n\n\tconst canAddMore = !maxItems || selectedIds.length < maxItems;\n\n\t// Memoize actions to prevent infinite re-renders\n\tconst displayActions = React.useMemo(\n\t\t() => ({\n\t\t\tonEdit: !readOnly ? (item: any) => handleOpenEdit(item.id) : undefined,\n\t\t\tonRemove:\n\t\t\t\t!readOnly && (!required || selectedIds.length > 1)\n\t\t\t\t\t? (item: any) => handleRemove(item.id)\n\t\t\t\t\t: undefined,\n\t\t}),\n\t\t[readOnly, required, selectedIds.length, handleOpenEdit, handleRemove],\n\t);\n\n\treturn (\n\t\t<div className=\"space-y-2\">\n\t\t\t{label && (\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<label\n\t\t\t\t\t\thtmlFor={name}\n\t\t\t\t\t\tclassName=\"text-sm font-medium flex items-center gap-1.5\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{CollectionIcon && (\n\t\t\t\t\t\t\t<CollectionIcon className=\"size-3.5 text-muted-foreground\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{resolvedLabel}\n\t\t\t\t\t\t{required && <span className=\"text-destructive\">*</span>}\n\t\t\t\t\t\t{maxItems && (\n\t\t\t\t\t\t\t<span className=\"ml-2 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t({selectedIds.length}/{maxItems})\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</label>\n\t\t\t\t\t{localized && <LocaleBadge locale={locale || \"i18n\"} />}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Selected Items Display */}\n\t\t\t{selectedItems && selectedItems.length > 0 && (\n\t\t\t\t<RelationItemsDisplay\n\t\t\t\t\tdisplay={display}\n\t\t\t\t\titems={selectedItems}\n\t\t\t\t\tcollection={targetCollection}\n\t\t\t\t\tcollectionIcon={CollectionIcon}\n\t\t\t\t\teditable={!readOnly && !disabled}\n\t\t\t\t\torderable={orderable && !readOnly && !disabled}\n\t\t\t\t\tcolumns={displayColumns}\n\t\t\t\t\tfields={fields}\n\t\t\t\t\tgridColumns={gridColumns}\n\t\t\t\t\trenderItem={renderItem}\n\t\t\t\t\tactions={displayActions}\n\t\t\t\t\tcollectionConfig={targetConfig as any}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Add More */}\n\t\t\t{!readOnly && canAddMore && (\n\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t{/* Searchable Select to add existing items - uses server-side search */}\n\t\t\t\t\t<div className=\"flex-1\">\n\t\t\t\t\t\t<SelectSingle\n\t\t\t\t\t\t\tvalue={null}\n\t\t\t\t\t\t\tonChange={handleAdd}\n\t\t\t\t\t\t\tloadOptions={loadOptions}\n\t\t\t\t\t\t\tqueryKey={(search) =>\n\t\t\t\t\t\t\t\tqueryOpts.key([\n\t\t\t\t\t\t\t\t\t\"collections\",\n\t\t\t\t\t\t\t\t\ttargetCollection,\n\t\t\t\t\t\t\t\t\t\"find\",\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tlimit: 50,\n\t\t\t\t\t\t\t\t\t\tsearch,\n\t\t\t\t\t\t\t\t\t\twhere: filter ? filter({}) : undefined,\n\t\t\t\t\t\t\t\t\t\tselectedIds,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tprefetchOnMount\n\t\t\t\t\t\t\tplaceholder={resolvedPlaceholder || `${addLabel}...`}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\tclearable={false}\n\t\t\t\t\t\t\temptyMessage={noResultsLabel}\n\t\t\t\t\t\t\tdrawerTitle={addLabel}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Create Button */}\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tonClick={handleOpenCreate}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\ttitle={createLabel}\n\t\t\t\t\t\taria-label={createLabel}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Plus className=\"h-4 w-4\" />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Empty State */}\n\t\t\t{selectedIds.length === 0 && (\n\t\t\t\t<div className=\"rounded-lg border border-dashed p-4 text-center\">\n\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t{resolvedPlaceholder || emptyLabel}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Error message */}\n\t\t\t{error && <p className=\"text-sm text-destructive\">{error}</p>}\n\n\t\t\t{/* Side Sheet for Create/Edit */}\n\t\t\t<ResourceSheet\n\t\t\t\ttype=\"collection\"\n\t\t\t\tcollection={targetCollection}\n\t\t\t\titemId={editingItemId}\n\t\t\t\topen={isSheetOpen}\n\t\t\t\tonOpenChange={setIsSheetOpen}\n\t\t\t\tonSave={handleSheetSave}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","/**\n * RelationSelect Component\n *\n * Single relation field (one-to-one) with:\n * - Searchable select dropdown to choose existing item\n * - Plus button to create new related item (opens side sheet)\n * - Edit button to modify selected item (opens side sheet)\n * - Responsive: Popover on desktop, Drawer on mobile\n */\n\nimport { Pencil, Plus } from \"@phosphor-icons/react\";\nimport { createQuestpieQueryOptions } from \"@questpie/tanstack-query\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport * as React from \"react\";\nimport { toast } from \"sonner\";\nimport { useCollectionItem } from \"../../hooks/use-collection\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { selectAdmin, selectClient, useAdminStore } from \"../../runtime\";\nimport { SelectSingle } from \"../primitives/select-single\";\nimport type { SelectOption } from \"../primitives/types\";\nimport { ResourceSheet } from \"../sheets/resource-sheet\";\nimport { Button } from \"../ui/button\";\nimport { LocaleBadge } from \"./locale-badge\";\n\nexport interface RelationSelectProps<_T extends Questpie<any>> {\n\t/**\n\t * Field name\n\t */\n\tname: string;\n\n\t/**\n\t * Current value (ID of related item)\n\t */\n\tvalue?: string | null;\n\n\t/**\n\t * Change handler\n\t */\n\tonChange: (value: string | null) => void;\n\n\t/**\n\t * Target collection name\n\t */\n\ttargetCollection: string;\n\n\t/**\n\t * Label for the field\n\t */\n\tlabel?: string;\n\n\t/**\n\t * Localized field\n\t */\n\tlocalized?: boolean;\n\n\t/**\n\t * Active locale\n\t */\n\tlocale?: string;\n\n\t/**\n\t * Filter options based on form values\n\t */\n\tfilter?: (formValues: any) => any;\n\n\t/**\n\t * Is the field required\n\t */\n\trequired?: boolean;\n\n\t/**\n\t * Is the field disabled\n\t */\n\tdisabled?: boolean;\n\n\t/**\n\t * Is the field readonly\n\t */\n\treadOnly?: boolean;\n\n\t/**\n\t * Placeholder text\n\t */\n\tplaceholder?: string;\n\n\t/**\n\t * Error message\n\t */\n\terror?: string;\n\n\t/**\n\t * Custom render function for dropdown options\n\t */\n\trenderOption?: (item: any) => React.ReactNode;\n\n\t/**\n\t * Custom render function for selected value\n\t */\n\trenderValue?: (item: any) => React.ReactNode;\n}\n\nexport function RelationSelect<T extends Questpie<any>>({\n\tname,\n\tvalue,\n\tonChange,\n\ttargetCollection,\n\tlabel,\n\tfilter,\n\trequired,\n\tdisabled,\n\treadOnly,\n\tplaceholder,\n\terror,\n\tlocalized,\n\tlocale,\n\trenderOption,\n\trenderValue,\n}: RelationSelectProps<T>) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst resolvedLabel = label ? resolveText(label) : undefined;\n\tconst resolvedPlaceholder = placeholder\n\t\t? resolveText(placeholder)\n\t\t: undefined;\n\tconst labelText = resolvedLabel || targetCollection;\n\tconst selectLabel = t(\"relation.select\", { name: labelText });\n\tconst noResultsLabel = t(\"relation.noResults\", { name: labelText });\n\tconst createLabel = t(\"relation.createNew\", { name: labelText });\n\tconst [isSheetOpen, setIsSheetOpen] = React.useState(false);\n\tconst [editingItemId, setEditingItemId] = React.useState<\n\t\tstring | undefined\n\t>();\n\n\t// Get admin config for target collection\n\tconst admin = useAdminStore(selectAdmin);\n\tconst client = useAdminStore(selectClient);\n\tconst collections = admin?.getCollections() ?? {};\n\tconst targetConfig = collections[targetCollection];\n\tconst CollectionIcon = (targetConfig as any)?.icon as\n\t\t| React.ComponentType<{ className?: string }>\n\t\t| undefined;\n\n\t// Load options from server with search\n\tconst loadOptions = React.useCallback(\n\t\tasync (search: string): Promise<SelectOption<string>[]> => {\n\t\t\tif (!client) return [];\n\n\t\t\ttry {\n\t\t\t\tconst options: any = {\n\t\t\t\t\tlimit: 50,\n\t\t\t\t\tlocale,\n\t\t\t\t};\n\n\t\t\t\t// Add search filter for _title\n\t\t\t\tif (search) {\n\t\t\t\t\toptions.search = search;\n\t\t\t\t}\n\n\t\t\t\t// Add custom filter if provided\n\t\t\t\tif (filter) {\n\t\t\t\t\toptions.where = filter({});\n\t\t\t\t}\n\n\t\t\t\tconst response = await (client as any).collections[\n\t\t\t\t\ttargetCollection\n\t\t\t\t].find(options);\n\t\t\t\tconst docs = response?.docs || [];\n\n\t\t\t\treturn docs.map((item: any) => ({\n\t\t\t\t\tvalue: item.id,\n\t\t\t\t\tlabel: renderOption\n\t\t\t\t\t\t? String(renderOption(item))\n\t\t\t\t\t\t: item._title || item.id || \"\",\n\t\t\t\t\ticon: CollectionIcon ? (\n\t\t\t\t\t\t<CollectionIcon className=\"size-3.5 text-muted-foreground\" />\n\t\t\t\t\t) : undefined,\n\t\t\t\t}));\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to load relation options:\", error);\n\t\t\t\ttoast.error(\"Failed to load options\");\n\t\t\t\treturn [];\n\t\t\t}\n\t\t},\n\t\t[client, targetCollection, filter, renderOption, CollectionIcon, locale],\n\t);\n\n\tconst queryClient = useQueryClient();\n\tconst queryOpts = React.useMemo(\n\t\t() =>\n\t\t\tcreateQuestpieQueryOptions(\n\t\t\t\t(client ?? {}) as any,\n\t\t\t\t{\n\t\t\t\t\tkeyPrefix: [\"questpie\", \"collections\"],\n\t\t\t\t} as any,\n\t\t\t),\n\t\t[client],\n\t);\n\n\t// Refetch for mutations (after create/update)\n\tconst refetch = React.useCallback(async () => {\n\t\tqueryClient.invalidateQueries({\n\t\t\tqueryKey: queryOpts.key([\"collections\", targetCollection, \"find\"]),\n\t\t});\n\t\tqueryClient.invalidateQueries({\n\t\t\tqueryKey: queryOpts.key([\n\t\t\t\t\"collections\",\n\t\t\t\ttargetCollection,\n\t\t\t\t\"findOne\",\n\t\t\t\t{ where: { id: value || \"\" } },\n\t\t\t]),\n\t\t});\n\t}, [queryClient, queryOpts, targetCollection, value]);\n\n\t// Fetch selected item details using the hook\n\tconst { data: selectedItem } = useCollectionItem(\n\t\ttargetCollection,\n\t\tvalue || \"\",\n\t\tundefined,\n\t\t{ enabled: !!value },\n\t);\n\n\tconst selectedOptions = React.useMemo(() => {\n\t\tif (!selectedItem) return [];\n\t\treturn [\n\t\t\t{\n\t\t\t\tvalue: selectedItem.id,\n\t\t\t\tlabel: renderValue\n\t\t\t\t\t? String(renderValue(selectedItem))\n\t\t\t\t\t: selectedItem._title || selectedItem.id || \"\",\n\t\t\t\ticon: CollectionIcon ? (\n\t\t\t\t\t<CollectionIcon className=\"size-3.5 text-muted-foreground\" />\n\t\t\t\t) : undefined,\n\t\t\t},\n\t\t];\n\t}, [selectedItem, renderValue, CollectionIcon]);\n\n\tconst handleOpenCreate = () => {\n\t\tsetEditingItemId(undefined);\n\t\tsetIsSheetOpen(true);\n\t};\n\n\tconst handleOpenEdit = () => {\n\t\tif (!value) return;\n\t\tsetEditingItemId(value);\n\t\tsetIsSheetOpen(true);\n\t};\n\n\tconst handleValueChange = (newValue: string | null) => {\n\t\tonChange(newValue);\n\t};\n\n\t// Handle save from ResourceSheet\n\tconst handleSheetSave = React.useCallback(\n\t\tasync (result: any) => {\n\t\t\t// Select newly created item (create mode = no editingItemId)\n\t\t\tif (!editingItemId && result?.id) {\n\t\t\t\tonChange(result.id);\n\t\t\t}\n\t\t\tawait refetch();\n\t\t},\n\t\t[editingItemId, onChange, refetch],\n\t);\n\n\treturn (\n\t\t<div className=\"space-y-2\">\n\t\t\t{label && (\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<label\n\t\t\t\t\t\thtmlFor={name}\n\t\t\t\t\t\tclassName=\"text-sm font-medium flex items-center gap-1.5\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{CollectionIcon && (\n\t\t\t\t\t\t\t<CollectionIcon className=\"size-3.5 text-muted-foreground\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{resolvedLabel}\n\t\t\t\t\t\t{required && <span className=\"text-destructive\">*</span>}\n\t\t\t\t\t</label>\n\t\t\t\t\t{localized && <LocaleBadge locale={locale || \"i18n\"} />}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<div className=\"flex items-stretch gap-0\">\n\t\t\t\t{/* Searchable Select Dropdown - uses server-side search */}\n\t\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t\t<SelectSingle\n\t\t\t\t\t\tid={name}\n\t\t\t\t\t\tvalue={value || null}\n\t\t\t\t\t\tonChange={handleValueChange}\n\t\t\t\t\t\toptions={selectedOptions}\n\t\t\t\t\t\tloadOptions={loadOptions}\n\t\t\t\t\t\tqueryKey={(search) =>\n\t\t\t\t\t\t\tqueryOpts.key([\n\t\t\t\t\t\t\t\t\"collections\",\n\t\t\t\t\t\t\t\ttargetCollection,\n\t\t\t\t\t\t\t\t\"find\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tlimit: 50,\n\t\t\t\t\t\t\t\t\tlocale,\n\t\t\t\t\t\t\t\t\tsearch,\n\t\t\t\t\t\t\t\t\twhere: filter ? filter({}) : undefined,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprefetchOnMount\n\t\t\t\t\t\tplaceholder={resolvedPlaceholder || `${selectLabel}...`}\n\t\t\t\t\t\tdisabled={disabled || readOnly}\n\t\t\t\t\t\tclearable={!required}\n\t\t\t\t\t\temptyMessage={noResultsLabel}\n\t\t\t\t\t\tdrawerTitle={selectLabel}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t!readOnly && \"rounded-r-none\",\n\t\t\t\t\t\t\terror && \"border-destructive\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t\taria-invalid={!!error}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Action Buttons */}\n\t\t\t\t{!readOnly && (\n\t\t\t\t\t<div className=\"flex\">\n\t\t\t\t\t\t{/* Edit button (only if value is set) */}\n\t\t\t\t\t\t{value && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\tonClick={handleOpenEdit}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\ttitle={t(\"collection.edit\", { name: labelText })}\n\t\t\t\t\t\t\t\taria-label={t(\"collection.edit\", { name: labelText })}\n\t\t\t\t\t\t\t\tclassName=\"rounded-none border-l-0\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Pencil className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{/* Create button */}\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\tonClick={handleOpenCreate}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\ttitle={createLabel}\n\t\t\t\t\t\t\taria-label={createLabel}\n\t\t\t\t\t\t\tclassName=\"border-l-0 rounded-l-none\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Plus className=\"h-4 w-4\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Error message */}\n\t\t\t{error && <p className=\"text-sm text-destructive\">{error}</p>}\n\n\t\t\t{/* Side Sheet for Create/Edit */}\n\t\t\t<ResourceSheet\n\t\t\t\ttype=\"collection\"\n\t\t\t\tcollection={targetCollection}\n\t\t\t\titemId={editingItemId}\n\t\t\t\topen={isSheetOpen}\n\t\t\t\tonOpenChange={setIsSheetOpen}\n\t\t\t\tonSave={handleSheetSave}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","/**\n * RelationField Component\n *\n * Unified relation field that automatically chooses between:\n * - RelationSelect (single relation / one-to-one)\n * - RelationPicker (multiple relations / one-to-many, many-to-many)\n *\n * Integrates with react-hook-form via Controller.\n */\n\nimport type { Questpie } from \"questpie\";\nimport type * as React from \"react\";\nimport { type Control, Controller, useFormContext } from \"react-hook-form\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { RelationPicker, type RelationPickerProps } from \"./relation-picker\";\nimport { RelationSelect, type RelationSelectProps } from \"./relation-select\";\n\nexport type RelationFieldProps<T extends Questpie<any>> = {\n\t/**\n\t * Field name (for react-hook-form)\n\t */\n\tname: string;\n\n\t/**\n\t * Target collection name\n\t */\n\ttargetCollection: string;\n\n\t/**\n\t * Relation type:\n\t * - \"single\" (one-to-one) - uses RelationSelect\n\t * - \"multiple\" (one-to-many, many-to-many) - uses RelationPicker\n\t */\n\ttype: \"single\" | \"multiple\";\n\n\t/**\n\t * Label for the field\n\t */\n\tlabel?: string;\n\n\t/**\n\t * Description/help text\n\t */\n\tdescription?: string;\n\n\t/**\n\t * Localized field\n\t */\n\tlocalized?: boolean;\n\n\t/**\n\t * Active locale\n\t */\n\tlocale?: string;\n\n\t/**\n\t * Filter options based on form values\n\t */\n\tfilter?: (formValues: any) => any;\n\n\t/**\n\t * Is the field required\n\t */\n\trequired?: boolean;\n\n\t/**\n\t * Is the field disabled\n\t */\n\tdisabled?: boolean;\n\n\t/**\n\t * Is the field readonly\n\t */\n\treadOnly?: boolean;\n\n\t/**\n\t * Placeholder text\n\t */\n\tplaceholder?: string;\n\n\t/**\n\t * Enable drag-and-drop reordering (only for multiple type)\n\t */\n\torderable?: boolean;\n\n\t/**\n\t * Maximum number of items (only for multiple type)\n\t */\n\tmaxItems?: number;\n\n\t/**\n\t * Custom render function for dropdown options\n\t */\n\trenderOption?: (item: any) => React.ReactNode;\n\n\t/**\n\t * Custom render function for selected value (single) or items (multiple)\n\t */\n\trenderValue?: (item: any) => React.ReactNode;\n\n\t/**\n\t * Custom render function for selected items (only for multiple type)\n\t */\n\trenderItem?: (item: any, index: number) => React.ReactNode;\n\n\t/**\n\t * Form control (optional, will use useFormContext if not provided)\n\t */\n\tcontrol?: Control<any>;\n};\n\n/**\n * Unified relation field component that integrates with react-hook-form.\n *\n * Automatically chooses between RelationSelect (single) and RelationPicker (multiple)\n * based on the `type` prop.\n *\n * @example\n * ```tsx\n * // Single relation (one-to-one)\n * <RelationField\n * name=\"author\"\n * targetCollection=\"users\"\n * type=\"single\"\n * label=\"Author\"\n * required\n * />\n *\n * // Multiple relations (many-to-many)\n * <RelationField\n * name=\"tags\"\n * targetCollection=\"tags\"\n * type=\"multiple\"\n * label=\"Tags\"\n * maxItems={5}\n * orderable\n * />\n * ```\n */\nexport function RelationField<T extends Questpie<any>>({\n\tname,\n\ttargetCollection,\n\ttype,\n\tlabel,\n\tdescription,\n\tlocalized,\n\tlocale,\n\tfilter,\n\trequired,\n\tdisabled,\n\treadOnly,\n\tplaceholder,\n\torderable,\n\tmaxItems,\n\trenderOption,\n\trenderValue,\n\trenderItem,\n\tcontrol: controlProp,\n}: RelationFieldProps<T>) {\n\tconst resolveText = useResolveText();\n\tconst resolvedLabel = label ? resolveText(label) : undefined;\n\tconst resolvedDescription = description\n\t\t? resolveText(description)\n\t\t: undefined;\n\tconst formContext = useFormContext();\n\tconst control = controlProp ?? formContext?.control;\n\n\tif (!control) {\n\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\tconsole.warn(\n\t\t\t\t\"RelationField: No form control found. Make sure to use within FormProvider or pass control prop.\",\n\t\t\t);\n\t\t}\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={control}\n\t\t\trules={{\n\t\t\t\trequired: required ? `${resolvedLabel || name} is required` : undefined,\n\t\t\t}}\n\t\t\trender={({ field, fieldState }) => {\n\t\t\t\tconst error = fieldState.error?.message;\n\n\t\t\t\tif (type === \"single\") {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div className=\"space-y-1\">\n\t\t\t\t\t\t\t<RelationSelect<T>\n\t\t\t\t\t\t\t\tname={name}\n\t\t\t\t\t\t\t\tvalue={field.value as string | null}\n\t\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\t\ttargetCollection={targetCollection}\n\t\t\t\t\t\t\t\tlabel={resolvedLabel}\n\t\t\t\t\t\t\t\tlocalized={localized}\n\t\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\t\tfilter={filter}\n\t\t\t\t\t\t\t\trequired={required}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\t\terror={error}\n\t\t\t\t\t\t\t\trenderOption={renderOption}\n\t\t\t\t\t\t\t\trenderValue={renderValue}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{resolvedDescription && !error && (\n\t\t\t\t\t\t\t\t<p className=\"text-muted-foreground text-xs\">\n\t\t\t\t\t\t\t\t\t{resolvedDescription}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<div className=\"space-y-1\">\n\t\t\t\t\t\t<RelationPicker<T>\n\t\t\t\t\t\t\tname={name}\n\t\t\t\t\t\t\tvalue={field.value as string[] | null}\n\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\ttargetCollection={targetCollection}\n\t\t\t\t\t\t\tlabel={resolvedLabel}\n\t\t\t\t\t\t\tlocalized={localized}\n\t\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\t\tfilter={filter}\n\t\t\t\t\t\t\trequired={required}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\terror={error}\n\t\t\t\t\t\t\torderable={orderable}\n\t\t\t\t\t\t\tmaxItems={maxItems}\n\t\t\t\t\t\t\trenderOption={renderOption}\n\t\t\t\t\t\t\trenderItem={renderItem}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{resolvedDescription && !error && (\n\t\t\t\t\t\t\t<p className=\"text-muted-foreground text-xs\">\n\t\t\t\t\t\t\t\t{resolvedDescription}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}}\n\t\t/>\n\t);\n}\n","/**\n * ReverseRelationField Component\n *\n * Displays items from another collection that reference the current item.\n * Shows the \"other side\" of a relation with optional assignment controls.\n *\n * Supports two modes:\n * - linkToDetail: Click navigates to the item's detail page (default)\n * - openInSheet: Click opens item in a side sheet for quick editing\n *\n * @example\n * ```tsx\n * // On service detail - show all barbers that offer this service\n * <ReverseRelationField\n * name=\"offeredBy\"\n * label=\"Offered by\"\n * sourceCollection=\"barbers\"\n * sourceField=\"services\"\n * display=\"chips\"\n * openInSheet // Edit barbers in a side sheet\n * />\n * ```\n */\n\nimport { Plus, Spinner } from \"@phosphor-icons/react\";\nimport { createQuestpieQueryOptions } from \"@questpie/tanstack-query\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport { useFormContext, useWatch } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { useAdminRoutes } from \"../../hooks/use-admin-routes\";\nimport {\n\tuseCollectionList,\n\tuseCollectionUpdate,\n} from \"../../hooks/use-collection\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport {\n\tselectAdmin,\n\tselectClient,\n\tuseAdminStore,\n\tuseScopedLocale,\n} from \"../../runtime\";\nimport { SelectSingle } from \"../primitives/select-single\";\nimport type { SelectOption } from \"../primitives/types\";\nimport { ResourceSheet } from \"../sheets/resource-sheet\";\nimport { Button } from \"../ui/button\";\nimport type { BaseFieldProps, ReverseRelationFieldConfig } from \"./field-types\";\nimport { getAutoColumns } from \"./field-utils\";\nimport { LocaleBadge } from \"./locale-badge\";\nimport { type RelationDisplayMode, RelationItemsDisplay } from \"./relation\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ReverseRelationFieldProps\n\textends BaseFieldProps,\n\t\tReverseRelationFieldConfig {}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function ReverseRelationField({\n\tname,\n\tlabel,\n\tdescription,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tsourceCollection,\n\tsourceField,\n\tdisplay = \"list\",\n\tcolumns,\n\tfields,\n\tgridColumns,\n\tlimit = 10,\n\temptyMessage,\n\tlinkToDetail = true,\n\tallowCreate = false,\n\tallowAssign: allowAssignProp,\n\tcreateLabel,\n\topenInSheet = false,\n}: ReverseRelationFieldProps) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst resolvedCreateLabel = createLabel\n\t\t? resolveText(createLabel)\n\t\t: undefined;\n\tconst resolvedEmptyMessage = emptyMessage\n\t\t? resolveText(emptyMessage)\n\t\t: t(\"relation.noRelated\");\n\tconst parentForm = useFormContext();\n\tconst { collectionCreateUrl, toCollectionEdit, routes } = useAdminRoutes();\n\n\t// Sheet state\n\tconst [isSheetOpen, setIsSheetOpen] = React.useState(false);\n\tconst [editingItemId, setEditingItemId] = React.useState<\n\t\tstring | undefined\n\t>();\n\n\t// Get admin config for source collection\n\tconst admin = useAdminStore(selectAdmin);\n\tconst client = useAdminStore(selectClient);\n\t// Use scoped locale (from LocaleScopeProvider in ResourceSheet) or global locale\n\tconst { locale: contentLocale } = useScopedLocale();\n\tconst collections = admin?.getCollections() ?? {};\n\tconst sourceConfig = collections[sourceCollection];\n\tconst CollectionIcon = (sourceConfig as any)?.icon as\n\t\t| React.ComponentType<{ className?: string }>\n\t\t| undefined;\n\tconst sourceFieldConfig = (sourceConfig as any)?.fields?.[sourceField];\n\tconst sourceFieldOptions = (sourceFieldConfig as any)?.[\"~options\"] ?? {};\n\tconst sourceRelationName = sourceFieldOptions?.relationName ?? sourceField;\n\tconst sourceRelationType = sourceFieldOptions?.type;\n\tconst isRelationField = sourceFieldConfig?.name === \"relation\";\n\tconst isMultipleRelation = sourceRelationType === \"multiple\";\n\tconst isRequiredRelationField = sourceFieldOptions?.required === true;\n\tconst resolvedSourceLabel = resolveText(\n\t\t(sourceConfig as any)?.label ?? sourceCollection,\n\t);\n\tconst actionLabel = resolvedSourceLabel.replace(/s$/, \"\");\n\n\t// Watch the current item's ID\n\tconst currentId = useWatch({\n\t\tcontrol: parentForm.control,\n\t\tname: \"id\",\n\t});\n\tconst allowAssign = allowAssignProp ?? allowCreate;\n\tconst canAssign = allowAssign && !disabled;\n\tconst canRemove =\n\t\tcanAssign && (isMultipleRelation || !isRequiredRelationField);\n\tconst updateMutation = useCollectionUpdate(sourceCollection as any);\n\tconst queryClient = useQueryClient();\n\tconst queryOpts = React.useMemo(\n\t\t() =>\n\t\t\tcreateQuestpieQueryOptions(\n\t\t\t\t(client ?? {}) as any,\n\t\t\t\t{\n\t\t\t\t\tkeyPrefix: [\"questpie\", \"collections\"],\n\t\t\t\t\tlocale: contentLocale,\n\t\t\t\t} as any,\n\t\t\t),\n\t\t[client, contentLocale],\n\t);\n\n\t// Build create URL with prefill params (for link mode)\n\t// For multiple relations (M2M), encode as JSON array; for single, use plain string\n\tconst createUrl = React.useMemo(() => {\n\t\tif (!allowCreate || !currentId || !sourceCollection || !sourceField) {\n\t\t\treturn null;\n\t\t}\n\t\tconst baseUrl = collectionCreateUrl(sourceCollection as any);\n\t\tconst prefillValue = isMultipleRelation\n\t\t\t? JSON.stringify([currentId])\n\t\t\t: currentId;\n\t\treturn routes.withQuery(baseUrl, {\n\t\t\t[`prefill.${sourceField}`]: prefillValue,\n\t\t});\n\t}, [\n\t\tallowCreate,\n\t\tcurrentId,\n\t\tsourceCollection,\n\t\tsourceField,\n\t\tcollectionCreateUrl,\n\t\troutes,\n\t\tisMultipleRelation,\n\t]);\n\n\t// Build filter to find items that reference this item\n\tconst filter = React.useMemo(() => {\n\t\tif (!currentId) return undefined;\n\t\tif (!isRelationField) {\n\t\t\treturn {\n\t\t\t\t[sourceField]: currentId,\n\t\t\t};\n\t\t}\n\t\tif (isMultipleRelation) {\n\t\t\treturn {\n\t\t\t\t[sourceRelationName]: { some: { id: currentId } },\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\t[sourceRelationName]: { is: { id: currentId } },\n\t\t};\n\t}, [\n\t\tcurrentId,\n\t\tisRelationField,\n\t\tisMultipleRelation,\n\t\tsourceRelationName,\n\t\tsourceField,\n\t]);\n\n\t// Fetch related items\n\tconst { data, isLoading, refetch } = useCollectionList(\n\t\tsourceCollection,\n\t\t{\n\t\t\twhere: filter,\n\t\t\tlimit,\n\t\t},\n\t\t{\n\t\t\tenabled: !!currentId && !!sourceCollection && !!sourceField,\n\t\t},\n\t);\n\n\tconst items = data?.docs ?? [];\n\tconst totalCount = data?.totalDocs ?? items.length;\n\tconst selectedIds = React.useMemo(\n\t\t() => items.map((item: any) => item.id),\n\t\t[items],\n\t);\n\tconst assignLabel = t(\"relation.addItem\", { name: actionLabel });\n\tconst noResultsLabel = t(\"relation.noResults\", {\n\t\tname: actionLabel,\n\t});\n\tconst showAssignmentControls = canAssign && !!currentId;\n\tconst showCreateControls = allowCreate && !!currentId;\n\tconst showCreateInHeader = !showAssignmentControls;\n\tconst showActionRow =\n\t\tshowAssignmentControls || (showCreateControls && !showCreateInHeader);\n\tconst isMutationPending = updateMutation.isPending;\n\n\tconst loadOptions = React.useCallback(\n\t\tasync (search: string): Promise<SelectOption<string>[]> => {\n\t\t\tif (!client) return [];\n\n\t\t\ttry {\n\t\t\t\tconst options: any = {\n\t\t\t\t\tlimit: 50,\n\t\t\t\t};\n\n\t\t\t\tif (search) {\n\t\t\t\t\toptions.search = search;\n\t\t\t\t}\n\n\t\t\t\tconst response = await (client as any).collections[\n\t\t\t\t\tsourceCollection\n\t\t\t\t].find(options);\n\t\t\t\tconst docs = response?.docs ?? [];\n\n\t\t\t\treturn docs\n\t\t\t\t\t.filter((doc: any) => !selectedIds.includes(doc.id))\n\t\t\t\t\t.map((item: any) => ({\n\t\t\t\t\t\tvalue: item.id,\n\t\t\t\t\t\tlabel: item._title || item.id || \"\",\n\t\t\t\t\t\ticon: CollectionIcon ? (\n\t\t\t\t\t\t\t<CollectionIcon className=\"size-3.5 text-muted-foreground\" />\n\t\t\t\t\t\t) : undefined,\n\t\t\t\t\t}));\n\t\t\t} catch (loadError) {\n\t\t\t\tconst message =\n\t\t\t\t\tloadError instanceof Error\n\t\t\t\t\t\t? loadError.message\n\t\t\t\t\t\t: t(\"toast.loadFailed\");\n\t\t\t\ttoast.error(message);\n\t\t\t\treturn [];\n\t\t\t}\n\t\t},\n\t\t[client, sourceCollection, selectedIds, CollectionIcon, t],\n\t);\n\n\tconst resolveManyRelationIds = React.useCallback(\n\t\tasync (item: any): Promise<string[]> => {\n\t\t\tconst directValue = item?.[sourceRelationName] ?? item?.[sourceField];\n\t\t\tif (Array.isArray(directValue)) {\n\t\t\t\treturn directValue\n\t\t\t\t\t.map((entry: any) => (typeof entry === \"string\" ? entry : entry?.id))\n\t\t\t\t\t.filter(Boolean);\n\t\t\t}\n\t\t\tif (!client) return [];\n\t\t\tconst response = await (client as any).collections[\n\t\t\t\tsourceCollection\n\t\t\t].findOne({\n\t\t\t\twhere: { id: item.id },\n\t\t\t\twith: { [sourceRelationName]: true },\n\t\t\t});\n\t\t\tconst relatedItems = response?.[sourceRelationName];\n\t\t\tif (!Array.isArray(relatedItems)) return [];\n\t\t\treturn relatedItems\n\t\t\t\t.map((entry: any) => (typeof entry === \"string\" ? entry : entry?.id))\n\t\t\t\t.filter(Boolean);\n\t\t},\n\t\t[client, sourceCollection, sourceRelationName, sourceField],\n\t);\n\n\tconst handleAssign = React.useCallback(\n\t\tasync (value: string | null) => {\n\t\t\tif (!value || !currentId || !canAssign || isMutationPending) return;\n\t\t\ttry {\n\t\t\t\tif (isMultipleRelation) {\n\t\t\t\t\tawait updateMutation.mutateAsync({\n\t\t\t\t\t\tid: value,\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t[sourceField]: {\n\t\t\t\t\t\t\t\tconnect: { id: currentId },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tawait updateMutation.mutateAsync({\n\t\t\t\t\t\tid: value,\n\t\t\t\t\t\tdata: { [sourceField]: currentId },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttoast.success(t(\"toast.actionSuccess\"));\n\t\t\t\tawait refetch();\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", sourceCollection, \"find\"]),\n\t\t\t\t});\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", sourceCollection, \"findOne\"]),\n\t\t\t\t});\n\t\t\t} catch (assignError) {\n\t\t\t\tconst message =\n\t\t\t\t\tassignError instanceof Error\n\t\t\t\t\t\t? assignError.message\n\t\t\t\t\t\t: t(\"toast.actionFailed\");\n\t\t\t\ttoast.error(message);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tcanAssign,\n\t\t\tcurrentId,\n\t\t\tisMutationPending,\n\t\t\tisMultipleRelation,\n\t\t\tqueryClient,\n\t\t\tqueryOpts,\n\t\t\trefetch,\n\t\t\tsourceCollection,\n\t\t\tsourceField,\n\t\t\tt,\n\t\t\tupdateMutation,\n\t\t],\n\t);\n\n\tconst handleRemove = React.useCallback(\n\t\tasync (item: any) => {\n\t\t\tif (!currentId || !canRemove || isMutationPending) return;\n\t\t\ttry {\n\t\t\t\tif (isMultipleRelation) {\n\t\t\t\t\tconst existingIds = await resolveManyRelationIds(item);\n\t\t\t\t\tconst nextIds = existingIds.filter((id) => id !== currentId);\n\t\t\t\t\tif (nextIds.length === existingIds.length) return;\n\t\t\t\t\tawait updateMutation.mutateAsync({\n\t\t\t\t\t\tid: item.id,\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t[sourceField]: { set: nextIds },\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tawait updateMutation.mutateAsync({\n\t\t\t\t\t\tid: item.id,\n\t\t\t\t\t\tdata: { [sourceField]: null },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttoast.success(t(\"toast.actionSuccess\"));\n\t\t\t\tawait refetch();\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", sourceCollection, \"find\"]),\n\t\t\t\t});\n\t\t\t\tqueryClient.invalidateQueries({\n\t\t\t\t\tqueryKey: queryOpts.key([\"collections\", sourceCollection, \"findOne\"]),\n\t\t\t\t});\n\t\t\t} catch (removeError) {\n\t\t\t\tconst message =\n\t\t\t\t\tremoveError instanceof Error\n\t\t\t\t\t\t? removeError.message\n\t\t\t\t\t\t: t(\"toast.actionFailed\");\n\t\t\t\ttoast.error(message);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tcanRemove,\n\t\t\tcurrentId,\n\t\t\tisMutationPending,\n\t\t\tisMultipleRelation,\n\t\t\tqueryClient,\n\t\t\tqueryOpts,\n\t\t\trefetch,\n\t\t\tsourceCollection,\n\t\t\tresolveManyRelationIds,\n\t\t\tsourceField,\n\t\t\tt,\n\t\t\tupdateMutation,\n\t\t],\n\t);\n\n\t// Compute display columns for table mode\n\t// NOTE: This must be called before any early returns to maintain hook order\n\tconst displayColumns = React.useMemo(() => {\n\t\tif (columns && columns.length > 0) return columns;\n\t\tif (display === \"table\" && sourceConfig) {\n\t\t\treturn getAutoColumns(sourceConfig);\n\t\t}\n\t\treturn [\"_title\"];\n\t}, [columns, display, sourceConfig]);\n\n\t// Handle item click (for sheet mode)\n\tconst handleItemClick = React.useCallback(\n\t\t(item: any) => {\n\t\t\tif (openInSheet) {\n\t\t\t\tsetEditingItemId(item.id);\n\t\t\t\tsetIsSheetOpen(true);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (linkToDetail) {\n\t\t\t\ttoCollectionEdit(sourceCollection as any, item.id);\n\t\t\t}\n\t\t},\n\t\t[openInSheet, linkToDetail, sourceCollection, toCollectionEdit],\n\t);\n\tconst displayActions = React.useMemo(() => {\n\t\tconst actions: {\n\t\t\tonEdit?: (item: any) => void;\n\t\t\tonRemove?: (item: any) => void;\n\t\t} = {};\n\t\tif (openInSheet || (canAssign && linkToDetail)) {\n\t\t\tactions.onEdit = handleItemClick;\n\t\t}\n\t\tif (canRemove) {\n\t\t\tactions.onRemove = handleRemove;\n\t\t}\n\t\treturn Object.keys(actions).length > 0 ? actions : undefined;\n\t}, [\n\t\tcanAssign,\n\t\tcanRemove,\n\t\thandleItemClick,\n\t\thandleRemove,\n\t\tlinkToDetail,\n\t\topenInSheet,\n\t]);\n\tconst isEditable = canAssign;\n\tconst showLinkToDetail = linkToDetail && !openInSheet && !canAssign;\n\n\t// Handle create button click\n\tconst handleCreateClick = React.useCallback(() => {\n\t\tif (openInSheet) {\n\t\t\tsetEditingItemId(undefined);\n\t\t\tsetIsSheetOpen(true);\n\t\t}\n\t\t// If not openInSheet, the link will handle navigation\n\t}, [openInSheet]);\n\n\t// Handle save from ResourceSheet\n\tconst handleSheetSave = React.useCallback(async () => {\n\t\tawait refetch();\n\t\tqueryClient.invalidateQueries({\n\t\t\tqueryKey: queryOpts.key([\"collections\", sourceCollection, \"find\"]),\n\t\t});\n\t\tqueryClient.invalidateQueries({\n\t\t\tqueryKey: queryOpts.key([\"collections\", sourceCollection, \"findOne\"]),\n\t\t});\n\t}, [queryClient, queryOpts, refetch, sourceCollection]);\n\n\t// Default values for create mode (prefill relation field)\n\t// For multiple relations (M2M), wrap in array; for single relations, use string\n\tconst sheetDefaultValues = React.useMemo(() => {\n\t\tif (editingItemId) return undefined;\n\t\tconst prefillValue = isMultipleRelation ? [currentId] : currentId;\n\t\treturn { [sourceField]: prefillValue };\n\t}, [editingItemId, sourceField, currentId, isMultipleRelation]);\n\n\t// Loading state\n\tif (isLoading) {\n\t\treturn (\n\t\t\t<div className=\"space-y-2\">\n\t\t\t\t{label && (\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<span className=\"text-sm font-medium\">{resolveText(label)}</span>\n\t\t\t\t\t\t{localized && <LocaleBadge locale={locale || \"i18n\"} />}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"flex items-center gap-2 text-muted-foreground\">\n\t\t\t\t\t<Spinner className=\"size-4 animate-spin\" />\n\t\t\t\t\t<span className=\"text-sm\">{t(\"relation.loading\")}</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// No current ID (new item)\n\tif (!currentId) {\n\t\treturn (\n\t\t\t<div className=\"space-y-2\">\n\t\t\t\t{label && (\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<span className=\"text-sm font-medium\">{resolveText(label)}</span>\n\t\t\t\t\t\t{localized && <LocaleBadge locale={locale || \"i18n\"} />}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t{t(\"relation.saveFirst\")}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Create button component\n\tconst CreateButton = ({\n\t\tvariant = \"text\",\n\t}: {\n\t\tvariant?: \"text\" | \"icon\";\n\t}) => {\n\t\tif (!allowCreate || !currentId) return null;\n\n\t\tconst defaultLabel = t(\"relation.addItem\", {\n\t\t\tname: actionLabel,\n\t\t});\n\t\tconst buttonLabel = resolvedCreateLabel || defaultLabel;\n\t\tconst buttonIcon = <Plus className=\"size-4\" />;\n\t\tconst buttonContent =\n\t\t\tvariant === \"icon\" ? null : (\n\t\t\t\t<>\n\t\t\t\t\t<Plus className=\"size-4 mr-1\" />\n\t\t\t\t\t{buttonLabel}\n\t\t\t\t</>\n\t\t\t);\n\n\t\t// Open in sheet mode\n\t\tif (openInSheet) {\n\t\t\treturn (\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tsize={variant === \"icon\" ? \"icon\" : \"sm\"}\n\t\t\t\t\tonClick={handleCreateClick}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\ttitle={buttonLabel}\n\t\t\t\t\taria-label={buttonLabel}\n\t\t\t\t>\n\t\t\t\t\t{variant === \"icon\" ? buttonIcon : buttonContent}\n\t\t\t\t</Button>\n\t\t\t);\n\t\t}\n\n\t\t// Navigate to create page\n\t\tif (createUrl) {\n\t\t\treturn (\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tsize={variant === \"icon\" ? \"icon\" : \"sm\"}\n\t\t\t\t\tnativeButton={false}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\ttitle={buttonLabel}\n\t\t\t\t\taria-label={buttonLabel}\n\t\t\t\t\trender={\n\t\t\t\t\t\t// biome-ignore lint/a11y/useAnchorContent: base-ui renders children into the anchor\n\t\t\t\t\t\t<a href={createUrl} aria-label={buttonLabel} />\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t{variant === \"icon\" ? buttonIcon : buttonContent}\n\t\t\t\t</Button>\n\t\t\t);\n\t\t}\n\n\t\treturn null;\n\t};\n\n\t// Sheet JSX for create/edit (rendered inline to avoid component identity issues)\n\n\treturn (\n\t\t<div className=\"space-y-2\">\n\t\t\t{label && (\n\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<span className=\"text-sm font-medium\">{resolveText(label)}</span>\n\t\t\t\t\t\t{localized && <LocaleBadge locale={locale || \"i18n\"} />}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t{totalCount > items.length && (\n\t\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\tShowing {items.length} of {totalCount}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{showCreateInHeader && <CreateButton variant=\"text\" />}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{description && (\n\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t{resolveText(description)}\n\t\t\t\t</p>\n\t\t\t)}\n\n\t\t\t{showActionRow && (\n\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t{showAssignmentControls && (\n\t\t\t\t\t\t<div className=\"flex-1\">\n\t\t\t\t\t\t\t<SelectSingle\n\t\t\t\t\t\t\t\tvalue={null}\n\t\t\t\t\t\t\t\tonChange={handleAssign}\n\t\t\t\t\t\t\t\tloadOptions={loadOptions}\n\t\t\t\t\t\t\t\tqueryKey={(search) =>\n\t\t\t\t\t\t\t\t\tqueryOpts.key([\n\t\t\t\t\t\t\t\t\t\t\"collections\",\n\t\t\t\t\t\t\t\t\t\tsourceCollection,\n\t\t\t\t\t\t\t\t\t\t\"find\",\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tlimit: 50,\n\t\t\t\t\t\t\t\t\t\t\tsearch,\n\t\t\t\t\t\t\t\t\t\t\tselectedIds,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tprefetchOnMount\n\t\t\t\t\t\t\t\tplaceholder={`${assignLabel}...`}\n\t\t\t\t\t\t\t\tdisabled={disabled || isMutationPending}\n\t\t\t\t\t\t\t\tclearable={false}\n\t\t\t\t\t\t\t\temptyMessage={noResultsLabel}\n\t\t\t\t\t\t\t\tdrawerTitle={assignLabel}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t{showCreateControls && !showCreateInHeader && (\n\t\t\t\t\t\t<CreateButton variant=\"icon\" />\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Items Display using shared component */}\n\t\t\t<RelationItemsDisplay\n\t\t\t\tdisplay={display as RelationDisplayMode}\n\t\t\t\titems={items}\n\t\t\t\tcollection={sourceCollection}\n\t\t\t\tcollectionIcon={CollectionIcon}\n\t\t\t\teditable={isEditable}\n\t\t\t\tcolumns={displayColumns}\n\t\t\t\tfields={fields}\n\t\t\t\tgridColumns={gridColumns}\n\t\t\t\tlinkToDetail={showLinkToDetail}\n\t\t\t\temptyMessage={resolvedEmptyMessage}\n\t\t\t\tactions={displayActions}\n\t\t\t\tcollectionConfig={sourceConfig as any}\n\t\t\t/>\n\n\t\t\t{/* Create button in empty state (when no label header) */}\n\t\t\t{items.length === 0 &&\n\t\t\t\t!label &&\n\t\t\t\tallowCreate &&\n\t\t\t\t!showAssignmentControls && (\n\t\t\t\t\t<div className=\"mt-3 text-center\">\n\t\t\t\t\t\t<CreateButton variant=\"text\" />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t{/* Edit Sheet - using reusable ResourceSheet component */}\n\t\t\t{openInSheet && (\n\t\t\t\t<ResourceSheet\n\t\t\t\t\ttype=\"collection\"\n\t\t\t\t\tcollection={sourceCollection}\n\t\t\t\t\titemId={editingItemId}\n\t\t\t\t\topen={isSheetOpen}\n\t\t\t\t\tonOpenChange={setIsSheetOpen}\n\t\t\t\t\tonSave={handleSheetSave}\n\t\t\t\t\tdefaultValues={sheetDefaultValues}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","/**\n * Table Controls Component\n *\n * Popover with table manipulation controls.\n */\n\nimport type { Editor } from \"@tiptap/core\";\nimport * as React from \"react\";\n\nimport { useTranslation } from \"../../../i18n/hooks\";\nimport { Button } from \"../../ui/button\";\nimport {\n\tPopover,\n\tPopoverContent,\n\tPopoverHeader,\n\tPopoverTitle,\n\tPopoverTrigger,\n} from \"../../ui/popover\";\n\nexport type TableControlsProps = {\n\teditor: Editor;\n\tdisabled?: boolean;\n\tinTable: boolean;\n\ttriggerButton?: React.ReactNode;\n};\n\n/**\n * Table manipulation controls popover\n */\nexport function TableControls({\n\teditor,\n\tdisabled,\n\tinTable,\n\ttriggerButton,\n}: TableControlsProps) {\n\tconst { t } = useTranslation();\n\tconst isEditable = !disabled;\n\n\treturn (\n\t\t<Popover>\n\t\t\t<PopoverTrigger render={triggerButton || <div className=\"sr-only\" />} />\n\t\t\t<PopoverContent className=\"w-80\">\n\t\t\t\t<PopoverHeader>\n\t\t\t\t\t<PopoverTitle>{t(\"editor.table\")}</PopoverTitle>\n\t\t\t\t</PopoverHeader>\n\t\t\t\t<div className=\"grid grid-cols-2 gap-2\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\teditor\n\t\t\t\t\t\t\t\t.chain()\n\t\t\t\t\t\t\t\t.focus()\n\t\t\t\t\t\t\t\t.insertTable({\n\t\t\t\t\t\t\t\t\trows: 3,\n\t\t\t\t\t\t\t\t\tcols: 3,\n\t\t\t\t\t\t\t\t\twithHeaderRow: true,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.run()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.table\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().addRowBefore().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.addRowBefore\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().addRowAfter().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.addRowAfter\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().addColumnBefore().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.addColumnBefore\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().addColumnAfter().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.addColumnAfter\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().deleteRow().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.deleteRow\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().deleteColumn().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.deleteColumn\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleHeaderRow().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.toggleHeaderRow\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleHeaderColumn().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.toggleHeaderColumn\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().mergeCells().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.mergeCells\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().splitCell().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.splitCell\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().deleteTable().run()}\n\t\t\t\t\t\tdisabled={!isEditable || !inTable}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"editor.deleteTable\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n","/**\n * RichText Editor Toolbar Components\n *\n * Icon-based toolbar using Phosphor icons for a clean, modern UI.\n */\n\nimport {\n\tArrowClockwise,\n\tArrowCounterClockwise,\n\tCode,\n\tCodeBlock,\n\ttype Icon,\n\ttype IconWeight,\n\tImage as ImageIcon,\n\tLink as LinkIcon,\n\tListBullets,\n\tListNumbers,\n\tMinusCircle,\n\tQuotes,\n\tTable as TableIcon,\n\tTextAlignCenter,\n\tTextAlignJustify,\n\tTextAlignLeft,\n\tTextAlignRight,\n\tTextB,\n\tTextH,\n\tTextItalic,\n\tTextStrikethrough,\n\tTextUnderline,\n} from \"@phosphor-icons/react\";\nimport type { Editor } from \"@tiptap/core\";\nimport * as React from \"react\";\n\nimport { useTranslation } from \"../../../i18n/hooks\";\nimport { cn } from \"../../../utils\";\nimport { Button } from \"../../ui/button\";\nimport { TableControls } from \"./table-controls\";\nimport type { RichTextFeatures } from \"./types\";\n\n/**\n * Icon mapping for all editor actions\n */\nexport const EDITOR_ICONS = {\n\tundo: ArrowCounterClockwise,\n\tredo: ArrowClockwise,\n\tbold: TextB,\n\titalic: TextItalic,\n\tunderline: TextUnderline,\n\tstrikethrough: TextStrikethrough,\n\tcode: Code,\n\theading: TextH,\n\tbulletList: ListBullets,\n\torderedList: ListNumbers,\n\tblockquote: Quotes,\n\tcodeBlock: CodeBlock,\n\thorizontalRule: MinusCircle,\n\tlink: LinkIcon,\n\timage: ImageIcon,\n\ttable: TableIcon,\n\talignLeft: TextAlignLeft,\n\talignCenter: TextAlignCenter,\n\talignRight: TextAlignRight,\n\talignJustify: TextAlignJustify,\n} as const;\n\nexport type ToolbarButtonProps = {\n\tactive?: boolean;\n\tdisabled?: boolean;\n\ttitle?: string;\n\tonClick?: () => void;\n\ticon?: Icon;\n\tchildren?: React.ReactNode;\n\tshortcut?: string;\n\tclassName?: string;\n} & Omit<\n\tReact.ComponentProps<typeof Button>,\n\t\"variant\" | \"size\" | \"type\" | \"children\" | \"onClick\" | \"disabled\" | \"title\"\n>;\n\n/**\n * Icon-based toolbar button with tooltip showing keyboard shortcuts\n */\nexport function ToolbarButton({\n\tactive,\n\tdisabled,\n\ttitle,\n\tonClick,\n\ticon: IconComponent,\n\tchildren,\n\tshortcut,\n\tclassName,\n\t...rest\n}: ToolbarButtonProps) {\n\tconst tooltipText = React.useMemo(() => {\n\t\tif (!title && !shortcut) return undefined;\n\t\tif (shortcut) return `${title || \"\"} (${shortcut})`.trim();\n\t\treturn title;\n\t}, [title, shortcut]);\n\n\tconst iconWeight: IconWeight = active ? \"fill\" : \"regular\";\n\tconst buttonSize = IconComponent ? \"icon-xs\" : \"xs\";\n\n\treturn (\n\t\t<Button\n\t\t\ttype=\"button\"\n\t\t\tvariant=\"ghost\"\n\t\t\tsize={buttonSize}\n\t\t\tdata-active={active}\n\t\t\ttitle={tooltipText}\n\t\t\tdisabled={disabled}\n\t\t\tonClick={onClick}\n\t\t\tclassName={cn(\n\t\t\t\t\"text-muted-foreground hover:text-foreground hover:bg-transparent\",\n\t\t\t\t\"data-[active=true]:text-foreground data-[active=true]:bg-transparent\",\n\t\t\t\t\"aria-expanded:bg-transparent\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{IconComponent ? (\n\t\t\t\t<IconComponent size={16} weight={iconWeight} />\n\t\t\t) : (\n\t\t\t\tchildren\n\t\t\t)}\n\t\t</Button>\n\t);\n}\n\n/**\n * Toolbar button group with divider\n */\nexport function ToolbarGroup({ children }: { children: React.ReactNode }) {\n\treturn <div className=\"flex items-center gap-1\">{children}</div>;\n}\n\nexport type RichTextToolbarProps = {\n\teditor: Editor;\n\tfeatures: Required<RichTextFeatures>;\n\tdisabled?: boolean;\n\theadingValue: string;\n\tonHeadingChange: (value: string) => void;\n\tonLinkClick: () => void;\n\tonImageClick: () => void;\n\tonTableClick: () => void;\n\tinTable: boolean;\n};\n\n/**\n * Main toolbar component with icon-based buttons\n */\nexport function RichTextToolbar({\n\teditor,\n\tfeatures,\n\tdisabled,\n\theadingValue,\n\tonHeadingChange,\n\tonLinkClick,\n\tonImageClick,\n\tonTableClick,\n\tinTable,\n}: RichTextToolbarProps) {\n\tconst { t } = useTranslation();\n\tconst isEditable = !disabled;\n\n\treturn (\n\t\t<div className=\"flex flex-wrap items-center gap-1.5 border-b bg-muted/30 p-1.5\">\n\t\t\t{/* History Controls */}\n\t\t\t{features.history && (\n\t\t\t\t<ToolbarGroup>\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.undo}\n\t\t\t\t\t\tdisabled={!isEditable || !editor.can().undo()}\n\t\t\t\t\t\ttitle={t(\"editor.undo\")}\n\t\t\t\t\t\tshortcut=\"⌘Z\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().undo().run()}\n\t\t\t\t\t/>\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.redo}\n\t\t\t\t\t\tdisabled={!isEditable || !editor.can().redo()}\n\t\t\t\t\t\ttitle={t(\"editor.redo\")}\n\t\t\t\t\t\tshortcut=\"⌘⇧Z\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().redo().run()}\n\t\t\t\t\t/>\n\t\t\t\t</ToolbarGroup>\n\t\t\t)}\n\n\t\t\t{/* Heading Dropdown */}\n\t\t\t{features.heading && (\n\t\t\t\t<ToolbarGroup>\n\t\t\t\t\t<select\n\t\t\t\t\t\tclassName=\"h-6 rounded-sm border border-input/80 bg-input/20 px-2 text-xs\"\n\t\t\t\t\t\tvalue={headingValue}\n\t\t\t\t\t\tonChange={(event) => onHeadingChange(event.target.value)}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t>\n\t\t\t\t\t\t<option value=\"paragraph\">Paragraph</option>\n\t\t\t\t\t\t<option value=\"1\">Heading 1</option>\n\t\t\t\t\t\t<option value=\"2\">Heading 2</option>\n\t\t\t\t\t\t<option value=\"3\">Heading 3</option>\n\t\t\t\t\t\t<option value=\"4\">Heading 4</option>\n\t\t\t\t\t\t<option value=\"5\">Heading 5</option>\n\t\t\t\t\t\t<option value=\"6\">Heading 6</option>\n\t\t\t\t\t</select>\n\t\t\t\t</ToolbarGroup>\n\t\t\t)}\n\n\t\t\t{/* Text Formatting */}\n\t\t\t<ToolbarGroup>\n\t\t\t\t{features.bold && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.bold}\n\t\t\t\t\t\tactive={editor.isActive(\"bold\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.bold\")}\n\t\t\t\t\t\tshortcut=\"⌘B\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleBold().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.italic && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.italic}\n\t\t\t\t\t\tactive={editor.isActive(\"italic\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.italic\")}\n\t\t\t\t\t\tshortcut=\"⌘I\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleItalic().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.underline && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.underline}\n\t\t\t\t\t\tactive={editor.isActive(\"underline\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.underline\")}\n\t\t\t\t\t\tshortcut=\"⌘U\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleUnderline().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.strike && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.strikethrough}\n\t\t\t\t\t\tactive={editor.isActive(\"strike\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.strikethrough\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleStrike().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.code && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.code}\n\t\t\t\t\t\tactive={editor.isActive(\"code\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.code\")}\n\t\t\t\t\t\tshortcut=\"⌘E\"\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleCode().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.codeBlock && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.codeBlock}\n\t\t\t\t\t\tactive={editor.isActive(\"codeBlock\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.codeBlock\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleCodeBlock().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</ToolbarGroup>\n\n\t\t\t{/* Lists & Blocks */}\n\t\t\t<ToolbarGroup>\n\t\t\t\t{features.bulletList && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.bulletList}\n\t\t\t\t\t\tactive={editor.isActive(\"bulletList\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.unorderedList\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleBulletList().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.orderedList && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.orderedList}\n\t\t\t\t\t\tactive={editor.isActive(\"orderedList\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.orderedList\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleOrderedList().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.blockquote && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.blockquote}\n\t\t\t\t\t\tactive={editor.isActive(\"blockquote\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.quote\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().toggleBlockquote().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.horizontalRule && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.horizontalRule}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.horizontalRule\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().setHorizontalRule().run()}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</ToolbarGroup>\n\n\t\t\t{/* Text Alignment */}\n\t\t\t{features.align && (\n\t\t\t\t<ToolbarGroup>\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.alignLeft}\n\t\t\t\t\t\tactive={editor.isActive({ textAlign: \"left\" })}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.alignLeft\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().setTextAlign(\"left\").run()}\n\t\t\t\t\t/>\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.alignCenter}\n\t\t\t\t\t\tactive={editor.isActive({ textAlign: \"center\" })}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.alignCenter\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().setTextAlign(\"center\").run()}\n\t\t\t\t\t/>\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.alignRight}\n\t\t\t\t\t\tactive={editor.isActive({ textAlign: \"right\" })}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.alignRight\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().setTextAlign(\"right\").run()}\n\t\t\t\t\t/>\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.alignJustify}\n\t\t\t\t\t\tactive={editor.isActive({ textAlign: \"justify\" })}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.alignJustify\")}\n\t\t\t\t\t\tonClick={() => editor.chain().focus().setTextAlign(\"justify\").run()}\n\t\t\t\t\t/>\n\t\t\t\t</ToolbarGroup>\n\t\t\t)}\n\n\t\t\t{/* Media & Links */}\n\t\t\t<ToolbarGroup>\n\t\t\t\t{features.link && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.link}\n\t\t\t\t\t\tactive={editor.isActive(\"link\")}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.link\")}\n\t\t\t\t\t\tshortcut=\"⌘K\"\n\t\t\t\t\t\tonClick={onLinkClick}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.image && (\n\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\ticon={EDITOR_ICONS.image}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\ttitle={t(\"editor.image\")}\n\t\t\t\t\t\tonClick={onImageClick}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{features.table &&\n\t\t\t\t\t(features.tableControls ? (\n\t\t\t\t\t\t<TableControls\n\t\t\t\t\t\t\teditor={editor}\n\t\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\t\tinTable={inTable}\n\t\t\t\t\t\t\ttriggerButton={\n\t\t\t\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\t\t\t\ticon={EDITOR_ICONS.table}\n\t\t\t\t\t\t\t\t\tactive={inTable}\n\t\t\t\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\t\t\t\ttitle={t(\"editor.table\")}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\t\ticon={EDITOR_ICONS.table}\n\t\t\t\t\t\t\tactive={inTable}\n\t\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\t\ttitle={t(\"editor.table\")}\n\t\t\t\t\t\t\tonClick={onTableClick}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t</ToolbarGroup>\n\t\t</div>\n\t);\n}\n","/**\n * Bubble Menu Component\n *\n * Floating toolbar that appears on text selection.\n */\n\nimport type { Editor } from \"@tiptap/core\";\nimport { BubbleMenu as TiptapBubbleMenu } from \"@tiptap/react\";\nimport * as React from \"react\";\n\nimport { useTranslation } from \"../../../i18n/hooks\";\nimport { EDITOR_ICONS, ToolbarButton } from \"./toolbar\";\nimport type { RichTextFeatures } from \"./types\";\n\nexport type RichTextBubbleMenuProps = {\n\teditor: Editor;\n\tfeatures: Required<RichTextFeatures>;\n\tdisabled?: boolean;\n\tonLinkClick: () => void;\n};\n\n/**\n * Bubble menu that appears on text selection\n */\nexport function RichTextBubbleMenu({\n\teditor,\n\tfeatures,\n\tdisabled,\n\tonLinkClick,\n}: RichTextBubbleMenuProps) {\n\tconst { t } = useTranslation();\n\tconst isEditable = !disabled;\n\n\treturn (\n\t\t<TiptapBubbleMenu\n\t\t\teditor={editor}\n\t\t\tclassName=\"flex items-center gap-1 rounded-md border bg-background p-1 shadow-lg\"\n\t\t>\n\t\t\t{features.bold && (\n\t\t\t\t<ToolbarButton\n\t\t\t\t\ticon={EDITOR_ICONS.bold}\n\t\t\t\t\tactive={editor.isActive(\"bold\")}\n\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\ttitle={t(\"editor.bold\")}\n\t\t\t\t\tshortcut=\"⌘B\"\n\t\t\t\t\tonClick={() => editor.chain().focus().toggleBold().run()}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{features.italic && (\n\t\t\t\t<ToolbarButton\n\t\t\t\t\ticon={EDITOR_ICONS.italic}\n\t\t\t\t\tactive={editor.isActive(\"italic\")}\n\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\ttitle={t(\"editor.italic\")}\n\t\t\t\t\tshortcut=\"⌘I\"\n\t\t\t\t\tonClick={() => editor.chain().focus().toggleItalic().run()}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{features.underline && (\n\t\t\t\t<ToolbarButton\n\t\t\t\t\ticon={EDITOR_ICONS.underline}\n\t\t\t\t\tactive={editor.isActive(\"underline\")}\n\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\ttitle={t(\"editor.underline\")}\n\t\t\t\t\tshortcut=\"⌘U\"\n\t\t\t\t\tonClick={() => editor.chain().focus().toggleUnderline().run()}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{features.link && (\n\t\t\t\t<ToolbarButton\n\t\t\t\t\ticon={EDITOR_ICONS.link}\n\t\t\t\t\tactive={editor.isActive(\"link\")}\n\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\ttitle={t(\"editor.link\")}\n\t\t\t\t\tshortcut=\"⌘K\"\n\t\t\t\t\tonClick={onLinkClick}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</TiptapBubbleMenu>\n\t);\n}\n","/**\n * Slash Commands Component\n *\n * Provides the \"/\" command menu for quick insertion of blocks.\n */\n\nimport { type Editor, Extension, type Range } from \"@tiptap/core\";\nimport { ReactRenderer } from \"@tiptap/react\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport * as React from \"react\";\nimport tippy, { type Instance } from \"tippy.js\";\n\nimport { cn } from \"../../../utils\";\nimport type {\n\tSlashCommandItem,\n\tSlashCommandListHandle,\n\tSlashCommandListProps,\n} from \"./types\";\n\n/**\n * Slash command list component\n */\nexport const SlashCommandList = React.forwardRef<\n\tSlashCommandListHandle,\n\tSlashCommandListProps\n>(function SlashCommandList({ items, command }, ref) {\n\tconst [selectedIndex, setSelectedIndex] = React.useState(0);\n\n\tReact.useEffect(() => {\n\t\tif (items.length === 0) {\n\t\t\tsetSelectedIndex(0);\n\t\t\treturn;\n\t\t}\n\n\t\tsetSelectedIndex((prev) => Math.min(prev, items.length - 1));\n\t}, [items.length]);\n\n\tconst selectItem = (index: number) => {\n\t\tconst item = items[index];\n\t\tif (item) {\n\t\t\tcommand(item);\n\t\t}\n\t};\n\n\tReact.useImperativeHandle(ref, () => ({\n\t\tonKeyDown: ({ event }) => {\n\t\t\tif (items.length === 0) return false;\n\t\t\tif (event.key === \"ArrowDown\") {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tsetSelectedIndex((prev) => (prev + 1) % items.length);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (event.key === \"ArrowUp\") {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tsetSelectedIndex((prev) => (prev - 1 + items.length) % items.length);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (event.key === \"Enter\") {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tselectItem(selectedIndex);\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\t}));\n\n\treturn (\n\t\t<div className=\"qp-rich-text-editor__slash\">\n\t\t\t{items.length === 0 && (\n\t\t\t\t<div className=\"qp-rich-text-editor__slash-empty\">No results</div>\n\t\t\t)}\n\t\t\t{items.map((item, index) => (\n\t\t\t\t<button\n\t\t\t\t\tkey={item.title}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"qp-rich-text-editor__slash-item\",\n\t\t\t\t\t\tindex === selectedIndex\n\t\t\t\t\t\t\t? \"qp-rich-text-editor__slash-item--active\"\n\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t)}\n\t\t\t\t\tonMouseDown={(event) => event.preventDefault()}\n\t\t\t\t\tonClick={() => selectItem(index)}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"qp-rich-text-editor__slash-title\">{item.title}</span>\n\t\t\t\t\t{item.description && (\n\t\t\t\t\t\t<span className=\"qp-rich-text-editor__slash-description\">\n\t\t\t\t\t\t\t{item.description}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</button>\n\t\t\t))}\n\t\t</div>\n\t);\n});\n\n/**\n * Create slash command extension factory\n */\nexport function createSlashCommandExtension(\n\tgetItems: (editor: Editor) => SlashCommandItem[],\n) {\n\treturn Extension.create({\n\t\tname: \"slashCommand\",\n\t\taddOptions() {\n\t\t\treturn {\n\t\t\t\tsuggestion: {\n\t\t\t\t\tchar: \"/\",\n\t\t\t\t\tstartOfLine: true,\n\t\t\t\t\tcommand: ({\n\t\t\t\t\t\teditor,\n\t\t\t\t\t\trange,\n\t\t\t\t\t\tprops,\n\t\t\t\t\t}: {\n\t\t\t\t\t\teditor: Editor;\n\t\t\t\t\t\trange: Range;\n\t\t\t\t\t\tprops: SlashCommandItem;\n\t\t\t\t\t}) => {\n\t\t\t\t\t\teditor.chain().focus().deleteRange(range).run();\n\t\t\t\t\t\tprops.command(editor);\n\t\t\t\t\t},\n\t\t\t\t\titems: ({ query, editor }: { query: string; editor: Editor }) => {\n\t\t\t\t\t\tconst items = getItems(editor);\n\t\t\t\t\t\tif (!query) return items;\n\t\t\t\t\t\tconst search = query.toLowerCase();\n\t\t\t\t\t\treturn items.filter((item) => {\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\titem.title.toLowerCase().includes(search) ||\n\t\t\t\t\t\t\t\titem.description?.toLowerCase().includes(search) ||\n\t\t\t\t\t\t\t\titem.keywords?.some((keyword) =>\n\t\t\t\t\t\t\t\t\tkeyword.toLowerCase().includes(search),\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\trender: () => {\n\t\t\t\t\t\tlet component: ReactRenderer<SlashCommandListHandle> | null = null;\n\t\t\t\t\t\tlet popup: Instance[] | null = null;\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tonStart: (props: any) => {\n\t\t\t\t\t\t\t\tcomponent = new ReactRenderer(SlashCommandList, {\n\t\t\t\t\t\t\t\t\tprops,\n\t\t\t\t\t\t\t\t\teditor: props.editor,\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tif (!props.clientRect) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tpopup = tippy(\"body\", {\n\t\t\t\t\t\t\t\t\tgetReferenceClientRect: props.clientRect,\n\t\t\t\t\t\t\t\t\tappendTo: () => document.body,\n\t\t\t\t\t\t\t\t\tcontent: component.element,\n\t\t\t\t\t\t\t\t\tshowOnCreate: true,\n\t\t\t\t\t\t\t\t\tinteractive: true,\n\t\t\t\t\t\t\t\t\ttrigger: \"manual\",\n\t\t\t\t\t\t\t\t\tplacement: \"bottom-start\",\n\t\t\t\t\t\t\t\t\ttheme: \"qp-rich-text-editor\",\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\tonUpdate: (props: any) => {\n\t\t\t\t\t\t\t\tcomponent?.updateProps(props);\n\n\t\t\t\t\t\t\t\tif (!props.clientRect) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tpopup?.[0].setProps({\n\t\t\t\t\t\t\t\t\tgetReferenceClientRect: props.clientRect,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\tonKeyDown: (props: any) => {\n\t\t\t\t\t\t\t\tif (props.event.key === \"Escape\") {\n\t\t\t\t\t\t\t\t\tpopup?.[0].hide();\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn component?.ref?.onKeyDown(props) ?? false;\n\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\tonExit: () => {\n\t\t\t\t\t\t\t\tpopup?.[0].destroy();\n\t\t\t\t\t\t\t\tcomponent?.destroy();\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\taddProseMirrorPlugins() {\n\t\t\treturn [\n\t\t\t\tSuggestion({\n\t\t\t\t\teditor: this.editor,\n\t\t\t\t\t...this.options.suggestion,\n\t\t\t\t}),\n\t\t\t];\n\t\t},\n\t});\n}\n","/**\n * Tiptap Extensions Configuration\n *\n * Factory functions for creating and configuring Tiptap extensions.\n */\n\nimport type { Extension as TiptapExtension } from \"@tiptap/core\";\nimport CharacterCount from \"@tiptap/extension-character-count\";\nimport CodeBlockLowlight from \"@tiptap/extension-code-block-lowlight\";\nimport Image from \"@tiptap/extension-image\";\nimport Link from \"@tiptap/extension-link\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport Table from \"@tiptap/extension-table\";\nimport TableCell from \"@tiptap/extension-table-cell\";\nimport TableHeader from \"@tiptap/extension-table-header\";\nimport TableRow from \"@tiptap/extension-table-row\";\nimport TextAlign from \"@tiptap/extension-text-align\";\nimport Underline from \"@tiptap/extension-underline\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport { common, createLowlight } from \"lowlight\";\n\nimport { createSlashCommandExtension } from \"./slash-commands\";\nimport type { RichTextFeatures, SlashCommandItem } from \"./types\";\n\nconst lowlight = createLowlight(common);\n\n/**\n * Build Tiptap extensions based on feature configuration\n */\nexport function buildExtensions({\n\tfeatures,\n\tplaceholder,\n\tmaxCharacters,\n\tcustomExtensions,\n}: {\n\tfeatures: Required<RichTextFeatures>;\n\tplaceholder?: string;\n\tmaxCharacters?: number;\n\tcustomExtensions?: TiptapExtension[];\n}): TiptapExtension[] {\n\tconst starterKitConfig: Record<string, any> = {\n\t\tcodeBlock: false,\n\t};\n\n\tif (!features.bold) starterKitConfig.bold = false;\n\tif (!features.italic) starterKitConfig.italic = false;\n\tif (!features.strike) starterKitConfig.strike = false;\n\tif (!features.code) starterKitConfig.code = false;\n\tif (!features.blockquote) starterKitConfig.blockquote = false;\n\tif (!features.heading) starterKitConfig.heading = false;\n\tif (!features.bulletList) starterKitConfig.bulletList = false;\n\tif (!features.orderedList) starterKitConfig.orderedList = false;\n\tif (!features.bulletList && !features.orderedList) {\n\t\tstarterKitConfig.listItem = false;\n\t}\n\tif (!features.horizontalRule) starterKitConfig.horizontalRule = false;\n\tif (!features.history) starterKitConfig.history = false;\n\n\tconst extensions: TiptapExtension[] = [\n\t\tStarterKit.configure(starterKitConfig),\n\t\tPlaceholder.configure({\n\t\t\tplaceholder: placeholder || \"Start writing...\",\n\t\t}),\n\t];\n\n\tif (features.underline) {\n\t\textensions.push(Underline);\n\t}\n\n\tif (features.link) {\n\t\textensions.push(\n\t\t\tLink.configure({\n\t\t\t\topenOnClick: false,\n\t\t\t\tautolink: true,\n\t\t\t\tlinkOnPaste: true,\n\t\t\t}),\n\t\t);\n\t}\n\n\tif (features.align) {\n\t\textensions.push(TextAlign.configure({ types: [\"heading\", \"paragraph\"] }));\n\t}\n\n\tif (features.image) {\n\t\textensions.push(Image);\n\t}\n\n\tif (features.table) {\n\t\textensions.push(\n\t\t\tTable.configure({ resizable: true }),\n\t\t\tTableRow,\n\t\t\tTableHeader,\n\t\t\tTableCell,\n\t\t);\n\t}\n\n\tif (features.codeBlock) {\n\t\textensions.push(CodeBlockLowlight.configure({ lowlight }));\n\t}\n\n\tif (features.characterCount && maxCharacters) {\n\t\textensions.push(\n\t\t\tCharacterCount.configure({\n\t\t\t\tlimit: maxCharacters,\n\t\t\t}),\n\t\t);\n\t}\n\n\tif (features.slashCommands) {\n\t\textensions.push(\n\t\t\tcreateSlashCommandExtension((editor) => {\n\t\t\t\tconst commands: SlashCommandItem[] = [];\n\n\t\t\t\tif (features.heading) {\n\t\t\t\t\tcommands.push(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttitle: \"Heading 1\",\n\t\t\t\t\t\t\tdescription: \"Large section heading\",\n\t\t\t\t\t\t\tkeywords: [\"h1\"],\n\t\t\t\t\t\t\tcommand: (cmdEditor) =>\n\t\t\t\t\t\t\t\tcmdEditor.chain().focus().toggleHeading({ level: 1 }).run(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttitle: \"Heading 2\",\n\t\t\t\t\t\t\tdescription: \"Medium section heading\",\n\t\t\t\t\t\t\tkeywords: [\"h2\"],\n\t\t\t\t\t\t\tcommand: (cmdEditor) =>\n\t\t\t\t\t\t\t\tcmdEditor.chain().focus().toggleHeading({ level: 2 }).run(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttitle: \"Heading 3\",\n\t\t\t\t\t\t\tdescription: \"Small section heading\",\n\t\t\t\t\t\t\tkeywords: [\"h3\"],\n\t\t\t\t\t\t\tcommand: (cmdEditor) =>\n\t\t\t\t\t\t\t\tcmdEditor.chain().focus().toggleHeading({ level: 3 }).run(),\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tcommands.push({\n\t\t\t\t\ttitle: \"Paragraph\",\n\t\t\t\t\tdescription: \"Start with plain text\",\n\t\t\t\t\tkeywords: [\"text\"],\n\t\t\t\t\tcommand: (cmdEditor) => cmdEditor.chain().focus().setParagraph().run(),\n\t\t\t\t});\n\n\t\t\t\tif (features.bulletList) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\ttitle: \"Bullet list\",\n\t\t\t\t\t\tdescription: \"Create a bulleted list\",\n\t\t\t\t\t\tkeywords: [\"list\", \"ul\"],\n\t\t\t\t\t\tcommand: (cmdEditor) =>\n\t\t\t\t\t\t\tcmdEditor.chain().focus().toggleBulletList().run(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (features.orderedList) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\ttitle: \"Numbered list\",\n\t\t\t\t\t\tdescription: \"Create an ordered list\",\n\t\t\t\t\t\tkeywords: [\"list\", \"ol\"],\n\t\t\t\t\t\tcommand: (cmdEditor) =>\n\t\t\t\t\t\t\tcmdEditor.chain().focus().toggleOrderedList().run(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (features.blockquote) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\ttitle: \"Quote\",\n\t\t\t\t\t\tdescription: \"Capture a quote\",\n\t\t\t\t\t\tkeywords: [\"blockquote\"],\n\t\t\t\t\t\tcommand: (cmdEditor) =>\n\t\t\t\t\t\t\tcmdEditor.chain().focus().toggleBlockquote().run(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (features.codeBlock) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\ttitle: \"Code block\",\n\t\t\t\t\t\tdescription: \"Insert code snippet\",\n\t\t\t\t\t\tkeywords: [\"code\"],\n\t\t\t\t\t\tcommand: (cmdEditor) =>\n\t\t\t\t\t\t\tcmdEditor.chain().focus().toggleCodeBlock().run(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (features.horizontalRule) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\ttitle: \"Divider\",\n\t\t\t\t\t\tdescription: \"Insert a horizontal rule\",\n\t\t\t\t\t\tkeywords: [\"hr\"],\n\t\t\t\t\t\tcommand: (cmdEditor) =>\n\t\t\t\t\t\t\tcmdEditor.chain().focus().setHorizontalRule().run(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (features.table) {\n\t\t\t\t\tcommands.push({\n\t\t\t\t\t\ttitle: \"Table\",\n\t\t\t\t\t\tdescription: \"Insert a 3x3 table\",\n\t\t\t\t\t\tkeywords: [\"grid\"],\n\t\t\t\t\t\tcommand: (cmdEditor) =>\n\t\t\t\t\t\t\tcmdEditor\n\t\t\t\t\t\t\t\t.chain()\n\t\t\t\t\t\t\t\t.focus()\n\t\t\t\t\t\t\t\t.insertTable({ rows: 3, cols: 3, withHeaderRow: true })\n\t\t\t\t\t\t\t\t.run(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn commands;\n\t\t\t}),\n\t\t);\n\t}\n\n\tif (customExtensions?.length) {\n\t\textensions.push(...customExtensions);\n\t}\n\n\treturn extensions;\n}\n","/**\n * AssetPreview Primitive\n *\n * Displays an uploaded asset with thumbnail/icon, metadata, and actions.\n * Supports images, videos, PDFs, and other file types.\n *\n * @example\n * ```tsx\n * <AssetPreview\n * asset={asset}\n * onRemove={() => handleRemove(asset.id)}\n * onEdit={() => openEditDialog(asset)}\n * />\n * ```\n */\n\nimport * as React from \"react\";\nimport {\n\tFile,\n\tFileDoc,\n\tFileImage,\n\tFilePdf,\n\tFileVideo,\n\tFileAudio,\n\tFileCode,\n\tFileZip,\n\tFileCsv,\n\tPencil,\n\tTrash,\n\tX,\n\tSpinnerGap,\n\tDotsSixVertical,\n\tArrowSquareOut,\n} from \"@phosphor-icons/react\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../ui/button\";\nimport type { Asset } from \"../../hooks/use-upload\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AssetPreviewProps {\n\t/**\n\t * Asset data (from upload or existing record)\n\t */\n\tasset: Partial<Asset> & {\n\t\tid?: string;\n\t\tfilename?: string;\n\t\tmimeType?: string;\n\t\tsize?: number;\n\t\turl?: string;\n\t\talt?: string | null;\n\t};\n\n\t/**\n\t * Pending file object (for displaying local preview before upload)\n\t */\n\tpendingFile?: File;\n\n\t/**\n\t * Called when remove button is clicked\n\t */\n\tonRemove?: () => void;\n\n\t/**\n\t * Called when edit button is clicked\n\t */\n\tonEdit?: () => void;\n\n\t/**\n\t * Show loading state\n\t */\n\tloading?: boolean;\n\n\t/**\n\t * Upload progress (0-100)\n\t */\n\tprogress?: number;\n\n\t/**\n\t * Whether the preview is disabled\n\t */\n\tdisabled?: boolean;\n\n\t/**\n\t * Whether to show the drag handle (for sortable lists)\n\t */\n\tshowDragHandle?: boolean;\n\n\t/**\n\t * Drag handle props (from dnd-kit)\n\t */\n\tdragHandleProps?: React.HTMLAttributes<HTMLButtonElement>;\n\n\t/**\n\t * Display variant\n\t * @default \"card\"\n\t */\n\tvariant?: \"card\" | \"compact\" | \"thumbnail\";\n\n\t/**\n\t * Link to asset detail page (makes the preview clickable)\n\t */\n\thref?: string;\n\n\t/**\n\t * Called when the preview is clicked\n\t */\n\tonClick?: (id: string) => void;\n\n\t/**\n\t * Additional className\n\t */\n\tclassName?: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Get icon component based on MIME type\n */\nfunction getFileIcon(mimeType?: string) {\n\tif (!mimeType) return File;\n\n\tconst type = mimeType.toLowerCase();\n\n\tif (type.startsWith(\"image/\")) return FileImage;\n\tif (type.startsWith(\"video/\")) return FileVideo;\n\tif (type.startsWith(\"audio/\")) return FileAudio;\n\tif (type === \"application/pdf\") return FilePdf;\n\tif (\n\t\ttype.includes(\"zip\") ||\n\t\ttype.includes(\"compressed\") ||\n\t\ttype.includes(\"archive\")\n\t)\n\t\treturn FileZip;\n\tif (type.includes(\"csv\") || type.includes(\"spreadsheet\")) return FileCsv;\n\tif (\n\t\ttype.includes(\"word\") ||\n\t\ttype.includes(\"document\") ||\n\t\ttype === \"application/rtf\"\n\t)\n\t\treturn FileDoc;\n\tif (\n\t\ttype.includes(\"json\") ||\n\t\ttype.includes(\"javascript\") ||\n\t\ttype.includes(\"typescript\") ||\n\t\ttype.includes(\"xml\") ||\n\t\ttype.includes(\"html\")\n\t)\n\t\treturn FileCode;\n\n\treturn File;\n}\n\n/**\n * Check if MIME type is an image\n */\nfunction isImage(mimeType?: string): boolean {\n\treturn !!mimeType?.toLowerCase().startsWith(\"image/\");\n}\n\n/**\n * Format file size for display\n */\nfunction formatFileSize(bytes?: number): string {\n\tif (!bytes) return \"\";\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/**\n * Get file extension from filename or MIME type\n */\nfunction getExtension(filename?: string, mimeType?: string): string {\n\tif (filename) {\n\t\tconst parts = filename.split(\".\");\n\t\tif (parts.length > 1) {\n\t\t\treturn parts[parts.length - 1].toUpperCase();\n\t\t}\n\t}\n\tif (mimeType) {\n\t\tconst parts = mimeType.split(\"/\");\n\t\treturn parts[parts.length - 1].toUpperCase();\n\t}\n\treturn \"\";\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function AssetPreview({\n\tasset,\n\tpendingFile,\n\tonRemove,\n\tonEdit,\n\tloading = false,\n\tprogress,\n\tdisabled = false,\n\tshowDragHandle = false,\n\tdragHandleProps,\n\tvariant = \"card\",\n\thref,\n\tonClick,\n\tclassName,\n}: AssetPreviewProps) {\n\tconst [imageError, setImageError] = React.useState(false);\n\n\t// Get display values\n\tconst filename = asset.filename || pendingFile?.name || \"Unknown file\";\n\tconst mimeType = asset.mimeType || pendingFile?.type;\n\tconst size = asset.size || pendingFile?.size;\n\tconst isImageType = isImage(mimeType);\n\tconst FileIcon = getFileIcon(mimeType);\n\tconst extension = getExtension(filename, mimeType);\n\n\t// Build thumbnail URL\n\tconst thumbnailUrl = React.useMemo(() => {\n\t\t// If we have a pending file, create object URL\n\t\tif (pendingFile && isImageType) {\n\t\t\treturn URL.createObjectURL(pendingFile);\n\t\t}\n\t\t// If we have an asset URL and it's an image\n\t\tif (asset.url && isImageType) {\n\t\t\treturn asset.url;\n\t\t}\n\t\treturn null;\n\t}, [pendingFile, asset.url, isImageType]);\n\n\t// Clean up object URL on unmount\n\tReact.useEffect(() => {\n\t\treturn () => {\n\t\t\tif (pendingFile && thumbnailUrl) {\n\t\t\t\tURL.revokeObjectURL(thumbnailUrl);\n\t\t\t}\n\t\t};\n\t}, [pendingFile, thumbnailUrl]);\n\n\t// Thumbnail variant\n\tif (variant === \"thumbnail\") {\n\t\tconst content = (\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"group relative aspect-square overflow-hidden rounded-lg border\",\n\t\t\t\t\t\"bg-muted/30 border-border/60\",\n\t\t\t\t\tdisabled && \"opacity-60\",\n\t\t\t\t\tonClick && !disabled && \"cursor-pointer hover:border-border\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonClick={\n\t\t\t\t\tonClick && !disabled && asset.id\n\t\t\t\t\t\t? () => onClick(asset.id!)\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t{/* Thumbnail or icon */}\n\t\t\t\t{thumbnailUrl && !imageError ? (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={thumbnailUrl}\n\t\t\t\t\t\talt={asset.alt || filename}\n\t\t\t\t\t\tclassName=\"h-full w-full object-cover\"\n\t\t\t\t\t\tonError={() => setImageError(true)}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<div className=\"flex h-full w-full items-center justify-center\">\n\t\t\t\t\t\t<FileIcon\n\t\t\t\t\t\t\tclassName=\"text-muted-foreground size-8\"\n\t\t\t\t\t\t\tweight=\"regular\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Loading overlay */}\n\t\t\t\t{loading && (\n\t\t\t\t\t<div className=\"bg-background/80 absolute inset-0 flex items-center justify-center\">\n\t\t\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t\t\t<SpinnerGap\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground size-6 animate-spin\"\n\t\t\t\t\t\t\t\tweight=\"regular\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{typeof progress === \"number\" && (\n\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-[10px] font-medium\">\n\t\t\t\t\t\t\t\t\t{progress}%\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Action buttons (visible on hover) */}\n\t\t\t\t{!loading && !disabled && (onRemove || onEdit || href) && (\n\t\t\t\t\t<div className=\"absolute inset-0 flex items-center justify-center gap-1 bg-black/50 opacity-0 transition-opacity group-hover:opacity-100\">\n\t\t\t\t\t\t{href && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\tnativeButton={false}\n\t\t\t\t\t\t\t\trender={<a href={href} onClick={(e) => e.stopPropagation()} />}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ArrowSquareOut weight=\"bold\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onEdit && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\tonEdit();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Pencil weight=\"bold\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onRemove && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"destructive\"\n\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\tonRemove();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Trash weight=\"bold\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\n\t\treturn content;\n\t}\n\n\t// Compact variant\n\tif (variant === \"compact\") {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"group flex items-center gap-2 rounded-md border p-2\",\n\t\t\t\t\t\"bg-muted/30 border-border/60\",\n\t\t\t\t\tdisabled && \"opacity-60\",\n\t\t\t\t\tonClick && !disabled && \"cursor-pointer hover:border-border\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonClick={\n\t\t\t\t\tonClick && !disabled && asset.id\n\t\t\t\t\t\t? () => onClick(asset.id!)\n\t\t\t\t\t\t: undefined\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t{/* Drag handle */}\n\t\t\t\t{showDragHandle && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground -ml-1 cursor-grab touch-none active:cursor-grabbing\"\n\t\t\t\t\t\t{...dragHandleProps}\n\t\t\t\t\t>\n\t\t\t\t\t\t<DotsSixVertical className=\"size-4\" weight=\"bold\" />\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\n\t\t\t\t{/* Icon or thumbnail */}\n\t\t\t\t<div className=\"bg-muted flex size-8 shrink-0 items-center justify-center overflow-hidden rounded\">\n\t\t\t\t\t{thumbnailUrl && !imageError ? (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tsrc={thumbnailUrl}\n\t\t\t\t\t\t\talt={asset.alt || filename}\n\t\t\t\t\t\t\tclassName=\"h-full w-full object-cover\"\n\t\t\t\t\t\t\tonError={() => setImageError(true)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<FileIcon\n\t\t\t\t\t\t\tclassName=\"text-muted-foreground size-4\"\n\t\t\t\t\t\t\tweight=\"regular\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* File info */}\n\t\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t\t<p className=\"truncate text-sm font-medium\">{filename}</p>\n\t\t\t\t\t{size && (\n\t\t\t\t\t\t<p className=\"text-muted-foreground text-xs\">\n\t\t\t\t\t\t\t{formatFileSize(size)}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Loading indicator */}\n\t\t\t\t{loading && (\n\t\t\t\t\t<SpinnerGap\n\t\t\t\t\t\tclassName=\"text-muted-foreground size-4 shrink-0 animate-spin\"\n\t\t\t\t\t\tweight=\"regular\"\n\t\t\t\t\t/>\n\t\t\t\t)}\n\n\t\t\t\t{/* Action buttons */}\n\t\t\t\t{!loading && !disabled && (href || onEdit || onRemove) && (\n\t\t\t\t\t<div className=\"flex shrink-0 items-center gap-1\">\n\t\t\t\t\t\t{href && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\tnativeButton={false}\n\t\t\t\t\t\t\t\trender={<a href={href} onClick={(e) => e.stopPropagation()} />}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ArrowSquareOut weight=\"bold\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onEdit && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\tonEdit();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Pencil weight=\"bold\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onRemove && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\tonRemove();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tclassName=\"text-destructive hover:text-destructive\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<X weight=\"bold\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Card variant (default)\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"group relative overflow-hidden rounded-lg border\",\n\t\t\t\t\"bg-muted/30 border-border/60\",\n\t\t\t\tdisabled && \"opacity-60\",\n\t\t\t\tonClick && !disabled && \"cursor-pointer hover:border-border\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tonClick={\n\t\t\t\tonClick && !disabled && asset.id ? () => onClick(asset.id!) : undefined\n\t\t\t}\n\t\t>\n\t\t\t{/* Drag handle */}\n\t\t\t{showDragHandle && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground absolute left-2 top-2 z-10 cursor-grab touch-none rounded p-1 active:cursor-grabbing\"\n\t\t\t\t\t{...dragHandleProps}\n\t\t\t\t>\n\t\t\t\t\t<DotsSixVertical className=\"size-4\" weight=\"bold\" />\n\t\t\t\t</button>\n\t\t\t)}\n\n\t\t\t{/* Thumbnail area */}\n\t\t\t<div className=\"bg-muted/50 relative aspect-video w-full\">\n\t\t\t\t{thumbnailUrl && !imageError ? (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={thumbnailUrl}\n\t\t\t\t\t\talt={asset.alt || filename}\n\t\t\t\t\t\tclassName=\"h-full w-full object-contain\"\n\t\t\t\t\t\tonError={() => setImageError(true)}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<div className=\"flex h-full w-full flex-col items-center justify-center gap-2\">\n\t\t\t\t\t\t<FileIcon\n\t\t\t\t\t\t\tclassName=\"text-muted-foreground size-12\"\n\t\t\t\t\t\t\tweight=\"regular\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{extension && (\n\t\t\t\t\t\t\t<span className=\"bg-muted text-muted-foreground rounded px-2 py-0.5 text-xs font-medium\">\n\t\t\t\t\t\t\t\t{extension}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Loading overlay */}\n\t\t\t\t{loading && (\n\t\t\t\t\t<div className=\"bg-background/80 absolute inset-0 flex flex-col items-center justify-center gap-2\">\n\t\t\t\t\t\t<SpinnerGap\n\t\t\t\t\t\t\tclassName=\"text-muted-foreground size-8 animate-spin\"\n\t\t\t\t\t\t\tweight=\"regular\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{typeof progress === \"number\" && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground text-sm font-medium\">\n\t\t\t\t\t\t\t\t\t{progress}%\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<div className=\"bg-muted h-1.5 w-24 overflow-hidden rounded-full\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName=\"bg-primary h-full rounded-full transition-all duration-300\"\n\t\t\t\t\t\t\t\t\t\tstyle={{ width: `${progress}%` }}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Remove button (top right) */}\n\t\t\t\t{!loading && !disabled && onRemove && (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\tclassName=\"absolute right-2 top-2 opacity-0 transition-opacity group-hover:opacity-100\"\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\tonRemove();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<X weight=\"bold\" />\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* File info footer */}\n\t\t\t<div className=\"flex items-center gap-2 border-t p-2\">\n\t\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t\t<p className=\"truncate text-sm font-medium\" title={filename}>\n\t\t\t\t\t\t{filename}\n\t\t\t\t\t</p>\n\t\t\t\t\t<p className=\"text-muted-foreground text-xs\">\n\t\t\t\t\t\t{formatFileSize(size)}\n\t\t\t\t\t\t{mimeType && ` • ${mimeType.split(\"/\")[1]?.toUpperCase()}`}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Action buttons */}\n\t\t\t\t{!loading && !disabled && (href || onEdit) && (\n\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t{href && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon-sm\"\n\t\t\t\t\t\t\t\tnativeButton={false}\n\t\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t\t// biome-ignore lint/a11y/useAnchorContent: TODO: improve accessibility\n\t\t\t\t\t\t\t\t\t<a href={href} onClick={(e) => e.stopPropagation()} />\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ArrowSquareOut weight=\"bold\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onEdit && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon-sm\"\n\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\tonEdit();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Pencil weight=\"bold\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","/**\n * MediaGrid Component\n *\n * Reusable grid display for assets with selection support.\n * Used in MediaPickerDialog and potentially in assets table view.\n *\n * Features:\n * - Responsive columns (2-5)\n * - Single/multiple/no selection modes\n * - Loading skeleton\n * - Click handling\n *\n * @example\n * ```tsx\n * <MediaGrid\n * assets={assets}\n * selectedIds={selectedIds}\n * onSelectionChange={setSelectedIds}\n * selectionMode=\"multiple\"\n * />\n * ```\n */\n\nimport { Check } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport type { Asset } from \"../../hooks/use-upload\";\nimport { cn } from \"../../lib/utils\";\nimport { Skeleton } from \"../ui/skeleton\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface MediaGridProps {\n\t/**\n\t * Assets to display\n\t */\n\tassets: Asset[];\n\n\t/**\n\t * Currently selected asset IDs\n\t */\n\tselectedIds?: Set<string>;\n\n\t/**\n\t * Called when selection changes\n\t */\n\tonSelectionChange?: (ids: Set<string>) => void;\n\n\t/**\n\t * Selection mode\n\t * @default \"none\"\n\t */\n\tselectionMode?: \"single\" | \"multiple\" | \"none\";\n\n\t/**\n\t * Loading state (shows skeleton)\n\t */\n\tloading?: boolean;\n\n\t/**\n\t * Called when an asset is clicked\n\t */\n\tonAssetClick?: (asset: Asset) => void;\n\n\t/**\n\t * Number of columns\n\t * @default 4\n\t */\n\tcolumns?: 2 | 3 | 4 | 5;\n\n\t/**\n\t * Additional className\n\t */\n\tclassName?: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Get file icon color based on MIME type\n */\nfunction getAssetTypeColor(mimeType?: string): string {\n\tif (!mimeType) return \"bg-muted\";\n\n\tconst type = mimeType.toLowerCase();\n\n\tif (type.startsWith(\"image/\")) return \"bg-blue-500/10\";\n\tif (type.startsWith(\"video/\")) return \"bg-purple-500/10\";\n\tif (type.startsWith(\"audio/\")) return \"bg-pink-500/10\";\n\tif (type === \"application/pdf\") return \"bg-red-500/10\";\n\n\treturn \"bg-muted\";\n}\n\n/**\n * Check if MIME type is an image\n */\nfunction isImage(mimeType?: string): boolean {\n\treturn !!mimeType?.toLowerCase().startsWith(\"image/\");\n}\n\n// ============================================================================\n// Skeleton Component\n// ============================================================================\n\nfunction MediaGridSkeleton({ columns = 4 }: { columns?: 2 | 3 | 4 | 5 }) {\n\tconst count = columns * 3; // Show 3 rows\n\tconst skeletonKeys = React.useMemo(\n\t\t() => Array.from({ length: count }, () => crypto.randomUUID()),\n\t\t[count],\n\t);\n\tconst gridClass =\n\t\tcolumns === 2\n\t\t\t? \"grid-cols-2\"\n\t\t\t: columns === 3\n\t\t\t\t? \"grid-cols-2 sm:grid-cols-3\"\n\t\t\t\t: columns === 5\n\t\t\t\t\t? \"grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5\"\n\t\t\t\t\t: \"grid-cols-2 sm:grid-cols-3 lg:grid-cols-4\";\n\n\treturn (\n\t\t<div className={cn(\"grid gap-3\", gridClass)}>\n\t\t\t{skeletonKeys.map((key) => (\n\t\t\t\t<div key={key} className=\"space-y-2\">\n\t\t\t\t\t<Skeleton className=\"aspect-square w-full rounded-lg\" />\n\t\t\t\t\t<Skeleton className=\"h-4 w-3/4\" />\n\t\t\t\t</div>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Asset Item Component\n// ============================================================================\n\ninterface AssetItemProps {\n\tasset: Asset;\n\tselected: boolean;\n\tselectionMode: \"single\" | \"multiple\" | \"none\";\n\tonToggle: () => void;\n\tonClick?: () => void;\n}\n\nfunction AssetItem({\n\tasset,\n\tselected,\n\tselectionMode,\n\tonToggle,\n\tonClick,\n}: AssetItemProps) {\n\tconst [imageError, setImageError] = React.useState(false);\n\tconst thumbnailUrl = asset.url;\n\tconst isImageType = isImage(asset.mimeType);\n\tconst showCheckbox = selectionMode !== \"none\";\n\n\tconst handleClick = () => {\n\t\tif (selectionMode !== \"none\") {\n\t\t\tonToggle();\n\t\t}\n\t\tonClick?.();\n\t};\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={handleClick}\n\t\t\tclassName={cn(\n\t\t\t\t\"group relative aspect-square w-full overflow-hidden rounded-lg border\",\n\t\t\t\t\"transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n\t\t\t\tselected\n\t\t\t\t\t? \"ring-primary border-primary ring-2\"\n\t\t\t\t\t: \"border-border/60 hover:border-border\",\n\t\t\t\t\"bg-muted/30\",\n\t\t\t)}\n\t\t>\n\t\t\t{/* Thumbnail or icon */}\n\t\t\t{thumbnailUrl && isImageType && !imageError ? (\n\t\t\t\t<img\n\t\t\t\t\tsrc={thumbnailUrl}\n\t\t\t\t\talt={asset.alt || asset.filename || \"Asset\"}\n\t\t\t\t\tclassName=\"h-full w-full object-cover\"\n\t\t\t\t\tonError={() => setImageError(true)}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex h-full w-full items-center justify-center\",\n\t\t\t\t\t\tgetAssetTypeColor(asset.mimeType),\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"text-muted-foreground text-xs font-medium uppercase\">\n\t\t\t\t\t\t{asset.mimeType?.split(\"/\")[1]?.slice(0, 4) || \"FILE\"}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Selection checkbox */}\n\t\t\t{showCheckbox && (\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"absolute right-2 top-2 flex size-5 items-center justify-center rounded-full border-2 transition-all\",\n\t\t\t\t\t\tselected\n\t\t\t\t\t\t\t? \"bg-primary border-primary\"\n\t\t\t\t\t\t\t: \"border-white bg-black/20 backdrop-blur-sm group-hover:bg-black/40\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{selected && <Check weight=\"bold\" className=\"size-3 text-white\" />}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Filename overlay (on hover) */}\n\t\t\t{asset.filename && (\n\t\t\t\t<div className=\"absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/60 to-transparent p-2 opacity-0 transition-opacity group-hover:opacity-100\">\n\t\t\t\t\t<p className=\"truncate text-xs text-white\" title={asset.filename}>\n\t\t\t\t\t\t{asset.filename}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</button>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function MediaGrid({\n\tassets,\n\tselectedIds = new Set(),\n\tonSelectionChange,\n\tselectionMode = \"none\",\n\tloading = false,\n\tonAssetClick,\n\tcolumns = 4,\n\tclassName,\n}: MediaGridProps) {\n\t// Handle toggle selection\n\tconst handleToggle = (assetId: string) => {\n\t\tif (!onSelectionChange) return;\n\n\t\tconst newSelection = new Set(selectedIds);\n\n\t\tif (selectionMode === \"single\") {\n\t\t\t// Single mode: clear all and select only this one\n\t\t\tnewSelection.clear();\n\t\t\tnewSelection.add(assetId);\n\t\t} else {\n\t\t\t// Multiple mode: toggle this one\n\t\t\tif (newSelection.has(assetId)) {\n\t\t\t\tnewSelection.delete(assetId);\n\t\t\t} else {\n\t\t\t\tnewSelection.add(assetId);\n\t\t\t}\n\t\t}\n\n\t\tonSelectionChange(newSelection);\n\t};\n\n\t// Show loading skeleton\n\tif (loading) {\n\t\treturn (\n\t\t\t<div className={className}>\n\t\t\t\t<MediaGridSkeleton columns={columns} />\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Empty state\n\tif (assets.length === 0) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex flex-col items-center justify-center rounded-lg border border-dashed p-12\",\n\t\t\t\t\t\"bg-muted/30 text-muted-foreground\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<p className=\"text-sm\">No assets found</p>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Grid columns class\n\tconst gridClass =\n\t\tcolumns === 2\n\t\t\t? \"grid-cols-2\"\n\t\t\t: columns === 3\n\t\t\t\t? \"grid-cols-2 sm:grid-cols-3\"\n\t\t\t\t: columns === 5\n\t\t\t\t\t? \"grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5\"\n\t\t\t\t\t: \"grid-cols-2 sm:grid-cols-3 lg:grid-cols-4\";\n\n\treturn (\n\t\t<div className={cn(\"grid gap-3\", gridClass, className)}>\n\t\t\t{assets.map((asset) => (\n\t\t\t\t<AssetItem\n\t\t\t\t\tkey={asset.id}\n\t\t\t\t\tasset={asset}\n\t\t\t\t\tselected={selectedIds.has(asset.id)}\n\t\t\t\t\tselectionMode={selectionMode}\n\t\t\t\t\tonToggle={() => handleToggle(asset.id)}\n\t\t\t\t\tonClick={onAssetClick ? () => onAssetClick(asset) : undefined}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n","/**\n * MediaPickerDialog Component\n *\n * Dialog for searching and selecting existing assets from the media library.\n * Used in UploadField and UploadManyField to allow browsing existing files.\n *\n * Features:\n * - Search by filename\n * - MIME type filtering\n * - Responsive grid display\n * - Single/multiple selection modes\n * - Pagination support\n *\n * @example\n * ```tsx\n * <MediaPickerDialog\n * open={isOpen}\n * onOpenChange={setIsOpen}\n * mode=\"single\"\n * onSelect={(id) => field.onChange(id)}\n * />\n * ```\n */\n\nimport { FunnelSimple, MagnifyingGlass } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { toast } from \"sonner\";\nimport { useCollectionList } from \"../../hooks/use-collection\";\nimport type { Asset } from \"../../hooks/use-upload\";\nimport { AssetPreview } from \"../primitives/asset-preview\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"../ui/select\";\nimport {\n\tSheet,\n\tSheetContent,\n\tSheetDescription,\n\tSheetFooter,\n\tSheetHeader,\n\tSheetTitle,\n} from \"../ui/sheet\";\nimport { MediaGrid } from \"./media-grid\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface MediaPickerDialogProps {\n\t/**\n\t * Dialog open state\n\t */\n\topen: boolean;\n\n\t/**\n\t * Called when dialog open state changes\n\t */\n\tonOpenChange: (open: boolean) => void;\n\n\t/**\n\t * Selection mode\n\t * @default \"single\"\n\t */\n\tmode?: \"single\" | \"multiple\";\n\n\t/**\n\t * Accepted MIME types filter\n\t * @example [\"image/*\", \"video/*\"]\n\t */\n\taccept?: string[];\n\n\t/**\n\t * Called when assets are selected\n\t */\n\tonSelect: (ids: string | string[]) => void;\n\n\t/**\n\t * Maximum number of items (for multiple mode)\n\t */\n\tmaxItems?: number;\n\n\t/**\n\t * Target collection\n\t * @default \"assets\"\n\t */\n\tcollection?: string;\n}\n\n// ============================================================================\n// MIME Type Filters\n// ============================================================================\n\nconst MIME_TYPE_FILTERS = [\n\t{ value: \"all\", label: \"All Files\", mimePattern: undefined },\n\t{ value: \"images\", label: \"Images\", mimePattern: \"image/\" },\n\t{ value: \"videos\", label: \"Videos\", mimePattern: \"video/\" },\n\t{ value: \"audio\", label: \"Audio\", mimePattern: \"audio/\" },\n\t{ value: \"documents\", label: \"Documents\", mimePattern: \"application/pdf\" },\n];\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function MediaPickerDialog({\n\topen,\n\tonOpenChange,\n\tmode = \"single\",\n\taccept,\n\tonSelect,\n\tmaxItems,\n\tcollection = \"assets\",\n}: MediaPickerDialogProps) {\n\t// State\n\tconst [selectedIds, setSelectedIds] = React.useState<Set<string>>(new Set());\n\tconst [searchQuery, setSearchQuery] = React.useState(\"\");\n\tconst [mimeFilter, setMimeFilter] = React.useState(\"all\");\n\tconst [previewAssetId, setPreviewAssetId] = React.useState<string | null>(\n\t\tnull,\n\t);\n\n\t// Build where clause for query\n\tconst where = React.useMemo(() => {\n\t\tconst andConditions: any[] = [];\n\n\t\t// MIME type filter\n\t\tconst selectedFilter = MIME_TYPE_FILTERS.find(\n\t\t\t(f) => f.value === mimeFilter,\n\t\t);\n\t\tif (selectedFilter?.mimePattern) {\n\t\t\tandConditions.push({\n\t\t\t\tmimeType: { startsWith: selectedFilter.mimePattern },\n\t\t\t});\n\t\t}\n\n\t\t// Accept prop filter\n\t\tif (accept && accept.length > 0) {\n\t\t\tconst acceptPatterns = accept.map((pattern) => {\n\t\t\t\tif (pattern.startsWith(\".\")) {\n\t\t\t\t\treturn { filename: { endsWith: pattern } };\n\t\t\t\t}\n\t\t\t\tif (pattern.endsWith(\"/*\")) {\n\t\t\t\t\t// e.g., \"image/*\" -> \"image/\"\n\t\t\t\t\treturn { mimeType: { startsWith: pattern.slice(0, -1) } };\n\t\t\t\t}\n\t\t\t\t// Exact match\n\t\t\t\treturn { mimeType: pattern };\n\t\t\t});\n\n\t\t\tif (acceptPatterns.length === 1) {\n\t\t\t\tandConditions.push(acceptPatterns[0]);\n\t\t\t} else {\n\t\t\t\tandConditions.push({ OR: acceptPatterns });\n\t\t\t}\n\t\t}\n\n\t\tif (andConditions.length === 0) return undefined;\n\t\tif (andConditions.length === 1) return andConditions[0];\n\t\treturn { AND: andConditions };\n\t}, [mimeFilter, accept]);\n\n\tconst trimmedSearch = searchQuery.trim();\n\n\t// Fetch assets\n\tconst { data, isLoading } = useCollectionList(\n\t\tcollection,\n\t\t{\n\t\t\twhere,\n\t\t\tsearch: trimmedSearch || undefined,\n\t\t\tlimit: 50,\n\t\t\torderBy: { createdAt: \"desc\" },\n\t\t},\n\t\t{\n\t\t\tenabled: open,\n\t\t},\n\t);\n\n\tconst assets = (data?.docs || []) as Asset[];\n\tconst previewAsset = React.useMemo(\n\t\t() => assets.find((asset) => asset.id === previewAssetId) ?? null,\n\t\t[assets, previewAssetId],\n\t);\n\n\t// Reset state when dialog closes\n\tReact.useEffect(() => {\n\t\tif (!open) {\n\t\t\tsetSelectedIds(new Set());\n\t\t\tsetSearchQuery(\"\");\n\t\t\tsetMimeFilter(\"all\");\n\t\t\tsetPreviewAssetId(null);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!previewAssetId && assets.length > 0) {\n\t\t\tsetPreviewAssetId(assets[0].id);\n\t\t\treturn;\n\t\t}\n\n\t\tif (previewAssetId && assets.length > 0) {\n\t\t\tconst stillExists = assets.some((asset) => asset.id === previewAssetId);\n\t\t\tif (!stillExists) {\n\t\t\t\tsetPreviewAssetId(assets[0].id);\n\t\t\t}\n\t\t}\n\t}, [open, assets, previewAssetId]);\n\n\t// Handle selection change\n\tconst handleSelectionChange = (ids: Set<string>) => {\n\t\t// Check maxItems for multiple mode\n\t\tif (mode === \"multiple\" && maxItems && ids.size > maxItems) {\n\t\t\ttoast.warning(`Maximum ${maxItems} items allowed`);\n\t\t\treturn;\n\t\t}\n\n\t\tsetSelectedIds(ids);\n\t};\n\n\t// Handle select button click\n\tconst handleSelect = () => {\n\t\tif (selectedIds.size === 0) {\n\t\t\ttoast.error(\"Please select at least one asset\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (mode === \"single\") {\n\t\t\tconst [id] = Array.from(selectedIds);\n\t\t\tonSelect(id);\n\t\t} else {\n\t\t\tonSelect(Array.from(selectedIds));\n\t\t}\n\n\t\tonOpenChange(false);\n\t};\n\n\t// Handle cancel\n\tconst handleCancel = () => {\n\t\tonOpenChange(false);\n\t};\n\n\treturn (\n\t\t<Sheet open={open} onOpenChange={onOpenChange}>\n\t\t\t<SheetContent\n\t\t\t\tside=\"right\"\n\t\t\t\tclassName=\"data-[side=right]:sm:max-w-6xl w-full p-0\"\n\t\t\t>\n\t\t\t\t<SheetHeader className=\"px-6 pt-6\">\n\t\t\t\t\t<SheetTitle>Browse Media Library</SheetTitle>\n\t\t\t\t\t<SheetDescription>\n\t\t\t\t\t\t{mode === \"single\"\n\t\t\t\t\t\t\t? \"Select an asset from your library\"\n\t\t\t\t\t\t\t: `Select up to ${maxItems || \"multiple\"} assets`}\n\t\t\t\t\t</SheetDescription>\n\t\t\t\t</SheetHeader>\n\n\t\t\t\t<div className=\"flex flex-1 flex-col gap-4 overflow-hidden px-6 pb-6\">\n\t\t\t\t\t{/* Filters */}\n\t\t\t\t\t<div className=\"flex flex-col gap-3 border-b pb-4 sm:flex-row\">\n\t\t\t\t\t\t{/* Search input */}\n\t\t\t\t\t\t<div className=\"relative flex-1\">\n\t\t\t\t\t\t\t<MagnifyingGlass\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground absolute left-3 top-1/2 size-4 -translate-y-1/2\"\n\t\t\t\t\t\t\t\tweight=\"bold\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\tplaceholder=\"Search by filename...\"\n\t\t\t\t\t\t\t\tvalue={searchQuery}\n\t\t\t\t\t\t\t\tonChange={(e) => setSearchQuery(e.target.value)}\n\t\t\t\t\t\t\t\tclassName=\"pl-9\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{/* MIME type filter */}\n\t\t\t\t\t\t{!accept && (\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\tvalue={mimeFilter}\n\t\t\t\t\t\t\t\tonValueChange={(value) => setMimeFilter(value || \"all\")}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full sm:w-[180px]\">\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t\t\t<FunnelSimple weight=\"bold\" className=\"size-4\" />\n\t\t\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t{MIME_TYPE_FILTERS.map((filter) => (\n\t\t\t\t\t\t\t\t\t\t<SelectItem key={filter.value} value={filter.value}>\n\t\t\t\t\t\t\t\t\t\t\t{filter.label}\n\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Assets + Preview */}\n\t\t\t\t\t<div className=\"flex flex-1 gap-4 overflow-hidden\">\n\t\t\t\t\t\t<div className=\"flex-1 overflow-y-auto pr-1\">\n\t\t\t\t\t\t\t<MediaGrid\n\t\t\t\t\t\t\t\tassets={assets}\n\t\t\t\t\t\t\t\tselectedIds={selectedIds}\n\t\t\t\t\t\t\t\tonSelectionChange={handleSelectionChange}\n\t\t\t\t\t\t\t\tselectionMode={mode}\n\t\t\t\t\t\t\t\tloading={isLoading}\n\t\t\t\t\t\t\t\tcolumns={5}\n\t\t\t\t\t\t\t\tclassName=\"gap-2\"\n\t\t\t\t\t\t\t\tonAssetClick={(asset) => setPreviewAssetId(asset.id)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"hidden lg:flex w-80 xl:w-96 shrink-0 flex-col gap-3 border-l pl-4\">\n\t\t\t\t\t\t\t<p className=\"text-muted-foreground text-xs uppercase tracking-wide\">\n\t\t\t\t\t\t\t\tPreview\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t{previewAsset ? (\n\t\t\t\t\t\t\t\t<AssetPreview asset={previewAsset} variant=\"card\" />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-center rounded-lg border border-dashed p-6 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t\tSelect an asset to preview\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div className=\"lg:hidden border-t pt-4\">\n\t\t\t\t\t\t{previewAsset ? (\n\t\t\t\t\t\t\t<AssetPreview asset={previewAsset} variant=\"compact\" />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-center rounded-lg border border-dashed p-4 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\tSelect an asset to preview\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t<SheetFooter className=\"border-t px-6 py-4\">\n\t\t\t\t\t<div className=\"flex w-full justify-end gap-2\">\n\t\t\t\t\t\t<Button variant=\"outline\" onClick={handleCancel}>\n\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tonClick={handleSelect}\n\t\t\t\t\t\t\tdisabled={selectedIds.size === 0 || isLoading}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tSelect {selectedIds.size > 0 && `(${selectedIds.size})`}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</SheetFooter>\n\t\t\t</SheetContent>\n\t\t</Sheet>\n\t);\n}\n","/**\n * Image Popover Component\n *\n * Dialog for inserting images via URL or file upload.\n */\n\nimport type { Editor } from \"@tiptap/core\";\nimport * as React from \"react\";\nimport { toast } from \"sonner\";\n\nimport { useCollectionItem } from \"../../../hooks/use-collection\";\nimport { type Asset, useUpload } from \"../../../hooks/use-upload\";\nimport { useTranslation } from \"../../../i18n/hooks\";\nimport { MediaPickerDialog } from \"../../media/media-picker-dialog\";\nimport { Button } from \"../../ui/button\";\nimport { Input } from \"../../ui/input\";\nimport {\n\tPopover,\n\tPopoverContent,\n\tPopoverHeader,\n\tPopoverTitle,\n\tPopoverTrigger,\n} from \"../../ui/popover\";\nimport { sanitizeFilename } from \"../field-utils\";\n\nexport type ImagePopoverProps = {\n\teditor: Editor | null;\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\tdisabled?: boolean;\n\tonImageUpload?: (file: File) => Promise<string>;\n\timageCollection?: string;\n\tenableMediaLibrary?: boolean;\n};\n\n/**\n * Image insertion popover\n */\nexport function ImagePopover({\n\teditor,\n\topen,\n\tonOpenChange,\n\tdisabled,\n\tonImageUpload,\n\timageCollection,\n\tenableMediaLibrary,\n}: ImagePopoverProps) {\n\tconst { t } = useTranslation();\n\tconst [imageUrl, setImageUrl] = React.useState(\"\");\n\tconst [imageAlt, setImageAlt] = React.useState(\"\");\n\tconst [uploadingImage, setUploadingImage] = React.useState(false);\n\tconst fileInputRef = React.useRef<HTMLInputElement | null>(null);\n\tconst [isPickerOpen, setIsPickerOpen] = React.useState(false);\n\tconst [selectedAssetId, setSelectedAssetId] = React.useState<string | null>(\n\t\tnull,\n\t);\n\tconst { upload } = useUpload();\n\tconst collection = imageCollection ?? \"assets\";\n\tconst showMediaLibrary = enableMediaLibrary ?? true;\n\tconst { data: selectedAsset } = useCollectionItem(\n\t\tcollection,\n\t\tselectedAssetId || \"\",\n\t\tundefined,\n\t\t{ enabled: !!selectedAssetId },\n\t);\n\n\tconst handleInsertImageUrl = React.useCallback(() => {\n\t\tif (!editor || !imageUrl) return;\n\t\teditor\n\t\t\t.chain()\n\t\t\t.focus()\n\t\t\t.setImage({ src: imageUrl, alt: imageAlt || undefined })\n\t\t\t.run();\n\t\tsetImageUrl(\"\");\n\t\tsetImageAlt(\"\");\n\t\tonOpenChange(false);\n\t}, [editor, imageAlt, imageUrl, onOpenChange]);\n\n\tconst handleImageUpload = React.useCallback(\n\t\tasync (event: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst file = event.target.files?.[0];\n\t\t\tif (!file || !editor) return;\n\n\t\t\ttry {\n\t\t\t\tsetUploadingImage(true);\n\t\t\t\tlet url: string | undefined;\n\t\t\t\tif (onImageUpload) {\n\t\t\t\t\turl = await onImageUpload(file);\n\t\t\t\t} else {\n\t\t\t\t\tconst sanitizedName = sanitizeFilename(file.name);\n\t\t\t\t\tconst uploadFile =\n\t\t\t\t\t\tsanitizedName === file.name\n\t\t\t\t\t\t\t? file\n\t\t\t\t\t\t\t: new File([file], sanitizedName, { type: file.type });\n\t\t\t\t\tconst uploadedAsset = (await upload(uploadFile, {\n\t\t\t\t\t\tcollection,\n\t\t\t\t\t})) as Asset;\n\t\t\t\t\turl = uploadedAsset?.url;\n\t\t\t\t\tif (!url) {\n\t\t\t\t\t\tthrow new Error(t(\"upload.error\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (url) {\n\t\t\t\t\teditor\n\t\t\t\t\t\t.chain()\n\t\t\t\t\t\t.focus()\n\t\t\t\t\t\t.setImage({ src: url, alt: imageAlt || undefined })\n\t\t\t\t\t\t.run();\n\t\t\t\t\tsetImageUrl(\"\");\n\t\t\t\t\tsetImageAlt(\"\");\n\t\t\t\t\tonOpenChange(false);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconst uploadError =\n\t\t\t\t\terr instanceof Error ? err : new Error(t(\"upload.error\"));\n\t\t\t\ttoast.error(uploadError.message);\n\t\t\t} finally {\n\t\t\t\tsetUploadingImage(false);\n\t\t\t\tevent.target.value = \"\";\n\t\t\t}\n\t\t},\n\t\t[collection, editor, imageAlt, onImageUpload, onOpenChange, t, upload],\n\t);\n\n\tReact.useEffect(() => {\n\t\tif (!selectedAssetId || !selectedAsset || !editor) return;\n\t\tconst assetUrl = (selectedAsset as Asset | undefined)?.url;\n\t\tif (!assetUrl) {\n\t\t\ttoast.error(t(\"upload.error\"));\n\t\t\tsetSelectedAssetId(null);\n\t\t\treturn;\n\t\t}\n\t\teditor\n\t\t\t.chain()\n\t\t\t.focus()\n\t\t\t.setImage({\n\t\t\t\tsrc: assetUrl,\n\t\t\t\talt: imageAlt || (selectedAsset as Asset | undefined)?.alt || undefined,\n\t\t\t})\n\t\t\t.run();\n\t\tsetImageUrl(\"\");\n\t\tsetImageAlt(\"\");\n\t\tsetSelectedAssetId(null);\n\t\tonOpenChange(false);\n\t}, [editor, imageAlt, onOpenChange, selectedAsset, selectedAssetId, t]);\n\n\tconst handlePickerSelect = (ids: string | string[]) => {\n\t\tconst selectedId = Array.isArray(ids) ? ids[0] : ids;\n\t\tif (!selectedId) return;\n\t\tsetSelectedAssetId(selectedId);\n\t\tsetIsPickerOpen(false);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<Popover open={open} onOpenChange={onOpenChange}>\n\t\t\t\t<PopoverTrigger render={<div className=\"sr-only\" />} />\n\t\t\t\t<PopoverContent className=\"w-80\">\n\t\t\t\t\t<PopoverHeader>\n\t\t\t\t\t\t<PopoverTitle>{t(\"editor.image\")}</PopoverTitle>\n\t\t\t\t\t</PopoverHeader>\n\t\t\t\t\t<div className=\"space-y-3\">\n\t\t\t\t\t\t<div className=\"space-y-2\">\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tvalue={imageUrl}\n\t\t\t\t\t\t\t\tplaceholder=\"https://example.com/image.jpg\"\n\t\t\t\t\t\t\t\tonChange={(event) => setImageUrl(event.target.value)}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tvalue={imageAlt}\n\t\t\t\t\t\t\t\tplaceholder={t(\"editor.altText\")}\n\t\t\t\t\t\t\t\tonChange={(event) => setImageAlt(event.target.value)}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<div className=\"flex justify-end gap-2\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\t\tonClick={handleInsertImageUrl}\n\t\t\t\t\t\t\t\t\tdisabled={disabled || !imageUrl}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{t(\"editor.insertUrl\")}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div className=\"space-y-2\">\n\t\t\t\t\t\t\t<div className=\"text-xs font-medium\">\n\t\t\t\t\t\t\t\t{t(\"editor.uploadFile\")}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t\t\t\taccept=\"image/*\"\n\t\t\t\t\t\t\t\tonChange={handleImageUpload}\n\t\t\t\t\t\t\t\tclassName=\"sr-only\"\n\t\t\t\t\t\t\t\tdisabled={disabled || uploadingImage}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tonClick={() => fileInputRef.current?.click()}\n\t\t\t\t\t\t\t\t\tdisabled={disabled || uploadingImage}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{uploadingImage\n\t\t\t\t\t\t\t\t\t\t? t(\"editor.uploading\")\n\t\t\t\t\t\t\t\t\t\t: t(\"editor.chooseFile\")}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t{showMediaLibrary && (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => setIsPickerOpen(true)}\n\t\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{t(\"editor.browseLibrary\")}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</PopoverContent>\n\t\t\t</Popover>\n\t\t\t{showMediaLibrary && (\n\t\t\t\t<MediaPickerDialog\n\t\t\t\t\topen={isPickerOpen}\n\t\t\t\t\tonOpenChange={setIsPickerOpen}\n\t\t\t\t\tmode=\"single\"\n\t\t\t\t\taccept={[\"image/*\"]}\n\t\t\t\t\tonSelect={handlePickerSelect}\n\t\t\t\t\tcollection={collection}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","/**\n * Link Popover Component\n *\n * Dialog for inserting and editing links.\n */\n\nimport type { Editor } from \"@tiptap/core\";\nimport * as React from \"react\";\n\nimport { useTranslation } from \"../../../i18n/hooks\";\nimport { Button } from \"../../ui/button\";\nimport { Input } from \"../../ui/input\";\nimport {\n\tPopover,\n\tPopoverContent,\n\tPopoverHeader,\n\tPopoverTitle,\n\tPopoverTrigger,\n} from \"../../ui/popover\";\n\nexport type LinkPopoverProps = {\n\teditor: Editor | null;\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\tdisabled?: boolean;\n};\n\n/**\n * Link insertion/editing popover\n */\nexport function LinkPopover({\n\teditor,\n\topen,\n\tonOpenChange,\n\tdisabled,\n}: LinkPopoverProps) {\n\tconst { t } = useTranslation();\n\tconst [linkUrl, setLinkUrl] = React.useState(\"\");\n\n\tReact.useEffect(() => {\n\t\tif (!open || !editor) return;\n\t\tconst currentLink = editor.getAttributes(\"link\").href as string | undefined;\n\t\tsetLinkUrl(currentLink || \"\");\n\t}, [editor, open]);\n\n\tconst handleApplyLink = React.useCallback(() => {\n\t\tif (!editor) return;\n\t\tif (!linkUrl) {\n\t\t\teditor.chain().focus().unsetLink().run();\n\t\t\tonOpenChange(false);\n\t\t\treturn;\n\t\t}\n\n\t\teditor\n\t\t\t.chain()\n\t\t\t.focus()\n\t\t\t.setLink({\n\t\t\t\thref: linkUrl,\n\t\t\t\ttarget: \"_blank\",\n\t\t\t\trel: \"noopener noreferrer\",\n\t\t\t})\n\t\t\t.run();\n\t\tonOpenChange(false);\n\t}, [editor, linkUrl, onOpenChange]);\n\n\tconst handleRemoveLink = React.useCallback(() => {\n\t\tif (!editor) return;\n\t\teditor.chain().focus().unsetLink().run();\n\t\tonOpenChange(false);\n\t}, [editor, onOpenChange]);\n\n\treturn (\n\t\t<Popover open={open} onOpenChange={onOpenChange}>\n\t\t\t<PopoverTrigger render={<div className=\"sr-only\" />} />\n\t\t\t<PopoverContent className=\"w-72\">\n\t\t\t\t<PopoverHeader>\n\t\t\t\t\t<PopoverTitle>{t(\"editor.link\")}</PopoverTitle>\n\t\t\t\t</PopoverHeader>\n\t\t\t\t<div className=\"space-y-2\">\n\t\t\t\t\t<Input\n\t\t\t\t\t\tvalue={linkUrl}\n\t\t\t\t\t\tplaceholder=\"https://example.com\"\n\t\t\t\t\t\tonChange={(event) => setLinkUrl(event.target.value)}\n\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\tif (event.key === \"Enter\") {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\thandleApplyLink();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tautoFocus\n\t\t\t\t\t/>\n\t\t\t\t\t<div className=\"flex justify-end gap-2\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\tonClick={handleRemoveLink}\n\t\t\t\t\t\t\tdisabled={disabled || !editor?.isActive(\"link\")}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t(\"common.remove\")}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\tonClick={handleApplyLink}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t(\"common.apply\")}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t);\n}\n","/**\n * RichText Editor Presets\n *\n * Pre-configured feature sets for common use cases.\n */\n\nimport type { RichTextFeatures } from \"./types\";\n\n/**\n * Preset type\n */\nexport type RichTextPreset = \"minimal\" | \"simple\" | \"standard\" | \"advanced\";\n\n/**\n * MINIMAL - Only bubble menu with basic formatting\n *\n * Use case: Inline editing, comments, simple text fields\n * Features: Bold, Italic, Underline, Link\n * UI: No toolbar, only bubble menu on selection\n */\nexport const PRESET_MINIMAL: Required<RichTextFeatures> = {\n\ttoolbar: false,\n\tbubbleMenu: true,\n\tslashCommands: false,\n\thistory: true,\n\theading: false,\n\tbold: true,\n\titalic: true,\n\tunderline: true,\n\tstrike: false,\n\tcode: false,\n\tcodeBlock: false,\n\tblockquote: false,\n\tbulletList: false,\n\torderedList: false,\n\thorizontalRule: false,\n\talign: false,\n\tlink: true,\n\timage: false,\n\ttable: false,\n\ttableControls: false,\n\tcharacterCount: false,\n};\n\n/**\n * SIMPLE - Basic rich text without media\n *\n * Use case: Blog posts, articles, descriptions\n * Features: Headings, formatting, lists, quotes, links\n * UI: Compact toolbar with essential controls\n */\nexport const PRESET_SIMPLE: Required<RichTextFeatures> = {\n\ttoolbar: true,\n\tbubbleMenu: true,\n\tslashCommands: true,\n\thistory: true,\n\theading: true,\n\tbold: true,\n\titalic: true,\n\tunderline: true,\n\tstrike: true,\n\tcode: true,\n\tcodeBlock: false,\n\tblockquote: true,\n\tbulletList: true,\n\torderedList: true,\n\thorizontalRule: true,\n\talign: false,\n\tlink: true,\n\timage: false,\n\ttable: false,\n\ttableControls: false,\n\tcharacterCount: true,\n};\n\n/**\n * STANDARD - Full-featured editor (default)\n *\n * Use case: General-purpose content editing\n * Features: All formatting, alignment, images, basic tables\n * UI: Full toolbar with all standard controls\n */\nexport const PRESET_STANDARD: Required<RichTextFeatures> = {\n\ttoolbar: true,\n\tbubbleMenu: true,\n\tslashCommands: true,\n\thistory: true,\n\theading: true,\n\tbold: true,\n\titalic: true,\n\tunderline: true,\n\tstrike: true,\n\tcode: true,\n\tcodeBlock: true,\n\tblockquote: true,\n\tbulletList: true,\n\torderedList: true,\n\thorizontalRule: true,\n\talign: true,\n\tlink: true,\n\timage: true,\n\ttable: true,\n\ttableControls: true,\n\tcharacterCount: true,\n};\n\n/**\n * ADVANCED - Everything including advanced features\n *\n * Use case: Documentation, technical writing, complex layouts\n * Features: Everything in standard + advanced table controls\n * UI: Full toolbar with all advanced controls\n */\nexport const PRESET_ADVANCED: Required<RichTextFeatures> = {\n\t...PRESET_STANDARD,\n\t// Advanced preset currently same as standard\n\t// Reserved for future advanced features like:\n\t// - Custom blocks\n\t// - Collaboration\n\t// - Advanced table features\n\t// - Math equations\n\t// - Diagrams\n};\n\n/**\n * Get preset configuration by name\n */\nexport function getPreset(preset: RichTextPreset): Required<RichTextFeatures> {\n\tswitch (preset) {\n\t\tcase \"minimal\":\n\t\t\treturn PRESET_MINIMAL;\n\t\tcase \"simple\":\n\t\t\treturn PRESET_SIMPLE;\n\t\tcase \"standard\":\n\t\t\treturn PRESET_STANDARD;\n\t\tcase \"advanced\":\n\t\t\treturn PRESET_ADVANCED;\n\t\tdefault:\n\t\t\treturn PRESET_STANDARD;\n\t}\n}\n\n/**\n * Merge preset with custom feature overrides\n */\nexport function mergePresetFeatures(\n\tpreset: RichTextPreset,\n\toverrides?: Partial<RichTextFeatures>,\n): Required<RichTextFeatures> {\n\tconst basePreset = getPreset(preset);\n\treturn {\n\t\t...basePreset,\n\t\t...overrides,\n\t};\n}\n","/**\n * RichText Editor Type Definitions\n */\n\nimport type { Editor, Extension as TiptapExtension } from \"@tiptap/core\";\nimport type { FieldComponentProps } from \"../../../builder\";\nimport type { RichTextPreset } from \"./presets\";\n\n/**\n * Feature toggles for the RichText editor\n */\nexport type RichTextFeatures = {\n\ttoolbar?: boolean;\n\tbubbleMenu?: boolean;\n\tslashCommands?: boolean;\n\thistory?: boolean;\n\theading?: boolean;\n\tbold?: boolean;\n\titalic?: boolean;\n\tunderline?: boolean;\n\tstrike?: boolean;\n\tcode?: boolean;\n\tcodeBlock?: boolean;\n\tblockquote?: boolean;\n\tbulletList?: boolean;\n\torderedList?: boolean;\n\thorizontalRule?: boolean;\n\talign?: boolean;\n\tlink?: boolean;\n\timage?: boolean;\n\ttable?: boolean;\n\ttableControls?: boolean;\n\tcharacterCount?: boolean;\n};\n\n/**\n * Default feature configuration (all enabled)\n */\nexport const defaultFeatures: Required<RichTextFeatures> = {\n\ttoolbar: true,\n\tbubbleMenu: true,\n\tslashCommands: true,\n\thistory: true,\n\theading: true,\n\tbold: true,\n\titalic: true,\n\tunderline: true,\n\tstrike: true,\n\tcode: true,\n\tcodeBlock: true,\n\tblockquote: true,\n\tbulletList: true,\n\torderedList: true,\n\thorizontalRule: true,\n\talign: true,\n\tlink: true,\n\timage: true,\n\ttable: true,\n\ttableControls: true,\n\tcharacterCount: true,\n};\n\n/**\n * Props for the RichTextEditor component\n */\nexport interface RichTextEditorProps extends FieldComponentProps<any> {\n\t/**\n\t * Output format\n\t */\n\toutputFormat?: \"json\" | \"html\" | \"markdown\";\n\n\t/**\n\t * Custom Tiptap extensions\n\t */\n\textensions?: TiptapExtension[];\n\n\t/**\n\t * Preset configuration (minimal, simple, standard, advanced)\n\t * Can be overridden by features prop\n\t */\n\tpreset?: RichTextPreset;\n\n\t/**\n\t * Feature toggles (overrides preset)\n\t */\n\tfeatures?: RichTextFeatures;\n\n\t/**\n\t * Show character count\n\t */\n\tshowCharacterCount?: boolean;\n\n\t/**\n\t * Max character limit\n\t */\n\tmaxCharacters?: number;\n\n\t/**\n\t * Enable image uploads\n\t */\n\tenableImages?: boolean;\n\n\t/**\n\t * Image upload handler\n\t */\n\tonImageUpload?: (file: File) => Promise<string>;\n\n\t/**\n\t * Target collection for image uploads\n\t */\n\timageCollection?: string;\n\n\t/**\n\t * Enable media library picker for images\n\t */\n\tenableMediaLibrary?: boolean;\n}\n\n/**\n * Output value type\n */\nexport type OutputValue = Record<string, any> | string;\n\n/**\n * Slash command item\n */\nexport type SlashCommandItem = {\n\ttitle: string;\n\tdescription?: string;\n\tkeywords?: string[];\n\tcommand: (editor: Editor) => void;\n};\n\n/**\n * Slash command list props\n */\nexport type SlashCommandListProps = {\n\titems: SlashCommandItem[];\n\tcommand: (item: SlashCommandItem) => void;\n};\n\n/**\n * Slash command list handle (ref API)\n */\nexport type SlashCommandListHandle = {\n\tonKeyDown: (props: { event: KeyboardEvent }) => boolean;\n};\n","/**\n * RichText Editor Utility Functions\n */\n\nimport type { Editor } from \"@tiptap/core\";\n\nimport type { OutputValue } from \"./types\";\n\n/**\n * Get the current heading level or \"paragraph\"\n */\nexport function getHeadingLevel(editor: Editor | null): string {\n\tif (!editor) return \"paragraph\";\n\tfor (let level = 1; level <= 6; level += 1) {\n\t\tif (editor.isActive(\"heading\", { level })) {\n\t\t\treturn String(level);\n\t\t}\n\t}\n\treturn \"paragraph\";\n}\n\n/**\n * Get output in the specified format\n */\nexport function getOutput(\n\teditor: Editor,\n\toutputFormat: \"json\" | \"html\" | \"markdown\",\n): OutputValue {\n\tif (outputFormat === \"html\") {\n\t\treturn editor.getHTML();\n\t}\n\n\tif (outputFormat === \"markdown\") {\n\t\tconst markdown = (editor.storage as any)?.markdown?.getMarkdown?.();\n\t\tif (typeof markdown === \"string\") {\n\t\t\treturn markdown;\n\t\t}\n\t\treturn editor.getHTML();\n\t}\n\n\treturn editor.getJSON();\n}\n\n/**\n * Compare two output values for equality\n */\nexport function isSameValue(\n\ta: OutputValue | undefined,\n\tb: OutputValue | undefined,\n): boolean {\n\tif (a === b) return true;\n\tif (!a || !b) return false;\n\tif (typeof a === \"string\" && typeof b === \"string\") return a === b;\n\ttry {\n\t\treturn JSON.stringify(a) === JSON.stringify(b);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Get character and word count from editor\n */\nexport function getCharacterCount(editor: Editor | null): {\n\tcharacters: number;\n\twords: number;\n} {\n\tif (!editor) return { characters: 0, words: 0 };\n\tconst storage = editor.storage as any;\n\tif (storage?.characterCount) {\n\t\treturn {\n\t\t\tcharacters: storage.characterCount.characters(),\n\t\t\twords: storage.characterCount.words(),\n\t\t};\n\t}\n\tconst text = editor.getText();\n\tconst words = text.trim().length ? text.trim().split(/\\s+/).length : 0;\n\treturn { characters: text.length, words };\n}\n","/**\n * RichTextEditor Component\n *\n * Tiptap-based rich text editor with modern icon-based toolbar.\n */\n\nimport { EditorContent, useEditor } from \"@tiptap/react\";\nimport * as React from \"react\";\n\nimport { useResolveText } from \"../../../i18n/hooks\";\nimport { cn } from \"../../../utils\";\nimport { Label } from \"../../ui/label\";\nimport { LocaleBadge } from \"../locale-badge\";\nimport { RichTextBubbleMenu } from \"./bubble-menu\";\nimport { buildExtensions } from \"./extensions\";\nimport { ImagePopover } from \"./image-popover\";\nimport { LinkPopover } from \"./link-popover\";\nimport { mergePresetFeatures } from \"./presets\";\nimport { RichTextToolbar } from \"./toolbar\";\nimport {\n\tdefaultFeatures,\n\ttype OutputValue,\n\ttype RichTextEditorProps,\n} from \"./types\";\nimport {\n\tgetCharacterCount,\n\tgetHeadingLevel,\n\tgetOutput,\n\tisSameValue,\n} from \"./utils\";\n\nexport type { RichTextPreset } from \"./presets\";\n// Re-export types\nexport type { RichTextEditorProps, RichTextFeatures } from \"./types\";\n\n// Re-export variant components\nexport {\n\tRichTextAdvanced,\n\tRichTextMinimal,\n\tRichTextSimple,\n\tRichTextStandard,\n} from \"./variants\";\n\n/**\n * Main RichText Editor Component\n */\nexport function RichTextEditor({\n\tname,\n\tvalue,\n\tonChange,\n\tdisabled,\n\treadOnly,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\terror,\n\tlocalized,\n\tlocale,\n\toutputFormat = \"json\",\n\textensions,\n\tpreset,\n\tfeatures,\n\tshowCharacterCount,\n\tmaxCharacters,\n\tenableImages,\n\tonImageUpload,\n\timageCollection,\n\tenableMediaLibrary,\n}: RichTextEditorProps) {\n\tconst resolveText = useResolveText();\n\tconst resolvedLabel = label ? resolveText(label) : undefined;\n\tconst resolvedDescription = description\n\t\t? resolveText(description)\n\t\t: undefined;\n\n\t// Popover states\n\tconst [linkOpen, setLinkOpen] = React.useState(false);\n\tconst [imageOpen, setImageOpen] = React.useState(false);\n\tconst lastEmittedValueRef = React.useRef<OutputValue | undefined>(undefined);\n\n\t// Resolved feature flags with preset support\n\tconst resolvedFeatures = React.useMemo(() => {\n\t\t// If preset is specified, merge with features\n\t\tif (preset) {\n\t\t\treturn mergePresetFeatures(preset, features);\n\t\t}\n\t\t// Otherwise use default features + overrides\n\t\treturn {\n\t\t\t...defaultFeatures,\n\t\t\t...features,\n\t\t};\n\t}, [preset, features]);\n\n\tconst allowImages = resolvedFeatures.image && (enableImages ?? true);\n\tconst allowLinks = resolvedFeatures.link;\n\tconst allowTables = resolvedFeatures.table;\n\tconst allowBubbleMenu = resolvedFeatures.bubbleMenu;\n\tconst allowToolbar = resolvedFeatures.toolbar;\n\tconst allowCharacterCount =\n\t\tresolvedFeatures.characterCount && (showCharacterCount || maxCharacters);\n\n\t// Build Tiptap extensions\n\tconst resolvedExtensions = React.useMemo(\n\t\t() =>\n\t\t\tbuildExtensions({\n\t\t\t\tfeatures: resolvedFeatures,\n\t\t\t\tplaceholder,\n\t\t\t\tmaxCharacters,\n\t\t\t\tcustomExtensions: extensions,\n\t\t\t}),\n\t\t[resolvedFeatures, placeholder, maxCharacters, extensions],\n\t);\n\n\t// Initialize editor\n\tconst editor = useEditor({\n\t\textensions: resolvedExtensions,\n\t\tcontent: value ?? \"\",\n\t\teditorProps: {\n\t\t\tattributes: {\n\t\t\t\tclass: \"qp-rich-text-editor__content\",\n\t\t\t},\n\t\t},\n\t\teditable: !disabled && !readOnly,\n\t\tonUpdate: ({ editor: currentEditor }) => {\n\t\t\tif (disabled || readOnly) return;\n\t\t\tconst nextValue = getOutput(currentEditor, outputFormat);\n\t\t\tlastEmittedValueRef.current = nextValue as OutputValue;\n\t\t\tonChange?.(nextValue);\n\t\t},\n\t});\n\n\tconst isEditable = !disabled && !readOnly;\n\tconst headingValue = getHeadingLevel(editor);\n\tconst inTable = editor?.isActive(\"table\") ?? false;\n\n\t// Update editor editable state\n\tReact.useEffect(() => {\n\t\tif (!editor) return;\n\t\teditor.setEditable(isEditable);\n\t}, [editor, isEditable]);\n\n\t// Sync external value changes\n\tReact.useEffect(() => {\n\t\tif (!editor) return;\n\t\tif (value === undefined) return;\n\t\tif (isSameValue(value, lastEmittedValueRef.current)) {\n\t\t\treturn;\n\t\t}\n\t\tlastEmittedValueRef.current = value as OutputValue;\n\t\teditor.commands.setContent(value ?? \"\", false);\n\t}, [editor, value]);\n\n\t// Character count\n\tconst characterCount = getCharacterCount(editor);\n\n\treturn (\n\t\t<div className=\"space-y-2\" data-disabled={disabled || readOnly}>\n\t\t\t{resolvedLabel && (\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<Label htmlFor={name}>\n\t\t\t\t\t\t{resolvedLabel}\n\t\t\t\t\t\t{required && <span className=\"text-destructive ml-1\">*</span>}\n\t\t\t\t\t</Label>\n\t\t\t\t\t{localized && <LocaleBadge locale={locale || \"i18n\"} />}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"qp-rich-text-editor rounded-md border border-input/80 bg-input/20 backdrop-blur-sm\",\n\t\t\t\t\tdisabled || readOnly ? \"opacity-60\" : \"\",\n\t\t\t\t\terror ? \"border-destructive\" : \"border-input\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{/* Toolbar */}\n\t\t\t\t{editor && allowToolbar && (\n\t\t\t\t\t<RichTextToolbar\n\t\t\t\t\t\teditor={editor}\n\t\t\t\t\t\tfeatures={resolvedFeatures}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\theadingValue={headingValue}\n\t\t\t\t\t\tonHeadingChange={(value) => {\n\t\t\t\t\t\t\tif (!editor) return;\n\t\t\t\t\t\t\tif (value === \"paragraph\") {\n\t\t\t\t\t\t\t\teditor.chain().focus().setParagraph().run();\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\teditor\n\t\t\t\t\t\t\t\t.chain()\n\t\t\t\t\t\t\t\t.focus()\n\t\t\t\t\t\t\t\t.toggleHeading({\n\t\t\t\t\t\t\t\t\tlevel: Number(value) as 1 | 2 | 3 | 4 | 5 | 6,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.run();\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonLinkClick={() => setLinkOpen(true)}\n\t\t\t\t\t\tonImageClick={() => setImageOpen(true)}\n\t\t\t\t\t\tonTableClick={() => {\n\t\t\t\t\t\t\t// Insert table directly when clicking toolbar button\n\t\t\t\t\t\t\tif (!inTable) {\n\t\t\t\t\t\t\t\teditor\n\t\t\t\t\t\t\t\t\t.chain()\n\t\t\t\t\t\t\t\t\t.focus()\n\t\t\t\t\t\t\t\t\t.insertTable({\n\t\t\t\t\t\t\t\t\t\trows: 3,\n\t\t\t\t\t\t\t\t\t\tcols: 3,\n\t\t\t\t\t\t\t\t\t\twithHeaderRow: true,\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.run();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinTable={inTable}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\n\t\t\t\t{/* Bubble Menu */}\n\t\t\t\t{editor && allowBubbleMenu && (\n\t\t\t\t\t<RichTextBubbleMenu\n\t\t\t\t\t\teditor={editor}\n\t\t\t\t\t\tfeatures={resolvedFeatures}\n\t\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\t\tonLinkClick={() => setLinkOpen(true)}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\n\t\t\t\t{/* Editor Content */}\n\t\t\t\t<EditorContent editor={editor} id={name} />\n\n\t\t\t\t{/* Character Count */}\n\t\t\t\t{allowCharacterCount && showCharacterCount && (\n\t\t\t\t\t<div className=\"flex items-center justify-between border-t bg-muted/30 px-2 py-1 text-xs text-muted-foreground\">\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t{characterCount.words} word{characterCount.words === 1 ? \"\" : \"s\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t{characterCount.characters}\n\t\t\t\t\t\t\t{typeof maxCharacters === \"number\" ? ` / ${maxCharacters}` : \"\"}{\" \"}\n\t\t\t\t\t\t\tcharacters\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Link Popover */}\n\t\t\t{allowLinks && (\n\t\t\t\t<LinkPopover\n\t\t\t\t\teditor={editor}\n\t\t\t\t\topen={linkOpen}\n\t\t\t\t\tonOpenChange={setLinkOpen}\n\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Image Popover */}\n\t\t\t{allowImages && (\n\t\t\t\t<ImagePopover\n\t\t\t\t\teditor={editor}\n\t\t\t\t\topen={imageOpen}\n\t\t\t\t\tonOpenChange={setImageOpen}\n\t\t\t\t\tdisabled={!isEditable}\n\t\t\t\t\tonImageUpload={onImageUpload}\n\t\t\t\t\timageCollection={imageCollection}\n\t\t\t\t\tenableMediaLibrary={enableMediaLibrary}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Description & Error */}\n\t\t\t{resolvedDescription && (\n\t\t\t\t<p className=\"text-muted-foreground text-xs\">{resolvedDescription}</p>\n\t\t\t)}\n\t\t\t{error && <p className=\"text-destructive text-xs\">{error}</p>}\n\t\t</div>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { useResolvedControl } from \"./field-utils\";\nimport type { RichTextEditorProps } from \"./rich-text-editor\";\nimport { RichTextEditor } from \"./rich-text-editor\";\n\nexport function RichTextField({\n\tname,\n\tcontrol,\n\tonChange,\n\t...props\n}: RichTextEditorProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<RichTextEditor\n\t\t\t\t\t{...props}\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={field.value}\n\t\t\t\t\tonChange={(value) => {\n\t\t\t\t\t\tfield.onChange(value);\n\t\t\t\t\t\tonChange?.(value);\n\t\t\t\t\t}}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t/>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","\"use client\";\n\nimport { Clock, X } from \"@phosphor-icons/react\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport type { TimeInputProps } from \"./types\";\n\n/**\n * Time Input Primitive\n *\n * A time-only input using the native HTML time picker.\n * Returns time as string in \"HH:mm\" or \"HH:mm:ss\" format.\n *\n * @example\n * ```tsx\n * <TimeInput\n * value={selectedTime}\n * onChange={setSelectedTime}\n * placeholder=\"Select time\"\n * />\n * ```\n */\nexport function TimeInput({\n\tvalue,\n\tonChange,\n\tprecision = \"minute\",\n\tplaceholder = \"Select time\",\n\tdisabled,\n\tclassName,\n\tid,\n\t\"aria-invalid\": ariaInvalid,\n}: TimeInputProps) {\n\tconst resolveText = useResolveText();\n\n\tconst handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst timeValue = e.target.value;\n\t\tonChange(timeValue || null);\n\t};\n\n\tconst handleClear = (e: React.MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tonChange(null);\n\t};\n\n\treturn (\n\t\t<div className=\"relative\">\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex h-9 w-full items-center gap-2 border border-input/80 bg-input/20 backdrop-blur-sm px-3 py-2 text-sm\",\n\t\t\t\t\t\"focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2\",\n\t\t\t\t\tdisabled && \"cursor-not-allowed opacity-50\",\n\t\t\t\t\tariaInvalid && \"border-destructive\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<Clock className=\"size-4 text-muted-foreground\" />\n\t\t\t\t<input\n\t\t\t\t\ttype=\"time\"\n\t\t\t\t\tid={id}\n\t\t\t\t\tvalue={value ?? \"\"}\n\t\t\t\t\tonChange={handleChange}\n\t\t\t\t\tstep={precision === \"second\" ? 1 : 60}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\t\tplaceholder={resolveText(placeholder)}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex-1 bg-transparent outline-none\",\n\t\t\t\t\t\t\"placeholder:text-muted-foreground\",\n\t\t\t\t\t\t\"disabled:cursor-not-allowed\",\n\t\t\t\t\t\t// Hide the native clock icon in some browsers\n\t\t\t\t\t\t\"[&::-webkit-calendar-picker-indicator]:hidden\",\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t\t{value && !disabled && (\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleClear}\n\t\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground\"\n\t\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\t>\n\t\t\t\t\t\t<X className=\"size-4\" />\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { Controller } from \"react-hook-form\";\nimport { TimeInput } from \"../primitives/time-input\";\nimport type { TimeFieldProps } from \"./field-types\";\nimport { useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\nexport function TimeField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n\tprecision,\n}: TimeFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => {\n\t\t\t\treturn (\n\t\t\t\t\t<FieldWrapper\n\t\t\t\t\t\tname={name}\n\t\t\t\t\t\tlabel={label}\n\t\t\t\t\t\tdescription={description}\n\t\t\t\t\t\trequired={required}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tlocalized={localized}\n\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TimeInput\n\t\t\t\t\t\t\tid={name}\n\t\t\t\t\t\t\tvalue={field.value ?? null}\n\t\t\t\t\t\t\tonChange={field.onChange}\n\t\t\t\t\t\t\tprecision={precision}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\taria-invalid={!!fieldState.error}\n\t\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FieldWrapper>\n\t\t\t\t);\n\t\t\t}}\n\t\t/>\n\t);\n}\n","/**\n * UploadField Component\n *\n * Single file upload field integrated with react-hook-form.\n * Value is the asset ID (like a relation field).\n *\n * @example\n * ```tsx\n * <UploadField\n * name=\"featuredImage\"\n * label=\"Featured Image\"\n * accept={[\"image/*\"]}\n * maxSize={5_000_000}\n * />\n * ```\n */\n\nimport { FolderOpen } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport {\n\tController,\n\ttype ControllerRenderProps,\n\ttype FieldValues,\n} from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { useCollectionItem } from \"../../hooks/use-collection\";\nimport { type Asset, useUpload } from \"../../hooks/use-upload\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { MediaPickerDialog } from \"../media/media-picker-dialog\";\nimport { AssetPreview } from \"../primitives/asset-preview\";\nimport { Dropzone } from \"../primitives/dropzone\";\nimport { ResourceSheet } from \"../sheets\";\nimport { Button } from \"../ui/button\";\nimport type { BaseFieldProps } from \"./field-types\";\nimport { sanitizeFilename, useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UploadFieldProps extends BaseFieldProps {\n\t/**\n\t * Target collection for uploads\n\t * @default \"assets\"\n\t */\n\tcollection?: string;\n\n\t/**\n\t * Accepted file types (MIME types or extensions)\n\t * @example [\"image/*\", \"application/pdf\"]\n\t */\n\taccept?: string[];\n\n\t/**\n\t * Maximum file size in bytes\n\t */\n\tmaxSize?: number;\n\n\t/**\n\t * Show image preview for uploaded files\n\t * @default true\n\t */\n\tshowPreview?: boolean;\n\n\t/**\n\t * Allow editing alt/caption (opens edit dialog)\n\t * @default true\n\t */\n\teditable?: boolean;\n\n\t/**\n\t * Preview variant\n\t * @default \"card\"\n\t */\n\tpreviewVariant?: \"card\" | \"compact\" | \"thumbnail\";\n\n\t/**\n\t * Callback when upload starts\n\t */\n\tonUploadStart?: () => void;\n\n\t/**\n\t * Callback when upload completes\n\t */\n\tonUploadComplete?: (asset: Asset) => void;\n\n\t/**\n\t * Callback when upload fails\n\t */\n\tonUploadError?: (error: Error) => void;\n}\n\n// ============================================================================\n// Inner Component (handles hooks properly)\n// ============================================================================\n\ninterface UploadFieldInnerProps {\n\tfield: ControllerRenderProps<FieldValues, string>;\n\terror?: string;\n\tcollection: string;\n\taccept?: string[];\n\tmaxSize?: number;\n\tshowPreview: boolean;\n\teditable: boolean;\n\tpreviewVariant: \"card\" | \"compact\" | \"thumbnail\";\n\tdisabled?: boolean;\n\tplaceholder?: string;\n\tonUploadStart?: () => void;\n\tonUploadComplete?: (asset: Asset) => void;\n\tonUploadError?: (error: Error) => void;\n\tclassName?: string;\n}\n\nfunction UploadFieldInner({\n\tfield,\n\terror,\n\tcollection,\n\taccept,\n\tmaxSize,\n\tshowPreview,\n\teditable,\n\tpreviewVariant,\n\tdisabled,\n\tplaceholder,\n\tonUploadStart,\n\tonUploadComplete,\n\tonUploadError,\n\tclassName,\n}: UploadFieldInnerProps) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst resolvedPlaceholder = placeholder\n\t\t? resolveText(placeholder)\n\t\t: undefined;\n\tconst { upload, isUploading, progress, error: uploadError } = useUpload();\n\tconst [isPickerOpen, setIsPickerOpen] = React.useState(false);\n\tconst [isEditSheetOpen, setIsEditSheetOpen] = React.useState(false);\n\n\t// The field value is an asset ID (string) or null\n\tconst assetId = field.value as string | null | undefined;\n\n\t// Fetch the asset data if we have an ID\n\tconst { data: asset, isLoading: isLoadingAsset } = useCollectionItem(\n\t\tcollection,\n\t\tassetId || \"\",\n\t\tundefined,\n\t\t{\n\t\t\tenabled: !!assetId && showPreview,\n\t\t},\n\t);\n\n\t/**\n\t * Handle file drop/selection\n\t */\n\tconst handleDrop = async (files: File[]) => {\n\t\tif (files.length === 0 || disabled) return;\n\n\t\tconst originalFile = files[0];\n\n\t\t// Sanitize filename\n\t\tconst sanitizedName = sanitizeFilename(originalFile.name);\n\t\tconst file = new File([originalFile], sanitizedName, {\n\t\t\ttype: originalFile.type,\n\t\t});\n\n\t\ttry {\n\t\t\tonUploadStart?.();\n\n\t\t\tconst uploadedAsset = await upload(file, {\n\t\t\t\tcollection,\n\t\t\t});\n\n\t\t\t// Set the asset ID as the field value\n\t\t\tfield.onChange(uploadedAsset.id);\n\t\t\tonUploadComplete?.(uploadedAsset);\n\t\t} catch (err) {\n\t\t\tconst uploadErr =\n\t\t\t\terr instanceof Error ? err : new Error(t(\"upload.error\"));\n\t\t\tonUploadError?.(uploadErr);\n\t\t\t// Only show toast, don't duplicate with inline error\n\t\t\ttoast.error(uploadErr.message);\n\t\t}\n\t};\n\n\t/**\n\t * Handle remove\n\t */\n\tconst handleRemove = () => {\n\t\tfield.onChange(null);\n\t};\n\n\t/**\n\t * Handle edit - opens ResourceSheet for the asset\n\t */\n\tconst handleEdit = () => {\n\t\tif (assetId) {\n\t\t\tsetIsEditSheetOpen(true);\n\t\t}\n\t};\n\n\t/**\n\t * Handle validation errors from dropzone\n\t */\n\tconst handleValidationError = (errors: { message: string }[]) => {\n\t\tfor (const validationError of errors) {\n\t\t\ttoast.error(validationError.message);\n\t\t}\n\t};\n\n\t// Build hint text\n\tconst hintText = React.useMemo(() => {\n\t\tconst parts: string[] = [];\n\t\tif (accept?.length) {\n\t\t\tconst types = accept\n\t\t\t\t.map((t) => {\n\t\t\t\t\tif (t.startsWith(\"image/\")) return \"Images\";\n\t\t\t\t\tif (t.startsWith(\"video/\")) return \"Videos\";\n\t\t\t\t\tif (t.startsWith(\"audio/\")) return \"Audio\";\n\t\t\t\t\tif (t === \"application/pdf\") return \"PDF\";\n\t\t\t\t\treturn t;\n\t\t\t\t})\n\t\t\t\t.filter((v, i, a) => a.indexOf(v) === i);\n\t\t\tparts.push(types.join(\", \"));\n\t\t}\n\t\tif (maxSize) {\n\t\t\tconst mb = (maxSize / (1024 * 1024)).toFixed(0);\n\t\t\tparts.push(`Max ${mb}MB`);\n\t\t}\n\t\treturn parts.join(\" • \") || undefined;\n\t}, [accept, maxSize]);\n\n\tconst hasValue = !!assetId;\n\tconst isLoading = isUploading || (hasValue && isLoadingAsset);\n\n\t/**\n\t * Handle asset selection from media picker\n\t */\n\tconst handlePickerSelect = (id: string | string[]) => {\n\t\tif (typeof id === \"string\") {\n\t\t\tfield.onChange(id);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{/* Show preview if we have an asset */}\n\t\t\t{hasValue && showPreview && asset ? (\n\t\t\t\t<AssetPreview\n\t\t\t\t\tasset={asset as Asset}\n\t\t\t\t\tloading={isLoading}\n\t\t\t\t\tprogress={isUploading ? progress : undefined}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tvariant={previewVariant}\n\t\t\t\t\tonRemove={disabled ? undefined : handleRemove}\n\t\t\t\t\tonEdit={editable && !disabled ? handleEdit : undefined}\n\t\t\t\t/>\n\t\t\t) : hasValue && showPreview && isLoadingAsset ? (\n\t\t\t\t// Loading state while fetching asset\n\t\t\t\t<AssetPreview\n\t\t\t\t\tasset={{ id: assetId }}\n\t\t\t\t\tloading={true}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tvariant={previewVariant}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t// Show dropzone for empty state or when uploading\n\t\t\t\t<Dropzone\n\t\t\t\t\tonDrop={handleDrop}\n\t\t\t\t\taccept={accept}\n\t\t\t\t\tmaxSize={maxSize}\n\t\t\t\t\tmultiple={false}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tloading={isUploading}\n\t\t\t\t\tprogress={isUploading ? progress : undefined}\n\t\t\t\t\tlabel={resolvedPlaceholder || \"Drop file here or click to browse\"}\n\t\t\t\t\thint={hintText}\n\t\t\t\t\tonValidationError={handleValidationError}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Browse Library Button */}\n\t\t\t{!hasValue && !isUploading && !disabled && (\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tonClick={() => setIsPickerOpen(true)}\n\t\t\t\t\tclassName=\"mt-2 w-full\"\n\t\t\t\t>\n\t\t\t\t\t<FolderOpen weight=\"bold\" className=\"mr-2 size-4\" />\n\t\t\t\t\tBrowse Library\n\t\t\t\t</Button>\n\t\t\t)}\n\n\t\t\t{/* Media Picker Dialog */}\n\t\t\t<MediaPickerDialog\n\t\t\t\topen={isPickerOpen}\n\t\t\t\tonOpenChange={setIsPickerOpen}\n\t\t\t\tmode=\"single\"\n\t\t\t\taccept={accept}\n\t\t\t\tonSelect={handlePickerSelect}\n\t\t\t\tcollection={collection}\n\t\t\t/>\n\n\t\t\t{/* Edit Sheet */}\n\t\t\t{assetId && (\n\t\t\t\t<ResourceSheet\n\t\t\t\t\ttype=\"collection\"\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\titemId={assetId}\n\t\t\t\t\topen={isEditSheetOpen}\n\t\t\t\t\tonOpenChange={setIsEditSheetOpen}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Show field validation error (upload errors shown via toast) */}\n\t\t\t{error && <p className=\"text-destructive mt-1 text-xs\">{error}</p>}\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function UploadField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n\tcollection = \"assets\",\n\taccept,\n\tmaxSize,\n\tshowPreview = true,\n\teditable = true,\n\tpreviewVariant = \"card\",\n\tonUploadStart,\n\tonUploadComplete,\n\tonUploadError,\n}: UploadFieldProps) {\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => (\n\t\t\t\t<FieldWrapper\n\t\t\t\t\tname={name}\n\t\t\t\t\tlabel={label}\n\t\t\t\t\tdescription={description}\n\t\t\t\t\trequired={required}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tlocalized={localized}\n\t\t\t\t\tlocale={locale}\n\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t>\n\t\t\t\t\t<UploadFieldInner\n\t\t\t\t\t\tfield={field}\n\t\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t\t\tcollection={collection}\n\t\t\t\t\t\taccept={accept}\n\t\t\t\t\t\tmaxSize={maxSize}\n\t\t\t\t\t\tshowPreview={showPreview}\n\t\t\t\t\t\teditable={editable}\n\t\t\t\t\t\tpreviewVariant={previewVariant}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tonUploadStart={onUploadStart}\n\t\t\t\t\t\tonUploadComplete={onUploadComplete}\n\t\t\t\t\t\tonUploadError={onUploadError}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t/>\n\t\t\t\t</FieldWrapper>\n\t\t\t)}\n\t\t/>\n\t);\n}\n","/**\n * UploadManyField Component\n *\n * Multiple file upload field integrated with react-hook-form.\n * Value is an array of asset IDs (like a relation field).\n * Supports drag-and-drop reordering.\n *\n * @example\n * ```tsx\n * <UploadManyField\n * name=\"gallery\"\n * label=\"Gallery\"\n * accept={[\"image/*\"]}\n * maxItems={10}\n * orderable\n * />\n * ```\n */\n\nimport {\n\tclosestCenter,\n\tDndContext,\n\ttype DragEndEvent,\n\tKeyboardSensor,\n\tPointerSensor,\n\tuseSensor,\n\tuseSensors,\n} from \"@dnd-kit/core\";\nimport {\n\tarrayMove,\n\trectSortingStrategy,\n\tSortableContext,\n\tsortableKeyboardCoordinates,\n\tuseSortable,\n\tverticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { FolderOpen } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport {\n\tController,\n\ttype ControllerRenderProps,\n\ttype FieldValues,\n} from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { type Asset, useUpload } from \"../../hooks/use-upload\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { selectClient, useAdminStore } from \"../../runtime\";\nimport { MediaPickerDialog } from \"../media/media-picker-dialog\";\nimport { AssetPreview } from \"../primitives/asset-preview\";\nimport { Dropzone } from \"../primitives/dropzone\";\nimport { ResourceSheet } from \"../sheets\";\nimport { Button } from \"../ui/button\";\nimport type { BaseFieldProps } from \"./field-types\";\nimport { sanitizeFilename, useResolvedControl } from \"./field-utils\";\nimport { FieldWrapper } from \"./field-wrapper\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UploadManyFieldProps extends BaseFieldProps {\n\t/**\n\t * Target collection for uploads\n\t * @default \"assets\"\n\t */\n\tcollection?: string;\n\n\t/**\n\t * Accepted file types (MIME types or extensions)\n\t * @example [\"image/*\", \"application/pdf\"]\n\t */\n\taccept?: string[];\n\n\t/**\n\t * Maximum file size in bytes\n\t */\n\tmaxSize?: number;\n\n\t/**\n\t * Maximum number of files\n\t */\n\tmaxItems?: number;\n\n\t/**\n\t * Enable drag-and-drop reordering\n\t * @default false\n\t */\n\torderable?: boolean;\n\n\t/**\n\t * Layout for previews\n\t * @default \"grid\"\n\t */\n\tlayout?: \"grid\" | \"list\";\n\n\t/**\n\t * Allow editing alt/caption (opens edit dialog)\n\t * @default true\n\t */\n\teditable?: boolean;\n\n\t/**\n\t * Callback when upload starts\n\t */\n\tonUploadStart?: () => void;\n\n\t/**\n\t * Callback when upload completes\n\t */\n\tonUploadComplete?: (assets: Asset[]) => void;\n\n\t/**\n\t * Callback when upload fails\n\t */\n\tonUploadError?: (error: Error) => void;\n}\n\n// ============================================================================\n// Sortable Item Component\n// ============================================================================\n\ninterface SortableAssetItemProps {\n\tid: string;\n\tasset: Asset | null;\n\tloading?: boolean;\n\tprogress?: number;\n\tdisabled?: boolean;\n\tvariant: \"compact\" | \"thumbnail\";\n\torderable?: boolean;\n\teditable?: boolean;\n\thref?: string;\n\tonRemove?: () => void;\n\tonEdit?: () => void;\n}\n\nfunction SortableAssetItem({\n\tid,\n\tasset,\n\tloading,\n\tprogress,\n\tdisabled,\n\tvariant,\n\torderable,\n\teditable,\n\thref,\n\tonRemove,\n\tonEdit,\n}: SortableAssetItemProps) {\n\tconst {\n\t\tattributes,\n\t\tlisteners,\n\t\tsetNodeRef,\n\t\ttransform,\n\t\ttransition,\n\t\tisDragging,\n\t} = useSortable({ id });\n\n\tconst style = {\n\t\ttransform: CSS.Transform.toString(transform),\n\t\ttransition,\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tref={setNodeRef}\n\t\t\tstyle={style}\n\t\t\tclassName={isDragging ? \"opacity-50\" : \"\"}\n\t\t>\n\t\t\t<AssetPreview\n\t\t\t\tasset={asset || { id }}\n\t\t\t\tloading={loading}\n\t\t\t\tprogress={progress}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tvariant={variant}\n\t\t\t\tshowDragHandle={orderable && !disabled}\n\t\t\t\tdragHandleProps={\n\t\t\t\t\torderable ? { ...attributes, ...listeners } : undefined\n\t\t\t\t}\n\t\t\t\thref={href}\n\t\t\t\tonRemove={disabled ? undefined : onRemove}\n\t\t\t\tonEdit={editable && !disabled ? onEdit : undefined}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Inner Component (handles hooks properly)\n// ============================================================================\n\ninterface UploadManyFieldInnerProps {\n\tfield: ControllerRenderProps<FieldValues, string>;\n\terror?: string;\n\tcollection: string;\n\taccept?: string[];\n\tmaxSize?: number;\n\tmaxItems?: number;\n\torderable: boolean;\n\tlayout: \"grid\" | \"list\";\n\teditable: boolean;\n\tdisabled?: boolean;\n\tplaceholder?: string;\n\tonUploadStart?: () => void;\n\tonUploadComplete?: (assets: Asset[]) => void;\n\tonUploadError?: (error: Error) => void;\n\tclassName?: string;\n}\n\nfunction UploadManyFieldInner({\n\tfield,\n\tcollection,\n\taccept,\n\tmaxSize,\n\tmaxItems,\n\torderable,\n\tlayout,\n\teditable,\n\tdisabled,\n\tplaceholder,\n\tonUploadStart,\n\tonUploadComplete,\n\tonUploadError,\n\tclassName,\n}: UploadManyFieldInnerProps) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst resolvedPlaceholder = placeholder\n\t\t? resolveText(placeholder)\n\t\t: undefined;\n\tconst { uploadMany, isUploading, progress } = useUpload();\n\tconst client = useAdminStore(selectClient);\n\tconst [isPickerOpen, setIsPickerOpen] = React.useState(false);\n\tconst [editAssetId, setEditAssetId] = React.useState<string | null>(null);\n\n\t// Track pending uploads (files being uploaded)\n\tconst [pendingUploads, setPendingUploads] = React.useState<\n\t\t{ id: string; file: File }[]\n\t>([]);\n\n\t// Track fetched assets (lazy init to avoid creating Map on every render)\n\tconst [fetchedAssets, setFetchedAssets] = React.useState<Map<string, Asset>>(\n\t\t() => new Map(),\n\t);\n\n\t// DnD sensors\n\tconst sensors = useSensors(\n\t\tuseSensor(PointerSensor),\n\t\tuseSensor(KeyboardSensor, {\n\t\t\tcoordinateGetter: sortableKeyboardCoordinates,\n\t\t}),\n\t);\n\n\t// The field value is an array of asset IDs\n\tconst assetIds = (field.value as string[] | null | undefined) || [];\n\n\t// Fetch assets that we don't have yet\n\tReact.useEffect(() => {\n\t\tif (!client || assetIds.length === 0) return;\n\n\t\tconst missingIds = assetIds.filter((id) => !fetchedAssets.has(id));\n\t\tif (missingIds.length === 0) return;\n\n\t\tlet cancelled = false;\n\n\t\t(async () => {\n\t\t\tfor (const id of missingIds) {\n\t\t\t\tif (cancelled) return;\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await (client as any).collections[\n\t\t\t\t\t\tcollection\n\t\t\t\t\t].findOne({ where: { id } });\n\t\t\t\t\tif (!cancelled && response) {\n\t\t\t\t\t\tsetFetchedAssets((prev) =>\n\t\t\t\t\t\t\tnew Map(prev).set(id, response as Asset),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} catch (fetchError) {\n\t\t\t\t\tif (!cancelled) {\n\t\t\t\t\t\tconsole.error(\"Failed to fetch asset:\", fetchError);\n\t\t\t\t\t\ttoast.error(\"Failed to load asset\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [assetIds, collection, fetchedAssets, client]);\n\n\t/**\n\t * Handle file drop/selection\n\t */\n\tconst handleDrop = async (files: File[]) => {\n\t\tif (files.length === 0 || disabled) return;\n\n\t\t// Check max items\n\t\tconst remainingSlots = maxItems ? maxItems - assetIds.length : files.length;\n\t\tconst filesToUpload = files.slice(0, remainingSlots);\n\n\t\tif (filesToUpload.length < files.length) {\n\t\t\ttoast.warning(\n\t\t\t\tt(\"toast.maxFilesWarning\", {\n\t\t\t\t\tremaining: remainingSlots,\n\t\t\t\t\tmax: maxItems,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tif (filesToUpload.length === 0) return;\n\n\t\t// Sanitize filenames\n\t\tconst sanitizedFiles = filesToUpload.map((file) => {\n\t\t\tconst sanitizedName = sanitizeFilename(file.name);\n\t\t\treturn new File([file], sanitizedName, { type: file.type });\n\t\t});\n\n\t\t// Create pending upload entries with temporary IDs\n\t\tconst pending = sanitizedFiles.map((file, index) => ({\n\t\t\tid: `pending-${Date.now()}-${index}`,\n\t\t\tfile,\n\t\t}));\n\t\tsetPendingUploads(pending);\n\n\t\ttry {\n\t\t\tonUploadStart?.();\n\n\t\t\tconst uploadedAssets = await uploadMany(sanitizedFiles, {\n\t\t\t\tcollection,\n\t\t\t});\n\n\t\t\t// Add uploaded asset IDs to field value\n\t\t\tconst newIds = uploadedAssets.map((a) => a.id);\n\t\t\tfield.onChange([...assetIds, ...newIds]);\n\n\t\t\t// Add to fetched assets cache\n\t\t\tfor (const asset of uploadedAssets) {\n\t\t\t\tsetFetchedAssets((prev) => new Map(prev).set(asset.id, asset));\n\t\t\t}\n\n\t\t\tonUploadComplete?.(uploadedAssets);\n\t\t} catch (err) {\n\t\t\tconst uploadError =\n\t\t\t\terr instanceof Error ? err : new Error(t(\"upload.error\"));\n\t\t\tonUploadError?.(uploadError);\n\t\t\ttoast.error(uploadError.message);\n\t\t} finally {\n\t\t\tsetPendingUploads([]);\n\t\t}\n\t};\n\n\t/**\n\t * Handle remove\n\t */\n\tconst handleRemove = (idToRemove: string) => {\n\t\tfield.onChange(assetIds.filter((id) => id !== idToRemove));\n\t};\n\n\t/**\n\t * Handle edit - opens ResourceSheet for the asset\n\t */\n\tconst handleEdit = (id: string) => {\n\t\tsetEditAssetId(id);\n\t};\n\n\t/**\n\t * Handle drag end for reordering\n\t */\n\tconst handleDragEnd = (event: DragEndEvent) => {\n\t\tconst { active, over } = event;\n\n\t\tif (over && active.id !== over.id) {\n\t\t\tconst oldIndex = assetIds.indexOf(active.id as string);\n\t\t\tconst newIndex = assetIds.indexOf(over.id as string);\n\n\t\t\tif (oldIndex !== -1 && newIndex !== -1) {\n\t\t\t\tconst reordered = arrayMove(assetIds, oldIndex, newIndex);\n\t\t\t\tfield.onChange(reordered);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Handle validation errors from dropzone\n\t */\n\tconst handleValidationError = (errors: { message: string }[]) => {\n\t\tfor (const validationError of errors) {\n\t\t\ttoast.error(validationError.message);\n\t\t}\n\t};\n\n\t/**\n\t * Handle asset selection from media picker\n\t */\n\tconst handlePickerSelect = (ids: string | string[]) => {\n\t\tconst newIds = Array.isArray(ids) ? ids : [ids];\n\n\t\t// Check max items\n\t\tconst totalAfterAdd = assetIds.length + newIds.length;\n\t\tif (maxItems && totalAfterAdd > maxItems) {\n\t\t\ttoast.warning(`Maximum ${maxItems} items allowed`);\n\t\t\t// Add only what fits\n\t\t\tconst remainingSlots = maxItems - assetIds.length;\n\t\t\tconst idsToAdd = newIds.slice(0, remainingSlots);\n\t\t\tfield.onChange([...assetIds, ...idsToAdd]);\n\t\t} else {\n\t\t\tfield.onChange([...assetIds, ...newIds]);\n\t\t}\n\t};\n\n\t// Build hint text\n\tconst hintText = React.useMemo(() => {\n\t\tconst parts: string[] = [];\n\t\tif (accept?.length) {\n\t\t\tconst types = accept\n\t\t\t\t.map((t) => {\n\t\t\t\t\tif (t.startsWith(\"image/\")) return \"Images\";\n\t\t\t\t\tif (t.startsWith(\"video/\")) return \"Videos\";\n\t\t\t\t\tif (t.startsWith(\"audio/\")) return \"Audio\";\n\t\t\t\t\tif (t === \"application/pdf\") return \"PDF\";\n\t\t\t\t\treturn t;\n\t\t\t\t})\n\t\t\t\t.filter((v, i, a) => a.indexOf(v) === i);\n\t\t\tparts.push(types.join(\", \"));\n\t\t}\n\t\tif (maxSize) {\n\t\t\tconst mb = (maxSize / (1024 * 1024)).toFixed(0);\n\t\t\tparts.push(`Max ${mb}MB`);\n\t\t}\n\t\treturn parts.join(\" • \") || undefined;\n\t}, [accept, maxSize]);\n\n\tconst hasItems = assetIds.length > 0 || pendingUploads.length > 0;\n\tconst canAddMore = !maxItems || assetIds.length < maxItems;\n\tconst previewVariant = layout === \"grid\" ? \"thumbnail\" : \"compact\";\n\tconst sortingStrategy =\n\t\tlayout === \"grid\" ? rectSortingStrategy : verticalListSortingStrategy;\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{/* Items Grid/List with DnD */}\n\t\t\t{hasItems && (\n\t\t\t\t<DndContext\n\t\t\t\t\tsensors={sensors}\n\t\t\t\t\tcollisionDetection={closestCenter}\n\t\t\t\t\tonDragEnd={handleDragEnd}\n\t\t\t\t>\n\t\t\t\t\t<SortableContext\n\t\t\t\t\t\titems={assetIds}\n\t\t\t\t\t\tstrategy={sortingStrategy}\n\t\t\t\t\t\tdisabled={!orderable}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\tlayout === \"grid\"\n\t\t\t\t\t\t\t\t\t? \"mb-3 grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4\"\n\t\t\t\t\t\t\t\t\t: \"mb-3 space-y-2\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{/* Existing assets */}\n\t\t\t\t\t\t\t{assetIds.map((id) => (\n\t\t\t\t\t\t\t\t<SortableAssetItem\n\t\t\t\t\t\t\t\t\tkey={id}\n\t\t\t\t\t\t\t\t\tid={id}\n\t\t\t\t\t\t\t\t\tasset={fetchedAssets.get(id) || null}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\tvariant={previewVariant}\n\t\t\t\t\t\t\t\t\torderable={orderable}\n\t\t\t\t\t\t\t\t\teditable={editable}\n\t\t\t\t\t\t\t\t\tonRemove={() => handleRemove(id)}\n\t\t\t\t\t\t\t\t\tonEdit={() => handleEdit(id)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t\t{/* Pending uploads */}\n\t\t\t\t\t\t\t{pendingUploads.map((pending, index) => (\n\t\t\t\t\t\t\t\t<div key={pending.id}>\n\t\t\t\t\t\t\t\t\t<AssetPreview\n\t\t\t\t\t\t\t\t\t\tasset={{ filename: pending.file.name }}\n\t\t\t\t\t\t\t\t\t\tpendingFile={pending.file}\n\t\t\t\t\t\t\t\t\t\tloading={true}\n\t\t\t\t\t\t\t\t\t\tprogress={\n\t\t\t\t\t\t\t\t\t\t\t// Distribute overall progress among pending files\n\t\t\t\t\t\t\t\t\t\t\tMath.min(\n\t\t\t\t\t\t\t\t\t\t\t\t100,\n\t\t\t\t\t\t\t\t\t\t\t\tMath.max(\n\t\t\t\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprogress - (index / pendingUploads.length) * 100,\n\t\t\t\t\t\t\t\t\t\t\t\t) *\n\t\t\t\t\t\t\t\t\t\t\t\t\t(pendingUploads.length /\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(pendingUploads.length - index)),\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t\t\t\t\t\tvariant={previewVariant}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</SortableContext>\n\t\t\t\t</DndContext>\n\t\t\t)}\n\n\t\t\t{/* Dropzone for adding more */}\n\t\t\t{canAddMore && !isUploading && (\n\t\t\t\t<Dropzone\n\t\t\t\t\tonDrop={handleDrop}\n\t\t\t\t\taccept={accept}\n\t\t\t\t\tmaxSize={maxSize}\n\t\t\t\t\tmultiple={true}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tloading={isUploading}\n\t\t\t\t\tprogress={isUploading ? progress : undefined}\n\t\t\t\t\tlabel={\n\t\t\t\t\t\thasItems\n\t\t\t\t\t\t\t? \"Drop more files or click to add\"\n\t\t\t\t\t\t\t: resolvedPlaceholder || \"Drop files here or click to browse\"\n\t\t\t\t\t}\n\t\t\t\t\thint={hintText}\n\t\t\t\t\tonValidationError={handleValidationError}\n\t\t\t\t\tclassName={hasItems ? \"min-h-[80px]\" : undefined}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Browse Library Button */}\n\t\t\t{canAddMore && !isUploading && !disabled && (\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tonClick={() => setIsPickerOpen(true)}\n\t\t\t\t\tclassName=\"mt-2 w-full\"\n\t\t\t\t>\n\t\t\t\t\t<FolderOpen weight=\"bold\" className=\"mr-2 size-4\" />\n\t\t\t\t\tBrowse Library\n\t\t\t\t</Button>\n\t\t\t)}\n\n\t\t\t{/* Media Picker Dialog */}\n\t\t\t<MediaPickerDialog\n\t\t\t\topen={isPickerOpen}\n\t\t\t\tonOpenChange={setIsPickerOpen}\n\t\t\t\tmode=\"multiple\"\n\t\t\t\taccept={accept}\n\t\t\t\tonSelect={handlePickerSelect}\n\t\t\t\tmaxItems={maxItems ? maxItems - assetIds.length : undefined}\n\t\t\t\tcollection={collection}\n\t\t\t/>\n\n\t\t\t{/* Edit Sheet */}\n\t\t\t{editAssetId && (\n\t\t\t\t<ResourceSheet\n\t\t\t\t\ttype=\"collection\"\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\titemId={editAssetId}\n\t\t\t\t\topen={!!editAssetId}\n\t\t\t\t\tonOpenChange={(open: boolean) => !open && setEditAssetId(null)}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{/* Uploading state */}\n\t\t\t{isUploading && !canAddMore && (\n\t\t\t\t<div className=\"text-muted-foreground flex items-center justify-center gap-2 rounded-lg border border-dashed p-4 text-sm\">\n\t\t\t\t\tUploading... {progress}%\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function UploadManyField({\n\tname,\n\tlabel,\n\tdescription,\n\tplaceholder,\n\trequired,\n\tdisabled,\n\tlocalized,\n\tlocale,\n\tcontrol,\n\tclassName,\n\tcollection = \"assets\",\n\taccept,\n\tmaxSize,\n\tmaxItems,\n\torderable = false,\n\tlayout = \"grid\",\n\teditable = true,\n\tonUploadStart,\n\tonUploadComplete,\n\tonUploadError,\n}: UploadManyFieldProps) {\n\tconst resolveText = useResolveText();\n\tconst resolvedControl = useResolvedControl(control);\n\n\treturn (\n\t\t<Controller\n\t\t\tname={name}\n\t\t\tcontrol={resolvedControl}\n\t\t\trender={({ field, fieldState }) => {\n\t\t\t\tconst assetIds = (field.value as string[] | null | undefined) || [];\n\n\t\t\t\treturn (\n\t\t\t\t\t<FieldWrapper\n\t\t\t\t\t\tname={name}\n\t\t\t\t\t\tlabel={\n\t\t\t\t\t\t\tlabel\n\t\t\t\t\t\t\t\t? `${resolveText(label)}${\n\t\t\t\t\t\t\t\t\t\tmaxItems ? ` (${assetIds.length}/${maxItems})` : \"\"\n\t\t\t\t\t\t\t\t\t}`\n\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdescription={description}\n\t\t\t\t\t\trequired={required}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tlocalized={localized}\n\t\t\t\t\t\tlocale={locale}\n\t\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t\t>\n\t\t\t\t\t\t<UploadManyFieldInner\n\t\t\t\t\t\t\tfield={field}\n\t\t\t\t\t\t\terror={fieldState.error?.message}\n\t\t\t\t\t\t\tcollection={collection}\n\t\t\t\t\t\t\taccept={accept}\n\t\t\t\t\t\t\tmaxSize={maxSize}\n\t\t\t\t\t\t\tmaxItems={maxItems}\n\t\t\t\t\t\t\torderable={orderable}\n\t\t\t\t\t\t\tlayout={layout}\n\t\t\t\t\t\t\teditable={editable}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\tonUploadStart={onUploadStart}\n\t\t\t\t\t\t\tonUploadComplete={onUploadComplete}\n\t\t\t\t\t\t\tonUploadError={onUploadError}\n\t\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</FieldWrapper>\n\t\t\t\t);\n\t\t\t}}\n\t\t/>\n\t);\n}\n","/**\n * Field Builder\n *\n * Defines reusable field types with form and cell components.\n */\n\nimport type React from \"react\";\nimport type { z } from \"zod\";\nimport type {\n\tBaseFieldConfigProps,\n\tBaseFieldProps,\n\tMaybeLazyComponent,\n} from \"../types/common\";\nimport type { FieldHookContext, SelectOption } from \"../types/field-types\";\n\n// ============================================================================\n// Zod Schema Building Context\n// ============================================================================\n\n/**\n * Context provided to createZod callbacks for building nested schemas\n */\nexport interface ZodBuildContext {\n\t/**\n\t * Recursively builds a Zod schema for any field definition.\n\t * Use this for nested fields in object/array types.\n\t */\n\tbuildSchema: (fieldDef: FieldDefinition) => z.ZodTypeAny;\n\n\t/**\n\t * Field registry for resolving nested fields callbacks.\n\t * Used to create the `r` proxy in `fields: ({ r }) => ({...})`\n\t */\n\tregistry: Record<string, FieldBuilder<any>>;\n}\n\n/**\n * Function type for creating Zod schema from field options\n */\nexport type CreateZodFn<TOptions = any> = (\n\topts: TOptions,\n\tctx: ZodBuildContext,\n) => z.ZodTypeAny;\n\n/**\n * Field state options (readOnly, disabled, hidden)\n */\nexport interface FieldStateOptions {\n\t/**\n\t * Whether field is read-only (can be dynamic based on form values).\n\t * Read-only fields look normal but cannot be edited.\n\t * Note: Fields with `compute` are automatically read-only.\n\t */\n\treadOnly?: boolean | ((values: Record<string, any>) => boolean);\n\n\t/**\n\t * Whether field is disabled (can be dynamic based on form values).\n\t * Disabled fields appear grayed out and cannot be edited.\n\t */\n\tdisabled?: boolean | ((values: Record<string, any>) => boolean);\n\n\t/**\n\t * Whether field is hidden (can be dynamic based on form values).\n\t * Hidden fields are not rendered. Default is false (visible).\n\t *\n\t * Note: undefined/false = visible, true = hidden\n\t * This follows JavaScript falsy semantics for better DX.\n\t */\n\thidden?: boolean | ((values: Record<string, any>) => boolean);\n}\n\n/**\n * Hook options for field interactivity\n */\nexport interface FieldHookOptions {\n\t/**\n\t * Compute field value from other fields (proxy-tracked dependencies).\n\t * Makes the field read-only and virtual (not submitted to backend).\n\t *\n\t * Dependencies are automatically detected via Proxy tracking.\n\t * Works in both forms (reactive) and tables (static).\n\t *\n\t * @example\n\t * ```ts\n\t * pricePerMinute: r.number({\n\t * compute: (values) => values.price / values.duration,\n\t * })\n\t * ```\n\t */\n\tcompute?: (values: Record<string, any>) => any;\n\n\t/**\n\t * Called when field value changes.\n\t * Use for side effects like updating other fields.\n\t * Can be async for API calls.\n\t *\n\t * @example\n\t * ```ts\n\t * name: r.text({\n\t * onChange: (value, { setValue }) => {\n\t * setValue('slug', slugify(value));\n\t * },\n\t * })\n\t * ```\n\t */\n\tonChange?: (value: any, ctx: FieldHookContext) => void | Promise<void>;\n\n\t/**\n\t * Dynamic default value for new records.\n\t * Can be a static value, sync function, or async function.\n\t * Only evaluated when creating new records (not on edit).\n\t *\n\t * @example\n\t * ```ts\n\t * status: r.select({\n\t * defaultValue: 'draft',\n\t * // or dynamic:\n\t * defaultValue: async () => fetchDefaultStatus(),\n\t * })\n\t * ```\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 for select-type fields.\n\t * Dependencies are automatically detected via Proxy tracking.\n\t *\n\t * @example\n\t * ```ts\n\t * subcategory: r.select({\n\t * loadOptions: async (values) => {\n\t * // Automatically re-fetches when values.category changes\n\t * return fetchSubcategories(values.category);\n\t * },\n\t * })\n\t * ```\n\t */\n\tloadOptions?: (values: Record<string, any>) => Promise<SelectOption[]>;\n}\n\n/**\n * UI options that can be set when defining a field in a collection.\n * These are the \"soft\" options from BaseFieldProps that make sense in config.\n */\nexport type FieldUIOptions = Partial<\n\tPick<\n\t\tBaseFieldConfigProps,\n\t\t\"label\" | \"description\" | \"placeholder\" | \"required\"\n\t> &\n\t\tPick<BaseFieldProps, \"localized\">\n> &\n\tFieldStateOptions &\n\tFieldHookOptions;\n\n/**\n * Field definition - stored in admin registry\n */\nexport interface FieldDefinition<\n\tTName extends string = string,\n\tTOptions = any,\n> {\n\treadonly name: TName;\n\treadonly \"~options\": TOptions;\n\tfield: { component: MaybeLazyComponent };\n\tcell?: { component: MaybeLazyComponent };\n\t/**\n\t * Creates a Zod schema from field options.\n\t * If not provided, a generic schema based on field type will be used.\n\t */\n\tcreateZod?: CreateZodFn<TOptions>;\n}\n\n/**\n * Field builder state\n */\nexport interface FieldBuilderState {\n\treadonly name: string;\n\treadonly \"~options\": any;\n\treadonly component: MaybeLazyComponent;\n\treadonly cellComponent?: MaybeLazyComponent;\n\treadonly createZod?: CreateZodFn;\n}\n\n/**\n * Field builder class\n *\n * Also implements FieldDefinition interface so it can be used directly in registries.\n */\nexport class FieldBuilder<TState extends FieldBuilderState>\n\timplements FieldDefinition<TState[\"name\"], TState[\"~options\"]>\n{\n\tconstructor(public readonly state: TState) {}\n\n\t// Implement FieldDefinition interface via getters\n\tget name(): TState[\"name\"] {\n\t\treturn this.state.name;\n\t}\n\n\tget \"~options\"(): TState[\"~options\"] {\n\t\treturn this.state[\"~options\"];\n\t}\n\n\tget field() {\n\t\treturn { component: this.state.component };\n\t}\n\n\tget cell() {\n\t\treturn this.state.cellComponent\n\t\t\t? { component: this.state.cellComponent }\n\t\t\t: undefined;\n\t}\n\n\tget createZod(): CreateZodFn<TState[\"~options\"]> | undefined {\n\t\treturn this.state.createZod;\n\t}\n\n\t/**\n\t * Override options - returns new builder with updated state\n\t */\n\t$options<TNewOptions>(\n\t\toptions: TNewOptions,\n\t): FieldBuilder<Omit<TState, \"~options\"> & { \"~options\": TNewOptions }> {\n\t\treturn new FieldBuilder({\n\t\t\t...this.state,\n\t\t\t\"~options\": options,\n\t\t} as any);\n\t}\n\n\t/**\n\t * Set cell component for table views\n\t */\n\twithCell<TNewCellComponent extends MaybeLazyComponent>(\n\t\tcomponent: TNewCellComponent,\n\t): FieldBuilder<\n\t\tOmit<TState, \"cellComponent\"> & { cellComponent: TNewCellComponent }\n\t> {\n\t\treturn new FieldBuilder({\n\t\t\t...this.state,\n\t\t\tcellComponent: component,\n\t\t} as any);\n\t}\n}\n\n/**\n * Inferred options type for a field\n */\ntype InferFieldOptions<\n\tTConfig extends Record<string, any>,\n\tTComponent extends MaybeLazyComponent,\n> = [TConfig] extends [Record<string, never>]\n\t? ExtractComponentOptions<TComponent>\n\t: TConfig & FieldUIOptions;\n\n/**\n * Create a field definition\n *\n * @param name - Field type name (e.g. \"text\", \"relation\")\n * @param config - Component and optional config type\n *\n * @example\n * ```ts\n * // With explicit config type and createZod\n * const relationField = field(\"relation\", {\n * component: RelationField,\n * config: {} as RelationFieldConfig,\n * createZod: (opts, ctx) => z.string(),\n * });\n *\n * // Without config (infers from component props)\n * const textField = field(\"text\", {\n * component: TextField,\n * createZod: (opts) => {\n * let schema = z.string();\n * if (opts.maxLength) schema = schema.max(opts.maxLength);\n * return opts.required ? schema : schema.optional().nullable();\n * },\n * });\n * ```\n */\nexport function field<\n\tTName extends string,\n\tTConfig extends Record<string, any> = Record<string, never>,\n\tTComponent extends MaybeLazyComponent = MaybeLazyComponent,\n\tTCellComponent extends MaybeLazyComponent | undefined = undefined,\n>(\n\tname: TName,\n\toptions: {\n\t\tcomponent: TComponent;\n\t\tcell?: TCellComponent;\n\t\tconfig?: TConfig;\n\t\t/**\n\t\t * Creates a Zod schema from field options.\n\t\t * Called during form validation schema generation.\n\t\t */\n\t\tcreateZod?: CreateZodFn<InferFieldOptions<TConfig, TComponent>>;\n\t},\n): FieldBuilder<{\n\tname: TName;\n\t\"~options\": InferFieldOptions<TConfig, TComponent>;\n\tcomponent: TComponent;\n\tcellComponent: TCellComponent;\n\tcreateZod: typeof options.createZod;\n}> {\n\treturn new FieldBuilder({\n\t\tname,\n\t\t\"~options\": {} as any,\n\t\tcomponent: options.component,\n\t\tcellComponent: options.cell,\n\t\tcreateZod: options.createZod,\n\t} as any);\n}\n\n/**\n * Extract field-specific options from component props.\n * Omits BaseFieldProps to get only field-specific config.\n */\ntype ExtractComponentOptions<TComponent> =\n\tTComponent extends React.ComponentType<infer TProps>\n\t\t? Omit<TProps, keyof BaseFieldProps> & FieldUIOptions\n\t\t: Record<string, never>;\n","/**\n * Built-in Field Definitions\n *\n * Using field builder to create all default fields.\n * Each field has explicit config type for proper autocomplete.\n * Each field includes createZod for automatic validation schema generation.\n */\n\nimport { z } from \"zod\";\nimport type { AssetPreviewFieldProps } from \"../../components/fields/asset-preview-field.js\";\nimport type { BlocksFieldConfig } from \"../../components/fields/blocks-field/index.js\";\nimport type {\n\tArrayFieldConfig,\n\tBooleanFieldConfig,\n\tDateFieldConfig,\n\tDateTimeFieldConfig,\n\tEmbeddedFieldConfig,\n\tJsonFieldConfig,\n\tNumberFieldConfig,\n\tObjectFieldConfig,\n\tRelationFieldConfig,\n\tReverseRelationFieldConfig,\n\tRichTextFieldConfig,\n\tSelectFieldConfig,\n\tTextareaFieldConfig,\n\tTextFieldConfig,\n\tTimeFieldConfig,\n\tUploadFieldConfig,\n\tUploadManyFieldConfig,\n} from \"../../components/fields/field-types.js\";\nimport {\n\tArrayField,\n\tAssetPreviewField,\n\tBlocksField,\n\tCheckboxField,\n\tDateField,\n\tDatetimeField,\n\tEmailField,\n\tEmbeddedCollectionField,\n\tJsonField,\n\tNumberField,\n\tObjectField,\n\tPasswordField,\n\tRelationField,\n\tReverseRelationField,\n\tRichTextField,\n\tSelectField,\n\tSwitchField,\n\tTextareaField,\n\tTextField,\n\tTimeField,\n\tUploadField,\n\tUploadManyField,\n} from \"../../components/fields/index.js\";\nimport {\n\tAssetThumbnail,\n\tBlocksCell,\n\tBooleanCell,\n\tDateCell,\n\tDateTimeCell,\n\tEmailCell,\n\tJsonCell,\n\tNumberCell,\n\tObjectCell,\n\tRelationCell,\n\tReverseRelationCell,\n\tRichTextCell,\n\tSelectCell,\n\tTextCell,\n\tTimeCell,\n\tUploadCell,\n\tUploadManyCell,\n} from \"../../views/collection/cells/index.js\";\nimport {\n\ttype FieldDefinition,\n\tfield,\n\ttype ZodBuildContext,\n} from \"../field/field\";\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Wraps a schema as optional/nullable based on required option\n */\nfunction wrapOptional<T extends z.ZodTypeAny>(\n\tschema: T,\n\trequired?: boolean,\n): z.ZodTypeAny {\n\tif (required) return schema;\n\treturn schema.optional().nullable();\n}\n\n/**\n * Creates a field registry proxy for nested fields callbacks.\n * This allows `fields: ({ r }) => ({ name: r.text() })` to work.\n */\nexport function createRegistryProxy(\n\tregistry: Record<string, any>,\n): Record<string, (opts?: any) => any> {\n\treturn new Proxy({} as Record<string, (opts?: any) => any>, {\n\t\tget(_, fieldType: string) {\n\t\t\treturn (opts: any = {}) => {\n\t\t\t\tconst fieldDef = registry[fieldType];\n\t\t\t\tif (!fieldDef) {\n\t\t\t\t\tthrow new Error(`Unknown field type: ${fieldType}`);\n\t\t\t\t}\n\t\t\t\t// Return a new field builder with the provided options\n\t\t\t\treturn fieldDef.$options(opts);\n\t\t\t};\n\t\t},\n\t});\n}\n\n/**\n * Recursively builds schema for nested fields using the context\n */\nfunction buildNestedSchema(\n\tnestedFields: Record<string, FieldDefinition>,\n\tctx: ZodBuildContext,\n): z.ZodObject<Record<string, z.ZodTypeAny>> {\n\tconst shape: Record<string, z.ZodTypeAny> = {};\n\tfor (const [name, fieldDef] of Object.entries(nestedFields)) {\n\t\tshape[name] = ctx.buildSchema(fieldDef);\n\t}\n\treturn z.object(shape);\n}\n\n// ============================================================================\n// Text-based Fields\n// ============================================================================\n\nexport const textField = field(\"text\", {\n\tcomponent: TextField,\n\tcell: TextCell,\n\tconfig: {} as TextFieldConfig,\n\tcreateZod: (opts) => {\n\t\tlet schema = z.string();\n\t\tif (opts.maxLength) {\n\t\t\tschema = schema.max(\n\t\t\t\topts.maxLength,\n\t\t\t\t`Must be at most ${opts.maxLength} characters`,\n\t\t\t);\n\t\t}\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const numberField = field(\"number\", {\n\tcomponent: NumberField,\n\tcell: NumberCell,\n\tconfig: {} as NumberFieldConfig,\n\tcreateZod: (opts) => {\n\t\tlet schema = z.number();\n\t\tif (opts.min !== undefined) {\n\t\t\tschema = schema.min(opts.min, `Must be at least ${opts.min}`);\n\t\t}\n\t\tif (opts.max !== undefined) {\n\t\t\tschema = schema.max(opts.max, `Must be at most ${opts.max}`);\n\t\t}\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const emailField = field(\"email\", {\n\tcomponent: EmailField,\n\tcell: EmailCell,\n\tconfig: {} as TextFieldConfig,\n\tcreateZod: (opts) => {\n\t\tlet schema = z.email(\"Invalid email address\");\n\t\tif (opts.maxLength) {\n\t\t\tschema = schema.max(\n\t\t\t\topts.maxLength,\n\t\t\t\t`Must be at most ${opts.maxLength} characters`,\n\t\t\t);\n\t\t}\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const passwordField = field(\"password\", {\n\tcomponent: PasswordField,\n\tcell: TextCell,\n\tconfig: {} as TextFieldConfig,\n\tcreateZod: (opts) => {\n\t\tlet schema = z.string();\n\t\tif (opts.maxLength) {\n\t\t\tschema = schema.max(\n\t\t\t\topts.maxLength,\n\t\t\t\t`Must be at most ${opts.maxLength} characters`,\n\t\t\t);\n\t\t}\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const textareaField = field(\"textarea\", {\n\tcomponent: TextareaField,\n\tcell: TextCell,\n\tconfig: {} as TextareaFieldConfig,\n\tcreateZod: (opts) => {\n\t\tlet schema = z.string();\n\t\tif (opts.maxLength) {\n\t\t\tschema = schema.max(\n\t\t\t\topts.maxLength,\n\t\t\t\t`Must be at most ${opts.maxLength} characters`,\n\t\t\t);\n\t\t}\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\n// ============================================================================\n// Boolean Fields\n// ============================================================================\n\nexport const checkboxField = field(\"checkbox\", {\n\tcomponent: CheckboxField,\n\tcell: BooleanCell,\n\tconfig: {} as BooleanFieldConfig,\n\tcreateZod: (opts) => {\n\t\tconst schema = z.boolean();\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const switchField = field(\"switch\", {\n\tcomponent: SwitchField,\n\tcell: BooleanCell,\n\tconfig: {} as BooleanFieldConfig,\n\tcreateZod: (opts) => {\n\t\tconst schema = z.boolean();\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\n// ============================================================================\n// Select Fields\n// ============================================================================\n\nexport const selectField = field(\"select\", {\n\tcomponent: SelectField,\n\tcell: SelectCell,\n\tconfig: {} as SelectFieldConfig,\n\tcreateZod: (opts) => {\n\t\t// If we have options, create an enum schema\n\t\tif (opts.options && opts.options.length > 0) {\n\t\t\tconst values = opts.options.map((o: any) => o.value);\n\t\t\t// Handle mixed string/number values\n\t\t\tconst schema = z\n\t\t\t\t.union([z.string(), z.number()])\n\t\t\t\t.refine((val) => values.includes(val), {\n\t\t\t\t\tmessage: \"Invalid selection\",\n\t\t\t\t});\n\t\t\treturn wrapOptional(schema, opts.required);\n\t\t}\n\t\t// Fallback to string/number union\n\t\tconst schema = z.union([z.string(), z.number()]);\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\n// ============================================================================\n// Date/Time Fields\n// ============================================================================\n\nexport const dateField = field(\"date\", {\n\tcomponent: DateField,\n\tcell: DateCell,\n\tconfig: {} as DateFieldConfig,\n\tcreateZod: (opts) => {\n\t\t// Accept both Date objects and ISO strings\n\t\tconst schema = z\n\t\t\t.union([z.date(), z.string().datetime()])\n\t\t\t.transform((val) => (typeof val === \"string\" ? new Date(val) : val));\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const datetimeField = field(\"datetime\", {\n\tcomponent: DatetimeField,\n\tcell: DateTimeCell,\n\tconfig: {} as DateTimeFieldConfig,\n\tcreateZod: (opts) => {\n\t\tconst schema = z\n\t\t\t.union([z.date(), z.string().datetime()])\n\t\t\t.transform((val) => (typeof val === \"string\" ? new Date(val) : val));\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const timeField = field(\"time\", {\n\tcomponent: TimeField,\n\tcell: TimeCell,\n\tconfig: {} as TimeFieldConfig,\n\tcreateZod: (opts) => {\n\t\t// Time is stored as string \"HH:mm\" or \"HH:mm:ss\"\n\t\tconst schema = z\n\t\t\t.string()\n\t\t\t.regex(\n\t\t\t\t/^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/,\n\t\t\t\t\"Invalid time format\",\n\t\t\t);\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\n// ============================================================================\n// Relation Fields\n// ============================================================================\n\nexport const relationField = field(\"relation\", {\n\tcomponent: RelationField,\n\tcell: RelationCell,\n\tconfig: {} as RelationFieldConfig,\n\tcreateZod: (opts) => {\n\t\t// Single relation = string ID, multiple = array of string IDs\n\t\tif (opts.type === \"multiple\") {\n\t\t\tlet schema = z.array(z.string());\n\t\t\tif (opts.maxItems) {\n\t\t\t\tschema = schema.max(\n\t\t\t\t\topts.maxItems,\n\t\t\t\t\t`Maximum ${opts.maxItems} items allowed`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn wrapOptional(schema, opts.required);\n\t\t}\n\t\t// Single relation\n\t\tconst schema = z.string();\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const reverseRelationField = field(\"reverseRelation\", {\n\tcomponent: ReverseRelationField,\n\tcell: ReverseRelationCell,\n\tconfig: {} as ReverseRelationFieldConfig,\n\tcreateZod: (_opts) => {\n\t\t// Reverse relations are read-only, no validation needed\n\t\treturn z.any().optional();\n\t},\n});\n\n// ============================================================================\n// Complex Fields\n// ============================================================================\n\nexport const jsonField = field(\"json\", {\n\tcomponent: JsonField,\n\tcell: JsonCell,\n\tconfig: {} as JsonFieldConfig,\n\tcreateZod: (opts) => {\n\t\tconst schema = z.any();\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const objectField = field(\"object\", {\n\tcomponent: ObjectField,\n\tcell: ObjectCell,\n\tconfig: {} as ObjectFieldConfig,\n\tcreateZod: (opts, ctx) => {\n\t\t// If no fields defined, accept any object\n\t\tif (!opts.fields) {\n\t\t\tconst schema = z.record(z.string(), z.any());\n\t\t\treturn wrapOptional(schema, opts.required);\n\t\t}\n\n\t\t// Build nested fields schema using the registry proxy\n\t\tconst nestedFields = opts.fields({ r: createRegistryProxy(ctx.registry) });\n\t\tconst schema = buildNestedSchema(nestedFields, ctx);\n\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const arrayField = field(\"array\", {\n\tcomponent: ArrayField,\n\tcell: JsonCell,\n\tconfig: {} as ArrayFieldConfig,\n\tcreateZod: (opts, ctx) => {\n\t\tlet itemSchema: z.ZodTypeAny;\n\n\t\t// Object array - has `item` callback for complex items\n\t\tif (opts.item) {\n\t\t\tconst itemFields = opts.item({ r: createRegistryProxy(ctx.registry) });\n\t\t\titemSchema = buildNestedSchema(itemFields, ctx);\n\t\t}\n\t\t// Primitive array - use itemType\n\t\telse {\n\t\t\tswitch (opts.itemType) {\n\t\t\t\tcase \"text\":\n\t\t\t\t\titemSchema = z.string();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"number\":\n\t\t\t\t\titemSchema = z.number();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"email\":\n\t\t\t\t\titemSchema = z.string().email(\"Invalid email\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"textarea\":\n\t\t\t\t\titemSchema = z.string();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"select\":\n\t\t\t\t\tif (opts.options && opts.options.length > 0) {\n\t\t\t\t\t\tconst values = opts.options.map((o: any) => o.value);\n\t\t\t\t\t\titemSchema = z\n\t\t\t\t\t\t\t.union([z.string(), z.number()])\n\t\t\t\t\t\t\t.refine((val) => values.includes(val), {\n\t\t\t\t\t\t\t\tmessage: \"Invalid selection\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\titemSchema = z.union([z.string(), z.number()]);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\titemSchema = z.any();\n\t\t\t}\n\t\t}\n\n\t\tlet schema = z.array(itemSchema);\n\n\t\t// Apply min/max constraints\n\t\tif (opts.minItems !== undefined) {\n\t\t\tschema = schema.min(\n\t\t\t\topts.minItems,\n\t\t\t\t`Minimum ${opts.minItems} items required`,\n\t\t\t);\n\t\t}\n\t\tif (opts.maxItems !== undefined) {\n\t\t\tschema = schema.max(\n\t\t\t\topts.maxItems,\n\t\t\t\t`Maximum ${opts.maxItems} items allowed`,\n\t\t\t);\n\t\t}\n\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\n// ============================================================================\n// Upload Fields\n// ============================================================================\n\nexport const uploadField = field(\"upload\", {\n\tcomponent: UploadField,\n\tcell: UploadCell,\n\tconfig: {} as UploadFieldConfig,\n\tcreateZod: (opts) => {\n\t\t// Upload stores asset ID as string\n\t\tconst schema = z.string();\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const uploadManyField = field(\"uploadMany\", {\n\tcomponent: UploadManyField,\n\tcell: UploadManyCell,\n\tconfig: {} as UploadManyFieldConfig,\n\tcreateZod: (opts) => {\n\t\tlet schema = z.array(z.string());\n\t\tif (opts.maxItems) {\n\t\t\tschema = schema.max(\n\t\t\t\topts.maxItems,\n\t\t\t\t`Maximum ${opts.maxItems} files allowed`,\n\t\t\t);\n\t\t}\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const assetPreviewField = field(\"assetPreview\", {\n\tcomponent: AssetPreviewField,\n\tcell: ({ row }: { value: unknown; row?: any }) => {\n\t\treturn <AssetThumbnail asset={row?.original} size=\"sm\" />;\n\t},\n\tconfig: {} as AssetPreviewFieldProps,\n\tcreateZod: (_opts) => {\n\t\t// Asset preview is read-only display\n\t\treturn z.any().optional();\n\t},\n});\n\n// ============================================================================\n// Rich Text & Embedded\n// ============================================================================\n\nexport const richTextField = field(\"richText\", {\n\tcomponent: RichTextField,\n\tcell: RichTextCell,\n\tconfig: {} as RichTextFieldConfig,\n\tcreateZod: (opts) => {\n\t\t// Rich text can be JSON (TipTap), HTML, or Markdown\n\t\tlet schema: z.ZodTypeAny;\n\n\t\tswitch (opts.outputFormat) {\n\t\t\tcase \"html\":\n\t\t\tcase \"markdown\":\n\t\t\t\tschema = z.string();\n\t\t\t\tif (opts.maxCharacters) {\n\t\t\t\t\tschema = (schema as z.ZodString).max(\n\t\t\t\t\t\topts.maxCharacters,\n\t\t\t\t\t\t`Maximum ${opts.maxCharacters} characters`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// TipTap JSON format\n\t\t\t\tschema = z.any();\n\t\t}\n\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\nexport const embeddedField = field(\"embedded\", {\n\tcomponent: EmbeddedCollectionField,\n\tcell: JsonCell,\n\tconfig: {} as EmbeddedFieldConfig,\n\tcreateZod: (opts) => {\n\t\t// Embedded collections are arrays of objects\n\t\t// The actual schema depends on the embedded collection's fields\n\t\t// For now, we validate as array with min/max constraints\n\t\tlet schema = z.array(z.any());\n\n\t\tif (opts.minItems !== undefined) {\n\t\t\tschema = schema.min(\n\t\t\t\topts.minItems,\n\t\t\t\t`Minimum ${opts.minItems} items required`,\n\t\t\t);\n\t\t}\n\t\tif (opts.maxItems !== undefined) {\n\t\t\tschema = schema.max(\n\t\t\t\topts.maxItems,\n\t\t\t\t`Maximum ${opts.maxItems} items allowed`,\n\t\t\t);\n\t\t}\n\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\n// ============================================================================\n// Block Fields\n// ============================================================================\n\nexport const blocksField = field(\"blocks\", {\n\tcomponent: BlocksField,\n\tcell: BlocksCell,\n\tconfig: {} as BlocksFieldConfig,\n\tcreateZod: (opts) => {\n\t\t// Blocks content schema: { _tree: BlockNode[], _values: Record<string, Record<string, unknown>> }\n\t\tconst blockNodeSchema: z.ZodType<any> = z.lazy(() =>\n\t\t\tz.object({\n\t\t\t\tid: z.string(),\n\t\t\t\ttype: z.string(),\n\t\t\t\tchildren: z.array(blockNodeSchema),\n\t\t\t}),\n\t\t);\n\n\t\tlet schema = z.object({\n\t\t\t_tree: z.array(blockNodeSchema),\n\t\t\t_values: z.record(z.string(), z.record(z.string(), z.any())),\n\t\t});\n\n\t\t// Apply min/max block constraints\n\t\tif (opts.minBlocks !== undefined || opts.maxBlocks !== undefined) {\n\t\t\tschema = schema.refine(\n\t\t\t\t(data) => {\n\t\t\t\t\tconst count = countBlocks(data._tree);\n\t\t\t\t\tif (opts.minBlocks !== undefined && count < opts.minBlocks) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (opts.maxBlocks !== undefined && count > opts.maxBlocks) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tmessage:\n\t\t\t\t\t\topts.minBlocks !== undefined && opts.maxBlocks !== undefined\n\t\t\t\t\t\t\t? `Must have between ${opts.minBlocks} and ${opts.maxBlocks} blocks`\n\t\t\t\t\t\t\t: opts.minBlocks !== undefined\n\t\t\t\t\t\t\t\t? `Minimum ${opts.minBlocks} blocks required`\n\t\t\t\t\t\t\t\t: `Maximum ${opts.maxBlocks} blocks allowed`,\n\t\t\t\t},\n\t\t\t) as any;\n\t\t}\n\n\t\treturn wrapOptional(schema, opts.required);\n\t},\n});\n\n/**\n * Helper to count blocks in a tree\n */\nfunction countBlocks(tree: Array<{ children: Array<any> }>): number {\n\tlet count = 0;\n\tfor (const node of tree) {\n\t\tcount += 1;\n\t\tcount += countBlocks(node.children);\n\t}\n\treturn count;\n}\n\n// ============================================================================\n// Export All Built-in Fields\n// ============================================================================\n\n/**\n * All built-in fields\n */\nexport const builtInFields = {\n\ttext: textField,\n\tnumber: numberField,\n\temail: emailField,\n\tpassword: passwordField,\n\ttextarea: textareaField,\n\tcheckbox: checkboxField,\n\tswitch: switchField,\n\tselect: selectField,\n\tdate: dateField,\n\tdatetime: datetimeField,\n\ttime: timeField,\n\trelation: relationField,\n\treverseRelation: reverseRelationField,\n\tjson: jsonField,\n\tobject: objectField,\n\tarray: arrayField,\n\tupload: uploadField,\n\tuploadMany: uploadManyField,\n\tassetPreview: assetPreviewField,\n\trichText: richTextField,\n\tembedded: embeddedField,\n\tblocks: blocksField,\n} as const;\n","/**\n * Built-in Pages\n *\n * Default page definitions for the admin UI.\n * Includes auth flow pages and dashboard.\n */\n\nimport { page } from \"../page/page\";\n\n// ============================================================================\n// Auth Pages\n// ============================================================================\n\n/**\n * Login page - email/password authentication\n */\nexport const loginPage = page(\"login\", {\n component: () => import(\"../../views/pages/login-page\"),\n}).path(\"/login\");\n\n/**\n * Forgot password page - request password reset email\n */\nexport const forgotPasswordPage = page(\"forgot-password\", {\n component: () => import(\"../../views/pages/forgot-password-page\"),\n}).path(\"/forgot-password\");\n\n/**\n * Reset password page - set new password with token\n */\nexport const resetPasswordPage = page(\"reset-password\", {\n component: () => import(\"../../views/pages/reset-password-page\"),\n}).path(\"/reset-password\");\n\n/**\n * Setup page - create first admin account\n */\nexport const setupPage = page(\"setup\", {\n component: () => import(\"../../views/pages/setup-page\"),\n}).path(\"/setup\");\n\n// ============================================================================\n// Dashboard Page\n// ============================================================================\n\n/**\n * Dashboard page - main admin dashboard\n */\nexport const dashboardPage = page(\"dashboard\", {\n component: () => import(\"../../views/pages/dashboard-page\"),\n}).path(\"/\");\n\n// ============================================================================\n// Export All Built-in Pages\n// ============================================================================\n\n/**\n * All built-in pages as a record for use with AdminBuilder.pages()\n */\nexport const builtInPages = {\n login: loginPage,\n forgotPassword: forgotPasswordPage,\n resetPassword: resetPasswordPage,\n setup: setupPage,\n dashboard: dashboardPage,\n} as const;\n\n/**\n * Auth-only pages (without dashboard)\n * Includes setup page for first-time admin creation\n */\nexport const authPages = {\n login: loginPage,\n forgotPassword: forgotPasswordPage,\n resetPassword: resetPasswordPage,\n setup: setupPage,\n} as const;\n","/**\n * Header Actions\n *\n * Renders action buttons for the collection header area.\n * Primary actions are shown as buttons, secondary in a dropdown menu.\n */\n\n\"use client\";\n\nimport { DotsThreeVertical } from \"@phosphor-icons/react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport type {\n\tActionContext,\n\tActionDefinition,\n\tActionHelpers,\n\tActionQueryClient,\n\tHeaderActionsConfig,\n} from \"../../builder/collection/action-types\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { selectAuthClient, useAdminStore } from \"../../runtime/provider\";\nimport { Button } from \"../ui/button\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuSeparator,\n\tDropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport { ActionButton } from \"./action-button\";\n\nexport interface HeaderActionsProps<TItem = any> {\n\t/** Header actions config with primary/secondary */\n\tactions: HeaderActionsConfig<TItem>;\n\t/** Collection name */\n\tcollection: string;\n\t/** Action helpers */\n\thelpers: ActionHelpers;\n\t/** Callback when action dialog should open */\n\tonOpenDialog?: (action: ActionDefinition<TItem>) => void;\n}\n\n/**\n * HeaderActions - Renders action buttons in the header area\n *\n * Primary actions are shown as buttons.\n * Secondary actions are shown in a dropdown menu.\n *\n * @example\n * ```tsx\n * <HeaderActions\n * actions={{\n * primary: [createAction],\n * secondary: [exportAction, importAction],\n * }}\n * collection=\"posts\"\n * helpers={actionHelpers}\n * onOpenDialog={(action) => setDialogAction(action)}\n * />\n * ```\n */\nexport function HeaderActions<TItem = any>({\n\tactions,\n\tcollection,\n\thelpers,\n\tonOpenDialog,\n}: HeaderActionsProps<TItem>): React.ReactElement | null {\n\tconst resolveText = useResolveText();\n\tconst authClient = useAdminStore(selectAuthClient);\n\tconst queryClient = useQueryClient();\n\n\t// Wrapped query client for action context\n\tconst actionQueryClient: ActionQueryClient = React.useMemo(\n\t\t() => ({\n\t\t\tinvalidateQueries: (filters) => queryClient.invalidateQueries(filters),\n\t\t\trefetchQueries: (filters) => queryClient.refetchQueries(filters),\n\t\t\tresetQueries: (filters) => queryClient.resetQueries(filters),\n\t\t}),\n\t\t[queryClient],\n\t);\n\n\t// Build action context for visibility checks\n\tconst ctx: ActionContext<TItem> = React.useMemo(\n\t\t() => ({\n\t\t\tcollection,\n\t\t\thelpers,\n\t\t\tqueryClient: actionQueryClient,\n\t\t\tauthClient,\n\t\t}),\n\t\t[collection, helpers, actionQueryClient, authClient],\n\t);\n\n\t// Filter visible actions\n\tconst filterVisible = React.useCallback(\n\t\t(actionList: ActionDefinition<TItem>[] | undefined) => {\n\t\t\tif (!actionList) return [];\n\t\t\treturn actionList.filter((action) => {\n\t\t\t\tif (action.visible === undefined) return true;\n\t\t\t\tif (typeof action.visible === \"function\") {\n\t\t\t\t\treturn action.visible(ctx);\n\t\t\t\t}\n\t\t\t\treturn action.visible;\n\t\t\t});\n\t\t},\n\t\t[ctx],\n\t);\n\n\tconst visiblePrimary = React.useMemo(\n\t\t() => filterVisible(actions.primary),\n\t\t[actions.primary, filterVisible],\n\t);\n\n\tconst visibleSecondary = React.useMemo(\n\t\t() => filterVisible(actions.secondary),\n\t\t[actions.secondary, filterVisible],\n\t);\n\n\t// Group secondary actions by variant (destructive at the end)\n\tconst regularSecondary = visibleSecondary.filter(\n\t\t(a) => a.variant !== \"destructive\",\n\t);\n\tconst destructiveSecondary = visibleSecondary.filter(\n\t\t(a) => a.variant === \"destructive\",\n\t);\n\n\tif (visiblePrimary.length === 0 && visibleSecondary.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className=\"flex items-center gap-2\">\n\t\t\t{/* Primary actions as buttons */}\n\t\t\t{visiblePrimary.map((action) => (\n\t\t\t\t<ActionButton\n\t\t\t\t\tkey={action.id}\n\t\t\t\t\taction={action}\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\thelpers={helpers}\n\t\t\t\t\tonOpenDialog={onOpenDialog}\n\t\t\t\t/>\n\t\t\t))}\n\n\t\t\t{/* Secondary actions in dropdown */}\n\t\t\t{visibleSecondary.length > 0 && (\n\t\t\t\t<DropdownMenu>\n\t\t\t\t\t<DropdownMenuTrigger\n\t\t\t\t\t\trender={<Button variant=\"outline\" size=\"icon\" className=\"size-9\" />}\n\t\t\t\t\t>\n\t\t\t\t\t\t<DotsThreeVertical className=\"size-4\" />\n\t\t\t\t\t\t<span className=\"sr-only\">More actions</span>\n\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t<DropdownMenuContent align=\"end\">\n\t\t\t\t\t\t{regularSecondary.map((action) => {\n\t\t\t\t\t\t\tconst Icon = action.icon as\n\t\t\t\t\t\t\t\t| React.ComponentType<React.SVGProps<SVGSVGElement>>\n\t\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\t\tonClick={() => onOpenDialog?.(action)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{Icon && <Icon className=\"mr-2 size-4\" />}\n\t\t\t\t\t\t\t\t\t{resolveText(action.label)}\n\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\n\t\t\t\t\t\t{regularSecondary.length > 0 && destructiveSecondary.length > 0 && (\n\t\t\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{destructiveSecondary.map((action) => {\n\t\t\t\t\t\t\tconst Icon = action.icon as\n\t\t\t\t\t\t\t\t| React.ComponentType<React.SVGProps<SVGSVGElement>>\n\t\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\t\tvariant=\"destructive\"\n\t\t\t\t\t\t\t\t\tonClick={() => onOpenDialog?.(action)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{Icon && <Icon className=\"mr-2 size-4\" />}\n\t\t\t\t\t\t\t\t\t{resolveText(action.label)}\n\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t</DropdownMenu>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import {\n\tclosestCenter,\n\tDndContext,\n\ttype DragEndEvent,\n\tKeyboardSensor,\n\tPointerSensor,\n\tuseSensor,\n\tuseSensors,\n} from \"@dnd-kit/core\";\nimport {\n\tarrayMove,\n\tSortableContext,\n\tsortableKeyboardCoordinates,\n\tuseSortable,\n\tverticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { DotsSixVertical } from \"@phosphor-icons/react\";\nimport { useEffect, useState } from \"react\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { Checkbox } from \"../ui/checkbox\";\nimport type { AvailableField } from \"./types.js\";\n\nexport interface ColumnsTabProps {\n\tfields: AvailableField[];\n\tvisibleColumns: string[];\n\tonVisibleColumnsChange: (columns: string[]) => void;\n}\n\ninterface SortableColumnItemProps {\n\tfield: AvailableField;\n\tisVisible: boolean;\n\tonToggle: () => void;\n}\n\nfunction SortableColumnItem({\n\tfield,\n\tisVisible,\n\tonToggle,\n}: SortableColumnItemProps) {\n\tconst resolveText = useResolveText();\n\tconst {\n\t\tattributes,\n\t\tlisteners,\n\t\tsetNodeRef,\n\t\ttransform,\n\t\ttransition,\n\t\tisDragging,\n\t} = useSortable({ id: field.name });\n\n\tconst style = {\n\t\ttransform: CSS.Transform.toString(transform),\n\t\ttransition,\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tref={setNodeRef}\n\t\t\tstyle={style}\n\t\t\tclassName={`flex items-center gap-2 p-2.5 hover:bg-muted/50 border border-transparent hover:border-border rounded-lg transition-colors ${\n\t\t\t\tisDragging ? \"opacity-50 bg-muted/30\" : \"\"\n\t\t\t}`}\n\t\t>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"cursor-grab active:cursor-grabbing text-muted-foreground hover:text-foreground touch-none\"\n\t\t\t\t{...attributes}\n\t\t\t\t{...listeners}\n\t\t\t>\n\t\t\t\t<DotsSixVertical size={16} weight=\"bold\" />\n\t\t\t</button>\n\t\t\t<label className=\"flex items-center gap-3 flex-1 cursor-pointer\">\n\t\t\t\t<Checkbox checked={isVisible} onCheckedChange={onToggle} />\n\t\t\t\t<span className=\"text-sm font-medium\">{resolveText(field.label)}</span>\n\t\t\t\t<span className=\"text-xs text-muted-foreground ml-auto\">\n\t\t\t\t\t{field.type}\n\t\t\t\t</span>\n\t\t\t</label>\n\t\t</div>\n\t);\n}\n\n/**\n * Sort fields by visibleColumns order:\n * - Visible columns come first (in their stored order from visibleColumns)\n * - Hidden columns come after (in their original order from fields)\n */\nfunction sortFieldsByVisibleColumns(\n\tfields: AvailableField[],\n\tvisibleColumns: string[],\n): AvailableField[] {\n\tconst fieldMap = new Map(fields.map((f) => [f.name, f]));\n\tconst visibleSet = new Set(visibleColumns);\n\n\t// First: visible fields in visibleColumns order\n\tconst visibleFields: AvailableField[] = [];\n\tfor (const name of visibleColumns) {\n\t\tconst field = fieldMap.get(name);\n\t\tif (field) {\n\t\t\tvisibleFields.push(field);\n\t\t}\n\t}\n\n\t// Second: hidden fields in original order\n\tconst hiddenFields = fields.filter((f) => !visibleSet.has(f.name));\n\n\treturn [...visibleFields, ...hiddenFields];\n}\n\nexport function ColumnsTab({\n\tfields,\n\tvisibleColumns,\n\tonVisibleColumnsChange,\n}: ColumnsTabProps) {\n\t// Local state for field order - maintains drag order\n\t// Initialize with fields sorted by visibleColumns order\n\tconst [orderedFields, setOrderedFields] = useState<AvailableField[]>(() =>\n\t\tsortFieldsByVisibleColumns(fields, visibleColumns),\n\t);\n\n\t// Sync when fields prop changes (but preserve user's reordering)\n\tuseEffect(() => {\n\t\tsetOrderedFields((prev) => {\n\t\t\t// Keep existing order, add new fields at the end, remove deleted ones\n\t\t\tconst existingNames = new Set(prev.map((f) => f.name));\n\t\t\tconst newNames = new Set(fields.map((f) => f.name));\n\n\t\t\tconst kept = prev.filter((f) => newNames.has(f.name));\n\t\t\tconst added = fields.filter((f) => !existingNames.has(f.name));\n\n\t\t\treturn [...kept, ...added];\n\t\t});\n\t}, [fields]);\n\n\t// Sync when visibleColumns changes externally (e.g., loading a saved view)\n\t// This ensures the field order in the picker matches the stored column order\n\tuseEffect(() => {\n\t\tsetOrderedFields((prev) => {\n\t\t\tconst sorted = sortFieldsByVisibleColumns(prev, visibleColumns);\n\t\t\t// Only update if the order actually changed to avoid unnecessary re-renders\n\t\t\tconst prevOrder = prev.map((f) => f.name).join(\",\");\n\t\t\tconst newOrder = sorted.map((f) => f.name).join(\",\");\n\t\t\treturn prevOrder === newOrder ? prev : sorted;\n\t\t});\n\t}, [visibleColumns]);\n\n\tconst sensors = useSensors(\n\t\tuseSensor(PointerSensor),\n\t\tuseSensor(KeyboardSensor, {\n\t\t\tcoordinateGetter: sortableKeyboardCoordinates,\n\t\t}),\n\t);\n\n\tconst toggleColumn = (fieldName: string) => {\n\t\tif (visibleColumns.includes(fieldName)) {\n\t\t\tonVisibleColumnsChange(visibleColumns.filter((c) => c !== fieldName));\n\t\t} else {\n\t\t\t// Add at the end of visible columns in current order\n\t\t\tconst newVisible = [...visibleColumns, fieldName];\n\t\t\t// Sort by orderedFields order\n\t\t\tconst orderedVisible = orderedFields\n\t\t\t\t.map((f) => f.name)\n\t\t\t\t.filter((name) => newVisible.includes(name));\n\t\t\tonVisibleColumnsChange(orderedVisible);\n\t\t}\n\t};\n\n\tconst handleDragEnd = (event: DragEndEvent) => {\n\t\tconst { active, over } = event;\n\n\t\tif (over && active.id !== over.id) {\n\t\t\tconst oldIndex = orderedFields.findIndex((f) => f.name === active.id);\n\t\t\tconst newIndex = orderedFields.findIndex((f) => f.name === over.id);\n\n\t\t\t// Reorder the local fields state\n\t\t\tconst reorderedFields = arrayMove(orderedFields, oldIndex, newIndex);\n\t\t\tsetOrderedFields(reorderedFields);\n\n\t\t\t// Update visible columns to match new order\n\t\t\tconst newVisibleColumns = reorderedFields\n\t\t\t\t.map((f) => f.name)\n\t\t\t\t.filter((name) => visibleColumns.includes(name));\n\n\t\t\tonVisibleColumnsChange(newVisibleColumns);\n\t\t}\n\t};\n\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t<div className=\"space-y-2 py-4\">\n\t\t\t<p className=\"text-xs text-muted-foreground mb-4\">\n\t\t\t\t{t(\"viewOptions.columnsDragHint\")}\n\t\t\t</p>\n\t\t\t<DndContext\n\t\t\t\tsensors={sensors}\n\t\t\t\tcollisionDetection={closestCenter}\n\t\t\t\tonDragEnd={handleDragEnd}\n\t\t\t>\n\t\t\t\t<SortableContext\n\t\t\t\t\titems={orderedFields.map((f) => f.name)}\n\t\t\t\t\tstrategy={verticalListSortingStrategy}\n\t\t\t\t>\n\t\t\t\t\t{orderedFields.map((field) => (\n\t\t\t\t\t\t<SortableColumnItem\n\t\t\t\t\t\t\tkey={field.name}\n\t\t\t\t\t\t\tfield={field}\n\t\t\t\t\t\t\tisVisible={visibleColumns.includes(field.name)}\n\t\t\t\t\t\t\tonToggle={() => toggleColumn(field.name)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</SortableContext>\n\t\t\t</DndContext>\n\t\t\t{orderedFields.length === 0 && (\n\t\t\t\t<div className=\"text-center p-8 text-muted-foreground text-sm\">\n\t\t\t\t\t{t(\"viewOptions.noFieldsAvailable\")}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { Plus, Trash } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { selectClient, useAdminStore, useScopedLocale } from \"../../runtime\";\nimport { SelectMulti } from \"../primitives/select-multi\";\nimport { SelectSingle } from \"../primitives/select-single\";\nimport {\n\tisOptionGroup,\n\ttype SelectOption,\n\ttype SelectOptions,\n} from \"../primitives/types\";\nimport { Button } from \"../ui/button.js\";\nimport { Input } from \"../ui/input.js\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"../ui/select.js\";\nimport type { AvailableField, FilterOperator, FilterRule } from \"./types.js\";\n\nexport interface FiltersTabProps {\n\tfields: AvailableField[];\n\tfilters: FilterRule[];\n\tonFiltersChange: (filters: FilterRule[]) => void;\n}\n\nconst OPERATOR_KEYS: Record<string, string> = {\n\tcontains: \"filter.contains\",\n\tnot_contains: \"filter.notContains\",\n\tequals: \"filter.equals\",\n\tnot_equals: \"filter.notEquals\",\n\tstarts_with: \"filter.startsWith\",\n\tends_with: \"filter.endsWith\",\n\tgreater_than: \"filter.greaterThan\",\n\tless_than: \"filter.lessThan\",\n\tgreater_than_or_equal: \"filter.greaterThanOrEqual\",\n\tless_than_or_equal: \"filter.lessThanOrEqual\",\n\tin: \"filter.in\",\n\tnot_in: \"filter.notIn\",\n\tsome: \"filter.some\",\n\tevery: \"filter.every\",\n\tnone: \"filter.none\",\n\tis_empty: \"filter.isEmpty\",\n\tis_not_empty: \"filter.isNotEmpty\",\n};\n\nconst TEXT_OPERATORS: FilterOperator[] = [\n\t\"contains\",\n\t\"not_contains\",\n\t\"equals\",\n\t\"not_equals\",\n\t\"starts_with\",\n\t\"ends_with\",\n\t\"is_empty\",\n\t\"is_not_empty\",\n];\n\nconst NUMBER_OPERATORS: FilterOperator[] = [\n\t\"equals\",\n\t\"not_equals\",\n\t\"greater_than\",\n\t\"greater_than_or_equal\",\n\t\"less_than\",\n\t\"less_than_or_equal\",\n\t\"is_empty\",\n\t\"is_not_empty\",\n];\n\nconst DATE_OPERATORS: FilterOperator[] = [...NUMBER_OPERATORS];\n\nconst BOOLEAN_OPERATORS: FilterOperator[] = [\n\t\"equals\",\n\t\"not_equals\",\n\t\"is_empty\",\n\t\"is_not_empty\",\n];\n\nconst SELECT_OPERATORS: FilterOperator[] = [\n\t\"equals\",\n\t\"not_equals\",\n\t\"is_empty\",\n\t\"is_not_empty\",\n];\n\nconst RELATION_SINGLE_OPERATORS: FilterOperator[] = [\n\t\"equals\",\n\t\"not_equals\",\n\t\"in\",\n\t\"not_in\",\n\t\"is_empty\",\n\t\"is_not_empty\",\n];\n\nconst RELATION_MULTI_OPERATORS: FilterOperator[] = [\n\t\"some\",\n\t\"every\",\n\t\"none\",\n\t\"is_empty\",\n\t\"is_not_empty\",\n];\n\nconst PRESENCE_OPERATORS: FilterOperator[] = [\"is_empty\", \"is_not_empty\"];\n\nfunction isValuelessOperator(operator: FilterOperator) {\n\treturn operator === \"is_empty\" || operator === \"is_not_empty\";\n}\n\nfunction isMultiValueOperator(operator: FilterOperator) {\n\treturn (\n\t\toperator === \"in\" ||\n\t\toperator === \"not_in\" ||\n\t\toperator === \"some\" ||\n\t\toperator === \"every\" ||\n\t\toperator === \"none\"\n\t);\n}\n\nfunction normalizeSelectOptions(\n\toptions?: SelectOptions<unknown>,\n): SelectOption<string>[] {\n\tif (!options || options.length === 0) return [];\n\tconst flattened = options.flatMap((option) =>\n\t\tisOptionGroup(option) ? option.options : [option],\n\t);\n\treturn flattened.map((option) => ({\n\t\t...option,\n\t\tvalue: String(option.value),\n\t}));\n}\n\nfunction getOperatorsForField(field?: AvailableField): FilterOperator[] {\n\tif (!field) return TEXT_OPERATORS;\n\tconst fieldType = field.type;\n\tconst fieldOptions = field.options ?? {};\n\n\tconst isRichTextText =\n\t\tfieldType === \"richText\" &&\n\t\t(fieldOptions.outputFormat === \"html\" ||\n\t\t\tfieldOptions.outputFormat === \"markdown\");\n\n\tconst isTextType =\n\t\tfieldType === \"text\" ||\n\t\tfieldType === \"email\" ||\n\t\tfieldType === \"textarea\" ||\n\t\tisRichTextText;\n\n\tif (fieldType === \"relation\") {\n\t\treturn fieldOptions.type === \"multiple\"\n\t\t\t? RELATION_MULTI_OPERATORS\n\t\t\t: RELATION_SINGLE_OPERATORS;\n\t}\n\tif (isTextType) return TEXT_OPERATORS;\n\tif (fieldType === \"number\") return NUMBER_OPERATORS;\n\tif (\n\t\tfieldType === \"date\" ||\n\t\tfieldType === \"datetime\" ||\n\t\tfieldType === \"time\"\n\t) {\n\t\treturn DATE_OPERATORS;\n\t}\n\tif (fieldType === \"checkbox\" || fieldType === \"switch\") {\n\t\treturn BOOLEAN_OPERATORS;\n\t}\n\tif (fieldType === \"select\") return SELECT_OPERATORS;\n\n\treturn PRESENCE_OPERATORS;\n}\n\nfunction getDefaultValue(field: AvailableField, operator: FilterOperator) {\n\tif (isValuelessOperator(operator)) return null;\n\n\tif (field.type === \"relation\") {\n\t\tconst expectsMulti =\n\t\t\tfield.options?.type === \"multiple\" || isMultiValueOperator(operator);\n\t\treturn expectsMulti ? [] : \"\";\n\t}\n\n\tif (field.type === \"number\") return null;\n\tif (field.type === \"checkbox\" || field.type === \"switch\") return null;\n\tif (field.type === \"select\") return \"\";\n\tif (\n\t\tfield.type === \"date\" ||\n\t\tfield.type === \"datetime\" ||\n\t\tfield.type === \"time\"\n\t) {\n\t\treturn \"\";\n\t}\n\n\treturn \"\";\n}\n\nfunction normalizeValueForOperator(\n\tfield: AvailableField | undefined,\n\toperator: FilterOperator,\n\tvalue: FilterRule[\"value\"],\n): FilterRule[\"value\"] {\n\tif (isValuelessOperator(operator)) return null;\n\tif (!field) return value;\n\n\tif (field.type === \"relation\") {\n\t\tconst expectsMulti =\n\t\t\tfield.options?.type === \"multiple\" || isMultiValueOperator(operator);\n\t\tif (expectsMulti) {\n\t\t\treturn Array.isArray(value)\n\t\t\t\t? value.map((item) => String(item))\n\t\t\t\t: value\n\t\t\t\t\t? [String(value)]\n\t\t\t\t\t: [];\n\t\t}\n\t\tif (Array.isArray(value)) {\n\t\t\treturn value[0] ?? \"\";\n\t\t}\n\t\treturn value ?? \"\";\n\t}\n\n\tif (isMultiValueOperator(operator)) {\n\t\tif (Array.isArray(value)) return value.map((item) => String(item));\n\t\treturn value ? [String(value)] : [];\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value[0] ?? \"\";\n\t}\n\n\treturn value ?? \"\";\n}\n\nexport function FiltersTab({\n\tfields,\n\tfilters,\n\tonFiltersChange,\n}: FiltersTabProps) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst client = useAdminStore(selectClient);\n\tconst { locale: contentLocale } = useScopedLocale();\n\n\tconst filterableFields = React.useMemo(\n\t\t() =>\n\t\t\tfields.filter((field) => {\n\t\t\t\tif (!field?.name) return false;\n\t\t\t\tif (field.name === \"_title\") return false;\n\t\t\t\tif (field.type === \"reverseRelation\") return false;\n\t\t\t\tif (field.options?.compute) return false;\n\t\t\t\treturn true;\n\t\t\t}),\n\t\t[fields],\n\t);\n\n\tconst addFilter = () => {\n\t\tconst defaultField = filterableFields[0];\n\t\tif (!defaultField) return;\n\t\tconst operators = getOperatorsForField(defaultField);\n\t\tconst defaultOperator = operators[0] ?? \"equals\";\n\t\tconst newFilter: FilterRule = {\n\t\t\tid: crypto.randomUUID(),\n\t\t\tfield: defaultField.name,\n\t\t\toperator: defaultOperator,\n\t\t\tvalue: getDefaultValue(defaultField, defaultOperator),\n\t\t};\n\t\tonFiltersChange([...filters, newFilter]);\n\t};\n\n\tconst updateFilter = (id: string, updates: Partial<FilterRule>) => {\n\t\tonFiltersChange(\n\t\t\tfilters.map((f) => (f.id === id ? { ...f, ...updates } : f)),\n\t\t);\n\t};\n\n\tconst removeFilter = (id: string) => {\n\t\tonFiltersChange(filters.filter((f) => f.id !== id));\n\t};\n\n\tconst clearAllFilters = () => {\n\t\tonFiltersChange([]);\n\t};\n\n\tconst createRelationLoader = React.useCallback(\n\t\t(targetCollection: string) => async (search: string) => {\n\t\t\tif (!client) return [];\n\t\t\ttry {\n\t\t\t\tconst response = await (client as any).collections[\n\t\t\t\t\ttargetCollection\n\t\t\t\t].find({\n\t\t\t\t\tlimit: 50,\n\t\t\t\t\tsearch,\n\t\t\t\t\tlocale: contentLocale,\n\t\t\t\t});\n\t\t\t\tconst docs = response?.docs ?? [];\n\t\t\t\treturn docs.map((item: any) => ({\n\t\t\t\t\tvalue: String(item.id),\n\t\t\t\t\tlabel: item._title || item.id || \"\",\n\t\t\t\t}));\n\t\t\t} catch (_error) {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t},\n\t\t[client, contentLocale],\n\t);\n\n\treturn (\n\t\t<div className=\"space-y-4 py-4\">\n\t\t\t<p className=\"text-xs text-muted-foreground\">\n\t\t\t\t{t(\"viewOptions.filtersDescription\")}\n\t\t\t</p>\n\n\t\t\t{filters.map((filter, idx) => {\n\t\t\t\tconst field = fields.find((f) => f.name === filter.field);\n\t\t\t\tconst availableOperators = getOperatorsForField(field);\n\t\t\t\tconst activeOperator = availableOperators.includes(filter.operator)\n\t\t\t\t\t? filter.operator\n\t\t\t\t\t: (availableOperators[0] ?? \"equals\");\n\t\t\t\tconst selectOptions =\n\t\t\t\t\tfield?.type === \"select\"\n\t\t\t\t\t\t? normalizeSelectOptions(field.options?.options)\n\t\t\t\t\t\t: [];\n\n\t\t\t\tconst renderValueInput = () => {\n\t\t\t\t\tif (!field || isValuelessOperator(activeOperator)) return null;\n\n\t\t\t\t\tif (field.type === \"relation\") {\n\t\t\t\t\t\tconst targetCollection = field.options?.targetCollection as\n\t\t\t\t\t\t\t| string\n\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\tconst expectsMulti =\n\t\t\t\t\t\t\tfield.options?.type === \"multiple\" ||\n\t\t\t\t\t\t\tisMultiValueOperator(activeOperator);\n\n\t\t\t\t\t\tif (!targetCollection) {\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\tdisabled\n\t\t\t\t\t\t\t\t\tclassName=\"h-8 text-xs\"\n\t\t\t\t\t\t\t\t\tplaceholder={t(\"viewOptions.valuePlaceholder\")}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst labelText = field.label\n\t\t\t\t\t\t\t? resolveText(field.label)\n\t\t\t\t\t\t\t: field.name;\n\n\t\t\t\t\t\tif (expectsMulti) {\n\t\t\t\t\t\t\tconst selectedValues = Array.isArray(filter.value)\n\t\t\t\t\t\t\t\t? filter.value.map((val) => String(val))\n\t\t\t\t\t\t\t\t: filter.value\n\t\t\t\t\t\t\t\t\t? [String(filter.value)]\n\t\t\t\t\t\t\t\t\t: [];\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<SelectMulti\n\t\t\t\t\t\t\t\t\tvalue={selectedValues}\n\t\t\t\t\t\t\t\t\tonChange={(values) =>\n\t\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, { value: values })\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tloadOptions={createRelationLoader(targetCollection)}\n\t\t\t\t\t\t\t\t\tplaceholder={t(\"viewOptions.valuePlaceholder\")}\n\t\t\t\t\t\t\t\t\temptyMessage={t(\"relation.noResults\", { name: labelText })}\n\t\t\t\t\t\t\t\t\tdrawerTitle={t(\"relation.select\", { name: labelText })}\n\t\t\t\t\t\t\t\t\tclassName=\"h-8 text-xs\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst selectedValue =\n\t\t\t\t\t\t\tfilter.value === null || filter.value === undefined\n\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t: String(filter.value);\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<SelectSingle\n\t\t\t\t\t\t\t\tvalue={selectedValue}\n\t\t\t\t\t\t\t\tonChange={(value) =>\n\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, { value: value ?? \"\" })\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tloadOptions={createRelationLoader(targetCollection)}\n\t\t\t\t\t\t\t\tplaceholder={t(\"viewOptions.valuePlaceholder\")}\n\t\t\t\t\t\t\t\temptyMessage={t(\"relation.noResults\", { name: labelText })}\n\t\t\t\t\t\t\t\tdrawerTitle={t(\"relation.select\", { name: labelText })}\n\t\t\t\t\t\t\t\tclassName=\"h-8 text-xs\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (field.type === \"select\") {\n\t\t\t\t\t\tconst selectedValue =\n\t\t\t\t\t\t\tfilter.value === null || filter.value === undefined\n\t\t\t\t\t\t\t\t? null\n\t\t\t\t\t\t\t\t: String(filter.value);\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<SelectSingle\n\t\t\t\t\t\t\t\tvalue={selectedValue}\n\t\t\t\t\t\t\t\tonChange={(value) =>\n\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, { value: value ?? \"\" })\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\toptions={selectOptions}\n\t\t\t\t\t\t\t\tplaceholder={t(\"viewOptions.valuePlaceholder\")}\n\t\t\t\t\t\t\t\temptyMessage={t(\"table.noResults\")}\n\t\t\t\t\t\t\t\tclassName=\"h-8 text-xs\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (field.type === \"checkbox\" || field.type === \"switch\") {\n\t\t\t\t\t\tconst booleanValue =\n\t\t\t\t\t\t\ttypeof filter.value === \"boolean\"\n\t\t\t\t\t\t\t\t? String(filter.value)\n\t\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\tvalue={booleanValue}\n\t\t\t\t\t\t\t\tonValueChange={(value) =>\n\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, { value: value === \"true\" })\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"h-8 text-xs\">\n\t\t\t\t\t\t\t\t\t<SelectValue\n\t\t\t\t\t\t\t\t\t\tplaceholder={t(\"viewOptions.valuePlaceholder\")}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t<SelectItem value=\"true\">True</SelectItem>\n\t\t\t\t\t\t\t\t\t<SelectItem value=\"false\">False</SelectItem>\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (field.type === \"number\") {\n\t\t\t\t\t\tconst numberValue =\n\t\t\t\t\t\t\tfilter.value === null || filter.value === undefined\n\t\t\t\t\t\t\t\t? \"\"\n\t\t\t\t\t\t\t\t: String(filter.value);\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\t\tclassName=\"h-8 text-xs\"\n\t\t\t\t\t\t\t\tplaceholder={t(\"viewOptions.valuePlaceholder\")}\n\t\t\t\t\t\t\t\tvalue={numberValue}\n\t\t\t\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\t\t\t\tconst raw = event.target.value;\n\t\t\t\t\t\t\t\t\tconst next = raw.trim().length ? Number(raw) : null;\n\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, {\n\t\t\t\t\t\t\t\t\t\tvalue: Number.isNaN(next) ? null : next,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (field.type === \"date\") {\n\t\t\t\t\t\tconst dateValue =\n\t\t\t\t\t\t\ttypeof filter.value === \"string\" ? filter.value : \"\";\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\ttype=\"date\"\n\t\t\t\t\t\t\t\tclassName=\"h-8 text-xs\"\n\t\t\t\t\t\t\t\tvalue={dateValue}\n\t\t\t\t\t\t\t\tonChange={(event) =>\n\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, { value: event.target.value })\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (field.type === \"datetime\") {\n\t\t\t\t\t\tconst dateTimeValue =\n\t\t\t\t\t\t\ttypeof filter.value === \"string\" ? filter.value : \"\";\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\ttype=\"datetime-local\"\n\t\t\t\t\t\t\t\tclassName=\"h-8 text-xs\"\n\t\t\t\t\t\t\t\tvalue={dateTimeValue}\n\t\t\t\t\t\t\t\tonChange={(event) =>\n\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, { value: event.target.value })\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (field.type === \"time\") {\n\t\t\t\t\t\tconst timeValue =\n\t\t\t\t\t\t\ttypeof filter.value === \"string\" ? filter.value : \"\";\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\ttype=\"time\"\n\t\t\t\t\t\t\t\tclassName=\"h-8 text-xs\"\n\t\t\t\t\t\t\t\tvalue={timeValue}\n\t\t\t\t\t\t\t\tonChange={(event) =>\n\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, { value: event.target.value })\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\tclassName=\"h-8 text-xs\"\n\t\t\t\t\t\t\tplaceholder={t(\"viewOptions.valuePlaceholder\")}\n\t\t\t\t\t\t\tvalue={typeof filter.value === \"string\" ? filter.value : \"\"}\n\t\t\t\t\t\t\tonChange={(event) =>\n\t\t\t\t\t\t\t\tupdateFilter(filter.id, { value: event.target.value })\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tkey={filter.id}\n\t\t\t\t\t\tclassName=\"p-3 bg-muted/30 border border-border rounded-lg space-y-2\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"flex justify-between items-center\">\n\t\t\t\t\t\t\t<span className=\"text-xs font-semibold text-muted-foreground uppercase\">\n\t\t\t\t\t\t\t\t{t(\"viewOptions.filterNumber\", { number: idx + 1 })}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon-sm\"\n\t\t\t\t\t\t\t\tonClick={() => removeFilter(filter.id)}\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground hover:text-destructive\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Trash size={14} />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"grid grid-cols-2 gap-2\">\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\tvalue={filter.field || undefined}\n\t\t\t\t\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\t\t\t\t\tconst selectedField = fields.find((f) => f.name === value);\n\t\t\t\t\t\t\t\t\tconst operators = getOperatorsForField(selectedField);\n\t\t\t\t\t\t\t\t\tconst nextOperator = operators[0] ?? \"equals\";\n\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, {\n\t\t\t\t\t\t\t\t\t\tfield: value ?? \"\",\n\t\t\t\t\t\t\t\t\t\toperator: nextOperator,\n\t\t\t\t\t\t\t\t\t\tvalue: selectedField\n\t\t\t\t\t\t\t\t\t\t\t? getDefaultValue(selectedField, nextOperator)\n\t\t\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"h-8 text-xs\">\n\t\t\t\t\t\t\t\t\t<SelectValue>\n\t\t\t\t\t\t\t\t\t\t{filter.field\n\t\t\t\t\t\t\t\t\t\t\t? resolveText(\n\t\t\t\t\t\t\t\t\t\t\t\t\tfields.find((f) => f.name === filter.field)?.label ??\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfilter.field,\n\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t: t(\"viewOptions.selectField\")}\n\t\t\t\t\t\t\t\t\t</SelectValue>\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t{filterableFields.map((f) => (\n\t\t\t\t\t\t\t\t\t\t<SelectItem key={f.name} value={f.name}>\n\t\t\t\t\t\t\t\t\t\t\t{resolveText(f.label)}\n\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\tvalue={activeOperator || undefined}\n\t\t\t\t\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\t\t\t\t\tconst nextOperator = value as FilterOperator;\n\t\t\t\t\t\t\t\t\tupdateFilter(filter.id, {\n\t\t\t\t\t\t\t\t\t\toperator: nextOperator,\n\t\t\t\t\t\t\t\t\t\tvalue: normalizeValueForOperator(\n\t\t\t\t\t\t\t\t\t\t\tfield,\n\t\t\t\t\t\t\t\t\t\t\tnextOperator,\n\t\t\t\t\t\t\t\t\t\t\tfilter.value,\n\t\t\t\t\t\t\t\t\t\t) as FilterRule[\"value\"],\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"h-8 text-xs\">\n\t\t\t\t\t\t\t\t\t<SelectValue>\n\t\t\t\t\t\t\t\t\t\t{activeOperator\n\t\t\t\t\t\t\t\t\t\t\t? t(OPERATOR_KEYS[activeOperator] || activeOperator)\n\t\t\t\t\t\t\t\t\t\t\t: t(\"viewOptions.selectOperator\")}\n\t\t\t\t\t\t\t\t\t</SelectValue>\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t{availableOperators.map((op) => (\n\t\t\t\t\t\t\t\t\t\t<SelectItem key={op} value={op}>\n\t\t\t\t\t\t\t\t\t\t\t{t(OPERATOR_KEYS[op])}\n\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{renderValueInput()}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t})}\n\n\t\t\t{filters.length === 0 && (\n\t\t\t\t<div className=\"text-center p-8 border border-dashed border-border rounded-lg text-muted-foreground text-sm\">\n\t\t\t\t\t{t(\"viewOptions.noActiveFilters\")}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tonClick={addFilter}\n\t\t\t\t\tclassName=\"flex-1 gap-2 rounded-md\"\n\t\t\t\t\tdisabled={filterableFields.length === 0}\n\t\t\t\t>\n\t\t\t\t\t<Plus size={14} />\n\t\t\t\t\t{t(\"viewOptions.addFilter\")}\n\t\t\t\t</Button>\n\t\t\t\t{filters.length > 0 && (\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tonClick={clearAllFilters}\n\t\t\t\t\t\tclassName=\"rounded-md\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"viewOptions.clearAll\")}\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","/**\n * Slovak Admin UI Messages\n */\nexport const adminMessagesSK = {\n\t// Common\n\t\"common.save\": \"Uložiť\",\n\t\"common.cancel\": \"Zrušiť\",\n\t\"common.delete\": \"Vymazať\",\n\t\"common.edit\": \"Upraviť\",\n\t\"common.create\": \"Vytvoriť\",\n\t\"common.add\": \"Pridať\",\n\t\"common.remove\": \"Odstrániť\",\n\t\"common.close\": \"Zavrieť\",\n\t\"common.form\": \"Formulár\",\n\t\"common.search\": \"Hľadať\",\n\t\"common.filter\": \"Filter\",\n\t\"common.refresh\": \"Obnoviť\",\n\t\"common.loading\": \"Načítava sa...\",\n\t\"common.confirm\": \"Potvrdiť\",\n\t\"common.back\": \"Späť\",\n\t\"common.next\": \"Ďalej\",\n\t\"common.previous\": \"Predchádzajúce\",\n\t\"common.actions\": \"Akcie\",\n\t\"common.more\": \"Viac\",\n\t\"common.yes\": \"Áno\",\n\t\"common.no\": \"Nie\",\n\t\"common.ok\": \"OK\",\n\t\"common.apply\": \"Použiť\",\n\t\"common.reset\": \"Resetovať\",\n\t\"common.clear\": \"Vyčistiť\",\n\t\"common.selectAll\": \"Vybrať všetko\",\n\t\"common.deselectAll\": \"Zrušiť výber\",\n\t\"common.duplicate\": \"Duplikovať\",\n\t\"common.copy\": \"Kopírovať\",\n\t\"common.paste\": \"Prilepiť\",\n\t\"common.upload\": \"Nahrať\",\n\t\"common.download\": \"Stiahnuť\",\n\t\"common.preview\": \"Náhľad\",\n\t\"common.view\": \"Zobraziť\",\n\t\"common.open\": \"Otvoriť\",\n\t\"common.retry\": \"Skúsiť znova\",\n\t\"common.submit\": \"Odoslať\",\n\n\t// Navigation\n\t\"nav.dashboard\": \"Prehľad\",\n\t\"nav.collections\": \"Kolekcie\",\n\t\"nav.globals\": \"Globálne nastavenia\",\n\t\"nav.media\": \"Médiá\",\n\t\"nav.settings\": \"Nastavenia\",\n\t\"nav.logout\": \"Odhlásiť sa\",\n\t\"nav.home\": \"Domov\",\n\t\"nav.back\": \"Späť\",\n\n\t// Dashboard\n\t\"dashboard.title\": \"Prehľad\",\n\t\"dashboard.welcome\": \"Vitajte späť\",\n\t\"dashboard.recentActivity\": \"Posledná aktivita\",\n\t\"dashboard.quickActions\": \"Rýchle akcie\",\n\n\t// Collections\n\t\"collection.create\": \"Vytvoriť {{name}}\",\n\t\"collection.edit\": \"Upraviť {{name}}\",\n\t\"collection.delete\": \"Vymazať {{name}}\",\n\t\"collection.deleteConfirm\": \"Naozaj chcete vymazať tento {{name}}?\",\n\t\"collection.noItems\": \"Žiadne {{name}} sa nenašli\",\n\t\"collection.createFirst\": \"Vytvorte svoj prvý {{name}}\",\n\t\"collection.itemCount\": {\n\t\tone: \"{{count}} položka\",\n\t\tfew: \"{{count}} položky\",\n\t\tother: \"{{count}} položiek\",\n\t},\n\t\"collection.bulkDelete\": \"Vymazať vybrané\",\n\t\"collection.bulkDeleteConfirm\": \"Naozaj chcete vymazať {{count}} položiek?\",\n\t\"collection.bulkDeleteSuccess\": {\n\t\tone: \"Úspešne vymazaná {{count}} položka\",\n\t\tfew: \"Úspešne vymazané {{count}} položky\",\n\t\tother: \"Úspešne vymazaných {{count}} položiek\",\n\t},\n\t\"collection.bulkDeleteError\": \"Nepodarilo sa vymazať položky\",\n\t\"collection.bulkDeletePartial\": {\n\t\tone: \"Vymazaná {{success}} položka, {{failed}} zlyhalo\",\n\t\tfew: \"Vymazané {{success}} položky, {{failed}} zlyhalo\",\n\t\tother: \"Vymazaných {{success}} položiek, {{failed}} zlyhalo\",\n\t},\n\t\"collection.bulkActionFailed\": \"Hromadná akcia zlyhala\",\n\t\"collection.selected\": \"{{count}} vybraných\",\n\t\"collection.selectOnPage\": \"Všetky na tejto stránke\",\n\t\"collection.selectAllMatching\": \"Všetky zodpovedajúce filtru ({{count}})\",\n\t\"collection.clearSelection\": \"Zrušiť výber\",\n\t\"collection.list\": \"Zoznam {{name}}\",\n\t\"collection.new\": \"Nový {{name}}\",\n\t\"collection.duplicateSuccess\": \"{{name}} úspešne zduplikovaný\",\n\t\"collection.duplicateError\": \"Nepodarilo sa zduplikovať {{name}}\",\n\n\t// Relations\n\t\"relation.select\": \"Vybrať {{name}}\",\n\t\"relation.clear\": \"Vyčistiť výber\",\n\t\"relation.search\": \"Hľadať {{name}}...\",\n\t\"relation.noResults\": \"Žiadne {{name}} sa nenašli\",\n\t\"relation.loading\": \"Načítava sa...\",\n\t\"relation.createNew\": \"Vytvoriť nový {{name}}\",\n\t\"relation.selected\": \"{{count}} vybraných\",\n\t\"relation.removeItem\": \"Odstrániť {{name}}\",\n\t\"relation.addItem\": \"Pridať {{name}}\",\n\t\"relation.noneSelected\": \"Žiadne {{name}} nie sú vybrané\",\n\t\"relation.noRelated\": \"Žiadne súvisiace položky sa nenašli\",\n\t\"relation.saveFirst\":\n\t\t\"Najprv uložte túto položku, aby ste videli súvisiace položky.\",\n\n\t// Arrays\n\t\"array.empty\": \"Zatiaľ neboli pridané žiadne {{name}}\",\n\t\"array.addItem\": \"Pridať {{name}}\",\n\n\t// Blocks\n\t\"blocks.addAbove\": \"Pridať nad\",\n\t\"blocks.addBelow\": \"Pridať pod\",\n\t\"blocks.addChild\": \"Pridať vnorený blok\",\n\n\t// Forms\n\t\"form.id\": \"ID\",\n\t\"form.created\": \"Vytvorené\",\n\t\"form.updated\": \"Aktualizované\",\n\t\"form.required\": \"Toto pole je povinné\",\n\t\"form.invalid\": \"Neplatná hodnota\",\n\t\"form.saveChanges\": \"Uložiť zmeny\",\n\t\"form.unsavedChanges\": \"Máte neuložené zmeny\",\n\t\"form.discardChanges\": \"Zahodiť zmeny\",\n\t\"form.discardConfirm\":\n\t\t\"Naozaj chcete zahodiť vaše zmeny? Túto akciu nie je možné vrátiť späť.\",\n\t\"form.fieldRequired\": \"{{field}} je povinné\",\n\t\"form.fieldInvalid\": \"{{field}} je neplatné\",\n\t\"form.maxLength\": \"Maximálne {{max}} znakov\",\n\t\"form.minLength\": \"Minimálne {{min}} znakov\",\n\t\"form.maxValue\": \"Maximálne {{max}}\",\n\t\"form.minValue\": \"Minimálne {{min}}\",\n\t\"form.pattern\": \"Neplatný formát\",\n\t\"form.email\": \"Neplatná e-mailová adresa\",\n\t\"form.url\": \"Neplatná URL adresa\",\n\t\"form.createSuccess\": \"{{name}} úspešne vytvorený\",\n\t\"form.createError\": \"Nepodarilo sa vytvoriť {{name}}\",\n\t\"form.updateSuccess\": \"{{name}} úspešne aktualizovaný\",\n\t\"form.updateError\": \"Nepodarilo sa aktualizovať {{name}}\",\n\t\"form.deleteSuccess\": \"{{name}} úspešne vymazaný\",\n\t\"form.deleteError\": \"Nepodarilo sa vymazať {{name}}\",\n\n\t// Auth\n\t\"auth.login\": \"Prihlásiť sa\",\n\t\"auth.logout\": \"Odhlásiť sa\",\n\t\"auth.email\": \"E-mail\",\n\t\"auth.password\": \"Heslo\",\n\t\"auth.forgotPassword\": \"Zabudli ste heslo?\",\n\t\"auth.resetPassword\": \"Obnoviť heslo\",\n\t\"auth.signIn\": \"Prihlásiť sa\",\n\t\"auth.signOut\": \"Odhlásiť sa\",\n\t\"auth.signUp\": \"Registrovať sa\",\n\t\"auth.rememberMe\": \"Zapamätať si ma\",\n\t\"auth.invalidCredentials\": \"Neplatný e-mail alebo heslo\",\n\t\"auth.sessionExpired\": \"Vaša relácia vypršala. Prosím, prihláste sa znova.\",\n\t\"auth.emailPlaceholder\": \"vas@email.com\",\n\t\"auth.passwordPlaceholder\": \"Zadajte vaše heslo\",\n\t\"auth.signingIn\": \"Prihlasuje sa...\",\n\t\"auth.creatingAdmin\": \"Vytvára sa admin...\",\n\t\"auth.name\": \"Meno\",\n\t\"auth.namePlaceholder\": \"Vaše meno\",\n\t\"auth.confirmPassword\": \"Potvrdiť heslo\",\n\t\"auth.confirmPasswordPlaceholder\": \"Potvrďte vaše heslo\",\n\t\"auth.acceptInvite\": \"Prijať pozvánku\",\n\t\"auth.acceptingInvite\": \"Prijíma sa pozvánka...\",\n\t\"auth.dontHaveAccount\": \"Nemáte účet?\",\n\t\"auth.alreadyHaveAccount\": \"Už máte účet?\",\n\t\"auth.emailRequired\": \"E-mail je povinný\",\n\t\"auth.passwordRequired\": \"Heslo je povinné\",\n\t\"auth.passwordMinLength\": \"Heslo musí mať minimálne {{min}} znakov\",\n\t\"auth.nameRequired\": \"Meno je povinné\",\n\t\"auth.nameMinLength\": \"Meno musí mať minimálne {{min}} znaky\",\n\t\"auth.invalidEmail\": \"Neplatná e-mailová adresa\",\n\t\"auth.passwordMismatch\": \"Heslá sa nezhodujú\",\n\t\"auth.newPassword\": \"Nové heslo\",\n\t\"auth.newPasswordPlaceholder\": \"Zadajte nové heslo\",\n\t\"auth.sendResetLink\": \"Odoslať odkaz na obnovenie\",\n\t\"auth.sendingResetLink\": \"Odosiela sa...\",\n\t\"auth.resetLinkSent\": \"Odkaz na obnovenie hesla bol odoslaný na váš e-mail\",\n\t\"auth.resettingPassword\": \"Obnovuje sa heslo...\",\n\t\"auth.createFirstAdmin\": \"Vytvoriť prvého administrátora\",\n\t\"auth.setupTitle\": \"Nastavenie\",\n\t\"auth.setupDescription\":\n\t\t\"Vytvorte váš prvý administrátorský účet pre začatie.\",\n\t\"auth.profile\": \"Profil\",\n\t\"auth.myAccount\": \"Môj účet\",\n\n\t// Errors\n\t\"error.notFound\": \"Nenájdené\",\n\t\"error.serverError\": \"Chyba servera\",\n\t\"error.networkError\": \"Chyba siete. Skontrolujte vaše pripojenie.\",\n\t\"error.unauthorized\": \"Nemáte oprávnenie vykonať túto akciu\",\n\t\"error.forbidden\": \"Prístup zamietnutý\",\n\t\"error.validation\": \"Validácia zlyhala\",\n\t\"error.unknown\": \"Nastala neznáma chyba\",\n\t\"error.timeout\": \"Požiadavka vypršala. Skúste to prosím znova.\",\n\t\"error.conflict\": \"Nastal konflikt. Obnovte stránku a skúste znova.\",\n\n\t// Table\n\t\"table.rowsPerPage\": \"Riadkov na stránku\",\n\t\"table.of\": \"z\",\n\t\"table.noResults\": \"Žiadne výsledky\",\n\t\"table.selectAll\": \"Vybrať všetko\",\n\t\"table.selectRow\": \"Vybrať riadok\",\n\t\"table.showing\": \"Zobrazuje sa {{from}} až {{to}} z {{total}}\",\n\t\"table.page\": \"Stránka {{page}}\",\n\t\"table.firstPage\": \"Prvá stránka\",\n\t\"table.lastPage\": \"Posledná stránka\",\n\t\"table.nextPage\": \"Ďalšia stránka\",\n\t\"table.previousPage\": \"Predchádzajúca stránka\",\n\t\"table.sortAsc\": \"Zoradiť vzostupne\",\n\t\"table.sortDesc\": \"Zoradiť zostupne\",\n\t\"table.columns\": \"Stĺpce\",\n\t\"table.hideColumn\": \"Skryť stĺpec\",\n\t\"table.showColumn\": \"Zobraziť stĺpec\",\n\n\t// Upload\n\t\"upload.dropzone\": \"Presuňte súbory sem alebo kliknite pre nahranie\",\n\t\"upload.browse\": \"Prehľadať súbory\",\n\t\"upload.uploading\": \"Nahráva sa...\",\n\t\"upload.complete\": \"Nahrávanie dokončené\",\n\t\"upload.error\": \"Nahrávanie zlyhalo\",\n\t\"upload.maxSize\": \"Súbor musí byť menší ako {{size}}\",\n\t\"upload.invalidType\": \"Neplatný typ súboru. Povolené: {{types}}\",\n\t\"upload.remove\": \"Odstrániť súbor\",\n\t\"upload.replace\": \"Nahradiť súbor\",\n\t\"upload.preview\": \"Náhľad\",\n\t\"upload.noFile\": \"Žiadny súbor nevybraný\",\n\t\"upload.dragDrop\": \"Presuňte súbory sem\",\n\n\t// Editor\n\t\"editor.bold\": \"Tučné\",\n\t\"editor.italic\": \"Kurzíva\",\n\t\"editor.underline\": \"Podčiarknuté\",\n\t\"editor.strikethrough\": \"Prečiarknuté\",\n\t\"editor.heading\": \"Nadpis {{level}}\",\n\t\"editor.link\": \"Vložiť odkaz\",\n\t\"editor.image\": \"Vložiť obrázok\",\n\t\"editor.list\": \"Zoznam\",\n\t\"editor.orderedList\": \"Číslovaný zoznam\",\n\t\"editor.unorderedList\": \"Odrážkový zoznam\",\n\t\"editor.quote\": \"Citát\",\n\t\"editor.code\": \"Kód\",\n\t\"editor.codeBlock\": \"Blok kódu\",\n\t\"editor.table\": \"Vložiť tabuľku\",\n\t\"editor.undo\": \"Späť\",\n\t\"editor.redo\": \"Znova\",\n\t\"editor.alignLeft\": \"Zarovnať vľavo\",\n\t\"editor.alignCenter\": \"Zarovnať na stred\",\n\t\"editor.alignRight\": \"Zarovnať vpravo\",\n\t\"editor.alignJustify\": \"Do bloku\",\n\t\"editor.horizontalRule\": \"Vodorovná čiara\",\n\t\"editor.addRowBefore\": \"Pridať riadok pred\",\n\t\"editor.addRowAfter\": \"Pridať riadok za\",\n\t\"editor.addColumnBefore\": \"Pridať stĺpec pred\",\n\t\"editor.addColumnAfter\": \"Pridať stĺpec za\",\n\t\"editor.deleteRow\": \"Vymazať riadok\",\n\t\"editor.deleteColumn\": \"Vymazať stĺpec\",\n\t\"editor.deleteTable\": \"Vymazať tabuľku\",\n\t\"editor.toggleHeaderRow\": \"Prepnúť hlavičkový riadok\",\n\t\"editor.toggleHeaderColumn\": \"Prepnúť hlavičkový stĺpec\",\n\t\"editor.mergeCells\": \"Zlúčiť bunky\",\n\t\"editor.splitCell\": \"Rozdeliť bunku\",\n\t\"editor.insertUrl\": \"Vložiť URL\",\n\t\"editor.altText\": \"Alternatívny text (voliteľné)\",\n\t\"editor.uploadFile\": \"Nahrať súbor\",\n\t\"editor.chooseFile\": \"Vybrať súbor\",\n\t\"editor.uploading\": \"Nahráva sa...\",\n\t\"editor.browseLibrary\": \"Prehľadať knižnicu\",\n\n\t// Toasts\n\t\"toast.success\": \"Úspech\",\n\t\"toast.error\": \"Chyba\",\n\t\"toast.warning\": \"Upozornenie\",\n\t\"toast.info\": \"Informácia\",\n\t\"toast.saving\": \"Ukladám...\",\n\t\"toast.saveFailed\": \"Nepodarilo sa uložiť zmeny\",\n\t\"toast.saveSuccess\": \"Zmeny úspešne uložené\",\n\t\"toast.creating\": \"Vytváram...\",\n\t\"toast.createSuccess\": \"Úspešne vytvorené\",\n\t\"toast.createFailed\": \"Nepodarilo sa vytvoriť\",\n\t\"toast.deleting\": \"Odstraňujem...\",\n\t\"toast.deleteFailed\": \"Nepodarilo sa vymazať\",\n\t\"toast.deleteSuccess\": \"Úspešne vymazané\",\n\t\"toast.loadFailed\": \"Nepodarilo sa načítať dáta\",\n\t\"toast.uploadFailed\": \"Nepodarilo sa nahrať súbor\",\n\t\"toast.uploadSuccess\": \"Súbor úspešne nahraný\",\n\t\"toast.copySuccess\": \"Skopírované do schránky\",\n\t\"toast.copyFailed\": \"Nepodarilo sa skopírovať do schránky\",\n\t\"toast.idCopied\": \"ID skopírované do schránky\",\n\t\"toast.validationFailed\": \"Validácia zlyhala\",\n\t\"toast.validationDescription\": \"Skontrolujte formulár pre chyby\",\n\t\"toast.created\": \"{{name}} vytvorený\",\n\t\"toast.updated\": \"{{name}} aktualizovaný\",\n\t\"toast.resourceSaveFailed\": \"Nepodarilo sa uložiť {{name}}\",\n\t\"toast.editComingSoon\": \"Funkcia úprav bude čoskoro dostupná\",\n\t\"toast.maxFilesWarning\":\n\t\t\"Je možné pridať ešte {{remaining}} súbor(ov) (max {{max}})\",\n\t\"toast.settingsSaveFailed\": \"Nepodarilo sa uložiť nastavenia\",\n\t\"toast.actionSuccess\": \"Akcia úspešne dokončená\",\n\t\"toast.actionFailed\": \"Akcia zlyhala\",\n\t\"toast.localeChangedUnsaved\": \"Jazyk obsahu bol zmenený\",\n\t\"toast.localeChangedUnsavedDescription\":\n\t\t\"Vaše neuložené zmeny boli nahradené obsahom v novom jazyku.\",\n\n\t// Confirm\n\t\"confirm.delete\":\n\t\t\"Naozaj chcete toto vymazať? Túto akciu nie je možné vrátiť späť.\",\n\t\"confirm.discard\":\n\t\t\"Naozaj chcete zahodiť vaše zmeny? Túto akciu nie je možné vrátiť späť.\",\n\t\"confirm.unsavedChanges\": \"Máte neuložené zmeny. Naozaj chcete odísť?\",\n\t\"confirm.action\": \"Naozaj chcete pokračovať?\",\n\t\"confirm.irreversible\": \"Túto akciu nie je možné vrátiť späť.\",\n\t\"confirm.localeChange\": \"Zahodiť neuložené zmeny?\",\n\t\"confirm.localeChangeDescription\":\n\t\t\"Máte neuložené zmeny. Prepnutie jazyka obsahu zahodí vaše zmeny a načíta obsah v novom jazyku.\",\n\t\"confirm.localeChangeStay\": \"Zostať\",\n\t\"confirm.localeChangeDiscard\": \"Zahodiť a prepnúť\",\n\n\t// Status\n\t\"status.draft\": \"Koncept\",\n\t\"status.published\": \"Publikované\",\n\t\"status.archived\": \"Archivované\",\n\t\"status.pending\": \"Čakajúce\",\n\t\"status.active\": \"Aktívne\",\n\t\"status.inactive\": \"Neaktívne\",\n\n\t// Dates\n\t\"date.today\": \"Dnes\",\n\t\"date.yesterday\": \"Včera\",\n\t\"date.tomorrow\": \"Zajtra\",\n\t\"date.selectDate\": \"Vybrať dátum\",\n\t\"date.selectTime\": \"Vybrať čas\",\n\t\"date.clear\": \"Vyčistiť dátum\",\n\n\t// Accessibility\n\t\"a11y.openMenu\": \"Otvoriť menu\",\n\t\"a11y.closeMenu\": \"Zavrieť menu\",\n\t\"a11y.expand\": \"Rozbaliť\",\n\t\"a11y.collapse\": \"Zbaliť\",\n\t\"a11y.loading\": \"Načítava sa\",\n\t\"a11y.required\": \"Povinné\",\n\t\"a11y.optional\": \"Voliteľné\",\n\t\"a11y.selected\": \"Vybrané\",\n\t\"a11y.notSelected\": \"Nevybrané\",\n\n\t// Locale\n\t\"locale.language\": \"Jazyk\",\n\t\"locale.switchLanguage\": \"Zmeniť jazyk\",\n\t\"locale.contentLanguage\": \"Jazyk obsahu\",\n\t\"locale.uiLanguage\": \"Jazyk rozhrania\",\n\n\t// ===========================================\n\t// Default Collections\n\t// ===========================================\n\n\t// Users Collection\n\t\"defaults.users.label\": \"Používatelia\",\n\t\"defaults.users.description\": \"Správa administrátorov a ich rolí\",\n\t\"defaults.users.fields.name.label\": \"Meno\",\n\t\"defaults.users.fields.name.placeholder\": \"Zadajte meno používateľa\",\n\t\"defaults.users.fields.email.label\": \"E-mail\",\n\t\"defaults.users.fields.email.description\":\n\t\t\"E-mailová adresa (len na čítanie)\",\n\t\"defaults.users.fields.role.label\": \"Rola\",\n\t\"defaults.users.fields.role.options.admin\": \"Administrátor\",\n\t\"defaults.users.fields.role.options.user\": \"Používateľ\",\n\t\"defaults.users.fields.emailVerified.label\": \"E-mail overený\",\n\t\"defaults.users.fields.emailVerified.description\":\n\t\t\"Či používateľ overil svoju e-mailovú adresu\",\n\t\"defaults.users.fields.banned.label\": \"Zablokovaný\",\n\t\"defaults.users.fields.banned.description\":\n\t\t\"Zabrániť používateľovi v prístupe do systému\",\n\t\"defaults.users.fields.banReason.label\": \"Dôvod zablokovania\",\n\t\"defaults.users.fields.banReason.placeholder\":\n\t\t\"Zadajte dôvod zablokovania...\",\n\t\"defaults.users.sections.basicInfo\": \"Základné informácie\",\n\t\"defaults.users.sections.permissions\": \"Oprávnenia\",\n\t\"defaults.users.sections.accessControl\": \"Riadenie prístupu\",\n\t\"defaults.users.actions.createUser.label\": \"Vytvoriť používateľa\",\n\t\"defaults.users.actions.createUser.title\": \"Vytvoriť používateľa\",\n\t\"defaults.users.actions.createUser.description\":\n\t\t\"Vytvorte nový používateľský účet s prihlasovacími údajmi.\",\n\t\"defaults.users.actions.createUser.fields.password.label\": \"Heslo\",\n\t\"defaults.users.actions.createUser.fields.password.placeholder\":\n\t\t\"Zadajte heslo\",\n\t\"defaults.users.actions.createUser.submit\": \"Vytvoriť používateľa\",\n\t\"defaults.users.actions.createUser.success\":\n\t\t\"Používateľ {{email}} bol úspešne vytvorený. Zdieľajte prihlasovacie údaje s používateľom.\",\n\t\"defaults.users.actions.createUser.errorNoAuth\":\n\t\t\"Auth klient nie je nakonfigurovaný. Nie je možné vytvoriť používateľa.\",\n\t\"defaults.users.actions.resetPassword.label\": \"Obnoviť heslo\",\n\t\"defaults.users.actions.resetPassword.title\": \"Obnoviť heslo\",\n\t\"defaults.users.actions.resetPassword.description\":\n\t\t\"Nastavte nové heslo pre tohto používateľa.\",\n\t\"defaults.users.actions.resetPassword.fields.newPassword.label\": \"Nové heslo\",\n\t\"defaults.users.actions.resetPassword.fields.newPassword.placeholder\":\n\t\t\"Zadajte nové heslo\",\n\t\"defaults.users.actions.resetPassword.fields.confirmPassword.label\":\n\t\t\"Potvrdiť heslo\",\n\t\"defaults.users.actions.resetPassword.fields.confirmPassword.placeholder\":\n\t\t\"Potvrďte nové heslo\",\n\t\"defaults.users.actions.resetPassword.submit\": \"Obnoviť heslo\",\n\t\"defaults.users.actions.resetPassword.success\":\n\t\t\"Heslo bolo úspešne obnovené!\",\n\t\"defaults.users.actions.resetPassword.errorMismatch\": \"Heslá sa nezhodujú\",\n\t\"defaults.users.actions.delete.label\": \"Vymazať používateľa\",\n\n\t// Assets Collection\n\t\"defaults.assets.label\": \"Médiá\",\n\t\"defaults.assets.description\": \"Správa nahraných súborov a obrázkov\",\n\t\"defaults.assets.fields.preview.label\": \"Náhľad\",\n\t\"defaults.assets.fields.filename.label\": \"Názov súboru\",\n\t\"defaults.assets.fields.filename.description\":\n\t\t\"Pôvodný názov nahraného súboru\",\n\t\"defaults.assets.fields.mimeType.label\": \"Typ\",\n\t\"defaults.assets.fields.mimeType.description\": \"MIME typ súboru\",\n\t\"defaults.assets.fields.size.label\": \"Veľkosť (bajty)\",\n\t\"defaults.assets.fields.size.description\": \"Veľkosť súboru v bajtoch\",\n\t\"defaults.assets.fields.alt.label\": \"Alternatívny text\",\n\t\"defaults.assets.fields.alt.placeholder\": \"Opíšte obrázok pre prístupnosť\",\n\t\"defaults.assets.fields.alt.description\":\n\t\t\"Alternatívny text pre čítačky obrazovky\",\n\t\"defaults.assets.fields.caption.label\": \"Popisok\",\n\t\"defaults.assets.fields.caption.placeholder\": \"Pridajte popisok...\",\n\t\"defaults.assets.fields.visibility.label\": \"Viditeľnosť\",\n\t\"defaults.assets.fields.visibility.options.public\": \"Verejný\",\n\t\"defaults.assets.fields.visibility.options.private\": \"Súkromný\",\n\t\"defaults.assets.fields.visibility.description\":\n\t\t\"Verejné súbory sú prístupné bez autentifikácie. Súkromné súbory vyžadujú podpísanú URL.\",\n\t\"defaults.assets.sections.fileInfo\": \"Informácie o súbore\",\n\t\"defaults.assets.sections.metadata\": \"Metadáta\",\n\t\"defaults.assets.sections.metadata.description\":\n\t\t\"Pridajte popisné informácie pre prístupnosť a SEO\",\n\t\"defaults.assets.actions.upload.label\": \"Nahrať súbory\",\n\n\t// Default Sidebar\n\t\"defaults.sidebar.administration\": \"Administrácia\",\n\n\t// View Options (Filter Builder)\n\t\"viewOptions.title\": \"Možnosti zobrazenia\",\n\t\"viewOptions.columns\": \"Stĺpce\",\n\t\"viewOptions.filters\": \"Filtre\",\n\t\"viewOptions.savedViews\": \"Uložené zobrazenia\",\n\t\"viewOptions.apply\": \"Použiť\",\n\t\"viewOptions.reset\": \"Obnoviť\",\n\n\t// Saved Views Tab\n\t\"viewOptions.saveCurrentConfig\": \"Uložiť aktuálnu konfiguráciu\",\n\t\"viewOptions.viewNamePlaceholder\": \"Názov zobrazenia...\",\n\t\"viewOptions.saveDescription\": \"Uloží aktuálne stĺpce, filtre a zoradenie.\",\n\t\"viewOptions.noChangesToSave\": \"Žiadne filtre ani zmeny stĺpcov na uloženie.\",\n\t\"viewOptions.noSavedViews\": \"Zatiaľ žiadne uložené zobrazenia.\",\n\t\"viewOptions.filtersCount\": {\n\t\tone: \"{{count}} filter\",\n\t\tfew: \"{{count}} filtre\",\n\t\tother: \"{{count}} filtrov\",\n\t},\n\t\"viewOptions.columnsCount\": {\n\t\tone: \"{{count}} stĺpec\",\n\t\tfew: \"{{count}} stĺpce\",\n\t\tother: \"{{count}} stĺpcov\",\n\t},\n\t\"viewOptions.defaultView\": \"Predvolené\",\n\n\t// Columns Tab\n\t\"viewOptions.columnsDragHint\":\n\t\t\"Ťahaním zmeníte poradie, prepínačom zobrazíte/skryjete stĺpce.\",\n\t\"viewOptions.noFieldsAvailable\": \"Žiadne polia nie sú dostupné.\",\n\n\t// Filters Tab\n\t\"viewOptions.filtersDescription\":\n\t\t\"Zúžte výsledky pomocou vlastných pravidiel.\",\n\t\"viewOptions.filterNumber\": \"Filter #{{number}}\",\n\t\"viewOptions.selectField\": \"Vybrať pole\",\n\t\"viewOptions.selectOperator\": \"Vybrať operátor\",\n\t\"viewOptions.valuePlaceholder\": \"Hodnota...\",\n\t\"viewOptions.noActiveFilters\": \"Žiadne aktívne filtre.\",\n\t\"viewOptions.addFilter\": \"Pridať filter\",\n\t\"viewOptions.clearAll\": \"Vymazať všetko\",\n\t\"viewOptions.activeFilters\": {\n\t\tone: \"{{count}} aktívny filter\",\n\t\tfew: \"{{count}} aktívne filtre\",\n\t\tother: \"{{count}} aktívnych filtrov\",\n\t},\n\t\"viewOptions.clearFilters\": \"Vymazať filtre\",\n\n\t// Filter Operators\n\t\"filter.contains\": \"Obsahuje\",\n\t\"filter.notContains\": \"Neobsahuje\",\n\t\"filter.equals\": \"Rovná sa\",\n\t\"filter.notEquals\": \"Nerovná sa\",\n\t\"filter.startsWith\": \"Začína na\",\n\t\"filter.endsWith\": \"Končí na\",\n\t\"filter.greaterThan\": \"Väčšie ako\",\n\t\"filter.greaterThanOrEqual\": \"Väčšie alebo rovné\",\n\t\"filter.lessThan\": \"Menšie ako\",\n\t\"filter.lessThanOrEqual\": \"Menšie alebo rovné\",\n\t\"filter.in\": \"Je jeden z\",\n\t\"filter.notIn\": \"Nie je medzi\",\n\t\"filter.some\": \"Má aspoň jeden\",\n\t\"filter.every\": \"Má všetky\",\n\t\"filter.none\": \"Nemá žiadny\",\n\t\"filter.isEmpty\": \"Je prázdne\",\n\t\"filter.isNotEmpty\": \"Nie je prázdne\",\n\n\t// Preview\n\t\"preview.show\": \"Náhľad\",\n\t\"preview.hide\": \"Skryť náhľad\",\n\t\"preview.title\": \"Náhľad\",\n\t\"preview.livePreview\": \"Živý náhľad\",\n\t\"preview.fullscreen\": \"Celá obrazovka\",\n\t\"preview.close\": \"Zavrieť náhľad\",\n\t\"preview.loading\": \"Načítava sa náhľad...\",\n\n\t// Autosave\n\t\"autosave.saving\": \"Ukladá sa...\",\n\t\"autosave.saved\": \"Uložené\",\n\t\"autosave.unsavedChanges\": \"Neuložené zmeny\",\n\t\"autosave.justNow\": \"práve teraz\",\n\t\"autosave.secondsAgo\": {\n\t\tone: \"pred {{count}}s\",\n\t\tfew: \"pred {{count}}s\",\n\t\tother: \"pred {{count}}s\",\n\t},\n\t\"autosave.minutesAgo\": {\n\t\tone: \"pred {{count}}m\",\n\t\tfew: \"pred {{count}}m\",\n\t\tother: \"pred {{count}}m\",\n\t},\n\t\"autosave.hoursAgo\": {\n\t\tone: \"pred {{count}}h\",\n\t\tfew: \"pred {{count}}h\",\n\t\tother: \"pred {{count}}h\",\n\t},\n} as const;\n","import {\n\tArrowRight,\n\tFloppyDisk,\n\tSpinnerGap,\n\tTrash,\n} from \"@phosphor-icons/react\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"../../i18n/index.js\";\nimport { Button } from \"../ui/button.js\";\nimport { Input } from \"../ui/input.js\";\nimport type { FilterBuilderProps, SavedView } from \"./types.js\";\n\nexport interface SavedViewsTabProps {\n\tcollection: string;\n\tcurrentConfig: FilterBuilderProps[\"currentConfig\"];\n\tsavedViews: SavedView[];\n\tisLoading: boolean;\n\tonLoadView: (view: SavedView) => void;\n\tonSaveView: (\n\t\tname: string,\n\t\tconfig: FilterBuilderProps[\"currentConfig\"],\n\t) => void;\n\tonDeleteView: (viewId: string) => void;\n}\n\nexport function SavedViewsTab({\n\tcollection,\n\tcurrentConfig,\n\tsavedViews,\n\tisLoading,\n\tonLoadView,\n\tonSaveView,\n\tonDeleteView,\n}: SavedViewsTabProps) {\n\tconst { t } = useTranslation();\n\tconst [viewName, setViewName] = useState(\"\");\n\n\tconst handleSave = () => {\n\t\tif (!viewName.trim()) return;\n\t\tonSaveView(viewName.trim(), currentConfig);\n\t\tsetViewName(\"\");\n\t};\n\n\tconst hasActiveConfig =\n\t\tcurrentConfig.filters.length > 0 ||\n\t\tcurrentConfig.sortConfig !== null ||\n\t\tcurrentConfig.visibleColumns.length > 0;\n\n\treturn (\n\t\t<div className=\"space-y-6 py-4\">\n\t\t\t{/* Save Current Configuration */}\n\t\t\t<div className=\"bg-primary/5 p-4 border border-primary/20 rounded-lg\">\n\t\t\t\t<p className=\"block text-xs font-semibold uppercase text-primary mb-2\">\n\t\t\t\t\t{t(\"viewOptions.saveCurrentConfig\")}\n\t\t\t\t</p>\n\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t<Input\n\t\t\t\t\t\tclassName=\"flex-1 h-9 rounded-md\"\n\t\t\t\t\t\tplaceholder={t(\"viewOptions.viewNamePlaceholder\")}\n\t\t\t\t\t\tvalue={viewName}\n\t\t\t\t\t\tonChange={(e) => setViewName(e.target.value)}\n\t\t\t\t\t\tonKeyDown={(e) => e.key === \"Enter\" && handleSave()}\n\t\t\t\t\t/>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tonClick={handleSave}\n\t\t\t\t\t\tdisabled={!viewName.trim()}\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tclassName=\"h-9 px-3 rounded-md\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<FloppyDisk size={16} />\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t\t<p className=\"text-xs text-muted-foreground mt-2\">\n\t\t\t\t\t{t(\"viewOptions.saveDescription\")}\n\t\t\t\t</p>\n\t\t\t\t{!hasActiveConfig && (\n\t\t\t\t\t<p className=\"text-xs text-amber-600 mt-1\">\n\t\t\t\t\t\t{t(\"viewOptions.noChangesToSave\")}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Saved Views List */}\n\t\t\t<div className=\"space-y-2\">\n\t\t\t\t<p className=\"text-xs font-semibold uppercase text-muted-foreground mb-2\">\n\t\t\t\t\t{t(\"viewOptions.savedViews\")}\n\t\t\t\t</p>\n\n\t\t\t\t{isLoading && (\n\t\t\t\t\t<div className=\"flex justify-center p-4 text-muted-foreground\">\n\t\t\t\t\t\t<SpinnerGap className=\"size-5 animate-spin\" />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{!isLoading && savedViews.length === 0 && (\n\t\t\t\t\t<div className=\"text-center p-4 text-muted-foreground text-xs italic\">\n\t\t\t\t\t\t{t(\"viewOptions.noSavedViews\")}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{!isLoading &&\n\t\t\t\t\tsavedViews.map((view) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tkey={view.id}\n\t\t\t\t\t\t\tclassName=\"flex w-full items-center justify-between p-3 border border-border hover:border-primary/50 hover:shadow-sm bg-background group cursor-pointer transition-all rounded-lg text-left\"\n\t\t\t\t\t\t\tonClick={() => onLoadView(view)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div className=\"flex-1 min-w-0\">\n\t\t\t\t\t\t\t\t<p className=\"text-sm font-medium truncate group-hover:text-primary transition-colors\">\n\t\t\t\t\t\t\t\t\t{view.name}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t<p className=\"text-xs text-muted-foreground flex gap-2\">\n\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t{t(\"viewOptions.filtersCount\", {\n\t\t\t\t\t\t\t\t\t\t\tcount: view.configuration.filters.length,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span>•</span>\n\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t{t(\"viewOptions.columnsCount\", {\n\t\t\t\t\t\t\t\t\t\t\tcount: view.configuration.visibleColumns.length,\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t{view.isDefault && (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t<span>•</span>\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-primary\">\n\t\t\t\t\t\t\t\t\t\t\t\t{t(\"viewOptions.defaultView\")}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-1\">\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\tsize=\"icon-sm\"\n\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\tonDeleteView(view.id);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tclassName=\"opacity-0 group-hover:opacity-100 text-muted-foreground hover:text-destructive\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Trash size={14} />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t<ArrowRight\n\t\t\t\t\t\t\t\t\tsize={14}\n\t\t\t\t\t\t\t\t\tclassName=\"opacity-0 group-hover:opacity-100 text-primary transition-opacity\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { useEffect, useState } from \"react\";\nimport { useTranslation } from \"../../i18n/hooks.js\";\nimport { Button } from \"../ui/button.js\";\nimport {\n\tSheet,\n\tSheetContent,\n\tSheetFooter,\n\tSheetHeader,\n\tSheetTitle,\n} from \"../ui/sheet.js\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"../ui/tabs.js\";\nimport { ColumnsTab } from \"./columns-tab.js\";\nimport { FiltersTab } from \"./filters-tab.js\";\nimport { SavedViewsTab } from \"./saved-views-tab.js\";\nimport type {\n\tFilterBuilderProps,\n\tSavedView,\n\tViewConfiguration,\n} from \"./types.js\";\n\nexport interface FilterBuilderSheetProps extends FilterBuilderProps {\n\t/** Saved views for this collection */\n\tsavedViews?: SavedView[];\n\n\t/** Whether saved views are loading */\n\tsavedViewsLoading?: boolean;\n\n\t/** Callback when saving a new view */\n\tonSaveView?: (name: string, config: ViewConfiguration) => void;\n\n\t/** Callback when deleting a view */\n\tonDeleteView?: (viewId: string) => void;\n}\n\nexport function FilterBuilderSheet({\n\tcollection,\n\tavailableFields,\n\tcurrentConfig,\n\tonConfigChange,\n\tisOpen,\n\tonOpenChange,\n\tsavedViews = [],\n\tsavedViewsLoading = false,\n\tonSaveView,\n\tonDeleteView,\n}: FilterBuilderSheetProps) {\n\tconst { t } = useTranslation();\n\n\t// Local state for pending changes\n\tconst [localConfig, setLocalConfig] =\n\t\tuseState<ViewConfiguration>(currentConfig);\n\n\t// Reset local config when sheet opens or currentConfig changes externally\n\tuseEffect(() => {\n\t\tif (isOpen) {\n\t\t\tsetLocalConfig(currentConfig);\n\t\t}\n\t}, [isOpen, currentConfig]);\n\n\tconst handleLoadView = (view: SavedView) => {\n\t\tsetLocalConfig(view.configuration);\n\t};\n\n\tconst handleSaveView = (name: string) => {\n\t\tonSaveView?.(name, localConfig);\n\t};\n\n\tconst handleApply = () => {\n\t\tonConfigChange(localConfig);\n\t\tonOpenChange(false);\n\t};\n\n\tconst handleReset = () => {\n\t\tconst resetConfig: ViewConfiguration = {\n\t\t\tfilters: [],\n\t\t\tsortConfig: null,\n\t\t\tvisibleColumns: availableFields.map((f) => f.name),\n\t\t};\n\t\tsetLocalConfig(resetConfig);\n\t};\n\n\tconst hasChanges =\n\t\tJSON.stringify(localConfig) !== JSON.stringify(currentConfig);\n\n\treturn (\n\t\t<Sheet open={isOpen} onOpenChange={onOpenChange}>\n\t\t\t<SheetContent side=\"right\" className=\"sm:max-w-md flex flex-col p-0\">\n\t\t\t\t<SheetHeader className=\"px-6 pt-6\">\n\t\t\t\t\t<SheetTitle>{t(\"viewOptions.title\")}</SheetTitle>\n\t\t\t\t</SheetHeader>\n\n\t\t\t\t<div className=\"flex-1 overflow-y-auto px-6\">\n\t\t\t\t\t<Tabs defaultValue=\"columns\" className=\"mt-4\">\n\t\t\t\t\t\t<TabsList variant=\"line\" className=\"w-full\">\n\t\t\t\t\t\t\t<TabsTrigger value=\"columns\" className=\"flex-1\">\n\t\t\t\t\t\t\t\t{t(\"viewOptions.columns\")}\n\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t\t<TabsTrigger value=\"filters\" className=\"flex-1\">\n\t\t\t\t\t\t\t\t{t(\"viewOptions.filters\")}\n\t\t\t\t\t\t\t\t{localConfig.filters.length > 0 && (\n\t\t\t\t\t\t\t\t\t<span className=\"ml-1.5 bg-primary text-primary-foreground text-xs px-1.5 py-0.5 rounded-full\">\n\t\t\t\t\t\t\t\t\t\t{localConfig.filters.length}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t\t<TabsTrigger value=\"views\" className=\"flex-1\">\n\t\t\t\t\t\t\t\t{t(\"viewOptions.savedViews\")}\n\t\t\t\t\t\t\t</TabsTrigger>\n\t\t\t\t\t\t</TabsList>\n\n\t\t\t\t\t\t<TabsContent value=\"columns\">\n\t\t\t\t\t\t\t<ColumnsTab\n\t\t\t\t\t\t\t\tfields={availableFields}\n\t\t\t\t\t\t\t\tvisibleColumns={localConfig.visibleColumns}\n\t\t\t\t\t\t\t\tonVisibleColumnsChange={(columns) =>\n\t\t\t\t\t\t\t\t\tsetLocalConfig({ ...localConfig, visibleColumns: columns })\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</TabsContent>\n\n\t\t\t\t\t\t<TabsContent value=\"filters\">\n\t\t\t\t\t\t\t<FiltersTab\n\t\t\t\t\t\t\t\tfields={availableFields}\n\t\t\t\t\t\t\t\tfilters={localConfig.filters}\n\t\t\t\t\t\t\t\tonFiltersChange={(filters) =>\n\t\t\t\t\t\t\t\t\tsetLocalConfig({ ...localConfig, filters })\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</TabsContent>\n\n\t\t\t\t\t\t<TabsContent value=\"views\">\n\t\t\t\t\t\t\t<SavedViewsTab\n\t\t\t\t\t\t\t\tcollection={collection}\n\t\t\t\t\t\t\t\tcurrentConfig={localConfig}\n\t\t\t\t\t\t\t\tsavedViews={savedViews}\n\t\t\t\t\t\t\t\tisLoading={savedViewsLoading}\n\t\t\t\t\t\t\t\tonLoadView={handleLoadView}\n\t\t\t\t\t\t\t\tonSaveView={handleSaveView}\n\t\t\t\t\t\t\t\tonDeleteView={onDeleteView || (() => {})}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</TabsContent>\n\t\t\t\t\t</Tabs>\n\t\t\t\t</div>\n\n\t\t\t\t<SheetFooter className=\"border-t px-6 py-4 mt-4\">\n\t\t\t\t\t<div className=\"flex w-full gap-2\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\tonClick={handleReset}\n\t\t\t\t\t\t\tclassName=\"flex-1 rounded-md\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t(\"viewOptions.reset\")}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t<Button onClick={handleApply} className=\"flex-1 rounded-md\">\n\t\t\t\t\t\t\t{t(\"viewOptions.apply\")}\n\t\t\t\t\t\t\t{hasChanges && \" *\"}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</SheetFooter>\n\t\t\t</SheetContent>\n\t\t</Sheet>\n\t);\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface EmptyStateProps {\n /**\n * Title text (displayed in mono uppercase)\n * @example \"NO_DATA_FOUND\"\n */\n title: string;\n\n /**\n * Description text\n */\n description?: string;\n\n /**\n * Optional icon component\n */\n icon?: React.ComponentType<{ className?: string }>;\n\n /**\n * Optional action button/element\n */\n action?: React.ReactNode;\n\n /**\n * Height of the empty state container\n * @default \"h-64\"\n */\n height?: string;\n\n /**\n * Additional className\n */\n className?: string;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * EmptyState - Cyber-styled empty state component\n *\n * @example\n * ```tsx\n * <EmptyState\n * title=\"NO_RESULTS\"\n * description=\"Try adjusting your search or filters\"\n * />\n *\n * <EmptyState\n * title=\"NO_POSTS_YET\"\n * description=\"Create your first post to get started\"\n * action={<Button>Create Post</Button>}\n * />\n * ```\n */\nexport function EmptyState({\n title,\n description,\n icon: Icon,\n action,\n height = \"h-64\",\n className,\n}: EmptyStateProps): React.ReactElement {\n return (\n <div\n data-slot=\"empty-state\"\n className={cn(\n \"relative flex flex-col items-center justify-center\",\n \"border border-dashed border-border/40 bg-card/5\",\n height,\n className,\n )}\n >\n <div className=\"text-center\">\n {/* Glow dot or icon */}\n {Icon ? (\n <Icon className=\"mx-auto mb-4 size-8 text-muted-foreground/50\" />\n ) : (\n <div\n className=\"mx-auto mb-4 size-2 bg-primary/50\"\n style={{\n boxShadow: \"0 0 20px oklch(55% 0.3 300 / 0.25)\",\n }}\n />\n )}\n\n {/* Title */}\n <p className=\"font-mono text-sm uppercase tracking-wider text-muted-foreground\">\n {title}\n </p>\n\n {/* Description */}\n {description && (\n <p className=\"mt-2 text-xs text-muted-foreground/60\">{description}</p>\n )}\n\n {/* Action */}\n {action && <div className=\"mt-4\">{action}</div>}\n </div>\n </div>\n );\n}\n","import { cn } from \"../../lib/utils\";\n\nexport interface KbdProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode;\n}\n\n/**\n * Keyboard shortcut badge component\n *\n * @example\n * ```tsx\n * <Kbd>⌘K</Kbd>\n * <Kbd>ESC</Kbd>\n * ```\n */\nexport function Kbd({ className, children, ...props }: KbdProps) {\n return (\n <kbd\n className={cn(\n \"pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground\",\n className,\n )}\n {...props}\n >\n {children}\n </kbd>\n );\n}\n","import { MagnifyingGlass, SpinnerGap, X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupButton,\n InputGroupInput,\n} from \"./input-group\";\nimport { Kbd } from \"./kbd\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SearchInputProps extends Omit<\n React.ComponentProps<\"input\">,\n \"type\"\n> {\n /**\n * Keyboard shortcut to display (e.g., \"⌘K\")\n */\n shortcut?: string;\n\n /**\n * Callback when clear button is clicked\n */\n onClear?: () => void;\n\n /**\n * Show loading spinner instead of search icon\n */\n isLoading?: boolean;\n\n /**\n * Additional className for the container\n */\n containerClassName?: string;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * SearchInput - Consistent search input with icon, loading state, clear button, and keyboard shortcut\n *\n * @example\n * ```tsx\n * // Basic usage\n * <SearchInput\n * value={searchTerm}\n * onChange={(e) => setSearchTerm(e.target.value)}\n * onClear={() => setSearchTerm(\"\")}\n * placeholder=\"Search...\"\n * />\n *\n * // With keyboard shortcut\n * <SearchInput\n * shortcut=\"⌘K\"\n * onClick={openSearchDialog}\n * readOnly\n * />\n *\n * // Loading state\n * <SearchInput isLoading={isSearching} ... />\n * ```\n */\nexport function SearchInput({\n shortcut,\n onClear,\n isLoading = false,\n containerClassName,\n className,\n value,\n ...props\n}: SearchInputProps): React.ReactElement {\n const hasValue = value !== undefined && value !== \"\";\n const showClearButton = hasValue && onClear;\n const showShortcut = shortcut && !hasValue;\n\n return (\n <InputGroup className={cn(\"bg-transparent\", containerClassName)}>\n <InputGroupAddon align=\"inline-start\">\n {isLoading ? (\n <SpinnerGap className=\"size-4 animate-spin text-muted-foreground\" />\n ) : (\n <MagnifyingGlass className=\"size-4 text-muted-foreground\" />\n )}\n </InputGroupAddon>\n\n <InputGroupInput\n placeholder=\"Search...\"\n value={value}\n className={className}\n {...props}\n />\n\n {(showClearButton || showShortcut) && (\n <InputGroupAddon align=\"inline-end\">\n {showClearButton && (\n <InputGroupButton\n onClick={onClear}\n size=\"icon-xs\"\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <X className=\"size-3\" />\n </InputGroupButton>\n )}\n {showShortcut && <Kbd>{shortcut}</Kbd>}\n </InputGroupAddon>\n )}\n </InputGroup>\n );\n}\n","import type * as React from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\nfunction Table({ className, ...props }: React.ComponentProps<\"table\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"table-container\"\n\t\t\tclassName=\"relative w-full overflow-x-auto scrollbar-thin\"\n\t\t>\n\t\t\t<table\n\t\t\t\tdata-slot=\"table\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"w-full caption-bottom text-xs border-separate border-spacing-0\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<\"thead\">) {\n\treturn (\n\t\t<thead\n\t\t\tdata-slot=\"table-header\"\n\t\t\tclassName={cn(\n\t\t\t\t\"[&_tr]:border-b [&_tr]:border-border/40 bg-muted/80 sticky top-0 z-10\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\n\treturn (\n\t\t<tbody\n\t\t\tdata-slot=\"table-body\"\n\t\t\tclassName={cn(\"[&_tr:last-child]:border-0\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\n\treturn (\n\t\t<tfoot\n\t\t\tdata-slot=\"table-footer\"\n\t\t\tclassName={cn(\n\t\t\t\t\"bg-card/10 backdrop-blur-sm border-t border-border/40 font-medium [&>tr]:last:border-b-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\n\treturn (\n\t\t<tr\n\t\t\tdata-slot=\"table-row\"\n\t\t\tclassName={cn(\n\t\t\t\t// Alternating row colors (zebra striping) with solid backgrounds\n\t\t\t\t// Using group/row for sticky cells to match\n\t\t\t\t\"group/row bg-background hover:bg-muted data-[state=selected]:bg-accent border-b border-border/30 transition-colors\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\ninterface TableHeadProps extends React.ComponentProps<\"th\"> {\n\t/** Make this column sticky on the left. Value is the left offset in pixels. */\n\tstickyLeft?: number;\n\t/** Show separator border on the right (for last sticky column) */\n\tshowStickyBorder?: boolean;\n}\n\nfunction TableHead({\n\tclassName,\n\tstickyLeft,\n\tshowStickyBorder,\n\tstyle,\n\t...props\n}: TableHeadProps) {\n\tconst isSticky = stickyLeft !== undefined;\n\treturn (\n\t\t<th\n\t\t\tdata-slot=\"table-head\"\n\t\t\tdata-sticky-left={isSticky ? \"\" : undefined}\n\t\t\tclassName={cn(\n\t\t\t\t\"text-foreground bg-card h-10 px-2 text-left align-middle whitespace-nowrap [&:has([role=checkbox])]:px-2 font-mono text-[10px] font-black uppercase tracking-[0.1em] min-w-[100px]\",\n\t\t\t\t// Sticky column styles - solid background\n\t\t\t\tisSticky && \"sticky z-20 min-w-0\",\n\t\t\t\t// Only show border on last sticky column\n\t\t\t\tshowStickyBorder &&\n\t\t\t\t\t\"after:absolute after:right-0 after:top-0 after:bottom-0 after:w-px after:bg-border\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tstyle={{\n\t\t\t\t...style,\n\t\t\t\t...(isSticky ? { left: stickyLeft } : {}),\n\t\t\t}}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\ninterface TableCellProps extends React.ComponentProps<\"td\"> {\n\t/** Make this column sticky on the left. Value is the left offset in pixels. */\n\tstickyLeft?: number;\n\t/** Show separator border on the right (for last sticky column) */\n\tshowStickyBorder?: boolean;\n}\n\nfunction TableCell({\n\tclassName,\n\tstickyLeft,\n\tshowStickyBorder,\n\tstyle,\n\t...props\n}: TableCellProps) {\n\tconst isSticky = stickyLeft !== undefined;\n\treturn (\n\t\t<td\n\t\t\tdata-slot=\"table-cell\"\n\t\t\tdata-sticky-left={isSticky ? \"\" : undefined}\n\t\t\tclassName={cn(\n\t\t\t\t\"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:px-2 min-w-[100px]\",\n\t\t\t\t// Sticky column styles - inherit row background for zebra/hover/selected\n\t\t\t\tisSticky && \"sticky bg-inherit z-10 min-w-0\",\n\t\t\t\t// Only show border on last sticky column\n\t\t\t\tshowStickyBorder &&\n\t\t\t\t\t\"after:absolute after:right-0 after:top-0 after:bottom-0 after:w-px after:bg-border\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tstyle={{\n\t\t\t\t...style,\n\t\t\t\t...(isSticky ? { left: stickyLeft } : {}),\n\t\t\t}}\n\t\t\t{...props}\n\t\t>\n\t\t\t{props.children}\n\t\t</td>\n\t);\n}\n\nfunction TableCaption({\n\tclassName,\n\t...props\n}: React.ComponentProps<\"caption\">) {\n\treturn (\n\t\t<caption\n\t\t\tdata-slot=\"table-caption\"\n\t\t\tclassName={cn(\"text-muted-foreground mt-4 text-xs\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nexport {\n\tTable,\n\tTableHeader,\n\tTableBody,\n\tTableFooter,\n\tTableHead,\n\tTableRow,\n\tTableCell,\n\tTableCaption,\n};\n\nexport type { TableHeadProps, TableCellProps };\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\n\n// ============================================================================\n// Toolbar\n// ============================================================================\n\nexport interface ToolbarProps extends React.ComponentProps<\"div\"> {\n /**\n * Children elements\n */\n children: React.ReactNode;\n}\n\n/**\n * Toolbar - Container for toolbar elements with glass effect\n *\n * @example\n * ```tsx\n * <Toolbar>\n * <ToolbarSection className=\"flex-1\">\n * <SearchInput value={search} onChange={setSearch} />\n * </ToolbarSection>\n * <ToolbarSeparator />\n * <ToolbarSection>\n * <Button variant=\"outline\" size=\"sm\">Options</Button>\n * </ToolbarSection>\n * </Toolbar>\n * ```\n */\nexport function Toolbar({\n children,\n className,\n ...props\n}: ToolbarProps): React.ReactElement {\n return (\n <div\n data-slot=\"toolbar\"\n className={cn(\n \"bg-card/10 backdrop-blur-sm border border-border/40\",\n \"p-1 flex items-center gap-2\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n}\n\n// ============================================================================\n// ToolbarSection\n// ============================================================================\n\nexport interface ToolbarSectionProps extends React.ComponentProps<\"div\"> {\n /**\n * Children elements\n */\n children: React.ReactNode;\n}\n\n/**\n * ToolbarSection - Group of related toolbar elements\n */\nexport function ToolbarSection({\n children,\n className,\n ...props\n}: ToolbarSectionProps): React.ReactElement {\n return (\n <div\n data-slot=\"toolbar-section\"\n className={cn(\"flex items-center gap-1\", className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n\n// ============================================================================\n// ToolbarSeparator\n// ============================================================================\n\nexport interface ToolbarSeparatorProps extends React.ComponentProps<\"div\"> {}\n\n/**\n * ToolbarSeparator - Vertical separator between toolbar sections\n */\nexport function ToolbarSeparator({\n className,\n ...props\n}: ToolbarSeparatorProps): React.ReactElement {\n return (\n <div\n data-slot=\"toolbar-separator\"\n className={cn(\"h-4 w-px bg-border/40\", className)}\n {...props}\n />\n );\n}\n\n// ============================================================================\n// ToolbarGroup\n// ============================================================================\n\nexport interface ToolbarGroupProps extends React.ComponentProps<\"div\"> {\n /**\n * Children elements\n */\n children: React.ReactNode;\n}\n\n/**\n * ToolbarGroup - Tightly grouped toolbar buttons (no gap)\n */\nexport function ToolbarGroup({\n children,\n className,\n ...props\n}: ToolbarGroupProps): React.ReactElement {\n return (\n <div\n data-slot=\"toolbar-group\"\n className={cn(\"flex items-center\", className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n","/**\n * Floating Toolbar\n *\n * Unified floating toolbar that displays when:\n * - Rows are selected in a table view (bulk actions)\n * - Filters are active (filter indicator)\n *\n * Combines both functionalities into a single non-jumping UI element.\n */\n\n\"use client\";\n\nimport { CaretDown, Funnel, X } from \"@phosphor-icons/react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { Table } from \"@tanstack/react-table\";\nimport * as React from \"react\";\nimport type {\n\tActionContext,\n\tActionDefinition,\n\tActionHelpers,\n\tActionQueryClient,\n} from \"../../builder/collection/action-types\";\nimport { ConfirmationDialog } from \"../../components/actions/confirmation-dialog\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuSeparator,\n\tDropdownMenuTrigger,\n} from \"../../components/ui/dropdown-menu\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { selectAuthClient, useAdminStore } from \"../../runtime/provider\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface BulkActionToolbarProps<TItem = any> {\n\t/** TanStack Table instance */\n\ttable: Table<TItem>;\n\t/** Bulk actions to display */\n\tactions: ActionDefinition<TItem>[];\n\t/** Collection name */\n\tcollection: string;\n\t/** Action helpers */\n\thelpers: ActionHelpers;\n\t/** Total count of items matching current filter (for \"select all matching\") */\n\ttotalCount?: number;\n\t/** Number of items on current page */\n\tpageCount?: number;\n\t/** Callback when action dialog should open */\n\tonOpenDialog?: (action: ActionDefinition<TItem>, items: TItem[]) => void;\n\t/** Callback to select all items matching current filter */\n\tonSelectAllMatching?: () => Promise<void>;\n\t/** Callback to execute bulk delete */\n\tonBulkDelete?: (ids: string[]) => Promise<void>;\n\t/** Number of active filters (for filter indicator segment) */\n\tfilterCount?: number;\n\t/** Callback to clear all filters */\n\tonClearFilters?: () => void;\n\t/** Callback to open filter sheet */\n\tonOpenFilters?: () => void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * BulkActionToolbar - Shows selection count and bulk actions\n *\n * @example\n * ```tsx\n * {selectedItems.length > 0 && (\n * <BulkActionToolbar\n * table={table}\n * actions={bulkActions}\n * collection=\"posts\"\n * helpers={actionHelpers}\n * totalCount={totalItems}\n * pageCount={items.length}\n * />\n * )}\n * ```\n */\nexport function BulkActionToolbar<TItem = any>({\n\ttable,\n\tactions,\n\tcollection,\n\thelpers,\n\ttotalCount,\n\tpageCount,\n\tonOpenDialog,\n\tonSelectAllMatching,\n\tonBulkDelete,\n\tfilterCount = 0,\n\tonClearFilters,\n\tonOpenFilters,\n}: BulkActionToolbarProps<TItem>): React.ReactElement | null {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\tconst authClient = useAdminStore(selectAuthClient);\n\tconst queryClient = useQueryClient();\n\tconst [confirmAction, setConfirmAction] =\n\t\tReact.useState<ActionDefinition<TItem> | null>(null);\n\tconst [isLoading, setIsLoading] = React.useState(false);\n\tconst [isSelectingAll, setIsSelectingAll] = React.useState(false);\n\n\t// Wrapped query client for action context\n\tconst actionQueryClient: ActionQueryClient = React.useMemo(\n\t\t() => ({\n\t\t\tinvalidateQueries: (filters) => queryClient.invalidateQueries(filters),\n\t\t\trefetchQueries: (filters) => queryClient.refetchQueries(filters),\n\t\t\tresetQueries: (filters) => queryClient.resetQueries(filters),\n\t\t}),\n\t\t[queryClient],\n\t);\n\n\t// Get selected items\n\tconst selectedRows = table.getSelectedRowModel().rows;\n\tconst selectedItems = React.useMemo(\n\t\t() => selectedRows.map((row) => row.original),\n\t\t[selectedRows],\n\t);\n\tconst selectedCount = selectedItems.length;\n\n\t// Build action context for bulk operations\n\tconst ctx: ActionContext<TItem[]> = React.useMemo(\n\t\t() => ({\n\t\t\titem: selectedItems,\n\t\t\tcollection,\n\t\t\thelpers,\n\t\t\tqueryClient: actionQueryClient,\n\t\t\tauthClient,\n\t\t}),\n\t\t[selectedItems, collection, helpers, actionQueryClient, authClient],\n\t);\n\n\t// Filter visible actions\n\tconst visibleActions = React.useMemo(() => {\n\t\treturn actions.filter((action) => {\n\t\t\tif (action.visible === undefined) return true;\n\t\t\tif (typeof action.visible === \"function\") {\n\t\t\t\t// For bulk actions, pass the array of items\n\t\t\t\treturn action.visible(ctx as any);\n\t\t\t}\n\t\t\treturn action.visible;\n\t\t});\n\t}, [actions, ctx]);\n\n\t// Don't render if nothing selected AND no active filters (after all hooks)\n\tconst hasFilters = filterCount > 0;\n\tconst hasSelection = selectedCount > 0;\n\tif (!hasSelection && !hasFilters) return null;\n\n\t// Execute bulk action handler\n\tconst executeBulkAction = async (action: ActionDefinition<TItem>) => {\n\t\tconst { handler } = action;\n\n\t\t// Handle built-in deleteMany action\n\t\tif (action.id === \"deleteMany\" && onBulkDelete) {\n\t\t\tsetIsLoading(true);\n\t\t\ttry {\n\t\t\t\tconst ids = selectedItems.map((item: any) => item?.id).filter(Boolean);\n\t\t\t\tawait onBulkDelete(ids);\n\t\t\t\ttable.resetRowSelection();\n\t\t\t} catch (_error) {\n\t\t\t\thelpers.toast.error(t(\"collection.bulkDeleteError\"));\n\t\t\t} finally {\n\t\t\t\tsetIsLoading(false);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (handler.type) {\n\t\t\tcase \"api\": {\n\t\t\t\tsetIsLoading(true);\n\t\t\t\ttry {\n\t\t\t\t\t// For bulk API calls, would need to send all IDs\n\t\t\t\t\tconst ids = selectedItems\n\t\t\t\t\t\t.map((item: any) => item?.id)\n\t\t\t\t\t\t.filter(Boolean);\n\t\t\t\t\thelpers.toast.info(\n\t\t\t\t\t\t`Bulk API call: ${handler.method || \"POST\"} ${handler.endpoint} (${ids.length} items)`,\n\t\t\t\t\t);\n\t\t\t\t\thelpers.refresh();\n\t\t\t\t\ttable.resetRowSelection();\n\t\t\t\t} catch (_error) {\n\t\t\t\t\thelpers.toast.error(t(\"collection.bulkActionFailed\"));\n\t\t\t\t} finally {\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"custom\": {\n\t\t\t\tsetIsLoading(true);\n\t\t\t\ttry {\n\t\t\t\t\t// Pass all items to the custom handler\n\t\t\t\t\tawait handler.fn(ctx as any);\n\t\t\t\t\ttable.resetRowSelection();\n\t\t\t\t} catch (_error) {\n\t\t\t\t\thelpers.toast.error(t(\"collection.bulkActionFailed\"));\n\t\t\t\t} finally {\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"dialog\":\n\t\t\tcase \"form\": {\n\t\t\t\tonOpenDialog?.(action, selectedItems);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"navigate\": {\n\t\t\t\t// Navigate doesn't make sense for bulk actions\n\t\t\t\thelpers.toast.error(\n\t\t\t\t\t\"Navigate action not supported for bulk operations\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Handle action click\n\tconst handleActionClick = (action: ActionDefinition<TItem>) => {\n\t\tif (action.confirmation) {\n\t\t\tsetConfirmAction(action);\n\t\t} else {\n\t\t\texecuteBulkAction(action);\n\t\t}\n\t};\n\n\t// Handle confirmation\n\tconst handleConfirm = async () => {\n\t\tif (confirmAction) {\n\t\t\tawait executeBulkAction(confirmAction);\n\t\t\tsetConfirmAction(null);\n\t\t}\n\t};\n\n\t// Handle select all matching\n\tconst handleSelectAllMatching = async () => {\n\t\tif (!onSelectAllMatching) return;\n\t\tsetIsSelectingAll(true);\n\t\ttry {\n\t\t\tawait onSelectAllMatching();\n\t\t} finally {\n\t\t\tsetIsSelectingAll(false);\n\t\t}\n\t};\n\n\t// Check if action is disabled\n\tconst isDisabled = (action: ActionDefinition<TItem>) => {\n\t\tif (action.disabled === undefined) return false;\n\t\tif (typeof action.disabled === \"function\") {\n\t\t\treturn action.disabled(ctx as any);\n\t\t}\n\t\treturn action.disabled;\n\t};\n\n\t// Group actions: regular and destructive\n\tconst regularActions = visibleActions.filter(\n\t\t(a) => a.variant !== \"destructive\",\n\t);\n\tconst destructiveActions = visibleActions.filter(\n\t\t(a) => a.variant === \"destructive\",\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{/* Fixed toolbar at bottom of screen */}\n\t\t\t<div className=\"fixed bottom-6 left-1/2 -translate-x-1/2 z-50 animate-in slide-in-from-bottom-4 fade-in duration-200 max-w-[calc(100%-2rem)] sm:max-w-none\">\n\t\t\t\t<div className=\"flex items-center gap-2 sm:gap-3 px-3 sm:px-4 py-2 sm:py-2.5 bg-background/95 backdrop-blur-md border border-border shadow-lg rounded-full overflow-x-auto\">\n\t\t\t\t\t{/* Filter segment - shows when filters are active */}\n\t\t\t\t\t{hasFilters && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div className=\"flex items-center gap-2 shrink-0\">\n\t\t\t\t\t\t\t\t{onOpenFilters ? (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\tonClick={onOpenFilters}\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 px-2 text-xs gap-2\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Funnel size={14} weight=\"fill\" className=\"text-primary\" />\n\t\t\t\t\t\t\t\t\t\t{t(\"viewOptions.activeFilters\", { count: filterCount })}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<Funnel size={14} weight=\"fill\" className=\"text-primary\" />\n\t\t\t\t\t\t\t\t\t\t<span className=\"text-sm font-medium whitespace-nowrap\">\n\t\t\t\t\t\t\t\t\t\t\t{t(\"viewOptions.activeFilters\", { count: filterCount })}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{onClearFilters && (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\tonClick={onClearFilters}\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 px-2 text-xs\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{t(\"viewOptions.clearFilters\")}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Divider between filter and selection segments */}\n\t\t\t\t\t\t\t{hasSelection && <div className=\"h-4 w-px bg-border shrink-0\" />}\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Selection segment - shows when rows are selected */}\n\t\t\t\t\t{hasSelection && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{/* Selection count */}\n\t\t\t\t\t\t\t<span className=\"text-sm font-medium whitespace-nowrap shrink-0\">\n\t\t\t\t\t\t\t\t{t(\"collection.selected\", { count: selectedCount })}\n\t\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t\t{/* Divider */}\n\t\t\t\t\t\t\t<div className=\"h-4 w-px bg-border shrink-0\" />\n\n\t\t\t\t\t\t\t{/* Select dropdown */}\n\t\t\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t\t\t<DropdownMenuTrigger\n\t\t\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"gap-1 h-7 px-2 shrink-0\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdisabled={isSelectingAll}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{t(\"common.selectAll\").split(\" \")[0]}\n\t\t\t\t\t\t\t\t\t<CaretDown className=\"size-3\" />\n\t\t\t\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t\t\t\t<DropdownMenuContent align=\"center\" side=\"top\" sideOffset={8}>\n\t\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\t\tonClick={() => table.toggleAllPageRowsSelected(true)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{t(\"collection.selectOnPage\")}\n\t\t\t\t\t\t\t\t\t\t{pageCount ? ` (${pageCount})` : \"\"}\n\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t{onSelectAllMatching &&\n\t\t\t\t\t\t\t\t\t\ttotalCount &&\n\t\t\t\t\t\t\t\t\t\ttotalCount > (pageCount ?? 0) && (\n\t\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem onClick={handleSelectAllMatching}>\n\t\t\t\t\t\t\t\t\t\t\t\t{t(\"collection.selectAllMatching\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\tcount: totalCount,\n\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t\t\t\t\t<DropdownMenuItem onClick={() => table.resetRowSelection()}>\n\t\t\t\t\t\t\t\t\t\t{t(\"collection.clearSelection\")}\n\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t\t\t</DropdownMenu>\n\n\t\t\t\t\t\t\t{/* Bulk actions dropdown */}\n\t\t\t\t\t\t\t{visibleActions.length > 0 && (\n\t\t\t\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t\t\t\t<DropdownMenuTrigger\n\t\t\t\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"gap-1 h-7 px-2 shrink-0\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{t(\"common.actions\")}\n\t\t\t\t\t\t\t\t\t\t<CaretDown className=\"size-3\" />\n\t\t\t\t\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t\t\t\t\t<DropdownMenuContent align=\"center\" side=\"top\" sideOffset={8}>\n\t\t\t\t\t\t\t\t\t\t{regularActions.map((action) => {\n\t\t\t\t\t\t\t\t\t\t\tconst Icon = action.icon as\n\t\t\t\t\t\t\t\t\t\t\t\t| React.ComponentType<React.SVGProps<SVGSVGElement>>\n\t\t\t\t\t\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleActionClick(action)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={isDisabled(action) || isLoading}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{Icon && <Icon className=\"mr-2 size-4\" />}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{resolveText(action.label)}\n\t\t\t\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t})}\n\n\t\t\t\t\t\t\t\t\t\t{regularActions.length > 0 &&\n\t\t\t\t\t\t\t\t\t\t\tdestructiveActions.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{destructiveActions.map((action) => {\n\t\t\t\t\t\t\t\t\t\t\tconst Icon = action.icon as\n\t\t\t\t\t\t\t\t\t\t\t\t| React.ComponentType<React.SVGProps<SVGSVGElement>>\n\t\t\t\t\t\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={action.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"destructive\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleActionClick(action)}\n\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={isDisabled(action) || isLoading}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{Icon && <Icon className=\"mr-2 size-4\" />}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{resolveText(action.label)}\n\t\t\t\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t\t\t\t</DropdownMenu>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Clear selection button */}\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon-sm\"\n\t\t\t\t\t\t\t\tonClick={() => table.resetRowSelection()}\n\t\t\t\t\t\t\t\tclassName=\"size-7 shrink-0\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<X className=\"size-4\" />\n\t\t\t\t\t\t\t\t<span className=\"sr-only\">\n\t\t\t\t\t\t\t\t\t{t(\"collection.clearSelection\")}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Confirmation dialog */}\n\t\t\t{confirmAction?.confirmation && (\n\t\t\t\t<ConfirmationDialog\n\t\t\t\t\topen={!!confirmAction}\n\t\t\t\t\tonOpenChange={(open) => !open && setConfirmAction(null)}\n\t\t\t\t\tconfig={{\n\t\t\t\t\t\t...confirmAction.confirmation,\n\t\t\t\t\t\t// Override description to include count\n\t\t\t\t\t\tdescription: confirmAction.confirmation.description\n\t\t\t\t\t\t\t? `${confirmAction.confirmation.description} (${selectedCount} items)`\n\t\t\t\t\t\t\t: `This will affect ${selectedCount} items.`,\n\t\t\t\t\t}}\n\t\t\t\t\tonConfirm={handleConfirm}\n\t\t\t\t\tloading={isLoading}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","/**\n * Collection Builder Types\n */\n\nimport type { I18nText } from \"../../i18n/types.js\";\nimport type { AdminBuilder } from \"../admin-builder\";\nimport type { FieldDefinition } from \"../field/field\";\nimport type { IconComponent, MaybeLazyComponent } from \"../types/common\";\nimport type { FormViewConfig } from \"../types/field-types\";\nimport type { ActionsConfig } from \"./action-types\";\n\n/**\n * Collection metadata for navigation and display\n */\nexport interface CollectionMeta {\n\t/** Display label - supports inline translations */\n\tlabel?: I18nText;\n\ticon?: IconComponent | string;\n\tgroup?: string;\n\torder?: number;\n\thidden?: boolean;\n}\n\n// ============================================================================\n// Column Configuration\n// ============================================================================\n\n/**\n * Column configuration for list views\n * Can be a simple field name or detailed config object\n */\nexport type ColumnConfig<TFieldNames extends string = string> =\n\t| TFieldNames\n\t| ColumnConfigObject<TFieldNames>;\n\n/**\n * Detailed column configuration object\n */\nexport interface ColumnConfigObject<TFieldNames extends string = string> {\n\t/**\n\t * Field name to display\n\t */\n\tfield: TFieldNames;\n\n\t/**\n\t * Custom header label (defaults to field label)\n\t */\n\theader?: string;\n\n\t/**\n\t * Column width (CSS value like \"200px\", \"20%\", etc.)\n\t */\n\twidth?: string | number;\n\n\t/**\n\t * Minimum column width\n\t */\n\tminWidth?: string | number;\n\n\t/**\n\t * Maximum column width\n\t */\n\tmaxWidth?: string | number;\n\n\t/**\n\t * Enable sorting for this column\n\t * @default true\n\t */\n\tsortable?: boolean;\n\n\t/**\n\t * Custom cell renderer component\n\t * Overrides the field's default cell component\n\t */\n\tcell?: MaybeLazyComponent;\n\n\t/**\n\t * Column visibility\n\t * Can be a boolean or function for conditional visibility\n\t */\n\tvisible?: boolean | ((row: any) => boolean);\n\n\t/**\n\t * Custom CSS class for column cells\n\t */\n\tclassName?: string;\n\n\t/**\n\t * Text alignment\n\t */\n\talign?: \"left\" | \"center\" | \"right\";\n}\n\n/**\n * Helper to normalize column config to field name\n */\nexport function getColumnFieldName<T extends string>(\n\tcolumn: ColumnConfig<T>,\n): T {\n\treturn typeof column === \"string\" ? column : column.field;\n}\n\n/**\n * Helper to get column config object (normalizes string to object)\n */\nexport function normalizeColumnConfig<T extends string>(\n\tcolumn: ColumnConfig<T>,\n): ColumnConfigObject<T> {\n\treturn typeof column === \"string\" ? { field: column } : column;\n}\n\n// ============================================================================\n// List View Configuration\n// ============================================================================\n\n/**\n * List view configuration\n */\nexport interface ListViewConfig<TFieldNames extends string = string> {\n\t/**\n\t * Columns to display (field names or column configs)\n\t */\n\tcolumns?: ColumnConfig<TFieldNames>[];\n\n\t/**\n\t * Relations to include in query\n\t */\n\twith?: string[];\n\n\t/**\n\t * Default sort\n\t */\n\tdefaultSort?: {\n\t\tfield: TFieldNames;\n\t\tdirection: \"asc\" | \"desc\";\n\t};\n\n\t/**\n\t * Enable search\n\t * @default true\n\t */\n\tsearchable?: boolean;\n\n\t/**\n\t * Searchable fields (defaults to all text-like fields)\n\t */\n\tsearchFields?: TFieldNames[];\n\n\t/**\n\t * Enable row selection\n\t * @default false\n\t */\n\tselectable?: boolean;\n\n\t/**\n\t * Enable pagination\n\t * @default true\n\t */\n\tpaginated?: boolean;\n\n\t/**\n\t * Default page size\n\t * @default 25\n\t */\n\tpageSize?: number;\n\n\t/**\n\t * Available page size options\n\t * @default [10, 25, 50, 100]\n\t */\n\tpageSizeOptions?: number[];\n\n\t/**\n\t * Actions configuration for list view\n\t */\n\tactions?: ActionsConfig;\n}\n\n/**\n * Collection configuration - runtime config object\n */\nexport interface CollectionConfig<TFieldNames extends string = string> {\n\t/**\n\t * Collection name\n\t */\n\tname: string;\n\n\t/**\n\t * Collection metadata (for navigation/display)\n\t */\n\tmeta?: CollectionMeta;\n\n\t/**\n\t * Display label - supports inline translations\n\t */\n\tlabel?: I18nText;\n\n\t/**\n\t * Icon\n\t */\n\ticon?: IconComponent | string;\n\n\t/**\n\t * Description - supports inline translations\n\t */\n\tdescription?: I18nText;\n\n\t/**\n\t * Field configurations (FieldDefinition objects)\n\t */\n\tfields?: Record<string, FieldDefinition>;\n\n\t/**\n\t * List view configuration\n\t */\n\tlist?: ListViewConfig<TFieldNames>;\n\n\t/**\n\t * Form view configuration\n\t */\n\tform?: FormViewConfig;\n\n\t/**\n\t * Navigation group\n\t */\n\tgroup?: string;\n\n\t/**\n\t * Sort order\n\t */\n\torder?: number;\n\n\t/**\n\t * Hide from navigation\n\t */\n\thidden?: boolean;\n}\n\n/**\n * Preview configuration for live preview in form view\n */\nexport interface PreviewConfig {\n\t/**\n\t * URL builder function that returns preview URL for current form values\n\t * @param values - Current form values\n\t * @param locale - Current content locale\n\t * @returns Preview URL string\n\t */\n\turl: (values: Record<string, unknown>, locale: string) => string;\n\t/**\n\t * Whether preview is enabled (default: true)\n\t */\n\tenabled?: boolean;\n\t/**\n\t * Position of the preview panel (default: \"right\")\n\t */\n\tposition?: \"right\" | \"bottom\";\n\t/**\n\t * Default width/height percentage of preview panel (default: 50)\n\t */\n\tdefaultWidth?: number;\n\t/**\n\t * Minimum width/height percentage (default: 30)\n\t */\n\tminWidth?: number;\n\t/**\n\t * Maximum width/height percentage (default: 70)\n\t */\n\tmaxWidth?: number;\n}\n\n/**\n * Autosave configuration for form view\n */\nexport interface AutoSaveConfig {\n\t/**\n\t * Whether autosave is enabled\n\t * @default false\n\t */\n\tenabled?: boolean;\n\t/**\n\t * Debounce delay in milliseconds before autosave triggers\n\t * @default 500 (0.5s as specified)\n\t */\n\tdebounce?: number;\n\t/**\n\t * Show autosave status indicator in form header\n\t * @default true\n\t */\n\tindicator?: boolean;\n\t/**\n\t * Warn user before navigating away with unsaved changes\n\t * @default true\n\t */\n\tpreventNavigation?: boolean;\n}\n\n/**\n * Collection builder state - internal state during building\n */\nexport interface CollectionBuilderState<\n\tTAdminApp extends AdminBuilder<any> = AdminBuilder<any>,\n> {\n\treadonly name: string;\n\treadonly \"~adminApp\": TAdminApp;\n\t/** Display label - supports inline translations */\n\treadonly label?: I18nText;\n\t/** Description - supports inline translations */\n\treadonly description?: I18nText;\n\treadonly icon?: IconComponent;\n\treadonly fields?: Record<string, FieldDefinition<any, any>>;\n\treadonly list?: any; // View result from .list() callback\n\treadonly form?: any; // View result from .form() callback\n\treadonly preview?: PreviewConfig; // Preview configuration\n\treadonly autoSave?: AutoSaveConfig; // Autosave configuration\n}\n","/**\n * Column Defaults Computation\n *\n * Functions for computing default visible columns and available fields\n * Extracted from build-columns.tsx\n */\n\nimport type { FieldDefinition } from \"../../../builder/field/field\";\nimport { formatFieldLabel } from \"../cells/shared/cell-helpers\";\nimport type { ColumnField, ComputeDefaultColumnsOptions } from \"./types\";\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * System fields that are typically auto-generated and not user-editable\n */\nexport const SYSTEM_FIELDS = new Set([\n\t\"id\",\n\t\"createdAt\",\n\t\"updatedAt\",\n\t\"deletedAt\",\n\t\"createdBy\",\n\t\"updatedBy\",\n]);\n\n/**\n * Field types that are typically not shown by default in list view\n * (too complex or take up too much space)\n */\nexport const EXCLUDED_DEFAULT_FIELD_TYPES = new Set([\n\t\"relation\",\n\t\"reverseRelation\",\n\t\"upload\",\n\t\"uploadMany\",\n\t\"json\",\n\t\"object\",\n\t\"richText\",\n\t\"textarea\",\n]);\n\n/**\n * Maximum number of content fields to show by default\n */\nexport const MAX_DEFAULT_CONTENT_FIELDS = 4;\n\n// ============================================================================\n// Default Column Computation\n// ============================================================================\n\n/**\n * Compute sane default visible columns for a collection\n *\n * Default columns are selected with the following logic:\n * 1. If configuredColumns is provided (from .list()), use those + title\n * 2. Otherwise, auto-detect:\n * - Title field first\n * - Up to 4 content fields (non-system, non-relation, non-upload)\n * - `createdAt` at the end (if timestamps enabled)\n *\n * @param fields - Field definitions from collection config\n * @param options - Optional metadata and configured columns\n * @returns Array of field names for default visible columns\n */\nexport function computeDefaultColumns(\n\tfields?: Record<string, FieldDefinition>,\n\toptions?: ComputeDefaultColumnsOptions,\n): string[] {\n\t// Determine the title column to use\n\tconst titleFieldName = options?.meta?.title?.fieldName;\n\tconst titleType = options?.meta?.title?.type;\n\tconst useTitleField = titleType === \"field\" && titleFieldName;\n\tconst titleColumn = useTitleField ? titleFieldName : \"_title\";\n\n\t// If columns are explicitly configured in .list(), use those\n\tif (options?.configuredColumns && options.configuredColumns.length > 0) {\n\t\tconst configuredNames = options.configuredColumns.map((col) =>\n\t\t\ttypeof col === \"string\" ? col : col.field,\n\t\t);\n\n\t\t// Always include title column first, then configured columns (excluding title to avoid dupe)\n\t\tconst defaultCols: string[] = [titleColumn];\n\t\tfor (const colName of configuredNames) {\n\t\t\tif (colName !== titleColumn) {\n\t\t\t\tdefaultCols.push(colName);\n\t\t\t}\n\t\t}\n\t\treturn defaultCols;\n\t}\n\n\t// No configured columns - auto-detect defaults\n\tconst defaultCols: string[] = [titleColumn];\n\n\tif (!fields || Object.keys(fields).length === 0) {\n\t\treturn defaultCols;\n\t}\n\n\t// Get content fields (non-system, non-excluded types)\n\tconst contentFields = Object.entries(fields)\n\t\t.filter(([key, fieldDef]) => {\n\t\t\t// Skip system fields\n\t\t\tif (SYSTEM_FIELDS.has(key)) return false;\n\n\t\t\t// Skip the title field if we're already showing it\n\t\t\tif (useTitleField && key === titleFieldName) return false;\n\n\t\t\t// Skip complex field types\n\t\t\tconst fieldType = fieldDef?.name ?? \"text\";\n\t\t\tif (EXCLUDED_DEFAULT_FIELD_TYPES.has(fieldType)) return false;\n\n\t\t\treturn true;\n\t\t})\n\t\t.map(([key]) => key);\n\n\t// Add up to MAX_DEFAULT_CONTENT_FIELDS content fields\n\tconst selectedContentFields = contentFields.slice(\n\t\t0,\n\t\tMAX_DEFAULT_CONTENT_FIELDS,\n\t);\n\tdefaultCols.push(...selectedContentFields);\n\n\t// Add createdAt at the end if timestamps enabled (from meta or field existence)\n\tconst hasTimestamps = options?.meta?.timestamps ?? !!fields.createdAt;\n\tif (hasTimestamps && fields.createdAt) {\n\t\tdefaultCols.push(\"createdAt\");\n\t}\n\n\treturn defaultCols;\n}\n\n// ============================================================================\n// Available Fields\n// ============================================================================\n\n/**\n * Get all available fields for the column picker\n *\n * Includes all fields (both content and system fields) so users can\n * choose to display any field in their view.\n *\n * @param fields - Field definitions from collection config\n * @param options - Optional metadata from backend\n * @returns Array of available field info for the column picker\n */\nexport function getAllAvailableFields(\n\tfields?: Record<string, FieldDefinition>,\n\toptions?: ComputeDefaultColumnsOptions,\n): ColumnField[] {\n\tconst availableFields: ColumnField[] = [];\n\n\t// Determine title field from meta\n\tconst titleFieldName = options?.meta?.title?.fieldName;\n\tconst titleType = options?.meta?.title?.type;\n\tconst useTitleField = titleType === \"field\" && titleFieldName;\n\n\t// Only add _title as an option if title is NOT a real field\n\t// (i.e., title is virtual/computed, so _title is the way to access it)\n\tif (!useTitleField) {\n\t\t// For virtual titles, show the virtual field's label instead of generic \"Title\"\n\t\tif (titleType === \"virtual\" && titleFieldName && fields?.[titleFieldName]) {\n\t\t\tconst titleFieldDef = fields[titleFieldName];\n\t\t\tconst titleFieldOptions = titleFieldDef?.[\"~options\"] ?? {};\n\t\t\tconst titleLabel =\n\t\t\t\ttitleFieldOptions.label ?? formatFieldLabel(titleFieldName);\n\t\t\tavailableFields.push({\n\t\t\t\tname: \"_title\",\n\t\t\t\tlabel: titleLabel,\n\t\t\t\ttype: \"text\",\n\t\t\t\tisSystem: false,\n\t\t\t\toptions: undefined,\n\t\t\t});\n\t\t} else {\n\t\t\t// Fallback to generic \"Title\" when no title defined or field not found\n\t\t\tavailableFields.push({\n\t\t\t\tname: \"_title\",\n\t\t\t\tlabel: \"Title\",\n\t\t\t\ttype: \"text\",\n\t\t\t\tisSystem: false,\n\t\t\t\toptions: undefined,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (!fields) return availableFields;\n\n\t// Add all fields from config (except virtual title field to avoid duplication)\n\tfor (const [key, fieldDef] of Object.entries(fields)) {\n\t\t// Skip the virtual title field since we already added _title for it\n\t\tif (titleType === \"virtual\" && key === titleFieldName) continue;\n\n\t\tconst fieldType = fieldDef?.name ?? \"text\";\n\t\tconst fieldOptions = fieldDef?.[\"~options\"] ?? {};\n\t\tconst label = fieldOptions.label ?? formatFieldLabel(key);\n\t\tconst isSystem = SYSTEM_FIELDS.has(key);\n\n\t\tavailableFields.push({\n\t\t\tname: key,\n\t\t\tlabel,\n\t\t\ttype: fieldType,\n\t\t\tisSystem,\n\t\t\toptions: fieldOptions,\n\t\t});\n\t}\n\n\treturn availableFields;\n}\n\n/**\n * Format field name as header (camelCase to Title Case)\n */\nexport function formatHeader(fieldName: string): string {\n\treturn formatFieldLabel(fieldName);\n}\n","/**\n * Column Builder\n *\n * Generates TanStack Table column definitions from collection config.\n * Simplified version - uses field registry or DefaultCell fallback.\n */\n\nimport type { ColumnDef } from \"@tanstack/react-table\";\nimport type * as React from \"react\";\nimport {\n\ttype ColumnConfig,\n\tnormalizeColumnConfig,\n} from \"../../../builder/collection/types\";\nimport type { FieldDefinition } from \"../../../builder/field/field\";\nimport { LocaleSwitcher } from \"../../../components/locale-switcher\";\nimport { useResolveText } from \"../../../i18n/hooks\";\nimport type { I18nText } from \"../../../i18n/types\";\nimport { useSafeContentLocales, useScopedLocale } from \"../../../runtime\";\nimport { DefaultCell, TextCell } from \"../cells\";\nimport { computeDefaultColumns, formatHeader } from \"./column-defaults\";\nimport type { BuildColumnsOptions } from \"./types\";\n\n// ============================================================================\n// Header Component with I18nText Resolution\n// ============================================================================\n\n/**\n * Column header component that resolves I18nText labels\n */\nfunction ColumnHeader({\n\tlabel,\n\tfallback,\n\tlocalized,\n}: {\n\tlabel: I18nText | undefined;\n\tfallback: string;\n\tlocalized?: boolean;\n}) {\n\tconst resolveText = useResolveText();\n\tconst contentLocales = useSafeContentLocales();\n\t// Use scoped locale (from LocaleScopeProvider in ResourceSheet) or global locale\n\tconst { locale: contentLocale, setLocale: setContentLocale } =\n\t\tuseScopedLocale();\n\tconst resolvedLocale =\n\t\tcontentLocale ??\n\t\tcontentLocales?.defaultLocale ??\n\t\tcontentLocales?.locales[0]?.code;\n\tconst localeOptions = contentLocales?.locales?.length\n\t\t? contentLocales.locales\n\t\t: resolvedLocale\n\t\t\t? [{ code: resolvedLocale }]\n\t\t\t: [];\n\tconst showLocaleSwitcher = localized && localeOptions.length > 0;\n\n\treturn (\n\t\t<span className=\"inline-flex items-center gap-1.5\">\n\t\t\t<span>{resolveText(label, fallback)}</span>\n\t\t\t{showLocaleSwitcher && (\n\t\t\t\t<LocaleSwitcher\n\t\t\t\t\tlocales={localeOptions}\n\t\t\t\t\tvalue={resolvedLocale}\n\t\t\t\t\tonChange={setContentLocale}\n\t\t\t\t\tlabelMode=\"code\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t</span>\n\t);\n}\n\n// ============================================================================\n// Field Types Needing fieldDef\n// ============================================================================\n\n/**\n * Field types that need fieldDef passed to their cell component\n * (for nested field definitions, labels, etc.)\n */\nconst FIELD_TYPES_NEEDING_FIELD_DEF = new Set([\n\t\"object\",\n\t\"array\",\n\t\"relation\",\n\t\"reverseRelation\",\n]);\n\n// ============================================================================\n// Column Builder\n// ============================================================================\n\n/**\n * Build column definitions from collection config\n *\n * Simplified cell resolution:\n * 1. Custom from .list() config\n * 2. From field registry (.cell)\n * 3. Ultra-simple DefaultCell fallback\n *\n * NO getCellForFieldType() switch statement needed!\n *\n * @param options - Build options with config and fallbacks\n * @returns Array of TanStack Table column definitions\n *\n * @example\n * ```tsx\n * const columns = buildColumns({\n * config: collectionsConfig.posts,\n * fallbackColumns: ['id', 'title', 'createdAt'],\n * meta: collectionMeta,\n * });\n *\n * <CollectionList collection=\"posts\" columns={columns} />\n * ```\n */\nexport function buildColumns<TData extends Record<string, unknown>>(\n\toptions: BuildColumnsOptions,\n): ColumnDef<TData>[] {\n\tconst {\n\t\tconfig,\n\t\tfallbackColumns = [\"id\"],\n\t\tbuildAllColumns = false,\n\t\tmeta,\n\t} = options;\n\tconst fields = config?.fields ?? {};\n\tconst listConfig = config?.list;\n\n\tconst isLocalizedField = (\n\t\tfield: string,\n\t\tdefinition?: FieldDefinition,\n\t): boolean => {\n\t\tconst fieldOptions = definition?.[\"~options\"] ?? {};\n\t\treturn fieldOptions.localized !== undefined\n\t\t\t? !!fieldOptions.localized\n\t\t\t: (meta?.localizedFields?.includes(field) ?? false);\n\t};\n\n\t// Determine title column based on meta\n\t// If meta says title is a real \"field\", use that field instead of _title\n\tconst titleFieldName = meta?.title?.fieldName;\n\tconst titleType = meta?.title?.type;\n\tconst titleColumn =\n\t\ttitleType === \"field\" && titleFieldName ? titleFieldName : \"_title\";\n\n\t// Determine which columns to build\n\tlet columnConfigs: ColumnConfig<string>[];\n\n\tif (buildAllColumns) {\n\t\t// Build ALL columns for all fields (used when user can toggle visibility)\n\t\t// Include title column (real field or _title) first, then all other fields\n\t\tconst allFields = Object.keys(fields);\n\t\t// If title is a real field, don't duplicate it\n\t\tconst otherFields =\n\t\t\ttitleColumn === \"_title\"\n\t\t\t\t? allFields\n\t\t\t\t: allFields.filter((f) => f !== titleColumn);\n\t\tcolumnConfigs = [titleColumn, ...otherFields];\n\t} else if (listConfig?.columns && listConfig.columns.length > 0) {\n\t\t// Use explicitly defined columns\n\t\tcolumnConfigs = listConfig.columns;\n\t} else if (Object.keys(fields).length > 0) {\n\t\t// Use sane defaults - limited content fields + createdAt\n\t\tcolumnConfigs = computeDefaultColumns(fields, { meta });\n\t} else {\n\t\t// Use fallback - include title column first\n\t\tcolumnConfigs = [\n\t\t\ttitleColumn,\n\t\t\t...fallbackColumns.filter((c) => c !== titleColumn && c !== \"_title\"),\n\t\t];\n\t}\n\n\t// Build column definitions\n\treturn columnConfigs.map((colConfig) => {\n\t\tconst normalized = normalizeColumnConfig(colConfig);\n\t\tconst fieldName = normalized.field;\n\t\tconst fieldDef = fields[fieldName];\n\n\t\t// Special handling for _title virtual field (computed by backend)\n\t\tif (fieldName === \"_title\") {\n\t\t\tconst titleIsLocalized = titleFieldName\n\t\t\t\t? isLocalizedField(titleFieldName, fields[titleFieldName])\n\t\t\t\t: false;\n\t\t\t// Determine the label for _title column\n\t\t\t// For virtual titles, use the virtual field's label instead of generic \"Title\"\n\t\t\tlet titleLabel: I18nText = \"Title\";\n\t\t\tlet titleFallback = \"Title\";\n\t\t\tif (titleType === \"virtual\" && titleFieldName && fields[titleFieldName]) {\n\t\t\t\tconst virtualFieldDef = fields[titleFieldName];\n\t\t\t\tconst virtualFieldOptions = virtualFieldDef?.[\"~options\"] ?? {};\n\t\t\t\ttitleLabel = virtualFieldOptions.label;\n\t\t\t\ttitleFallback = formatHeader(titleFieldName);\n\t\t\t}\n\n\t\t\tconst columnDef: ColumnDef<TData> = {\n\t\t\t\taccessorKey: \"_title\",\n\t\t\t\theader: normalized.header\n\t\t\t\t\t? () => <ColumnHeader label={normalized.header} fallback=\"Title\" />\n\t\t\t\t\t: () => <ColumnHeader label={titleLabel} fallback={titleFallback} />,\n\t\t\t\tcell: ({ row }) => {\n\t\t\t\t\tconst value = row.getValue(\"_title\");\n\t\t\t\t\treturn <TextCell value={value} />;\n\t\t\t\t},\n\t\t\t\tenableSorting: false, // _title is virtual, can't sort on it directly\n\t\t\t};\n\t\t\treturn columnDef;\n\t\t}\n\n\t\tconst fieldType = fieldDef?.name ?? \"text\";\n\t\tconst fieldOptions = fieldDef?.[\"~options\"] ?? {};\n\t\tconst isLocalized = isLocalizedField(fieldName, fieldDef);\n\n\t\t// ========== SIMPLIFIED CELL RESOLUTION ==========\n\t\t// Priority chain - just 3 lines!\n\t\tlet CellComponent: React.ComponentType<{\n\t\t\tvalue: unknown;\n\t\t\trow?: unknown;\n\t\t\tfieldDef?: FieldDefinition;\n\t\t}>;\n\n\t\tif (normalized.cell) {\n\t\t\t// 1. Custom cell from .list() config\n\t\t\tCellComponent = normalized.cell as React.ComponentType<{\n\t\t\t\tvalue: unknown;\n\t\t\t\trow?: unknown;\n\t\t\t\tfieldDef?: FieldDefinition;\n\t\t\t}>;\n\t\t} else if (fieldDef?.cell?.component) {\n\t\t\t// 2. Cell from field registry (most common)\n\t\t\tCellComponent = fieldDef.cell.component as React.ComponentType<{\n\t\t\t\tvalue: unknown;\n\t\t\t\trow?: unknown;\n\t\t\t\tfieldDef?: FieldDefinition;\n\t\t\t}>;\n\t\t} else {\n\t\t\t// 3. Ultra-simple DefaultCell fallback\n\t\t\tCellComponent = DefaultCell;\n\t\t}\n\n\t\t// Check if this field type needs fieldDef passed to the cell\n\t\tconst needsFieldDef = FIELD_TYPES_NEEDING_FIELD_DEF.has(fieldType);\n\n\t\t// For relation fields, use relationName as accessor if specified\n\t\t// This allows fetching expanded relation data (e.g., row.customer) instead of FK (row.customerId)\n\t\t// If relationName is not specified, we use the field name (which shows the raw FK value)\n\t\tconst accessorKey: string =\n\t\t\tfieldType === \"relation\" && fieldOptions.relationName\n\t\t\t\t? fieldOptions.relationName\n\t\t\t\t: fieldName;\n\n\t\t// Build column def\n\t\t// Use fieldName as id (for lookup in visibleColumns) and accessorKey for data access\n\t\tconst headerLabel = normalized.header ?? fieldOptions.label;\n\t\tconst headerFallback = formatHeader(fieldName);\n\t\t// Check if field is computed\n\t\tconst computeFn = fieldOptions.compute as\n\t\t\t| ((values: Record<string, any>) => any)\n\t\t\t| undefined;\n\t\tconst isComputed = typeof computeFn === \"function\";\n\n\t\tconst columnDef: ColumnDef<TData> = {\n\t\t\tid: fieldName, // Always use field name as id for consistent lookup\n\t\t\taccessorKey: isComputed ? undefined : accessorKey, // Computed fields don't have accessor\n\t\t\theader: () => (\n\t\t\t\t<ColumnHeader label={headerLabel} fallback={headerFallback} />\n\t\t\t),\n\t\t\tcell: ({ row, getValue }) => {\n\t\t\t\t// For computed fields, compute value from row data\n\t\t\t\tconst value = isComputed\n\t\t\t\t\t? computeFn(row.original as Record<string, any>)\n\t\t\t\t\t: getValue();\n\t\t\t\t// Pass fieldDef for object/array/relation types to enable advanced rendering\n\t\t\t\treturn needsFieldDef ? (\n\t\t\t\t\t<CellComponent value={value} row={row} fieldDef={fieldDef} />\n\t\t\t\t) : (\n\t\t\t\t\t<CellComponent value={value} row={row} />\n\t\t\t\t);\n\t\t\t},\n\t\t\t// Computed fields are not sortable (no DB column)\n\t\t\tenableSorting: isComputed ? false : normalized.sortable !== false,\n\t\t};\n\n\t\t// Add size config if specified\n\t\tif (normalized.width) {\n\t\t\t(columnDef as any).size =\n\t\t\t\ttypeof normalized.width === \"number\"\n\t\t\t\t\t? normalized.width\n\t\t\t\t\t: Number.parseInt(normalized.width, 10) || undefined;\n\t\t}\n\t\tif (normalized.minWidth) {\n\t\t\t(columnDef as any).minSize =\n\t\t\t\ttypeof normalized.minWidth === \"number\"\n\t\t\t\t\t? normalized.minWidth\n\t\t\t\t\t: Number.parseInt(normalized.minWidth, 10) || undefined;\n\t\t}\n\t\tif (normalized.maxWidth) {\n\t\t\t(columnDef as any).maxSize =\n\t\t\t\ttypeof normalized.maxWidth === \"number\"\n\t\t\t\t\t? normalized.maxWidth\n\t\t\t\t\t: Number.parseInt(normalized.maxWidth, 10) || undefined;\n\t\t}\n\n\t\t// Add meta for alignment/className\n\t\tif (normalized.align || normalized.className) {\n\t\t\t(columnDef as any).meta = {\n\t\t\t\talign: normalized.align,\n\t\t\t\tclassName: normalized.className,\n\t\t\t};\n\t\t}\n\n\t\treturn columnDef;\n\t});\n}\n","/**\n * Table View - Default list view component\n *\n * Renders collection items in a table with columns, sorting, filtering, and search.\n * This is the default list view registered in the admin view registry.\n */\n\nimport { SlidersHorizontalIcon, SpinnerGap } from \"@phosphor-icons/react\";\nimport {\n\ttype ColumnDef,\n\tflexRender,\n\tgetCoreRowModel,\n\tgetSortedRowModel,\n\ttype RowSelectionState,\n\ttype SortingState,\n\tuseReactTable,\n} from \"@tanstack/react-table\";\nimport * as React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport type { ActionsConfig } from \"../../builder/collection/action-types\";\nimport type {\n\tCollectionBuilderState,\n\tListViewConfig,\n} from \"../../builder/collection/types\";\nimport { ActionDialog } from \"../../components/actions/action-dialog\";\nimport { HeaderActions } from \"../../components/actions/header-actions\";\nimport { FilterBuilderSheet } from \"../../components/filter-builder/filter-builder-sheet\";\nimport type {\n\tAvailableField,\n\tViewConfiguration,\n} from \"../../components/filter-builder/types\";\nimport { LocaleSwitcher } from \"../../components/locale-switcher\";\nimport { flattenOptions } from \"../../components/primitives/types\";\nimport { Button } from \"../../components/ui/button\";\nimport { Checkbox } from \"../../components/ui/checkbox\";\nimport { EmptyState } from \"../../components/ui/empty-state\";\nimport { SearchInput } from \"../../components/ui/search-input\";\nimport {\n\tTable,\n\tTableBody,\n\tTableCell,\n\tTableHead,\n\tTableHeader,\n\tTableRow,\n} from \"../../components/ui/table\";\nimport {\n\tToolbar,\n\tToolbarSection,\n\tToolbarSeparator,\n} from \"../../components/ui/toolbar\";\nimport { useActions } from \"../../hooks/use-action\";\nimport {\n\tuseCollectionDelete,\n\tuseCollectionList,\n} from \"../../hooks/use-collection\";\nimport { useCollectionMeta } from \"../../hooks/use-collection-meta\";\nimport {\n\tuseDeleteSavedView,\n\tuseSavedViews,\n\tuseSaveView,\n} from \"../../hooks/use-saved-views\";\nimport { useDebouncedValue, useSearch } from \"../../hooks/use-search\";\nimport { useViewState } from \"../../hooks/use-view-state\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { useSafeContentLocales, useScopedLocale } from \"../../runtime\";\nimport {\n\tautoExpandFields,\n\thasFieldsToExpand,\n} from \"../../utils/auto-expand-fields\";\n\nimport { BulkActionToolbar } from \"./bulk-action-toolbar\";\nimport {\n\tbuildColumns,\n\tcomputeDefaultColumns,\n\tgetAllAvailableFields,\n} from \"./columns\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Table view configuration from registry.\n *\n * Re-exports ListViewConfig for type consistency between builder and component.\n */\nexport type TableViewConfig = ListViewConfig;\n\n/**\n * Props for TableView component\n */\nexport interface TableViewProps {\n\t/**\n\t * Collection name\n\t */\n\tcollection: string;\n\n\t/**\n\t * Collection configuration from admin builder\n\t * Accepts CollectionBuilderState or any compatible config object\n\t */\n\tconfig?: Partial<CollectionBuilderState> | Record<string, any>;\n\n\t/**\n\t * View-specific configuration from registry\n\t */\n\tviewConfig?: TableViewConfig;\n\n\t/**\n\t * Navigate function for routing\n\t */\n\tnavigate: (path: string) => void;\n\n\t/**\n\t * Base path for admin routes (e.g., \"/admin\")\n\t */\n\tbasePath?: string;\n\n\t/**\n\t * Show search functionality\n\t * @default true\n\t */\n\tshowSearch?: boolean;\n\n\t/**\n\t * Show filter functionality\n\t * @default true\n\t */\n\tshowFilters?: boolean;\n\n\t/**\n\t * Show toolbar\n\t * @default true\n\t */\n\tshowToolbar?: boolean;\n\n\t/**\n\t * Custom header actions (in addition to configured actions)\n\t * @deprecated Use actions config instead\n\t */\n\theaderActions?: React.ReactNode;\n\n\t/**\n\t * Custom empty state\n\t */\n\temptyState?: React.ReactNode;\n\n\t/**\n\t * Actions configuration (header, row, bulk)\n\t * If not provided, defaults will be used\n\t */\n\tactionsConfig?: ActionsConfig;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * TableView - Default table-based list view for collections\n *\n * Features:\n * - Auto-generates columns from collection config\n * - Search and filter functionality\n * - Sortable columns\n * - Saved views support\n * - Auto-expands upload/relation fields\n *\n * @example\n * ```tsx\n * // Used automatically via registry when navigating to /admin/collections/:name\n * // Can also be used directly:\n * <TableView\n * collection=\"posts\"\n * config={postsConfig}\n * navigate={navigate}\n * basePath=\"/admin\"\n * />\n * ```\n */\nexport default function TableView({\n\tcollection,\n\tconfig,\n\tviewConfig,\n\tnavigate,\n\tbasePath = \"/admin\",\n\tshowSearch = true,\n\tshowFilters = true,\n\tshowToolbar = true,\n\theaderActions,\n\temptyState,\n\tactionsConfig,\n}: TableViewProps): React.ReactElement {\n\t// Use actionsConfig from prop or from config.list view config\n\t// Actions are now stored in the list view config, not at collection level\n\tconst resolvedActionsConfig =\n\t\tactionsConfig ??\n\t\t(config?.list as any)?.[\"~config\"]?.actions ??\n\t\t(config?.list as any)?.actions;\n\n\t// Fetch collection metadata from backend (for title field detection, timestamps, etc.)\n\tconst { data: collectionMeta } = useCollectionMeta(collection);\n\n\t// i18n translations\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\n\t// Locale switching (scoped or global)\n\tconst { locale: contentLocale, setLocale: setContentLocale } =\n\t\tuseScopedLocale();\n\tconst contentLocales = useSafeContentLocales();\n\tconst localeOptions = contentLocales?.locales ?? [];\n\n\t// Use actions hook for helpers and dialog state\n\tconst {\n\t\thelpers: actionHelpers,\n\t\tactions,\n\t\tdialogAction,\n\t\tdialogItem,\n\t\topenDialog,\n\t\tcloseDialog,\n\t} = useActions({\n\t\tcollection,\n\t\tactionsConfig: resolvedActionsConfig,\n\t});\n\n\t// Build columns from config - buildAllColumns enables showing any field user selects\n\tconst columns = useMemo(\n\t\t() =>\n\t\t\tbuildColumns({\n\t\t\t\tconfig: {\n\t\t\t\t\tfields: config?.fields,\n\t\t\t\t\tlist: config?.list,\n\t\t\t\t},\n\t\t\t\tfallbackColumns: [\"id\"],\n\t\t\t\tbuildAllColumns: true, // Build all columns so user can toggle any field\n\t\t\t\tmeta: collectionMeta, // Use meta to determine title field\n\t\t\t}),\n\t\t[config?.fields, config?.list, collectionMeta],\n\t);\n\n\t// Auto-detect fields to expand (uploads, relations)\n\tconst expandedFields = useMemo(\n\t\t() =>\n\t\t\tautoExpandFields({\n\t\t\t\tfields: config?.fields,\n\t\t\t\tlist: config?.list,\n\t\t\t\trelations: collectionMeta?.relations,\n\t\t\t}),\n\t\t[config?.fields, config?.list, collectionMeta?.relations],\n\t);\n\n\t// Filter builder sheet state\n\tconst [isSheetOpen, setIsSheetOpen] = useState(false);\n\tconst [searchTerm, setSearchTerm] = useState(\"\");\n\n\t// Default columns using configured columns from .list() or auto-detection\n\t// When .list({ columns: [...] }) is defined, those become the defaults\n\tconst defaultColumns = useMemo(\n\t\t() =>\n\t\t\tcomputeDefaultColumns(config?.fields, {\n\t\t\t\tmeta: collectionMeta,\n\t\t\t\tconfiguredColumns: config?.list?.columns,\n\t\t\t}),\n\t\t[config?.fields, config?.list?.columns, collectionMeta],\n\t);\n\n\t// View state (filters, sort, visible columns) - with database persistence\n\tconst viewState = useViewState(defaultColumns, undefined, collection);\n\n\t// Build query options from view state (filters, sort)\n\tconst queryOptions = useMemo(() => {\n\t\tconst options: any = {};\n\n\t\t// Add field expansion if needed\n\t\tif (hasFieldsToExpand(expandedFields)) {\n\t\t\toptions.with = expandedFields;\n\t\t}\n\n\t\t// Apply filters from view state\n\t\tif (viewState.config.filters.length > 0) {\n\t\t\tconst whereConditions: Record<string, any> = { ...options.where };\n\t\t\tconst relationNames = collectionMeta?.relations ?? [];\n\n\t\t\tconst isEmptyValue = (val: unknown) => {\n\t\t\t\tif (val === undefined || val === null) return true;\n\t\t\t\tif (typeof val === \"string\") return val.trim().length === 0;\n\t\t\t\tif (Array.isArray(val)) return val.length === 0;\n\t\t\t\treturn false;\n\t\t\t};\n\n\t\t\tconst normalizeSelectValue = (val: unknown, fieldOptions: any) => {\n\t\t\t\tconst optionsList = fieldOptions?.options;\n\t\t\t\tif (!optionsList) return val;\n\t\t\t\tconst map = new Map(\n\t\t\t\t\tflattenOptions(optionsList).map((opt) => [\n\t\t\t\t\t\tString(opt.value),\n\t\t\t\t\t\topt.value,\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tconst mapValue = (item: unknown) => map.get(String(item)) ?? item;\n\t\t\t\tif (Array.isArray(val)) return val.map(mapValue);\n\t\t\t\tif (val === undefined || val === null) return val;\n\t\t\t\treturn mapValue(val);\n\t\t\t};\n\n\t\t\tconst coerceValue = (val: unknown, fieldDef?: any) => {\n\t\t\t\tif (!fieldDef) return val;\n\t\t\t\tconst fieldType = fieldDef?.name ?? \"text\";\n\t\t\t\tconst fieldOptions = fieldDef?.[\"~options\"] ?? {};\n\n\t\t\t\tif (fieldType === \"number\" && typeof val === \"string\") {\n\t\t\t\t\tconst parsed = Number(val);\n\t\t\t\t\treturn Number.isNaN(parsed) ? val : parsed;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\t(fieldType === \"checkbox\" || fieldType === \"switch\") &&\n\t\t\t\t\ttypeof val === \"string\"\n\t\t\t\t) {\n\t\t\t\t\tif (val === \"true\") return true;\n\t\t\t\t\tif (val === \"false\") return false;\n\t\t\t\t}\n\t\t\t\tif (fieldType === \"select\") {\n\t\t\t\t\treturn normalizeSelectValue(val, fieldOptions);\n\t\t\t\t}\n\n\t\t\t\treturn val;\n\t\t\t};\n\n\t\t\tconst toArray = (val: unknown): unknown[] => {\n\t\t\t\tif (Array.isArray(val)) return val;\n\t\t\t\tif (val === undefined || val === null || val === \"\") return [];\n\t\t\t\treturn [val];\n\t\t\t};\n\n\t\t\tconst buildRelationCondition = (\n\t\t\t\toperator: string,\n\t\t\t\tval: unknown,\n\t\t\t\trelationType: \"single\" | \"multiple\",\n\t\t\t) => {\n\t\t\t\tconst isMultiple = relationType === \"multiple\";\n\t\t\t\tconst ids = toArray(val);\n\n\t\t\t\tswitch (operator) {\n\t\t\t\t\tcase \"equals\":\n\t\t\t\t\t\treturn isMultiple ? { some: { id: val } } : { is: { id: val } };\n\t\t\t\t\tcase \"not_equals\":\n\t\t\t\t\t\treturn isMultiple ? { none: { id: val } } : { isNot: { id: val } };\n\t\t\t\t\tcase \"in\":\n\t\t\t\t\t\treturn isMultiple\n\t\t\t\t\t\t\t? { some: { id: { in: ids } } }\n\t\t\t\t\t\t\t: { is: { id: { in: ids } } };\n\t\t\t\t\tcase \"not_in\":\n\t\t\t\t\t\treturn isMultiple\n\t\t\t\t\t\t\t? { none: { id: { in: ids } } }\n\t\t\t\t\t\t\t: { isNot: { id: { in: ids } } };\n\t\t\t\t\tcase \"some\":\n\t\t\t\t\t\treturn { some: { id: { in: ids } } };\n\t\t\t\t\tcase \"every\":\n\t\t\t\t\t\treturn { every: { id: { in: ids } } };\n\t\t\t\t\tcase \"none\":\n\t\t\t\t\t\treturn { none: { id: { in: ids } } };\n\t\t\t\t\tcase \"is_empty\":\n\t\t\t\t\t\treturn isMultiple ? { none: {} } : { isNot: {} };\n\t\t\t\t\tcase \"is_not_empty\":\n\t\t\t\t\t\treturn isMultiple ? { some: {} } : { is: {} };\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor (const filter of viewState.config.filters) {\n\t\t\t\tconst { field, operator, value } = filter;\n\t\t\t\tif (!field || field === \"_title\") continue;\n\n\t\t\t\tconst fieldDef = config?.fields?.[field] as any;\n\t\t\t\tconst fieldType = fieldDef?.name ?? \"text\";\n\t\t\t\tconst fieldOptions = fieldDef?.[\"~options\"] ?? {};\n\t\t\t\tconst relationName =\n\t\t\t\t\tfieldType === \"relation\"\n\t\t\t\t\t\t? ((fieldOptions.relationName as string | undefined) ?? field)\n\t\t\t\t\t\t: undefined;\n\t\t\t\tconst hasRelation =\n\t\t\t\t\trelationName &&\n\t\t\t\t\t(relationNames.length === 0 || relationNames.includes(relationName));\n\t\t\t\tconst isRelationField = fieldType === \"relation\" && !!hasRelation;\n\n\t\t\t\tconst requiresValue =\n\t\t\t\t\toperator !== \"is_empty\" && operator !== \"is_not_empty\";\n\t\t\t\tif (requiresValue && isEmptyValue(value)) continue;\n\n\t\t\t\tconst normalizedValue = coerceValue(value, fieldDef);\n\n\t\t\t\tif (isRelationField && relationName) {\n\t\t\t\t\tconst relationType =\n\t\t\t\t\t\tfieldOptions.type === \"multiple\" ? \"multiple\" : \"single\";\n\t\t\t\t\tconst condition = buildRelationCondition(\n\t\t\t\t\t\toperator,\n\t\t\t\t\t\tnormalizedValue,\n\t\t\t\t\t\trelationType,\n\t\t\t\t\t);\n\t\t\t\t\tif (condition) {\n\t\t\t\t\t\twhereConditions[relationName] = condition;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tswitch (operator) {\n\t\t\t\t\tcase \"equals\":\n\t\t\t\t\t\twhereConditions[field] = normalizedValue;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"not_equals\":\n\t\t\t\t\t\twhereConditions[field] = { ne: normalizedValue };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"contains\":\n\t\t\t\t\t\twhereConditions[field] = { contains: normalizedValue };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"not_contains\":\n\t\t\t\t\t\twhereConditions[field] = {\n\t\t\t\t\t\t\tnotIlike: `%${normalizedValue}%`,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"starts_with\":\n\t\t\t\t\t\twhereConditions[field] = { startsWith: normalizedValue };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"ends_with\":\n\t\t\t\t\t\twhereConditions[field] = { endsWith: normalizedValue };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"greater_than\":\n\t\t\t\t\t\twhereConditions[field] = { gt: normalizedValue };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"less_than\":\n\t\t\t\t\t\twhereConditions[field] = { lt: normalizedValue };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"greater_than_or_equal\":\n\t\t\t\t\t\twhereConditions[field] = { gte: normalizedValue };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"less_than_or_equal\":\n\t\t\t\t\t\twhereConditions[field] = { lte: normalizedValue };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"in\": {\n\t\t\t\t\t\tconst values = Array.isArray(normalizedValue)\n\t\t\t\t\t\t\t? normalizedValue\n\t\t\t\t\t\t\t: [normalizedValue];\n\t\t\t\t\t\twhereConditions[field] = { in: values };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"not_in\": {\n\t\t\t\t\t\tconst values = Array.isArray(normalizedValue)\n\t\t\t\t\t\t\t? normalizedValue\n\t\t\t\t\t\t\t: [normalizedValue];\n\t\t\t\t\t\twhereConditions[field] = { notIn: values };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"is_empty\":\n\t\t\t\t\t\twhereConditions[field] = { isNull: true };\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"is_not_empty\":\n\t\t\t\t\t\twhereConditions[field] = { isNotNull: true };\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toptions.where = whereConditions;\n\t\t}\n\n\t\t// Apply sort from view state\n\t\tif (viewState.config.sortConfig) {\n\t\t\tconst { field, direction } = viewState.config.sortConfig;\n\t\t\toptions.orderBy = { [field]: direction };\n\t\t}\n\n\t\treturn options;\n\t}, [\n\t\texpandedFields,\n\t\tviewState.config.filters,\n\t\tviewState.config.sortConfig,\n\t\tconfig?.fields,\n\t\tcollectionMeta?.relations,\n\t]);\n\n\t// Debounce search term for API requests (300ms)\n\tconst debouncedSearchTerm = useDebouncedValue(searchTerm, 300);\n\tconst isSearching = debouncedSearchTerm.trim().length > 0;\n\n\t// Search API for FTS-powered search\n\t// Returns full records with search metadata (_search.score, _search.highlights)\n\tconst {\n\t\tdata: searchData,\n\t\tisLoading: searchLoading,\n\t\tisFetching: searchFetching,\n\t} = useSearch(\n\t\t{\n\t\t\tcollection,\n\t\t\tquery: debouncedSearchTerm,\n\t\t\tlimit: 100,\n\t\t\thighlights: true,\n\t\t},\n\t\t{ enabled: isSearching },\n\t);\n\n\t// Data fetching with filters and sort applied (normal browsing)\n\tconst { data: listData, isLoading: listLoading } = useCollectionList(\n\t\tcollection as any,\n\t\tqueryOptions,\n\t\t{ enabled: !isSearching },\n\t);\n\n\t// Merge data sources - search returns full records directly now\n\tconst isLoading = isSearching ? searchLoading : listLoading;\n\tconst isSearchActive = isSearching && searchFetching;\n\n\t// Saved views hooks\n\tconst { data: savedViewsData, isLoading: savedViewsLoading } =\n\t\tuseSavedViews(collection);\n\tconst saveViewMutation = useSaveView(collection);\n\tconst deleteViewMutation = useDeleteSavedView(collection);\n\n\t// Delete mutation for bulk actions\n\tconst deleteMutation = useCollectionDelete(collection as any);\n\n\t// Build available fields from config for column picker\n\t// All fields are available in Options, but defaults come from .list() config\n\tconst availableFields: AvailableField[] = useMemo(() => {\n\t\treturn getAllAvailableFields(config?.fields, { meta: collectionMeta });\n\t}, [config?.fields, collectionMeta]);\n\n\t// Filter columns based on visibleColumns from view state\n\t// Includes checkbox selection column as first column\n\tconst visibleColumnDefs = useMemo(() => {\n\t\t// Checkbox selection column (first column, sticky)\n\t\tconst selectCol: ColumnDef<any> = {\n\t\t\tid: \"_select\",\n\t\t\theader: ({ table: t }) => {\n\t\t\t\tconst isAllSelected = t.getIsAllPageRowsSelected();\n\t\t\t\tconst isSomeSelected = t.getIsSomePageRowsSelected();\n\t\t\t\treturn (\n\t\t\t\t\t// biome-ignore lint/a11y/noStaticElementInteractions: <explanation>\n\t\t\t\t\t<div\n\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t\tonKeyDown={(e) => e.stopPropagation()}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Checkbox\n\t\t\t\t\t\t\tchecked={isAllSelected}\n\t\t\t\t\t\t\tindeterminate={!isAllSelected && isSomeSelected}\n\t\t\t\t\t\t\tonCheckedChange={(checked) =>\n\t\t\t\t\t\t\t\tt.toggleAllPageRowsSelected(!!checked)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\taria-label=\"Select all\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t},\n\t\t\tcell: ({ row }) => {\n\t\t\t\tconst isSelected = row.getIsSelected();\n\t\t\t\tconst canSelect = row.getCanSelect();\n\t\t\t\treturn (\n\t\t\t\t\t// biome-ignore lint/a11y/noStaticElementInteractions: <explanation>\n\t\t\t\t\t<div\n\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t\tonKeyDown={(e) => e.stopPropagation()}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Checkbox\n\t\t\t\t\t\t\tchecked={isSelected}\n\t\t\t\t\t\t\tdisabled={!canSelect}\n\t\t\t\t\t\t\tonCheckedChange={(checked) => row.toggleSelected(!!checked)}\n\t\t\t\t\t\t\taria-label=\"Select row\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t},\n\t\t\tsize: 40,\n\t\t\tenableSorting: false,\n\t\t\tenableHiding: false,\n\t\t};\n\n\t\t// Determine title column name from meta\n\t\tconst titleFieldName = collectionMeta?.title?.fieldName;\n\t\tconst titleType = collectionMeta?.title?.type;\n\t\tconst titleColName =\n\t\t\ttitleType === \"field\" && titleFieldName ? titleFieldName : \"_title\";\n\n\t\t// Start with checkbox column\n\t\tconst orderedColumns: ColumnDef<any>[] = [selectCol];\n\n\t\t// Always add title column first (after checkbox) if it exists\n\t\tconst titleCol = columns.find(\n\t\t\t(c) =>\n\t\t\t\t(c as any).accessorKey === titleColName ||\n\t\t\t\t(c as any).id === titleColName,\n\t\t);\n\t\tif (titleCol) {\n\t\t\torderedColumns.push(titleCol as ColumnDef<any>);\n\t\t}\n\n\t\t// Add remaining visible columns (excluding title since it's already added)\n\t\tfor (const colName of viewState.config.visibleColumns) {\n\t\t\t// Skip title column - already added first\n\t\t\tif (colName === titleColName) continue;\n\n\t\t\tconst col = columns.find(\n\t\t\t\t(c) => (c as any).accessorKey === colName || (c as any).id === colName,\n\t\t\t);\n\t\t\tif (col) {\n\t\t\t\torderedColumns.push(col as ColumnDef<any>);\n\t\t\t}\n\t\t}\n\n\t\treturn orderedColumns;\n\t}, [columns, viewState.config.visibleColumns, collectionMeta]);\n\n\t// Table sorting state - sync with view state\n\tconst [sorting, setSorting] = React.useState<SortingState>(() => {\n\t\tif (viewState.config.sortConfig) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: viewState.config.sortConfig.field,\n\t\t\t\t\tdesc: viewState.config.sortConfig.direction === \"desc\",\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\t\treturn [];\n\t});\n\n\t// Row selection state\n\tconst [rowSelection, setRowSelection] = React.useState<RowSelectionState>({});\n\n\t// Sync table sorting with view state\n\tconst handleSortingChange = React.useCallback(\n\t\t(updater: SortingState | ((old: SortingState) => SortingState)) => {\n\t\t\tconst newSorting =\n\t\t\t\ttypeof updater === \"function\" ? updater(sorting) : updater;\n\t\t\tsetSorting(newSorting);\n\t\t\tif (newSorting.length > 0) {\n\t\t\t\tviewState.setSort({\n\t\t\t\t\tfield: newSorting[0].id,\n\t\t\t\t\tdirection: newSorting[0].desc ? \"desc\" : \"asc\",\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tviewState.setSort(null);\n\t\t\t}\n\t\t},\n\t\t[sorting, viewState],\n\t);\n\n\t// Get items from appropriate data source\n\t// Search returns full records directly with _search metadata\n\t// List returns normal CRUD results\n\tconst items = useMemo(() => {\n\t\tif (isSearching) {\n\t\t\treturn searchData?.docs ?? [];\n\t\t}\n\t\treturn listData?.docs ?? [];\n\t}, [isSearching, searchData?.docs, listData?.docs]);\n\n\t// Search results are already sorted by score, list results are server-sorted\n\tconst filteredItems = items;\n\n\tconst table = useReactTable({\n\t\tdata: filteredItems as any[],\n\t\tcolumns: visibleColumnDefs,\n\t\tgetCoreRowModel: getCoreRowModel(),\n\t\tgetSortedRowModel: getSortedRowModel(),\n\t\tonSortingChange: handleSortingChange,\n\t\tenableRowSelection: true,\n\t\tonRowSelectionChange: setRowSelection,\n\t\tgetRowId: (row: any) => row.id, // Use item ID as row ID for selection\n\t\tstate: {\n\t\t\tsorting,\n\t\t\trowSelection,\n\t\t},\n\t});\n\n\t// Handlers\n\tconst handleSaveView = (name: string, config: ViewConfiguration) => {\n\t\tsaveViewMutation.mutate({\n\t\t\tname,\n\t\t\tconfiguration: config,\n\t\t});\n\t};\n\n\tconst handleDeleteView = (viewId: string) => {\n\t\tdeleteViewMutation.mutate(viewId);\n\t};\n\n\tconst handleRowClick = (item: any) => {\n\t\tnavigate(`${basePath}/collections/${collection}/${item.id}`);\n\t};\n\n\t// Bulk delete handler\n\tconst handleBulkDelete = React.useCallback(\n\t\tasync (ids: string[]) => {\n\t\t\t// Delete items in parallel\n\t\t\tconst results = await Promise.allSettled(\n\t\t\t\tids.map((id) => deleteMutation.mutateAsync({ id })),\n\t\t\t);\n\n\t\t\tconst successCount = results.filter(\n\t\t\t\t(r) => r.status === \"fulfilled\",\n\t\t\t).length;\n\t\t\tconst failCount = results.filter((r) => r.status === \"rejected\").length;\n\n\t\t\tif (failCount === 0) {\n\t\t\t\tactionHelpers.toast.success(\n\t\t\t\t\tt(\"collection.bulkDeleteSuccess\", { count: successCount }),\n\t\t\t\t);\n\t\t\t} else if (successCount === 0) {\n\t\t\t\tactionHelpers.toast.error(t(\"collection.bulkDeleteError\"));\n\t\t\t} else {\n\t\t\t\tactionHelpers.toast.warning(\n\t\t\t\t\tt(\"collection.bulkDeletePartial\", {\n\t\t\t\t\t\tsuccess: successCount,\n\t\t\t\t\t\tfailed: failCount,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[deleteMutation, actionHelpers, t],\n\t);\n\n\tif (isLoading) {\n\t\treturn (\n\t\t\t<div className=\"container\">\n\t\t\t\t<div className=\"flex h-64 items-center justify-center text-muted-foreground\">\n\t\t\t\t\t<SpinnerGap className=\"size-6 animate-spin\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"container\">\n\t\t\t<div className=\"space-y-4\">\n\t\t\t\t{/* Header - Title & Actions */}\n\t\t\t\t<div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n\t\t\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t\t\t\t<h1 className=\"text-2xl md:text-3xl font-extrabold tracking-tight truncate\">\n\t\t\t\t\t\t\t\t{resolveText(config?.label, collection)}\n\t\t\t\t\t\t\t</h1>\n\t\t\t\t\t\t\t{localeOptions.length > 0 && (\n\t\t\t\t\t\t\t\t<LocaleSwitcher\n\t\t\t\t\t\t\t\t\tlocales={localeOptions}\n\t\t\t\t\t\t\t\t\tvalue={contentLocale}\n\t\t\t\t\t\t\t\t\tonChange={setContentLocale}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{config?.description && (\n\t\t\t\t\t\t\t<p className=\"text-muted-foreground text-sm mt-1 line-clamp-2\">\n\t\t\t\t\t\t\t\t{resolveText(config.description)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex items-center gap-2 shrink-0\">\n\t\t\t\t\t\t{headerActions}\n\t\t\t\t\t\t{(actions.header.primary?.length ||\n\t\t\t\t\t\t\tactions.header.secondary?.length) && (\n\t\t\t\t\t\t\t<HeaderActions\n\t\t\t\t\t\t\t\tactions={actions.header}\n\t\t\t\t\t\t\t\tcollection={collection}\n\t\t\t\t\t\t\t\thelpers={actionHelpers}\n\t\t\t\t\t\t\t\tonOpenDialog={(action) => openDialog(action)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Toolbar */}\n\t\t\t\t{showToolbar && (\n\t\t\t\t\t<div className=\"space-y-2\">\n\t\t\t\t\t\t<Toolbar>\n\t\t\t\t\t\t\t{/* Search */}\n\t\t\t\t\t\t\t{showSearch && (\n\t\t\t\t\t\t\t\t<ToolbarSection className=\"flex-1\">\n\t\t\t\t\t\t\t\t\t<SearchInput\n\t\t\t\t\t\t\t\t\t\tvalue={searchTerm}\n\t\t\t\t\t\t\t\t\t\tonChange={(e) => setSearchTerm(e.target.value)}\n\t\t\t\t\t\t\t\t\t\tonClear={() => setSearchTerm(\"\")}\n\t\t\t\t\t\t\t\t\t\tplaceholder={t(\"common.search\")}\n\t\t\t\t\t\t\t\t\t\tcontainerClassName=\"border-none bg-transparent dark:bg-transparent\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</ToolbarSection>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Separator + Options */}\n\t\t\t\t\t\t\t{showFilters && (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t{showSearch && <ToolbarSeparator />}\n\t\t\t\t\t\t\t\t\t<ToolbarSection>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => setIsSheetOpen(true)}\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"gap-2\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<SlidersHorizontalIcon size={16} />\n\t\t\t\t\t\t\t\t\t\t\t{t(\"viewOptions.title\")}\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t</ToolbarSection>\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</Toolbar>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Floating toolbar - shows when rows selected OR filters active */}\n\t\t\t\t<BulkActionToolbar\n\t\t\t\t\ttable={table}\n\t\t\t\t\tactions={actions.bulk}\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\thelpers={actionHelpers}\n\t\t\t\t\ttotalCount={isSearching ? searchData?.total : listData?.totalDocs}\n\t\t\t\t\tpageCount={filteredItems.length}\n\t\t\t\t\tonOpenDialog={(action, items) => openDialog(action, items)}\n\t\t\t\t\tonBulkDelete={handleBulkDelete}\n\t\t\t\t\tfilterCount={viewState.config.filters.length}\n\t\t\t\t\tonOpenFilters={() => setIsSheetOpen(true)}\n\t\t\t\t\tonClearFilters={() =>\n\t\t\t\t\t\tviewState.setConfig({ ...viewState.config, filters: [] })\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t{/* Table */}\n\t\t\t\t<div className=\"bg-card/5 backdrop-blur-sm border border-border/40 overflow-hidden\">\n\t\t\t\t\t<Table>\n\t\t\t\t\t\t<TableHeader>\n\t\t\t\t\t\t\t{table.getHeaderGroups().map((headerGroup) => (\n\t\t\t\t\t\t\t\t<TableRow key={headerGroup.id} className=\"hover:bg-transparent\">\n\t\t\t\t\t\t\t\t\t{headerGroup.headers.map((header, headerIndex) => {\n\t\t\t\t\t\t\t\t\t\t// First column (checkbox) is sticky at left=0, width ~36px\n\t\t\t\t\t\t\t\t\t\t// Second column (title) is sticky at left=36px\n\t\t\t\t\t\t\t\t\t\tconst stickyLeft =\n\t\t\t\t\t\t\t\t\t\t\theaderIndex === 0\n\t\t\t\t\t\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t\t\t\t\t\t: headerIndex === 1\n\t\t\t\t\t\t\t\t\t\t\t\t\t? 36\n\t\t\t\t\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\t\t\t\t// Only show border on the last sticky column (title)\n\t\t\t\t\t\t\t\t\t\tconst showStickyBorder = headerIndex === 1;\n\t\t\t\t\t\t\t\t\t\t// Checkbox column gets compact styling\n\t\t\t\t\t\t\t\t\t\tconst isCheckboxCol = headerIndex === 0;\n\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t<TableHead\n\t\t\t\t\t\t\t\t\t\t\t\tkey={header.id}\n\t\t\t\t\t\t\t\t\t\t\t\tstickyLeft={stickyLeft}\n\t\t\t\t\t\t\t\t\t\t\t\tshowStickyBorder={showStickyBorder}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\t\t\t\t\t\tisCheckboxCol ? \"w-9 min-w-9 px-1.5\" : undefined\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{header.isPlaceholder ? null : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\theader.column.getCanSort()\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? \"cursor-pointer select-none flex items-center gap-2 hover:text-foreground transition-colors\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: \"\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={header.column.getToggleSortingHandler()}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{flexRender(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\theader.column.columnDef.header,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\theader.getContext(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{header.column.getIsSorted() && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{header.column.getIsSorted() === \"asc\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? \"↑\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: \"↓\"}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</TableHead>\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</TableHeader>\n\t\t\t\t\t\t<TableBody>\n\t\t\t\t\t\t\t{table.getRowModel().rows?.length ? (\n\t\t\t\t\t\t\t\ttable.getRowModel().rows.map((row) => (\n\t\t\t\t\t\t\t\t\t<TableRow\n\t\t\t\t\t\t\t\t\t\tkey={row.id}\n\t\t\t\t\t\t\t\t\t\tdata-state={row.getIsSelected() && \"selected\"}\n\t\t\t\t\t\t\t\t\t\tclassName=\"group\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{row.getVisibleCells().map((cell, cellIndex) => {\n\t\t\t\t\t\t\t\t\t\t\t// First column (checkbox) is sticky at left=0, width ~36px\n\t\t\t\t\t\t\t\t\t\t\t// Second column (title) is sticky at left=36px\n\t\t\t\t\t\t\t\t\t\t\tconst stickyLeft =\n\t\t\t\t\t\t\t\t\t\t\t\tcellIndex === 0 ? 0 : cellIndex === 1 ? 36 : undefined;\n\t\t\t\t\t\t\t\t\t\t\t// Only show border on the last sticky column (title)\n\t\t\t\t\t\t\t\t\t\t\tconst showStickyBorder = cellIndex === 1;\n\t\t\t\t\t\t\t\t\t\t\t// Checkbox column gets compact styling\n\t\t\t\t\t\t\t\t\t\t\tconst isCheckboxCol = cellIndex === 0;\n\n\t\t\t\t\t\t\t\t\t\t\t// Title column (index 1) is clickable\n\t\t\t\t\t\t\t\t\t\t\tconst isTitleCol = cellIndex === 1;\n\n\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t<TableCell\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={cell.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\tstickyLeft={stickyLeft}\n\t\t\t\t\t\t\t\t\t\t\t\t\tshowStickyBorder={showStickyBorder}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tisCheckboxCol ? \"w-9 min-w-9 px-1.5\" : undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{isTitleCol ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleRowClick(row.original)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-left underline underline-offset-2 decoration-muted-foreground/50 hover:decoration-foreground transition-colors cursor-pointer\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{flexRender(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcell.column.columnDef.cell,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcell.getContext(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tflexRender(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcell.column.columnDef.cell,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcell.getContext(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<TableRow>\n\t\t\t\t\t\t\t\t\t<TableCell colSpan={visibleColumnDefs.length} className=\"p-0\">\n\t\t\t\t\t\t\t\t\t\t{emptyState || (\n\t\t\t\t\t\t\t\t\t\t\t<EmptyState\n\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"NO_RESULTS\"\n\t\t\t\t\t\t\t\t\t\t\t\tdescription={\n\t\t\t\t\t\t\t\t\t\t\t\t\tisSearching\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"collectionSearch.noResults\")\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: \"No items found in this collection\"\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\theight=\"h-48\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</TableCell>\n\t\t\t\t\t\t\t\t</TableRow>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</TableBody>\n\t\t\t\t\t</Table>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Footer - Item count */}\n\t\t\t\t<div className=\"text-sm text-muted-foreground flex items-center gap-2\">\n\t\t\t\t\t{isSearchActive && (\n\t\t\t\t\t\t<SpinnerGap className=\"size-3 animate-spin\" />\n\t\t\t\t\t)}\n\t\t\t\t\t{filteredItems.length} item{filteredItems.length !== 1 ? \"s\" : \"\"}\n\t\t\t\t\t{isSearching && searchData?.total !== undefined && (\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t({searchData.total} match{searchData.total !== 1 ? \"es\" : \"\"} found)\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Filter Builder Sheet */}\n\t\t\t\t<FilterBuilderSheet\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\tavailableFields={availableFields}\n\t\t\t\t\tcurrentConfig={viewState.config}\n\t\t\t\t\tonConfigChange={viewState.setConfig}\n\t\t\t\t\tisOpen={isSheetOpen}\n\t\t\t\t\tonOpenChange={setIsSheetOpen}\n\t\t\t\t\tsavedViews={savedViewsData?.docs ?? []}\n\t\t\t\t\tsavedViewsLoading={savedViewsLoading}\n\t\t\t\t\tonSaveView={handleSaveView}\n\t\t\t\t\tonDeleteView={handleDeleteView}\n\t\t\t\t/>\n\n\t\t\t\t{/* Action Dialog */}\n\t\t\t\t{dialogAction && (\n\t\t\t\t\t<ActionDialog\n\t\t\t\t\t\topen={!!dialogAction}\n\t\t\t\t\t\tonOpenChange={(open) => !open && closeDialog()}\n\t\t\t\t\t\taction={dialogAction}\n\t\t\t\t\t\tcollection={collection}\n\t\t\t\t\t\titem={dialogItem}\n\t\t\t\t\t\thelpers={actionHelpers}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","/**\n * View Builders (List & Edit)\n *\n * Defines reusable view components for collections.\n */\n\nimport type { MaybeLazyComponent } from \"../types/common\";\n\n// ============================================================================\n// Config Extraction Types\n// ============================================================================\n\n/**\n * Extract viewConfig type from a view component's props.\n *\n * Looks for `viewConfig?: T` prop and extracts T.\n * Returns `unknown` if not found (will be refined by $config).\n */\ntype ExtractViewConfigFromComponent<TComponent> =\n\tTComponent extends React.ComponentType<infer P>\n\t\t? P extends { viewConfig?: infer C }\n\t\t\t? C\n\t\t\t: unknown\n\t\t: unknown;\n\n/**\n * Extract config from lazy component: () => Promise<{ default: Component }>\n */\ntype ExtractViewConfigFromLazy<TComponent> = TComponent extends () => Promise<{\n\tdefault: infer C;\n}>\n\t? ExtractViewConfigFromComponent<C>\n\t: ExtractViewConfigFromComponent<TComponent>;\n\n// ============================================================================\n// View Definitions\n// ============================================================================\n\n/**\n * List view definition\n */\nexport interface ListViewDefinition<\n\tTName extends string = string,\n\tTConfig = unknown,\n> {\n\treadonly name: TName;\n\treadonly kind: \"list\";\n\treadonly \"~config\": TConfig;\n\treadonly component: MaybeLazyComponent;\n}\n\n/**\n * Edit view definition\n */\nexport interface EditViewDefinition<\n\tTName extends string = string,\n\tTConfig = unknown,\n> {\n\treadonly name: TName;\n\treadonly kind: \"edit\";\n\treadonly \"~config\": TConfig;\n\treadonly component: MaybeLazyComponent;\n}\n\n// ============================================================================\n// Builder State Types\n// ============================================================================\n\nexport interface ListViewBuilderState<TConfig = unknown> {\n\treadonly name: string;\n\treadonly kind: \"list\";\n\treadonly \"~config\": TConfig;\n\treadonly component: MaybeLazyComponent;\n}\n\nexport interface EditViewBuilderState<TConfig = unknown> {\n\treadonly name: string;\n\treadonly kind: \"edit\";\n\treadonly \"~config\": TConfig;\n\treadonly component: MaybeLazyComponent;\n}\n\n// ============================================================================\n// View Builders\n// ============================================================================\n\n/**\n * List view builder - implements ListViewDefinition for unified type handling\n */\nexport class ListViewBuilder<TState extends ListViewBuilderState>\n\timplements ListViewDefinition<TState[\"name\"], TState[\"~config\"]>\n{\n\tconstructor(public readonly state: TState) {}\n\n\tget name(): TState[\"name\"] {\n\t\treturn this.state.name;\n\t}\n\n\tget kind(): \"list\" {\n\t\treturn \"list\";\n\t}\n\n\tget \"~config\"(): TState[\"~config\"] {\n\t\treturn this.state[\"~config\"];\n\t}\n\n\tget component(): TState[\"component\"] {\n\t\treturn this.state.component;\n\t}\n\n\t/**\n\t * Set or override config value and type.\n\t *\n\t * @param config - Optional config value (for runtime) or omit for type-only override\n\t */\n\t$config<TNewConfig>(\n\t\tconfig?: TNewConfig,\n\t): ListViewBuilder<Omit<TState, \"~config\"> & { \"~config\": TNewConfig }> {\n\t\treturn new ListViewBuilder({\n\t\t\t...this.state,\n\t\t\t\"~config\": config ?? this.state[\"~config\"],\n\t\t} as Omit<TState, \"~config\"> & { \"~config\": TNewConfig });\n\t}\n}\n\n/**\n * Edit view builder - implements EditViewDefinition for unified type handling\n */\nexport class EditViewBuilder<TState extends EditViewBuilderState>\n\timplements EditViewDefinition<TState[\"name\"], TState[\"~config\"]>\n{\n\tconstructor(public readonly state: TState) {}\n\n\tget name(): TState[\"name\"] {\n\t\treturn this.state.name;\n\t}\n\n\tget kind(): \"edit\" {\n\t\treturn \"edit\";\n\t}\n\n\tget \"~config\"(): TState[\"~config\"] {\n\t\treturn this.state[\"~config\"];\n\t}\n\n\tget component(): TState[\"component\"] {\n\t\treturn this.state.component;\n\t}\n\n\t/**\n\t * Set or override config value and type.\n\t *\n\t * @param config - Optional config value (for runtime) or omit for type-only override\n\t */\n\t$config<TNewConfig>(\n\t\tconfig?: TNewConfig,\n\t): EditViewBuilder<Omit<TState, \"~config\"> & { \"~config\": TNewConfig }> {\n\t\treturn new EditViewBuilder({\n\t\t\t...this.state,\n\t\t\t\"~config\": config ?? this.state[\"~config\"],\n\t\t} as Omit<TState, \"~config\"> & { \"~config\": TNewConfig });\n\t}\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a list view with automatic config type extraction.\n *\n * The config type is extracted from the component's `viewConfig` prop.\n * If extraction fails, use `.$config<MyConfigType>()` to set it manually.\n *\n * @example\n * ```ts\n * // Auto-extraction from component props\n * const tableView = listView(\"table\", { component: TableView });\n * // ^? ListViewBuilder<{ ~config: TableViewConfig }>\n *\n * // Manual config type for lazy imports\n * const lazyTable = listView(\"table\", { component: () => import('./TableView') })\n * .$config<TableViewConfig>();\n * ```\n */\nexport function listView<\n\tTName extends string,\n\tTComponent extends MaybeLazyComponent,\n>(\n\tname: TName,\n\tconfig: { component: TComponent },\n): ListViewBuilder<{\n\tname: TName;\n\tkind: \"list\";\n\t\"~config\": ExtractViewConfigFromLazy<TComponent>;\n\tcomponent: TComponent;\n}> {\n\treturn new ListViewBuilder({\n\t\tname,\n\t\tkind: \"list\",\n\t\t\"~config\": {} as ExtractViewConfigFromLazy<TComponent>,\n\t\tcomponent: config.component,\n\t});\n}\n\n/**\n * Create an edit view with automatic config type extraction.\n *\n * @example\n * ```ts\n * const formView = editView(\"form\", { component: FormView });\n * // ^? EditViewBuilder<{ ~config: FormViewRegistryConfig }>\n * ```\n */\nexport function editView<\n\tTName extends string,\n\tTComponent extends MaybeLazyComponent,\n>(\n\tname: TName,\n\tconfig: { component: TComponent },\n): EditViewBuilder<{\n\tname: TName;\n\tkind: \"edit\";\n\t\"~config\": ExtractViewConfigFromLazy<TComponent>;\n\tcomponent: TComponent;\n}> {\n\treturn new EditViewBuilder({\n\t\tname,\n\t\tkind: \"edit\",\n\t\t\"~config\": {} as ExtractViewConfigFromLazy<TComponent>,\n\t\tcomponent: config.component,\n\t});\n}\n","/**\n * Built-in View Definitions\n */\n\nimport FormView from \"../../views/collection/form-view.js\";\nimport TableView from \"../../views/collection/table-view.js\";\nimport { listView, editView } from \"../view/view\";\n\n/**\n * Table list view\n */\nexport const tableView = listView(\"table\", { component: TableView });\n\n/**\n * Form edit view\n */\nexport const formView = editView(\"form\", { component: FormView });\n\n/**\n * All built-in views\n */\nexport const builtInViews = {\n table: tableView,\n form: formView,\n} as const;\n","/**\n * Core Admin Module\n *\n * Default \"batteries included\" module with all built-in fields, views, and pages.\n * Uses the same extensibility API as custom modules - nothing is baked in.\n */\n\nimport { AdminBuilder } from \"../admin-builder\";\nimport { builtInFields } from \"./fields\";\nimport { builtInPages } from \"./pages\";\nimport { builtInViews } from \"./views\";\n\n/**\n * Core admin module - contains all built-in fields, views, and pages.\n *\n * Includes:\n * - Fields: text, email, password, textarea, number, checkbox, select, etc.\n * - Views: table (list), form (edit)\n * - Pages: login, forgot-password, reset-password, dashboard\n *\n * @example\n * ```ts\n * import { coreAdminModule } from \"@questpie/admin/client\";\n *\n * // Use directly to create collections\n * const barbers = coreAdminModule.collection(\"barbers\")\n * .fields(({ r }) => ({\n * name: r.text({ label: \"Name\" }),\n * email: r.email({ label: \"Email\" })\n * }))\n *\n * // Or compose into your own builder\n * const builder = qa<AppCMS>().use(coreAdminModule);\n * ```\n */\nexport const coreAdminModule = AdminBuilder.empty()\n .fields(builtInFields)\n .views(builtInViews)\n .pages(builtInPages);\n\n/**\n * Type of core admin module state\n */\nexport type CoreAdminModule = typeof coreAdminModule;\n","/**\n * QA Namespace\n *\n * Main entry point for admin builder API.\n */\n\nimport { AdminBuilder } from \"./admin-builder\";\nimport { block } from \"./block/block-builder\";\nimport { collection } from \"./collection/collection\";\nimport { field } from \"./field/field\";\nimport { global } from \"./global/global\";\nimport { page } from \"./page/page\";\nimport {\n\ttype SidebarBuilder,\n\tsidebar as sidebarBuilder,\n} from \"./sidebar/sidebar-builder\";\nimport type {\n\tBrandingConfig,\n\tDashboardConfig,\n\tSidebarConfig,\n} from \"./types/ui-config\";\nimport { editView, listView } from \"./view/view\";\nimport { widget } from \"./widget/widget\";\n\n/**\n * Create admin builder (starts empty)\n *\n * @example\n * ```ts\n * // Without backend types\n * const admin = qa().use(coreAdminModule);\n *\n * // With backend types for autocomplete\n * import type { AppCMS } from './server/cms';\n * const admin = qa<AppCMS>().use(coreAdminModule);\n * ```\n */\nfunction qaFactory<TApp = any>() {\n\treturn AdminBuilder.empty<TApp>();\n}\n\n// ============================================================================\n// Config Helper Functions\n// ============================================================================\n\n/**\n * Create a sidebar builder or validate a sidebar config\n *\n * @example\n * ```ts\n * // Builder pattern (recommended)\n * const sidebar = qa.sidebar()\n * .section(\"content\", s => s\n * .title(\"Content\")\n * .items([\n * { type: \"collection\", collection: \"posts\" },\n * ])\n * )\n *\n * // Config object pattern (simpler cases)\n * const sidebar = qa.sidebar({\n * sections: [\n * { id: \"content\", title: \"Content\", items: [...] }\n * ]\n * })\n * ```\n */\nfunction sidebar<TApp = any>(): SidebarBuilder<never, TApp>;\nfunction sidebar<T extends SidebarConfig>(config: T): T;\nfunction sidebar<TApp = any, T extends SidebarConfig = SidebarConfig>(\n\tconfig?: T,\n): SidebarBuilder<never, TApp> | T {\n\tif (config === undefined) {\n\t\treturn sidebarBuilder<TApp>();\n\t}\n\treturn config;\n}\n\n/**\n * Define dashboard configuration with type safety\n *\n * @example\n * ```ts\n * import { qa } from \"@questpie/admin/builder\";\n *\n * export const dashboardConfig = qa.dashboard({\n * layout: \"grid\",\n * widgets: [],\n * });\n * ```\n */\nfunction dashboard<T extends DashboardConfig>(config: T): T {\n\treturn config;\n}\n\n/**\n * Define branding configuration with type safety\n *\n * @example\n * ```ts\n * import { qa } from \"@questpie/admin/builder\";\n *\n * export const brandingConfig = qa.branding({\n * name: \"My Admin\",\n * primaryColor: \"#3b82f6\",\n * });\n * ```\n */\nfunction branding<T extends BrandingConfig>(config: T): T {\n\treturn config;\n}\n\n/**\n * QA namespace with helpers\n */\nexport const qa = Object.assign(qaFactory, {\n\t// Primitive definition helpers (for advanced use)\n\tfield,\n\tlistView,\n\teditView,\n\twidget,\n\tpage,\n\n\t// Standalone factories (for use outside builder context)\n\tcollection,\n\tglobal,\n\tblock,\n\n\t// Config helpers\n\tsidebar,\n\tdashboard,\n\tbranding,\n});\n","/**\n * Assets Collection Admin Config\n *\n * Default admin UI configuration for the built-in assets collection.\n * Provides media library functionality for managing uploaded files.\n */\n\nimport { Images, UploadSimple } from \"@phosphor-icons/react\";\nimport { lazy } from \"react\";\nimport { AssetThumbnail } from \"../../../views/collection/cells\";\nimport { coreAdminModule } from \"../core\";\n\n// Lazy load the bulk upload dialog\nconst BulkUploadDialog = lazy(() =>\n\timport(\"../../../components/media/bulk-upload-dialog\").then((m) => ({\n\t\tdefault: m.BulkUploadDialog,\n\t})),\n);\n\n/**\n * Asset preview cell - displays thumbnail for images, icon for other types\n * Row click handles navigation to detail page\n */\nfunction AssetPreviewCell({\n\trow,\n}: {\n\tvalue: unknown;\n\trow?: { original: Record<string, unknown> };\n}) {\n\treturn <AssetThumbnail asset={row?.original} size=\"md\" />;\n}\n\n/**\n * Assets collection admin configuration\n *\n * Provides admin UI for managing uploaded files with:\n * - File preview (images show thumbnails)\n * - Metadata editing (alt text, caption)\n * - Visibility control (public/private)\n * - Grid/table view toggle\n *\n * @example\n * ```ts\n * import { adminModule } from \"@questpie/admin/client\";\n *\n * const admin = qa().use(adminModule);\n * // Assets collection is automatically configured\n * ```\n */\nexport const assetsCollectionAdmin = coreAdminModule\n\t.collection(\"assets\")\n\t.meta({\n\t\tlabel: { key: \"defaults.assets.label\" },\n\t\ticon: Images,\n\t\tdescription: { key: \"defaults.assets.description\" },\n\t})\n\t.fields(({ r }) => ({\n\t\tpreview: r.assetPreview({\n\t\t\tlabel: { key: \"defaults.assets.fields.preview.label\" },\n\t\t}),\n\t\tfilename: r.text({\n\t\t\tlabel: { key: \"defaults.assets.fields.filename.label\" },\n\t\t\tdescription: { key: \"defaults.assets.fields.filename.description\" },\n\t\t}),\n\t\tmimeType: r.text({\n\t\t\tlabel: { key: \"defaults.assets.fields.mimeType.label\" },\n\t\t\tdescription: { key: \"defaults.assets.fields.mimeType.description\" },\n\t\t}),\n\t\tsize: r.number({\n\t\t\tlabel: { key: \"defaults.assets.fields.size.label\" },\n\t\t\tdescription: { key: \"defaults.assets.fields.size.description\" },\n\t\t}),\n\t\talt: r.text({\n\t\t\tlabel: { key: \"defaults.assets.fields.alt.label\" },\n\t\t\tplaceholder: { key: \"defaults.assets.fields.alt.placeholder\" },\n\t\t\tdescription: { key: \"defaults.assets.fields.alt.description\" },\n\t\t}),\n\t\tcaption: r.textarea({\n\t\t\tlabel: { key: \"defaults.assets.fields.caption.label\" },\n\t\t\tplaceholder: { key: \"defaults.assets.fields.caption.placeholder\" },\n\t\t\trows: 2,\n\t\t}),\n\t\tvisibility: r.select({\n\t\t\tlabel: { key: \"defaults.assets.fields.visibility.label\" },\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tvalue: \"public\",\n\t\t\t\t\tlabel: { key: \"defaults.assets.fields.visibility.options.public\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: \"private\",\n\t\t\t\t\tlabel: { key: \"defaults.assets.fields.visibility.options.private\" },\n\t\t\t\t},\n\t\t\t],\n\t\t\tdescription: { key: \"defaults.assets.fields.visibility.description\" },\n\t\t}),\n\t}))\n\t.list(({ v, f, a }) =>\n\t\tv.table({\n\t\t\tcolumns: [\n\t\t\t\t{\n\t\t\t\t\tfield: \"preview\" as any,\n\t\t\t\t\theader: \"\",\n\t\t\t\t\twidth: 60,\n\t\t\t\t\tsortable: false,\n\t\t\t\t\tcell: AssetPreviewCell,\n\t\t\t\t},\n\t\t\t\tf.filename,\n\t\t\t\tf.mimeType,\n\t\t\t\tf.size,\n\t\t\t\tf.visibility,\n\t\t\t],\n\t\t\tsearchFields: [f.filename, f.alt, f.caption],\n\t\t\tsearchable: true,\n\t\t\tdefaultSort: {\n\t\t\t\tfield: \"createdAt\" as any,\n\t\t\t\tdirection: \"desc\",\n\t\t\t},\n\t\t\tactions: {\n\t\t\t\theader: {\n\t\t\t\t\tprimary: [\n\t\t\t\t\t\ta.action({\n\t\t\t\t\t\t\tid: \"upload\",\n\t\t\t\t\t\t\tlabel: { key: \"defaults.assets.actions.upload.label\" },\n\t\t\t\t\t\t\ticon: UploadSimple,\n\t\t\t\t\t\t\tvariant: \"default\",\n\t\t\t\t\t\t\thandler: {\n\t\t\t\t\t\t\t\ttype: \"dialog\",\n\t\t\t\t\t\t\t\tcomponent: BulkUploadDialog,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t}),\n\t)\n\t.form(({ v, f }) =>\n\t\tv.form({\n\t\t\tsidebar: {\n\t\t\t\tposition: \"right\",\n\t\t\t\tfields: [f.visibility],\n\t\t\t},\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"section\",\n\t\t\t\t\tfields: [f.preview],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: \"section\",\n\t\t\t\t\tlabel: { key: \"defaults.assets.sections.fileInfo\" },\n\t\t\t\t\tlayout: \"grid\",\n\t\t\t\t\tcolumns: 2,\n\t\t\t\t\tfields: [f.filename, f.mimeType, f.size],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: \"section\",\n\t\t\t\t\tlabel: { key: \"defaults.assets.sections.metadata\" },\n\t\t\t\t\tdescription: { key: \"defaults.assets.sections.metadata.description\" },\n\t\t\t\t\tfields: [f.alt, f.caption],\n\t\t\t\t},\n\t\t\t],\n\t\t}),\n\t);\n","/**\n * User Collection Admin Config\n *\n * Default admin UI configuration for the built-in user collection.\n * Works with Better Auth's user model (admin plugin).\n */\n\nimport { LockKey, UserPlus, UsersIcon } from \"@phosphor-icons/react\";\nimport { coreAdminModule } from \"../core\";\n\n/**\n * User collection admin configuration\n *\n * Provides admin UI for managing users with:\n * - Name, email, and role fields\n * - Ban status management\n * - Table view with key columns\n * - Create user with credentials (no email dependency)\n *\n * @example\n * ```ts\n * import { adminStarterModule } from \"@questpie/admin/builder/defaults\";\n *\n * const admin = qa().use(adminStarterModule);\n * // User collection is automatically configured\n * ```\n */\nexport const userCollectionAdmin = coreAdminModule\n\t.collection(\"user\")\n\t.meta({\n\t\tlabel: { key: \"defaults.users.label\" },\n\t\ticon: UsersIcon,\n\t\tdescription: { key: \"defaults.users.description\" },\n\t})\n\t.fields(({ r }) => ({\n\t\tname: r.text({\n\t\t\tlabel: { key: \"defaults.users.fields.name.label\" },\n\t\t\tplaceholder: { key: \"defaults.users.fields.name.placeholder\" },\n\t\t}),\n\t\temail: r.email({\n\t\t\tlabel: { key: \"defaults.users.fields.email.label\" },\n\t\t\tdescription: { key: \"defaults.users.fields.email.description\" },\n\t\t}),\n\t\trole: r.select({\n\t\t\tlabel: { key: \"defaults.users.fields.role.label\" },\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tvalue: \"admin\",\n\t\t\t\t\tlabel: { key: \"defaults.users.fields.role.options.admin\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: \"user\",\n\t\t\t\t\tlabel: { key: \"defaults.users.fields.role.options.user\" },\n\t\t\t\t},\n\t\t\t],\n\t\t}),\n\t\temailVerified: r.checkbox({\n\t\t\tlabel: { key: \"defaults.users.fields.emailVerified.label\" },\n\t\t\tdescription: { key: \"defaults.users.fields.emailVerified.description\" },\n\t\t}),\n\t\tbanned: r.checkbox({\n\t\t\tlabel: { key: \"defaults.users.fields.banned.label\" },\n\t\t\tdescription: { key: \"defaults.users.fields.banned.description\" },\n\t\t}),\n\t\tbanReason: r.textarea({\n\t\t\tlabel: { key: \"defaults.users.fields.banReason.label\" },\n\t\t\tplaceholder: { key: \"defaults.users.fields.banReason.placeholder\" },\n\t\t\trows: 2,\n\t\t}),\n\t}))\n\t.list(({ v, f, a, r }) =>\n\t\tv.table({\n\t\t\tcolumns: [f.name, f.email, f.role, f.banned],\n\t\t\tsearchFields: [f.name, f.email],\n\t\t\tsearchable: true,\n\t\t\tdefaultSort: {\n\t\t\t\tfield: f.name,\n\t\t\t\tdirection: \"asc\",\n\t\t\t},\n\t\t\tactions: {\n\t\t\t\theader: {\n\t\t\t\t\tprimary: [\n\t\t\t\t\t\t// Create User - opens form dialog, shows credentials to copy\n\t\t\t\t\t\ta.action({\n\t\t\t\t\t\t\tid: \"createUser\",\n\t\t\t\t\t\t\tlabel: { key: \"defaults.users.actions.createUser.label\" },\n\t\t\t\t\t\t\ticon: UserPlus,\n\t\t\t\t\t\t\tvariant: \"default\",\n\t\t\t\t\t\t\thandler: {\n\t\t\t\t\t\t\t\ttype: \"form\",\n\t\t\t\t\t\t\t\tconfig: {\n\t\t\t\t\t\t\t\t\ttitle: { key: \"defaults.users.actions.createUser.title\" },\n\t\t\t\t\t\t\t\t\tdescription: {\n\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.createUser.description\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tfields: {\n\t\t\t\t\t\t\t\t\t\tname: r.text({\n\t\t\t\t\t\t\t\t\t\t\tlabel: { key: \"defaults.users.fields.name.label\" },\n\t\t\t\t\t\t\t\t\t\t\tplaceholder: {\n\t\t\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.fields.name.placeholder\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\temail: r.email({\n\t\t\t\t\t\t\t\t\t\t\tlabel: { key: \"defaults.users.fields.email.label\" },\n\t\t\t\t\t\t\t\t\t\t\tplaceholder: { key: \"auth.emailPlaceholder\" },\n\t\t\t\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\tpassword: r.password({\n\t\t\t\t\t\t\t\t\t\t\tlabel: {\n\t\t\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.createUser.fields.password.label\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tplaceholder: {\n\t\t\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.createUser.fields.password.placeholder\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\trole: r.select({\n\t\t\t\t\t\t\t\t\t\t\tlabel: { key: \"defaults.users.fields.role.label\" },\n\t\t\t\t\t\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.fields.role.options.user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: \"admin\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tlabel: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.fields.role.options.admin\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tsubmitLabel: {\n\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.createUser.submit\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tonSubmit: async (data, ctx) => {\n\t\t\t\t\t\t\t\t\t\tif (!ctx.authClient) {\n\t\t\t\t\t\t\t\t\t\t\tctx.helpers.toast.error(\n\t\t\t\t\t\t\t\t\t\t\t\tctx.helpers.t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"defaults.users.actions.createUser.errorNoAuth\",\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t// Use admin.createUser to create user without logging out current admin\n\t\t\t\t\t\t\t\t\t\t\tconst result = await ctx.authClient.admin.createUser({\n\t\t\t\t\t\t\t\t\t\t\t\temail: data.email,\n\t\t\t\t\t\t\t\t\t\t\t\tpassword: data.password,\n\t\t\t\t\t\t\t\t\t\t\t\tname: data.name,\n\t\t\t\t\t\t\t\t\t\t\t\trole: data.role || \"user\",\n\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\tif (result.error) {\n\t\t\t\t\t\t\t\t\t\t\t\tctx.helpers.toast.error(\n\t\t\t\t\t\t\t\t\t\t\t\t\tresult.error.message ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tctx.helpers.t(\"form.createError\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tname: ctx.helpers.t(\"defaults.users.label\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tctx.helpers.toast.success(\n\t\t\t\t\t\t\t\t\t\t\t\tctx.helpers.t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"defaults.users.actions.createUser.success\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\temail: data.email,\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\tawait ctx.helpers.invalidateCollection();\n\t\t\t\t\t\t\t\t\t\t\tctx.helpers.closeDialog();\n\t\t\t\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\t\t\t\tctx.helpers.toast.error(\n\t\t\t\t\t\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t\t\t\t\t\t\t\t: ctx.helpers.t(\"form.createError\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tname: ctx.helpers.t(\"defaults.users.label\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t\t\t],\n\t\t\t\t\tsecondary: [],\n\t\t\t\t},\n\t\t\t\tbulk: [\n\t\t\t\t\ta.deleteMany(),\n\t\t\t\t\ta.duplicate(), // Default visibility: only shows when 1 item selected\n\t\t\t\t],\n\t\t\t},\n\t\t}),\n\t)\n\t.form(({ v, f, a, r }) =>\n\t\tv.form({\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"section\",\n\t\t\t\t\tlabel: { key: \"defaults.users.sections.basicInfo\" },\n\t\t\t\t\tlayout: \"grid\",\n\t\t\t\t\tcolumns: 2,\n\t\t\t\t\tfields: [f.name, f.email],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: \"section\",\n\t\t\t\t\tlabel: { key: \"defaults.users.sections.permissions\" },\n\t\t\t\t\tfields: [f.role, f.emailVerified],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: \"section\",\n\t\t\t\t\tlabel: { key: \"defaults.users.sections.accessControl\" },\n\t\t\t\t\tfields: [f.banned, f.banReason],\n\t\t\t\t},\n\t\t\t],\n\t\t\tactions: {\n\t\t\t\tprimary: [],\n\t\t\t\tsecondary: [\n\t\t\t\t\t// Reset Password\n\t\t\t\t\ta.action({\n\t\t\t\t\t\tid: \"resetPassword\",\n\t\t\t\t\t\tlabel: { key: \"defaults.users.actions.resetPassword.label\" },\n\t\t\t\t\t\ticon: LockKey,\n\t\t\t\t\t\thandler: {\n\t\t\t\t\t\t\ttype: \"form\",\n\t\t\t\t\t\t\tconfig: {\n\t\t\t\t\t\t\t\ttitle: { key: \"defaults.users.actions.resetPassword.title\" },\n\t\t\t\t\t\t\t\tdescription: {\n\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.resetPassword.description\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tfields: {\n\t\t\t\t\t\t\t\t\tnewPassword: r.password({\n\t\t\t\t\t\t\t\t\t\tlabel: {\n\t\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.resetPassword.fields.newPassword.label\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tplaceholder: {\n\t\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.resetPassword.fields.newPassword.placeholder\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\tconfirmPassword: r.password({\n\t\t\t\t\t\t\t\t\t\tlabel: {\n\t\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.resetPassword.fields.confirmPassword.label\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tplaceholder: {\n\t\t\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.resetPassword.fields.confirmPassword.placeholder\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsubmitLabel: {\n\t\t\t\t\t\t\t\t\tkey: \"defaults.users.actions.resetPassword.submit\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tonSubmit: async (data, ctx) => {\n\t\t\t\t\t\t\t\t\tif (data.newPassword !== data.confirmPassword) {\n\t\t\t\t\t\t\t\t\t\tctx.helpers.toast.error(\n\t\t\t\t\t\t\t\t\t\t\tctx.helpers.t(\n\t\t\t\t\t\t\t\t\t\t\t\t\"defaults.users.actions.resetPassword.errorMismatch\",\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// TODO: Call Better Auth password reset API\n\t\t\t\t\t\t\t\t\t// Show new password to copy\n\t\t\t\t\t\t\t\t\tctx.helpers.toast.success(\n\t\t\t\t\t\t\t\t\t\tctx.helpers.t(\n\t\t\t\t\t\t\t\t\t\t\t\"defaults.users.actions.resetPassword.success\",\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tctx.helpers.closeDialog();\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t\t// Duplicate (default: only visible for single item)\n\t\t\t\t\ta.duplicate(),\n\t\t\t\t\t// Delete (default: with confirmation dialog)\n\t\t\t\t\ta.delete({ label: { key: \"defaults.users.actions.delete.label\" } }),\n\t\t\t\t],\n\t\t\t},\n\t\t}),\n\t);\n","/**\n * Admin Module (Client)\n *\n * \"Batteries included\" module that extends coreAdminModule with:\n * - User collection admin UI\n * - Auth pages (login, forgot-password, reset-password, setup)\n * - User management in sidebar\n *\n * This is the frontend counterpart to `adminModule` from `@questpie/admin/server`.\n *\n * @example\n * ```ts\n * import { qa, adminModule } from \"@questpie/admin/client\";\n *\n * const admin = qa()\n * .use(adminModule)\n * .collections({\n * posts: postsAdmin,\n * });\n * ```\n */\n\nimport { Images, Users } from \"@phosphor-icons/react\";\nimport { qa } from \"../qa\";\nimport { assetsCollectionAdmin } from \"./collections/assets\";\nimport { userCollectionAdmin } from \"./collections/user\";\nimport { coreAdminModule } from \"./core\";\n\n/**\n * Admin Module - the complete frontend config for QuestPie admin panel.\n *\n * Includes:\n * - All fields, views, and pages from coreAdminModule\n * - User collection admin UI\n * - Administration sidebar section with user management\n *\n * @example\n * ```ts\n * // Basic usage\n * import { qa, adminModule } from \"@questpie/admin/client\";\n *\n * const admin = qa()\n * .use(adminModule)\n * .collections({\n * posts: postsAdmin,\n * });\n * ```\n */\nexport const adminModule = coreAdminModule\n\t// Add built-in collection admin configs\n\t.collections({\n\t\tuser: userCollectionAdmin,\n\t\tassets: assetsCollectionAdmin,\n\t})\n\t// Add administration sidebar section\n\t.sidebar(\n\t\tqa.sidebar().section(\"administration\", (s) =>\n\t\t\ts.title({ key: \"defaults.sidebar.administration\" }).items([\n\t\t\t\t{ type: \"collection\", collection: \"user\", icon: Users },\n\t\t\t\t{ type: \"collection\", collection: \"assets\", icon: Images },\n\t\t\t]),\n\t\t),\n\t);\n\n/**\n * Type of admin module state\n */\nexport type AdminModule = typeof adminModule;\n","/**\n * Typed Helpers Factory\n *\n * Creates type-safe helpers for working with admin config.\n * Simplifies complex generics in components and hooks.\n */\n\nimport type { AdminBuilder } from \"./admin-builder\";\n\n/**\n * TODO: check if this may cause infinite types if used in collection itself\n * Create typed helpers from admin config\n *\n * @example\n * ```typescript\n * import { admin } from './admin';\n * import { createAdminHelpers } from '@questpie/admin/builder';\n *\n * export const h = createAdminHelpers<typeof admin>();\n * h.collection('posts'); // 'posts'\n * h.global('siteSettings'); // 'siteSettings'\n *\n */\nexport function createAdminHelpers<TAdmin extends AdminBuilder<any>>() {\n type TApp = TAdmin[\"state\"][\"~app\"];\n type TCollections = keyof TAdmin[\"state\"][\"collections\"];\n type TGlobals = keyof TAdmin[\"state\"][\"globals\"];\n\n return {\n collection(name: TCollections) {\n return name;\n },\n\n global(name: TGlobals) {\n return name;\n },\n\n /**\n * Navigation helpers\n *\n * TODO: We want to use aliases to build type-safe paths\n */\n // route: {\n // \tdashboard: () => {\n // \t\tconsole.warn(\"navigate.dashboard() not implemented\");\n // \t},\n // \tcollection: (name: TCollections) => {\n // \t\tconsole.warn(`navigate.collection(\"${String(name)}\") not implemented`);\n // \t},\n // \tcollectionCreate: (name: TCollections) => {\n // \t\tconsole.warn(\n // \t\t\t`navigate.collectionCreate(\"${String(name)}\") not implemented`,\n // \t\t);\n // \t},\n // \tcollectionEdit: (name: TCollections, id: string) => {\n // \t\tconsole.warn(\n // \t\t\t`navigate.collectionEdit(\"${String(name)}\", \"${id}\") not implemented`,\n // \t\t);\n // \t},\n // \tglobal: (name: TGlobals) => {\n // \t\tconsole.warn(`navigate.global(\"${String(name)}\") not implemented`);\n // \t},\n // },\n };\n}\n\n/**\n * Type of helpers created by createAdminHelpers\n */\nexport type AdminHelpers<TAdmin extends AdminBuilder<any>> = ReturnType<\n typeof createAdminHelpers<TAdmin>\n>;\n","import { cn } from \"../../lib/utils\";\nimport { SpinnerIcon } from \"@phosphor-icons/react\";\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <SpinnerIcon\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n {...props}\n />\n );\n}\n\nexport { Spinner };\n","/**\n * Auth Loading Component\n *\n * Full-page loading state shown while checking authentication.\n * Used as the default loadingFallback in AuthGuard.\n */\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Spinner } from \"../ui/spinner\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AuthLoadingProps {\n /**\n * Custom class name for the container\n */\n className?: string;\n\n /**\n * Loading message to display\n * @default \"Loading...\"\n */\n message?: string;\n\n /**\n * Show the loading message\n * @default true\n */\n showMessage?: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Full-page loading state for authentication\n *\n * @example\n * ```tsx\n * <AuthLoading message=\"Checking authentication...\" />\n * ```\n */\nexport function AuthLoading({\n className,\n message = \"Loading...\",\n showMessage = true,\n}: AuthLoadingProps): React.ReactElement {\n return (\n <div\n className={cn(\n \"flex min-h-screen flex-col items-center justify-center gap-4\",\n className,\n )}\n >\n <Spinner className=\"size-8 text-primary\" />\n {showMessage && (\n <p className=\"text-sm text-muted-foreground\">{message}</p>\n )}\n </div>\n );\n}\n\nexport default AuthLoading;\n","/**\n * Auth Guard Component\n *\n * Wraps protected content and handles authentication state.\n * Shows loading state while checking session, redirects to login\n * if not authenticated or missing required role.\n *\n * @example\n * ```tsx\n * <AuthGuard loginPath=\"/admin/login\" requiredRole=\"admin\">\n * <ProtectedContent />\n * </AuthGuard>\n * ```\n */\n\nimport * as React from \"react\";\nimport { useAuthClientSafe } from \"../../hooks/use-auth\";\nimport {\n selectBasePath,\n selectNavigate,\n useAdminStore,\n} from \"../../runtime/provider\";\nimport { AuthLoading } from \"./auth-loading\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AuthGuardProps {\n /**\n * Content to render when authenticated\n */\n children: React.ReactNode;\n\n /**\n * Fallback to show while checking session\n * @default <AuthLoading />\n */\n loadingFallback?: React.ReactNode;\n\n /**\n * Path to redirect to when not authenticated\n * @default \"{basePath}/login\"\n */\n loginPath?: string;\n\n /**\n * Custom component to show when unauthorized (instead of redirect)\n */\n unauthorizedFallback?: React.ReactNode;\n\n /**\n * Required role for access\n * @default \"admin\"\n */\n requiredRole?: string;\n\n /**\n * Disable the auth guard (render children directly)\n * Useful for public pages within the admin layout\n */\n disabled?: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Auth Guard Component\n *\n * Protects content by checking authentication state and user role.\n * Uses Better Auth's useSession() hook internally.\n */\nexport function AuthGuard({\n children,\n loadingFallback,\n loginPath,\n unauthorizedFallback,\n requiredRole = \"admin\",\n disabled = false,\n}: AuthGuardProps): React.ReactElement {\n const authClient = useAuthClientSafe();\n const basePath = useAdminStore(selectBasePath);\n const navigate = useAdminStore(selectNavigate);\n\n // If disabled, render children directly\n if (disabled) {\n return <>{children}</>;\n }\n\n // If no auth client provided, render children (auth is optional)\n if (!authClient) {\n return <>{children}</>;\n }\n\n // Use Better Auth's session hook\n const { data: session, isPending, error } = authClient.useSession();\n\n // Handle redirect after render (useEffect for side effects)\n const resolvedLoginPath = loginPath ?? `${basePath}/login`;\n const shouldRedirect =\n !isPending && (!session || session.user?.role !== requiredRole);\n\n React.useEffect(() => {\n if (shouldRedirect && !unauthorizedFallback) {\n // Store current path for redirect after login\n const currentPath =\n typeof window !== \"undefined\" ? window.location.pathname : \"\";\n const redirectUrl = currentPath\n ? `${resolvedLoginPath}?redirect=${encodeURIComponent(currentPath)}`\n : resolvedLoginPath;\n navigate(redirectUrl);\n }\n }, [shouldRedirect, unauthorizedFallback, resolvedLoginPath, navigate]);\n\n // Loading state\n if (isPending) {\n return <>{loadingFallback ?? <AuthLoading />}</>;\n }\n\n // Not authenticated or wrong role\n if (!session || session.user?.role !== requiredRole) {\n // Show unauthorized fallback if provided\n if (unauthorizedFallback) {\n return <>{unauthorizedFallback}</>;\n }\n\n // Otherwise show loading while redirect happens\n return <>{loadingFallback ?? <AuthLoading />}</>;\n }\n\n // Authenticated with correct role - render children\n return <>{children}</>;\n}\n\nexport default AuthGuard;\n","import type { ReactNode } from \"react\";\n\nimport { cn } from \"#questpie/admin/client/lib/utils\";\n\n/**\n * TipTap JSON node types\n */\nexport type TipTapNode = {\n\ttype: string;\n\tcontent?: TipTapNode[];\n\ttext?: string;\n\tmarks?: Array<{ type: string; attrs?: Record<string, unknown> }>;\n\tattrs?: Record<string, unknown>;\n};\n\nexport type TipTapDoc = {\n\ttype: \"doc\";\n\tcontent?: TipTapNode[];\n};\n\n/**\n * Style configuration for rich text elements\n */\nexport interface RichTextStyles {\n\tdoc?: string;\n\tparagraph?: string;\n\theading1?: string;\n\theading2?: string;\n\theading3?: string;\n\theading4?: string;\n\theading5?: string;\n\theading6?: string;\n\tblockquote?: string;\n\tcodeBlock?: string;\n\tbulletList?: string;\n\torderedList?: string;\n\tlistItem?: string;\n\tlink?: string;\n\timage?: string;\n\ttableWrapper?: string;\n\ttable?: string;\n\ttableRow?: string;\n\ttableCell?: string;\n\ttableHeader?: string;\n\thorizontalRule?: string;\n\tbold?: string;\n\titalic?: string;\n\tcode?: string;\n\tstrike?: string;\n\tunderline?: string;\n}\n\nconst defaultStyles: RichTextStyles = {\n\tdoc: \"prose prose-sm max-w-none\",\n\tparagraph: \"mb-4 last:mb-0\",\n\theading1: \"text-3xl font-bold mb-4\",\n\theading2: \"text-2xl font-bold mb-3\",\n\theading3: \"text-xl font-semibold mb-3\",\n\theading4: \"text-lg font-semibold mb-2\",\n\theading5: \"text-base font-semibold mb-2\",\n\theading6: \"text-sm font-semibold mb-2\",\n\tblockquote: \"border-l-4 border-gray-300 pl-4 italic my-4\",\n\tcodeBlock: \"bg-gray-100 rounded p-4 font-mono text-sm my-4 overflow-x-auto\",\n\tbulletList: \"list-disc list-inside mb-4\",\n\torderedList: \"list-decimal list-inside mb-4\",\n\tlistItem: \"mb-1\",\n\tlink: \"text-blue-600 hover:text-blue-800 underline\",\n\timage: \"my-4 rounded-lg\",\n\ttableWrapper: \"my-4 overflow-x-auto\",\n\ttable: \"w-full border-collapse\",\n\ttableRow: \"border-b\",\n\ttableCell: \"border border-gray-200 px-3 py-2 align-top\",\n\ttableHeader: \"border border-gray-200 px-3 py-2 text-left font-semibold\",\n\thorizontalRule: \"my-4 border-t border-gray-300\",\n\tbold: \"font-bold\",\n\titalic: \"italic\",\n\tcode: \"bg-gray-100 rounded px-1 py-0.5 font-mono text-sm\",\n\tstrike: \"line-through\",\n\tunderline: \"underline\",\n};\n\ninterface RichTextRendererProps {\n\t/**\n\t * TipTap JSON content to render\n\t */\n\tcontent: TipTapDoc | null | undefined;\n\t/**\n\t * Custom styles for elements\n\t */\n\tstyles?: Partial<RichTextStyles>;\n\t/**\n\t * Additional className for the root element\n\t */\n\tclassName?: string;\n}\n\n/**\n * Renders a single TipTap node\n */\nfunction renderNode(\n\tnode: TipTapNode,\n\tindex: number,\n\tstyles: RichTextStyles,\n): ReactNode {\n\t// Text node\n\tif (node.text !== undefined) {\n\t\tlet textNode: ReactNode = node.text;\n\n\t\t// Apply marks (bold, italic, etc.)\n\t\tif (node.marks) {\n\t\t\tfor (const mark of node.marks) {\n\t\t\t\tswitch (mark.type) {\n\t\t\t\t\tcase \"bold\":\n\t\t\t\t\t\ttextNode = (\n\t\t\t\t\t\t\t<strong key={index} className={styles.bold}>\n\t\t\t\t\t\t\t\t{textNode}\n\t\t\t\t\t\t\t</strong>\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"italic\":\n\t\t\t\t\t\ttextNode = (\n\t\t\t\t\t\t\t<em key={index} className={styles.italic}>\n\t\t\t\t\t\t\t\t{textNode}\n\t\t\t\t\t\t\t</em>\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"code\":\n\t\t\t\t\t\ttextNode = (\n\t\t\t\t\t\t\t<code key={index} className={styles.code}>\n\t\t\t\t\t\t\t\t{textNode}\n\t\t\t\t\t\t\t</code>\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"strike\":\n\t\t\t\t\t\ttextNode = (\n\t\t\t\t\t\t\t<s key={index} className={styles.strike}>\n\t\t\t\t\t\t\t\t{textNode}\n\t\t\t\t\t\t\t</s>\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"underline\":\n\t\t\t\t\t\ttextNode = (\n\t\t\t\t\t\t\t<u key={index} className={styles.underline}>\n\t\t\t\t\t\t\t\t{textNode}\n\t\t\t\t\t\t\t</u>\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"link\": {\n\t\t\t\t\t\tconst href = mark.attrs?.href as string | undefined;\n\t\t\t\t\t\tconst target = mark.attrs?.target as string | undefined;\n\t\t\t\t\t\tconst rel =\n\t\t\t\t\t\t\t(mark.attrs?.rel as string | undefined) ||\n\t\t\t\t\t\t\t(target === \"_blank\" ? \"noopener noreferrer\" : undefined);\n\t\t\t\t\t\ttextNode = (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\thref={href}\n\t\t\t\t\t\t\t\ttarget={target}\n\t\t\t\t\t\t\t\trel={rel}\n\t\t\t\t\t\t\t\tclassName={styles.link}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{textNode}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn textNode;\n\t}\n\n\t// Block nodes\n\tconst children = node.content?.map((child, i) =>\n\t\trenderNode(child, i, styles),\n\t);\n\n\tswitch (node.type) {\n\t\tcase \"doc\":\n\t\t\treturn <div key={index}>{children}</div>;\n\n\t\tcase \"paragraph\": {\n\t\t\tconst paragraphAlign = node.attrs?.textAlign as\n\t\t\t\t| \"left\"\n\t\t\t\t| \"center\"\n\t\t\t\t| \"right\"\n\t\t\t\t| \"justify\"\n\t\t\t\t| undefined;\n\t\t\treturn (\n\t\t\t\t<p\n\t\t\t\t\tkey={index}\n\t\t\t\t\tclassName={styles.paragraph}\n\t\t\t\t\tstyle={paragraphAlign ? { textAlign: paragraphAlign } : undefined}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</p>\n\t\t\t);\n\t\t}\n\n\t\tcase \"heading\": {\n\t\t\tconst level = Math.min(\n\t\t\t\t6,\n\t\t\t\tMath.max(1, (node.attrs?.level as number) || 1),\n\t\t\t);\n\t\t\tconst headingAlign = node.attrs?.textAlign as\n\t\t\t\t| \"left\"\n\t\t\t\t| \"center\"\n\t\t\t\t| \"right\"\n\t\t\t\t| \"justify\"\n\t\t\t\t| undefined;\n\t\t\tconst headingClass =\n\t\t\t\tstyles[`heading${level}` as keyof RichTextStyles] || styles.heading1;\n\t\t\ttype HeadingTagName = \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\";\n\t\t\tconst HeadingTag = `h${level}` as HeadingTagName;\n\t\t\treturn (\n\t\t\t\t<HeadingTag\n\t\t\t\t\tkey={index}\n\t\t\t\t\tclassName={headingClass}\n\t\t\t\t\tstyle={headingAlign ? { textAlign: headingAlign } : undefined}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</HeadingTag>\n\t\t\t);\n\t\t}\n\n\t\tcase \"blockquote\":\n\t\t\treturn (\n\t\t\t\t<blockquote key={index} className={styles.blockquote}>\n\t\t\t\t\t{children}\n\t\t\t\t</blockquote>\n\t\t\t);\n\n\t\tcase \"codeBlock\":\n\t\t\treturn (\n\t\t\t\t<pre key={index} className={styles.codeBlock}>\n\t\t\t\t\t<code>{children}</code>\n\t\t\t\t</pre>\n\t\t\t);\n\n\t\tcase \"bulletList\":\n\t\t\treturn (\n\t\t\t\t<ul key={index} className={styles.bulletList}>\n\t\t\t\t\t{children}\n\t\t\t\t</ul>\n\t\t\t);\n\n\t\tcase \"orderedList\":\n\t\t\treturn (\n\t\t\t\t<ol key={index} className={styles.orderedList}>\n\t\t\t\t\t{children}\n\t\t\t\t</ol>\n\t\t\t);\n\n\t\tcase \"listItem\":\n\t\t\treturn (\n\t\t\t\t<li key={index} className={styles.listItem}>\n\t\t\t\t\t{children}\n\t\t\t\t</li>\n\t\t\t);\n\n\t\tcase \"hardBreak\":\n\t\t\treturn <br key={index} />;\n\n\t\tcase \"horizontalRule\":\n\t\t\treturn <hr key={index} className={styles.horizontalRule} />;\n\n\t\tcase \"image\": {\n\t\t\tconst src = node.attrs?.src as string | undefined;\n\t\t\tif (!src) return null;\n\t\t\treturn (\n\t\t\t\t<img\n\t\t\t\t\tkey={index}\n\t\t\t\t\tsrc={src}\n\t\t\t\t\talt={(node.attrs?.alt as string | undefined) || \"\"}\n\t\t\t\t\ttitle={node.attrs?.title as string | undefined}\n\t\t\t\t\tclassName={styles.image}\n\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\tcase \"table\":\n\t\t\treturn (\n\t\t\t\t<div key={index} className={styles.tableWrapper}>\n\t\t\t\t\t<table className={styles.table}>\n\t\t\t\t\t\t<tbody>{children}</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t);\n\n\t\tcase \"tableRow\":\n\t\t\treturn (\n\t\t\t\t<tr key={index} className={styles.tableRow}>\n\t\t\t\t\t{children}\n\t\t\t\t</tr>\n\t\t\t);\n\n\t\tcase \"tableCell\":\n\t\t\treturn (\n\t\t\t\t<td\n\t\t\t\t\tkey={index}\n\t\t\t\t\tclassName={styles.tableCell}\n\t\t\t\t\tcolSpan={node.attrs?.colspan as number | undefined}\n\t\t\t\t\trowSpan={node.attrs?.rowspan as number | undefined}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</td>\n\t\t\t);\n\n\t\tcase \"tableHeader\":\n\t\t\treturn (\n\t\t\t\t<th\n\t\t\t\t\tkey={index}\n\t\t\t\t\tclassName={styles.tableHeader}\n\t\t\t\t\tcolSpan={node.attrs?.colspan as number | undefined}\n\t\t\t\t\trowSpan={node.attrs?.rowspan as number | undefined}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</th>\n\t\t\t);\n\n\t\tdefault:\n\t\t\t// Unknown node type - render children if available\n\t\t\treturn children ? <div key={index}>{children}</div> : null;\n\t}\n}\n\n/**\n * RichTextRenderer Component\n *\n * Renders TipTap JSON content with customizable styles.\n *\n * @example\n * ```tsx\n * const content = {\n * type: \"doc\",\n * content: [\n * {\n * type: \"paragraph\",\n * content: [{ type: \"text\", text: \"Hello world\" }]\n * }\n * ]\n * };\n *\n * <RichTextRenderer content={content} />\n * ```\n *\n * @example With custom styles\n * ```tsx\n * <RichTextRenderer\n * content={content}\n * styles={{\n * paragraph: \"text-lg leading-relaxed\",\n * heading1: \"text-4xl font-black\"\n * }}\n * />\n * ```\n */\nexport function RichTextRenderer({\n\tcontent,\n\tstyles: customStyles,\n\tclassName,\n}: RichTextRendererProps) {\n\tif (!content || !content.content || content.content.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst styles = { ...defaultStyles, ...customStyles };\n\n\treturn (\n\t\t<div className={cn(styles.doc, className)}>\n\t\t\t{content.content.map((node, i) => renderNode(node, i, styles))}\n\t\t</div>\n\t);\n}\n","/**\n * Accept Invite Form - complete registration after receiving invitation\n */\n\nimport { Lock, SpinnerGap, User, WarningCircle } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport { Alert, AlertDescription } from \"../../components/ui/alert\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n} from \"../../components/ui/field\";\nimport { Input } from \"../../components/ui/input\";\nimport { cn } from \"../../lib/utils\";\n\nexport type AcceptInviteFormValues = {\n name: string;\n password: string;\n confirmPassword: string;\n};\n\nexport type AcceptInviteFormProps = {\n /** Called when form is submitted with valid data */\n onSubmit: (values: AcceptInviteFormValues) => Promise<void>;\n /** Email from the invitation (display only) */\n email?: string;\n /** Additional class name */\n className?: string;\n /** Error message from auth */\n error?: string | null;\n /** Minimum password length */\n minPasswordLength?: number;\n};\n\n/**\n * Accept invite form for new users to complete registration\n *\n * @example\n * ```tsx\n * function AcceptInvitePage({ token }: { token: string }) {\n * const authClient = useAuthClient()\n * const [error, setError] = useState<string | null>(null)\n * const [invitation, setInvitation] = useState<any>(null)\n *\n * // Fetch invitation details on mount\n * useEffect(() => {\n * authClient.admin.getInvitation({ token })\n * .then(setInvitation)\n * .catch(() => setError('Invalid or expired invitation'))\n * }, [token])\n *\n * const handleAccept = async (values: AcceptInviteFormValues) => {\n * const result = await authClient.admin.acceptInvitation({\n * token,\n * name: values.name,\n * password: values.password,\n * })\n * if (result.error) {\n * setError(result.error.message)\n * } else {\n * // Redirect to admin\n * }\n * }\n *\n * return (\n * <AcceptInviteForm\n * onSubmit={handleAccept}\n * email={invitation?.email}\n * error={error}\n * />\n * )\n * }\n * ```\n */\nexport function AcceptInviteForm({\n onSubmit,\n email,\n className,\n error,\n minPasswordLength = 8,\n}: AcceptInviteFormProps) {\n const {\n register,\n handleSubmit,\n watch,\n formState: { errors, isSubmitting },\n } = useForm<AcceptInviteFormValues>({\n defaultValues: {\n name: \"\",\n password: \"\",\n confirmPassword: \"\",\n },\n });\n\n const password = watch(\"password\");\n\n const handleFormSubmit = handleSubmit(async (values) => {\n await onSubmit(values);\n });\n\n return (\n <form onSubmit={handleFormSubmit} className={cn(\"space-y-4\", className)}>\n <FieldGroup>\n {/* Email Display (read-only) */}\n {email && (\n <Field>\n <FieldLabel>Email</FieldLabel>\n <FieldContent>\n <Input type=\"email\" value={email} disabled className=\"bg-muted\" />\n <FieldDescription>\n This is the email address associated with your invitation\n </FieldDescription>\n </FieldContent>\n </Field>\n )}\n\n {/* Name Field */}\n <Field data-invalid={!!errors.name}>\n <FieldLabel htmlFor=\"accept-name\">Your Name</FieldLabel>\n <FieldContent>\n <div className=\"relative\">\n <User\n className=\"text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2\"\n weight=\"duotone\"\n />\n <Input\n id=\"accept-name\"\n type=\"text\"\n placeholder=\"Enter your name\"\n className=\"pl-8\"\n autoComplete=\"name\"\n aria-invalid={!!errors.name}\n {...register(\"name\", {\n required: \"Name is required\",\n minLength: {\n value: 2,\n message: \"Name must be at least 2 characters\",\n },\n })}\n />\n </div>\n <FieldError>{errors.name?.message}</FieldError>\n </FieldContent>\n </Field>\n\n {/* Password Field */}\n <Field data-invalid={!!errors.password}>\n <FieldLabel htmlFor=\"accept-password\">Password</FieldLabel>\n <FieldContent>\n <div className=\"relative\">\n <Lock\n className=\"text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2\"\n weight=\"duotone\"\n />\n <Input\n id=\"accept-password\"\n type=\"password\"\n placeholder=\"Create a password\"\n className=\"pl-8\"\n autoComplete=\"new-password\"\n aria-invalid={!!errors.password}\n {...register(\"password\", {\n required: \"Password is required\",\n minLength: {\n value: minPasswordLength,\n message: `Password must be at least ${minPasswordLength} characters`,\n },\n })}\n />\n </div>\n <FieldDescription>\n Must be at least {minPasswordLength} characters\n </FieldDescription>\n <FieldError>{errors.password?.message}</FieldError>\n </FieldContent>\n </Field>\n\n {/* Confirm Password Field */}\n <Field data-invalid={!!errors.confirmPassword}>\n <FieldLabel htmlFor=\"accept-confirm-password\">\n Confirm Password\n </FieldLabel>\n <FieldContent>\n <div className=\"relative\">\n <Lock\n className=\"text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2\"\n weight=\"duotone\"\n />\n <Input\n id=\"accept-confirm-password\"\n type=\"password\"\n placeholder=\"Confirm your password\"\n className=\"pl-8\"\n autoComplete=\"new-password\"\n aria-invalid={!!errors.confirmPassword}\n {...register(\"confirmPassword\", {\n required: \"Please confirm your password\",\n validate: (value) =>\n value === password || \"Passwords do not match\",\n })}\n />\n </div>\n <FieldError>{errors.confirmPassword?.message}</FieldError>\n </FieldContent>\n </Field>\n </FieldGroup>\n\n {/* Error Message */}\n {error && (\n <Alert variant=\"destructive\">\n <WarningCircle />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n {/* Submit Button */}\n <Button\n type=\"submit\"\n className=\"w-full\"\n size=\"lg\"\n disabled={isSubmitting}\n >\n {isSubmitting ? (\n <>\n <SpinnerGap className=\"animate-spin\" weight=\"bold\" />\n Creating account...\n </>\n ) : (\n \"Create Account\"\n )}\n </Button>\n </form>\n );\n}\n","/**\n * GlobalForm Component\n *\n * Form wrapper for editing global settings.\n * Globals are singleton records (like site settings, homepage config, etc.)\n */\n\nimport type { Questpie } from \"questpie\";\nimport { type QuestpieClient, QuestpieClientError } from \"questpie/client\";\nimport React from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n\tCard,\n\tCardContent,\n\tCardDescription,\n\tCardFooter,\n\tCardHeader,\n\tCardTitle,\n} from \"../../components/ui/card\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { useGlobal, useGlobalUpdate } from \"../../hooks/use-global\";\nimport { useTranslation } from \"../../i18n/hooks\";\n\n/**\n * Global data type helper\n */\ntype GlobalData<\n\tT extends Questpie<any>,\n\tK extends keyof QuestpieClient<T>[\"globals\"],\n> = Awaited<ReturnType<QuestpieClient<T>[\"globals\"][K][\"get\"]>>;\n\n/**\n * GlobalForm props\n */\nexport type GlobalFormProps<\n\tT extends Questpie<any>,\n\tK extends keyof QuestpieClient<T>[\"globals\"],\n> = {\n\t/**\n\t * Global name\n\t */\n\tglobal: K;\n\n\t/**\n\t * Custom field renderer\n\t */\n\tchildren: React.ReactNode;\n\n\t/**\n\t * On submit success callback\n\t */\n\tonSuccess?: (data: GlobalData<T, K>) => void;\n\n\t/**\n\t * On error callback\n\t */\n\tonError?: (error: Error) => void;\n\n\t/**\n\t * Form title\n\t */\n\ttitle?: string;\n\n\t/**\n\t * Form description\n\t */\n\tdescription?: string;\n\n\t/**\n\t * Header actions (e.g. locale switcher)\n\t */\n\theaderActions?: React.ReactNode;\n\n\t/**\n\t * Submit button text\n\t */\n\tsubmitText?: string;\n\n\t/**\n\t * Show loading skeleton\n\t */\n\tshowSkeleton?: boolean;\n};\n\n/**\n * GlobalForm - Form wrapper for CMS globals\n *\n * @example\n * ```tsx\n * import { GlobalForm } from '@questpie/admin/views/globals'\n * import type { cms } from './server/cms'\n *\n * function SiteSettingsForm() {\n * return (\n * <GlobalForm<typeof cms, 'siteSettings'>\n * global=\"siteSettings\"\n * title=\"Site Settings\"\n * description=\"Configure your site settings\"\n * onSuccess={() => toast.success('Settings saved!')}\n * >\n * <FormField name=\"siteName\" label=\"Site Name\" />\n * <FormField name=\"tagline\" label=\"Tagline\" />\n * </GlobalForm>\n * )\n * }\n * ```\n */\nexport function GlobalForm<\n\tT extends Questpie<any>,\n\tK extends keyof QuestpieClient<T>[\"globals\"],\n>({\n\tglobal: globalName,\n\tchildren,\n\tonSuccess,\n\tonError,\n\ttitle,\n\tdescription,\n\theaderActions,\n\tsubmitText = \"Save Changes\",\n\tshowSkeleton = true,\n}: GlobalFormProps<T, K>): React.ReactElement {\n\tconst { t } = useTranslation();\n\n\t// Fetch global data - cast globalName to satisfy the hook's expected type\n\tconst {\n\t\tdata: globalData,\n\t\tisLoading,\n\t\terror: fetchError,\n\t} = useGlobal(globalName as string, { localeFallback: false });\n\n\t// Update mutation\n\tconst updateMutation = useGlobalUpdate(globalName as string, {\n\t\tonSuccess: (data) => {\n\t\t\tonSuccess?.(data as unknown as GlobalData<T, K>);\n\t\t},\n\t\tonError: (error) => {\n\t\t\tonError?.(error);\n\t\t},\n\t});\n\n\t// Form setup\n\tconst form = useForm({\n\t\tdefaultValues: (globalData ?? {}) as any,\n\t});\n\n\t// Reset form when data loads\n\tReact.useEffect(() => {\n\t\tif (globalData) {\n\t\t\tform.reset(globalData as any);\n\t\t}\n\t}, [form, globalData]);\n\n\t// Handle submit\n\tconst onSubmit = async (data: any) => {\n\t\ttry {\n\t\t\tawait updateMutation.mutateAsync({ data });\n\t\t} catch (error) {\n\t\t\t// Handle field-level validation errors from the API\n\t\t\tif (\n\t\t\t\terror instanceof QuestpieClientError &&\n\t\t\t\terror.fieldErrors &&\n\t\t\t\terror.fieldErrors.length > 0\n\t\t\t) {\n\t\t\t\tfor (const fieldError of error.fieldErrors) {\n\t\t\t\t\tform.setError(fieldError.path as any, {\n\t\t\t\t\t\ttype: \"server\",\n\t\t\t\t\t\tmessage: fieldError.message,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\ttoast.error(t(\"toast.validationFailed\"), {\n\t\t\t\t\tdescription: t(\"toast.validationDescription\"),\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Handle generic errors\n\t\t\tconst message =\n\t\t\t\terror instanceof Error ? error.message : t(\"error.unknown\");\n\t\t\ttoast.error(t(\"toast.settingsSaveFailed\"), {\n\t\t\t\tdescription: message,\n\t\t\t});\n\t\t}\n\t};\n\n\t// Loading state\n\tif (isLoading && showSkeleton) {\n\t\treturn (\n\t\t\t<Card>\n\t\t\t\t{(title || headerActions) && (\n\t\t\t\t\t<CardHeader className=\"flex flex-wrap items-center justify-between gap-3\">\n\t\t\t\t\t\t{title && <Skeleton className=\"h-6 w-48\" />}\n\t\t\t\t\t\t{headerActions && <Skeleton className=\"h-9 w-32\" />}\n\t\t\t\t\t</CardHeader>\n\t\t\t\t)}\n\t\t\t\t<CardContent className=\"space-y-4\">\n\t\t\t\t\t<Skeleton className=\"h-10 w-full\" />\n\t\t\t\t\t<Skeleton className=\"h-10 w-full\" />\n\t\t\t\t\t<Skeleton className=\"h-10 w-full\" />\n\t\t\t\t</CardContent>\n\t\t\t\t<CardFooter className=\"flex justify-end\">\n\t\t\t\t\t<Skeleton className=\"h-10 w-24\" />\n\t\t\t\t</CardFooter>\n\t\t\t</Card>\n\t\t);\n\t}\n\n\t// Error state\n\tif (fetchError) {\n\t\treturn (\n\t\t\t<Card>\n\t\t\t\t<CardHeader>\n\t\t\t\t\t<CardTitle className=\"text-destructive\">Error</CardTitle>\n\t\t\t\t</CardHeader>\n\t\t\t\t<CardContent>\n\t\t\t\t\t<p className=\"text-muted-foreground\">\n\t\t\t\t\t\tFailed to load global settings: {fetchError.message}\n\t\t\t\t\t</p>\n\t\t\t\t</CardContent>\n\t\t\t</Card>\n\t\t);\n\t}\n\n\treturn (\n\t\t<FormProvider {...form}>\n\t\t\t<form onSubmit={form.handleSubmit(onSubmit)}>\n\t\t\t\t<Card>\n\t\t\t\t\t{(title || description || headerActions) && (\n\t\t\t\t\t\t<CardHeader className=\"flex flex-wrap items-start justify-between gap-3\">\n\t\t\t\t\t\t\t<div className=\"space-y-1\">\n\t\t\t\t\t\t\t\t{title && <CardTitle>{title}</CardTitle>}\n\t\t\t\t\t\t\t\t{description && (\n\t\t\t\t\t\t\t\t\t<CardDescription>{description}</CardDescription>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{headerActions && <div>{headerActions}</div>}\n\t\t\t\t\t\t</CardHeader>\n\t\t\t\t\t)}\n\t\t\t\t\t<CardContent className=\"space-y-4\">{children}</CardContent>\n\t\t\t\t\t<CardFooter className=\"flex justify-end gap-2\">\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\tdisabled={form.formState.isSubmitting || updateMutation.isPending}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{form.formState.isSubmitting || updateMutation.isPending\n\t\t\t\t\t\t\t\t? \"Saving...\"\n\t\t\t\t\t\t\t\t: submitText}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</CardFooter>\n\t\t\t\t</Card>\n\t\t\t</form>\n\t\t</FormProvider>\n\t);\n}\n","import * as React from \"react\";\n\nconst MOBILE_BREAKPOINT = 768;\n\nexport function useIsMobile() {\n const [isMobile, setIsMobile] = React.useState<boolean | undefined>(\n undefined,\n );\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n };\n mql.addEventListener(\"change\", onChange);\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\n return () => mql.removeEventListener(\"change\", onChange);\n }, []);\n\n return !!isMobile;\n}\n","\"use client\";\n\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { SidebarIcon } from \"@phosphor-icons/react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { useIsMobile } from \"../../hooks/use-mobile\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"./button\";\nimport { Input } from \"./input\";\nimport { Separator } from \"./separator\";\nimport {\n\tSheet,\n\tSheetContent,\n\tSheetDescription,\n\tSheetHeader,\n\tSheetTitle,\n} from \"./sheet\";\nimport { Skeleton } from \"./skeleton\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"./tooltip\";\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\";\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;\nconst SIDEBAR_WIDTH = \"16rem\";\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\";\nconst SIDEBAR_WIDTH_ICON = \"3rem\";\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\";\n\ntype SidebarContextProps = {\n\tstate: \"expanded\" | \"collapsed\";\n\topen: boolean;\n\tsetOpen: (open: boolean) => void;\n\topenMobile: boolean;\n\tsetOpenMobile: (open: boolean) => void;\n\tisMobile: boolean;\n\ttoggleSidebar: () => void;\n};\n\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null);\n\nfunction useSidebar() {\n\tconst context = React.useContext(SidebarContext);\n\tif (!context) {\n\t\tthrow new Error(\"useSidebar must be used within a SidebarProvider.\");\n\t}\n\n\treturn context;\n}\n\nfunction SidebarProvider({\n\tdefaultOpen = true,\n\topen: openProp,\n\tonOpenChange: setOpenProp,\n\tclassName,\n\tstyle,\n\tchildren,\n\t...props\n}: React.ComponentProps<\"div\"> & {\n\tdefaultOpen?: boolean;\n\topen?: boolean;\n\tonOpenChange?: (open: boolean) => void;\n}) {\n\tconst isMobile = useIsMobile();\n\tconst [openMobile, setOpenMobile] = React.useState(false);\n\n\t// This is the internal state of the sidebar.\n\t// We use openProp and setOpenProp for control from outside the component.\n\tconst [_open, _setOpen] = React.useState(defaultOpen);\n\tconst open = openProp ?? _open;\n\tconst setOpen = React.useCallback(\n\t\t(value: boolean | ((value: boolean) => boolean)) => {\n\t\t\tconst openState = typeof value === \"function\" ? value(open) : value;\n\t\t\tif (setOpenProp) {\n\t\t\t\tsetOpenProp(openState);\n\t\t\t} else {\n\t\t\t\t_setOpen(openState);\n\t\t\t}\n\n\t\t\t// This sets the cookie to keep the sidebar state.\n\t\t\tdocument.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;\n\t\t},\n\t\t[setOpenProp, open],\n\t);\n\n\t// Helper to toggle the sidebar.\n\tconst toggleSidebar = React.useCallback(() => {\n\t\treturn isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open);\n\t}, [isMobile, setOpen]);\n\n\t// Adds a keyboard shortcut to toggle the sidebar.\n\tReact.useEffect(() => {\n\t\tconst handleKeyDown = (event: KeyboardEvent) => {\n\t\t\tif (\n\t\t\t\tevent.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n\t\t\t\t(event.metaKey || event.ctrlKey)\n\t\t\t) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\ttoggleSidebar();\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener(\"keydown\", handleKeyDown);\n\t\treturn () => window.removeEventListener(\"keydown\", handleKeyDown);\n\t}, [toggleSidebar]);\n\n\t// We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n\t// This makes it easier to style the sidebar with Tailwind classes.\n\tconst state = open ? \"expanded\" : \"collapsed\";\n\n\tconst contextValue = React.useMemo<SidebarContextProps>(\n\t\t() => ({\n\t\t\tstate,\n\t\t\topen,\n\t\t\tsetOpen,\n\t\t\tisMobile,\n\t\t\topenMobile,\n\t\t\tsetOpenMobile,\n\t\t\ttoggleSidebar,\n\t\t}),\n\t\t[state, open, setOpen, isMobile, openMobile, toggleSidebar],\n\t);\n\n\treturn (\n\t\t<SidebarContext.Provider value={contextValue}>\n\t\t\t<div\n\t\t\t\tdata-slot=\"sidebar-wrapper\"\n\t\t\t\tstyle={\n\t\t\t\t\t{\n\t\t\t\t\t\t\"--sidebar-width\": SIDEBAR_WIDTH,\n\t\t\t\t\t\t\"--sidebar-width-icon\": SIDEBAR_WIDTH_ICON,\n\t\t\t\t\t\t...style,\n\t\t\t\t\t} as React.CSSProperties\n\t\t\t\t}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</SidebarContext.Provider>\n\t);\n}\n\nfunction Sidebar({\n\tside = \"left\",\n\tvariant = \"sidebar\",\n\tcollapsible = \"offExamples\",\n\tclassName,\n\tchildren,\n\t...props\n}: React.ComponentProps<\"div\"> & {\n\tside?: \"left\" | \"right\";\n\tvariant?: \"sidebar\" | \"floating\" | \"inset\";\n\tcollapsible?: \"offExamples\" | \"icon\" | \"none\";\n}) {\n\tconst { isMobile, state, openMobile, setOpenMobile } = useSidebar();\n\n\tif (collapsible === \"none\") {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tdata-slot=\"sidebar\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (isMobile) {\n\t\treturn (\n\t\t\t<Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\n\t\t\t\t<SheetContent\n\t\t\t\t\tdata-sidebar=\"sidebar\"\n\t\t\t\t\tdata-slot=\"sidebar\"\n\t\t\t\t\tdata-mobile=\"true\"\n\t\t\t\t\tclassName=\"bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0\"\n\t\t\t\t\tstyle={\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\n\t\t\t\t\t\t} as React.CSSProperties\n\t\t\t\t\t}\n\t\t\t\t\tside={side}\n\t\t\t\t>\n\t\t\t\t\t<SheetHeader className=\"sr-only\">\n\t\t\t\t\t\t<SheetTitle>Sidebar</SheetTitle>\n\t\t\t\t\t\t<SheetDescription>Displays the mobile sidebar.</SheetDescription>\n\t\t\t\t\t</SheetHeader>\n\t\t\t\t\t<div className=\"flex h-full w-full flex-col\">{children}</div>\n\t\t\t\t</SheetContent>\n\t\t\t</Sheet>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"group relative peer text-sidebar-foreground hidden md:block\"\n\t\t\tdata-state={state}\n\t\t\tdata-collapsible={state === \"collapsed\" ? collapsible : \"\"}\n\t\t\tdata-variant={variant}\n\t\t\tdata-side={side}\n\t\t\tdata-slot=\"sidebar\"\n\t\t>\n\t\t\t{/* This is what handles the sidebar gap on desktop */}\n\t\t\t<div\n\t\t\t\tdata-slot=\"sidebar-gap\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\" transition-[width] duration-200 ease-linear relative w-(--sidebar-width) bg-transparent\",\n\t\t\t\t\t\"group-data-[collapsible=offExamples]:w-0\",\n\t\t\t\t\t\"group-data-[side=right]:rotate-180\",\n\t\t\t\t\tvariant === \"floating\" || variant === \"inset\"\n\t\t\t\t\t\t? \"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]\"\n\t\t\t\t\t\t: \"group-data-[collapsible=icon]:w-(--sidebar-width-icon)\",\n\t\t\t\t)}\n\t\t\t/>\n\t\t\t<div\n\t\t\t\tdata-slot=\"sidebar-container\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"absolute inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex\",\n\t\t\t\t\tside === \"left\"\n\t\t\t\t\t\t? \"left-0 group-data-[collapsible=offExamples]:left-[calc(var(--sidebar-width)*-1)]\"\n\t\t\t\t\t\t: \"right-0 group-data-[collapsible=offExamples]:right-[calc(var(--sidebar-width)*-1)]\",\n\t\t\t\t\t// Adjust the padding for floating and inset variants.\n\t\t\t\t\tvariant === \"floating\" || variant === \"inset\"\n\t\t\t\t\t\t? \"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]\"\n\t\t\t\t\t\t: \"group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tdata-sidebar=\"sidebar\"\n\t\t\t\t\tdata-slot=\"sidebar-inner\"\n\t\t\t\t\tclassName=\"bg-sidebar/50 backdrop-blur-xl border-r border-sidebar-border/50 group-data-[variant=floating]:shadow-lg group-data-[variant=floating]:border flex size-full flex-col\"\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction SidebarTrigger({\n\tclassName,\n\tonClick,\n\t...props\n}: React.ComponentProps<typeof Button>) {\n\tconst { toggleSidebar } = useSidebar();\n\n\treturn (\n\t\t<Button\n\t\t\tdata-sidebar=\"trigger\"\n\t\t\tdata-slot=\"sidebar-trigger\"\n\t\t\tvariant=\"ghost\"\n\t\t\tsize=\"icon-sm\"\n\t\t\tclassName={className}\n\t\t\tonClick={(event) => {\n\t\t\t\tonClick?.(event);\n\t\t\t\ttoggleSidebar();\n\t\t\t}}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SidebarIcon />\n\t\t\t<span className=\"sr-only\">Toggle Sidebar</span>\n\t\t</Button>\n\t);\n}\n\nfunction SidebarRail({ className, ...props }: React.ComponentProps<\"button\">) {\n\tconst { toggleSidebar } = useSidebar();\n\n\treturn (\n\t\t<button\n\t\t\tdata-sidebar=\"rail\"\n\t\t\tdata-slot=\"sidebar-rail\"\n\t\t\taria-label=\"Toggle Sidebar\"\n\t\t\ttabIndex={-1}\n\t\t\tonClick={toggleSidebar}\n\t\t\ttitle=\"Toggle Sidebar\"\n\t\t\tclassName={cn(\n\t\t\t\t\"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex\",\n\t\t\t\t\"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize\",\n\t\t\t\t\"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize\",\n\t\t\t\t\"hover:group-data-[collapsible=offExamples]:bg-sidebar group-data-[collapsible=offExamples]:translate-x-0 group-data-[collapsible=offExamples]:after:left-full\",\n\t\t\t\t\"[[data-side=left][data-collapsible=offExamples]_&]:-right-2\",\n\t\t\t\t\"[[data-side=right][data-collapsible=offExamples]_&]:-left-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarInset({ className, ...props }: React.ComponentProps<\"main\">) {\n\treturn (\n\t\t<main\n\t\t\tdata-slot=\"sidebar-inset\"\n\t\t\tclassName={cn(\n\t\t\t\t\"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2 relative flex w-full flex-1 flex-col\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarInput({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof Input>) {\n\treturn (\n\t\t<Input\n\t\t\tdata-slot=\"sidebar-input\"\n\t\t\tdata-sidebar=\"input\"\n\t\t\tclassName={cn(\n\t\t\t\t\"bg-muted/20 dark:bg-muted/30 border-input h-8 w-full\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-header\"\n\t\t\tdata-sidebar=\"header\"\n\t\t\tclassName={cn(\"gap-2 h-16 p-2 flex flex-col\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-footer\"\n\t\t\tdata-sidebar=\"footer\"\n\t\t\tclassName={cn(\"gap-2 p-2 flex flex-col\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarSeparator({\n\tclassName,\n\t...props\n}: React.ComponentProps<typeof Separator>) {\n\treturn (\n\t\t<Separator\n\t\t\tdata-slot=\"sidebar-separator\"\n\t\t\tdata-sidebar=\"separator\"\n\t\t\tclassName={cn(\"bg-sidebar-border mx-2 w-full\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarContent({ className, ...props }: React.ComponentProps<\"div\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-content\"\n\t\t\tdata-sidebar=\"content\"\n\t\t\tclassName={cn(\n\t\t\t\t\"no-scrollbar gap-0 flex min-h-0 flex-1 flex-col overflow-auto group-data-[collapsible=icon]:overflow-hidden\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-group\"\n\t\t\tdata-sidebar=\"group\"\n\t\t\tclassName={cn(\n\t\t\t\t\"px-2 py-1 relative flex w-full min-w-0 flex-col\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarGroupLabel({\n\tclassName,\n\trender,\n\t...props\n}: useRender.ComponentProps<\"div\"> & React.ComponentProps<\"div\">) {\n\treturn useRender({\n\t\tdefaultTagName: \"div\",\n\t\tprops: mergeProps<\"div\">(\n\t\t\t{\n\t\t\t\tclassName: cn(\n\t\t\t\t\t\"text-sidebar-foreground/70 ring-sidebar-ring h-8 px-2 text-xs transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 flex shrink-0 items-center outline-hidden [&>svg]:shrink-0\",\n\t\t\t\t\tclassName,\n\t\t\t\t),\n\t\t\t},\n\t\t\tprops,\n\t\t),\n\t\trender,\n\t\tstate: {\n\t\t\tslot: \"sidebar-group-label\",\n\t\t\tsidebar: \"group-label\",\n\t\t},\n\t});\n}\n\nfunction SidebarGroupAction({\n\tclassName,\n\trender,\n\t...props\n}: useRender.ComponentProps<\"button\"> & React.ComponentProps<\"button\">) {\n\treturn useRender({\n\t\tdefaultTagName: \"button\",\n\t\tprops: mergeProps<\"button\">(\n\t\t\t{\n\t\t\t\tclassName: cn(\n\t\t\t\t\t\"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 w-5 p-0 focus-visible:ring-2 [&>svg]:size-4 flex aspect-square items-center justify-center outline-hidden transition-transform [&>svg]:shrink-0 after:absolute after:-inset-2 md:after:hidden group-data-[collapsible=icon]:hidden\",\n\t\t\t\t\tclassName,\n\t\t\t\t),\n\t\t\t},\n\t\t\tprops,\n\t\t),\n\t\trender,\n\t\tstate: {\n\t\t\tslot: \"sidebar-group-action\",\n\t\t\tsidebar: \"group-action\",\n\t\t},\n\t});\n}\n\nfunction SidebarGroupContent({\n\tclassName,\n\t...props\n}: React.ComponentProps<\"div\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-group-content\"\n\t\t\tdata-sidebar=\"group-content\"\n\t\t\tclassName={cn(\"text-xs w-full\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarMenu({ className, ...props }: React.ComponentProps<\"ul\">) {\n\treturn (\n\t\t<ul\n\t\t\tdata-slot=\"sidebar-menu\"\n\t\t\tdata-sidebar=\"menu\"\n\t\t\tclassName={cn(\"gap-px flex w-full min-w-0 flex-col\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarMenuItem({ className, ...props }: React.ComponentProps<\"li\">) {\n\treturn (\n\t\t<li\n\t\t\tdata-slot=\"sidebar-menu-item\"\n\t\t\tdata-sidebar=\"menu-item\"\n\t\t\tclassName={cn(\"group/menu-item relative\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nconst sidebarMenuButtonVariants = cva(\n\t\"ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-active:shadow-[0_0_10px_oklch(0.55_0.3_300_/_0.15)] data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 p-2 text-left text-xs transition-[width,height,padding,box-shadow] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0\",\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n\t\t\t\toutline:\n\t\t\t\t\t\"bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: \"h-8 text-xs\",\n\t\t\t\tsm: \"h-7 text-xs\",\n\t\t\t\tlg: \"h-12 text-xs group-data-[collapsible=icon]:p-0!\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nfunction SidebarMenuButton({\n\trender,\n\tisActive = false,\n\tvariant = \"default\",\n\tsize = \"default\",\n\ttooltip,\n\tclassName,\n\t...props\n}: useRender.ComponentProps<\"button\"> &\n\tReact.ComponentProps<\"button\"> & {\n\t\tisActive?: boolean;\n\t\ttooltip?: string | React.ComponentProps<typeof TooltipContent>;\n\t} & VariantProps<typeof sidebarMenuButtonVariants>) {\n\tconst { isMobile, state } = useSidebar();\n\tconst comp = useRender({\n\t\tdefaultTagName: \"button\",\n\t\tprops: mergeProps<\"button\">(\n\t\t\t{\n\t\t\t\tclassName: cn(sidebarMenuButtonVariants({ variant, size }), className),\n\t\t\t},\n\t\t\tprops,\n\t\t),\n\t\trender: !tooltip ? render : TooltipTrigger,\n\t\tstate: {\n\t\t\tslot: \"sidebar-menu-button\",\n\t\t\tsidebar: \"menu-button\",\n\t\t\tsize,\n\t\t\tactive: isActive,\n\t\t},\n\t});\n\n\tif (!tooltip) {\n\t\treturn comp;\n\t}\n\n\tif (typeof tooltip === \"string\") {\n\t\ttooltip = {\n\t\t\tchildren: tooltip,\n\t\t};\n\t}\n\n\treturn (\n\t\t<Tooltip>\n\t\t\t{comp}\n\t\t\t<TooltipContent\n\t\t\t\tside=\"right\"\n\t\t\t\talign=\"center\"\n\t\t\t\thidden={state !== \"collapsed\" || isMobile}\n\t\t\t\t{...tooltip}\n\t\t\t/>\n\t\t</Tooltip>\n\t);\n}\n\nfunction SidebarMenuAction({\n\tclassName,\n\trender,\n\tshowOnHover = false,\n\t...props\n}: useRender.ComponentProps<\"button\"> &\n\tReact.ComponentProps<\"button\"> & {\n\t\tshowOnHover?: boolean;\n\t}) {\n\treturn useRender({\n\t\tdefaultTagName: \"button\",\n\t\tprops: mergeProps<\"button\">(\n\t\t\t{\n\t\t\t\tclassName: cn(\n\t\t\t\t\t\"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 aspect-square w-5 p-0 peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 focus-visible:ring-2 [&>svg]:size-4 flex items-center justify-center outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 md:after:hidden [&>svg]:shrink-0\",\n\t\t\t\t\tshowOnHover &&\n\t\t\t\t\t\t\"peer-data-active/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-open:opacity-100 md:opacity-0\",\n\t\t\t\t\tclassName,\n\t\t\t\t),\n\t\t\t},\n\t\t\tprops,\n\t\t),\n\t\trender,\n\t\tstate: {\n\t\t\tslot: \"sidebar-menu-action\",\n\t\t\tsidebar: \"menu-action\",\n\t\t},\n\t});\n}\n\nfunction SidebarMenuBadge({\n\tclassName,\n\t...props\n}: React.ComponentProps<\"div\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-menu-badge\"\n\t\t\tdata-sidebar=\"menu-badge\"\n\t\t\tclassName={cn(\n\t\t\t\t\"text-sidebar-foreground peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 px-1 text-xs font-medium peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 flex items-center justify-center tabular-nums select-none group-data-[collapsible=icon]:hidden\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarMenuSkeleton({\n\tclassName,\n\tshowIcon = false,\n\t...props\n}: React.ComponentProps<\"div\"> & {\n\tshowIcon?: boolean;\n}) {\n\t// Random width between 50 to 90%.\n\tconst [width] = React.useState(() => {\n\t\treturn `${Math.floor(Math.random() * 40) + 50}%`;\n\t});\n\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"sidebar-menu-skeleton\"\n\t\t\tdata-sidebar=\"menu-skeleton\"\n\t\t\tclassName={cn(\"h-8 gap-2 px-2 flex items-center\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{showIcon && (\n\t\t\t\t<Skeleton className=\"size-4\" data-sidebar=\"menu-skeleton-icon\" />\n\t\t\t)}\n\t\t\t<Skeleton\n\t\t\t\tclassName=\"h-4 max-w-(--skeleton-width) flex-1\"\n\t\t\t\tdata-sidebar=\"menu-skeleton-text\"\n\t\t\t\tstyle={\n\t\t\t\t\t{\n\t\t\t\t\t\t\"--skeleton-width\": width,\n\t\t\t\t\t} as React.CSSProperties\n\t\t\t\t}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nfunction SidebarMenuSub({ className, ...props }: React.ComponentProps<\"ul\">) {\n\treturn (\n\t\t<ul\n\t\t\tdata-slot=\"sidebar-menu-sub\"\n\t\t\tdata-sidebar=\"menu-sub\"\n\t\t\tclassName={cn(\n\t\t\t\t\"border-sidebar-border mx-3.5 translate-x-px gap-1 border-l px-2.5 py-0.5 group-data-[collapsible=icon]:hidden flex min-w-0 flex-col\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarMenuSubItem({\n\tclassName,\n\t...props\n}: React.ComponentProps<\"li\">) {\n\treturn (\n\t\t<li\n\t\t\tdata-slot=\"sidebar-menu-sub-item\"\n\t\t\tdata-sidebar=\"menu-sub-item\"\n\t\t\tclassName={cn(\"group/menu-sub-item relative\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction SidebarMenuSubButton({\n\trender,\n\tsize = \"md\",\n\tisActive = false,\n\tclassName,\n\t...props\n}: useRender.ComponentProps<\"a\"> &\n\tReact.ComponentProps<\"a\"> & {\n\t\tsize?: \"sm\" | \"md\";\n\t\tisActive?: boolean;\n\t}) {\n\treturn useRender({\n\t\tdefaultTagName: \"a\",\n\t\tprops: mergeProps<\"a\">(\n\t\t\t{\n\t\t\t\tclassName: cn(\n\t\t\t\t\t\"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground h-7 gap-2 px-2 focus-visible:ring-2 data-[size=md]:text-xs data-[size=sm]:text-xs [&>svg]:size-4 flex min-w-0 -translate-x-px items-center overflow-hidden outline-hidden group-data-[collapsible=icon]:hidden disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:shrink-0\",\n\t\t\t\t\tclassName,\n\t\t\t\t),\n\t\t\t},\n\t\t\tprops,\n\t\t),\n\t\trender,\n\t\tstate: {\n\t\t\tslot: \"sidebar-menu-sub-button\",\n\t\t\tsidebar: \"menu-sub-button\",\n\t\t\tsize,\n\t\t\tactive: isActive,\n\t\t},\n\t});\n}\n\nexport {\n\tSidebar,\n\tSidebarContent,\n\tSidebarFooter,\n\tSidebarGroup,\n\tSidebarGroupAction,\n\tSidebarGroupContent,\n\tSidebarGroupLabel,\n\tSidebarHeader,\n\tSidebarInput,\n\tSidebarInset,\n\tSidebarMenu,\n\tSidebarMenuAction,\n\tSidebarMenuBadge,\n\tSidebarMenuButton,\n\tSidebarMenuItem,\n\tSidebarMenuSkeleton,\n\tSidebarMenuSub,\n\tSidebarMenuSubButton,\n\tSidebarMenuSubItem,\n\tSidebarProvider,\n\tSidebarRail,\n\tSidebarSeparator,\n\tSidebarTrigger,\n\tuseSidebar,\n};\n","\"use client\";\n\nimport type * as React from \"react\";\nimport { Toaster as Sonner, type ToasterProps } from \"sonner\";\nimport {\n\tInfo,\n\tWarning,\n\tXCircle,\n\tSpinner,\n\tCheckCircleIcon,\n} from \"@phosphor-icons/react\";\n\nexport interface AdminToasterProps extends ToasterProps {\n\t/**\n\t * Theme can be provided by parent app's theme context\n\t * Falls back to \"system\" if not provided\n\t */\n\ttheme?: \"light\" | \"dark\" | \"system\";\n}\n\nconst Toaster = ({ theme = \"system\", ...props }: AdminToasterProps) => {\n\treturn (\n\t\t<Sonner\n\t\t\ttheme={theme}\n\t\t\tclassName=\"toaster group\"\n\t\t\trichColors\n\t\t\ticons={{\n\t\t\t\tsuccess: <CheckCircleIcon className=\"size-4\" />,\n\t\t\t\tinfo: <Info className=\"size-4\" />,\n\t\t\t\twarning: <Warning className=\"size-4\" />,\n\t\t\t\terror: <XCircle className=\"size-4\" />,\n\t\t\t\tloading: <Spinner className=\"size-4 animate-spin\" />,\n\t\t\t}}\n\t\t\tstyle={\n\t\t\t\t{\n\t\t\t\t\t\"--normal-bg\": \"var(--popover)\",\n\t\t\t\t\t\"--normal-text\": \"var(--popover-foreground)\",\n\t\t\t\t\t\"--normal-border\": \"var(--border)\",\n\t\t\t\t\t\"--border-radius\": \"var(--radius)\",\n\t\t\t\t} as React.CSSProperties\n\t\t\t}\n\t\t\ttoastOptions={{\n\t\t\t\tclassNames: {\n\t\t\t\t\ttoast: \"cn-toast !backdrop-blur-sm !border\",\n\t\t\t\t\tdescription: \"!text-current/90\",\n\t\t\t\t\tsuccess: \"!bg-primary/10 !text-primary !border-primary/20 \",\n\t\t\t\t\terror: \"!bg-destructive/10 !text-destructive !border-destructive/20\",\n\t\t\t\t\twarning: \"!bg-yellow-600/10 !text-yellow-600 !border-yellow-600/20\",\n\t\t\t\t\tinfo: \"!bg-secondary/10 !text-secondary !border-secondary/20\",\n\t\t\t\t},\n\t\t\t}}\n\t\t\t{...props}\n\t\t/>\n\t);\n};\n\nexport { Toaster };\n","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\tlabel: I18nText;\n\thref: string;\n\ticon?: BreadcrumbIcon;\n}\n\n/**\n * Single breadcrumb item\n */\nexport interface Breadcrumb {\n\t/**\n\t * Display label (supports I18nText for localization)\n\t */\n\tlabel: I18nText;\n\n\t/**\n\t * Navigation href (optional - last item usually doesn't have one)\n\t */\n\thref?: string;\n\n\t/**\n\t * Icon component (optional)\n\t */\n\ticon?: BreadcrumbIcon;\n\n\t/**\n\t * Dropdown menu items for quick navigation\n\t * e.g., switch between collections or items\n\t */\n\tmenu?: {\n\t\titems: BreadcrumbMenuItem[];\n\t};\n}\n\n/**\n * Breadcrumb context value\n */\ninterface BreadcrumbContextValue {\n\tbreadcrumbs: Breadcrumb[];\n\tsetBreadcrumbs: (breadcrumbs: Breadcrumb[]) => void;\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst BreadcrumbContext = React.createContext<BreadcrumbContextValue | null>(\n\tnull,\n);\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport interface BreadcrumbProviderProps {\n\tchildren: React.ReactNode;\n}\n\nexport function BreadcrumbProvider({\n\tchildren,\n}: BreadcrumbProviderProps): React.ReactElement {\n\tconst [breadcrumbs, setBreadcrumbs] = React.useState<Breadcrumb[]>([]);\n\n\tconst value = React.useMemo(\n\t\t() => ({\n\t\t\tbreadcrumbs,\n\t\t\tsetBreadcrumbs,\n\t\t}),\n\t\t[breadcrumbs],\n\t);\n\n\treturn (\n\t\t<BreadcrumbContext.Provider value={value}>\n\t\t\t{children}\n\t\t</BreadcrumbContext.Provider>\n\t);\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Get breadcrumb context\n * @throws if used outside BreadcrumbProvider\n */\nexport function useBreadcrumbContext(): BreadcrumbContextValue {\n\tconst context = React.useContext(BreadcrumbContext);\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"useBreadcrumbContext must be used within a BreadcrumbProvider\",\n\t\t);\n\t}\n\treturn context;\n}\n\n/**\n * Get breadcrumb context (optional - returns null if not in provider)\n */\nexport function useBreadcrumbContextOptional(): BreadcrumbContextValue | null {\n\treturn 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\tconst context = useBreadcrumbContextOptional();\n\n\tReact.useEffect(() => {\n\t\tif (!context) return;\n\n\t\tcontext.setBreadcrumbs(breadcrumbs);\n\n\t\treturn () => {\n\t\t\tcontext.setBreadcrumbs([]);\n\t\t};\n\t}, [context, breadcrumbs]);\n}\n\n/**\n * Get current breadcrumbs (read-only)\n */\nexport function useCurrentBreadcrumbs(): Breadcrumb[] {\n\tconst context = useBreadcrumbContextOptional();\n\treturn context?.breadcrumbs ?? [];\n}\n","/**\n * Global Search\n *\n * Fast navigation to collections, globals, quick actions, AND actual records.\n * Uses ResponsiveDialog for desktop (Dialog) and mobile (fullscreen Drawer).\n *\n * Features:\n * - Navigation items: Collections, globals, create actions (client-side filter)\n * - Record search: Full-text search across ALL collections (server-side)\n * - Keyboard navigation: ↑↓ arrows, Enter to select, Esc to close\n * - Highlights: Shows search term highlighted in record titles\n */\n\nimport {\n\tFile,\n\tFolder,\n\tGear,\n\tMagnifyingGlass,\n\tPlus,\n\tSpinner,\n} from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useMemo, useState, useCallback, useRef, useEffect } from \"react\";\nimport { Kbd } from \"../../components/ui/kbd\";\nimport {\n\tResponsiveDialog,\n\tResponsiveDialogContent,\n} from \"../../components/ui/responsive-dialog\";\nimport { useDebouncedValue, useGlobalSearch } from \"../../hooks/use-search\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport { selectAdmin, selectBasePath, useAdminStore } from \"../../runtime\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface SearchItem {\n\tid: string;\n\ttype: \"collection\" | \"global\" | \"action\" | \"record\";\n\tlabel: string;\n\tsublabel?: string;\n\thref: string;\n\ticon?: React.ComponentType<{ className?: string }>;\n\tkeywords?: string[];\n\thighlights?: { title?: string };\n}\n\nexport interface GlobalSearchProps {\n\tisOpen: boolean;\n\tonClose: () => void;\n\tnavigate: (path: string) => void;\n\tbasePath?: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Simple fuzzy search - matches if query words appear anywhere in text\n */\nfunction fuzzyMatch(text: string, query: string): boolean {\n\tconst textLower = text.toLowerCase();\n\tconst queryWords = query.toLowerCase().split(/\\s+/).filter(Boolean);\n\n\treturn queryWords.every((word) => textLower.includes(word));\n}\n\n/**\n * Search and filter items based on query\n */\nfunction filterItems(items: SearchItem[], query: string): SearchItem[] {\n\tif (!query.trim()) return items;\n\n\treturn items.filter((item) => {\n\t\t// Match against label\n\t\tif (fuzzyMatch(item.label, query)) return true;\n\n\t\t// Match against keywords\n\t\tif (item.keywords?.some((kw) => fuzzyMatch(kw, query))) return true;\n\n\t\treturn false;\n\t});\n}\n\n// ============================================================================\n// Search Group Component\n// ============================================================================\n\ninterface SearchGroupProps {\n\ttitle: string;\n\titems: SearchItem[];\n\tselectedIndex: number;\n\tstartIndex: number;\n\tonSelect: (item: SearchItem) => void;\n\tonHover: (index: number) => void;\n}\n\nfunction SearchGroup({\n\ttitle,\n\titems,\n\tselectedIndex,\n\tstartIndex,\n\tonSelect,\n\tonHover,\n}: SearchGroupProps) {\n\tconst resolveText = useResolveText();\n\n\tif (items.length === 0) return null;\n\n\treturn (\n\t\t<div className=\"mb-4 last:mb-0\">\n\t\t\t<h3 className=\"mb-2 px-2 font-mono text-[10px] font-black uppercase tracking-[0.2em] text-muted-foreground\">\n\t\t\t\t{resolveText(title)}\n\t\t\t</h3>\n\t\t\t<div className=\"space-y-0.5\">\n\t\t\t\t{items.map((item, idx) => {\n\t\t\t\t\tconst globalIndex = startIndex + idx;\n\t\t\t\t\tconst isSelected = globalIndex === selectedIndex;\n\t\t\t\t\tconst Icon = item.icon;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={() => onSelect(item)}\n\t\t\t\t\t\t\tonMouseEnter={() => onHover(globalIndex)}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"flex w-full items-center gap-3 px-3 py-2.5 text-sm outline-none transition-colors rounded-md\",\n\t\t\t\t\t\t\t\tisSelected\n\t\t\t\t\t\t\t\t\t? \"bg-accent text-accent-foreground\"\n\t\t\t\t\t\t\t\t\t: \"hover:bg-accent/50 hover:text-accent-foreground\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{Icon && (\n\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4 text-muted-foreground shrink-0\" />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<div className=\"flex flex-col items-start min-w-0\">\n\t\t\t\t\t\t\t\t{item.highlights?.title ? (\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclassName=\"truncate\"\n\t\t\t\t\t\t\t\t\t\t// biome-ignore lint/security/noDangerouslySetInnerHtml: highlights from server\n\t\t\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{ __html: item.highlights.title }}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<span className=\"truncate\">{resolveText(item.label)}</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{item.sublabel && (\n\t\t\t\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground truncate\">\n\t\t\t\t\t\t\t\t\t\t{item.sublabel}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport function GlobalSearch({\n\tisOpen,\n\tonClose,\n\tnavigate,\n\tbasePath: basePathProp,\n}: GlobalSearchProps) {\n\tconst { t } = useTranslation();\n\tconst resolveText = useResolveText();\n\n\t// Get admin state\n\tconst admin = useAdminStore(selectAdmin);\n\tconst storeBasePath = useAdminStore(selectBasePath);\n\tconst basePath = basePathProp ?? storeBasePath ?? \"/admin\";\n\n\t// Search state\n\tconst [query, setQuery] = useState(\"\");\n\tconst [selectedIndex, setSelectedIndex] = useState(0);\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\n\t// Debounce query for record search (300ms)\n\tconst debouncedQuery = useDebouncedValue(query, 300);\n\n\t// Fetch records from search API\n\tconst { data: searchResults, isLoading: isSearching } = useGlobalSearch({\n\t\tquery: debouncedQuery,\n\t\tlimit: 10,\n\t\tenabled: debouncedQuery.trim().length >= 2,\n\t});\n\n\t// Build navigation items from admin config\n\tconst navItems = useMemo(() => {\n\t\tconst items: SearchItem[] = [];\n\t\tconst collections = admin?.getCollections() ?? {};\n\t\tconst globals = admin?.getGlobals() ?? {};\n\n\t\t// Add collections\n\t\tfor (const [name, config] of Object.entries(collections)) {\n\t\t\tconst label = resolveText((config as any).label, name);\n\t\t\t// Get icon from collection config (getCollections already extracts .state)\n\t\t\tconst icon = (config as any)?.icon || Folder;\n\t\t\titems.push({\n\t\t\t\tid: `col-${name}`,\n\t\t\t\ttype: \"collection\",\n\t\t\t\tlabel,\n\t\t\t\thref: `${basePath}/collections/${name}`,\n\t\t\t\ticon,\n\t\t\t\tkeywords: [name, \"collection\", \"list\"],\n\t\t\t});\n\t\t}\n\n\t\t// Add globals\n\t\tfor (const [name, config] of Object.entries(globals)) {\n\t\t\tconst label = resolveText((config as any).label, name);\n\t\t\t// Get icon from global config (getGlobals already extracts .state)\n\t\t\tconst icon = (config as any)?.icon || Gear;\n\t\t\titems.push({\n\t\t\t\tid: `glob-${name}`,\n\t\t\t\ttype: \"global\",\n\t\t\t\tlabel,\n\t\t\t\thref: `${basePath}/globals/${name}`,\n\t\t\t\ticon,\n\t\t\t\tkeywords: [name, \"global\", \"settings\", \"config\"],\n\t\t\t});\n\t\t}\n\n\t\t// Add quick actions (create new)\n\t\tfor (const [name, config] of Object.entries(collections)) {\n\t\t\tconst label = resolveText((config as any).label, name);\n\t\t\t// Get icon from collection config for the action too\n\t\t\tconst collectionIcon = (config as any)?.icon;\n\t\t\titems.push({\n\t\t\t\tid: `action-create-${name}`,\n\t\t\t\ttype: \"action\",\n\t\t\t\tlabel: t(\"globalSearch.createNew\", { name: label }),\n\t\t\t\thref: `${basePath}/collections/${name}/create`,\n\t\t\t\ticon: collectionIcon || Plus,\n\t\t\t\tkeywords: [\"create\", \"new\", \"add\", name],\n\t\t\t});\n\t\t}\n\n\t\treturn items;\n\t}, [admin, basePath, resolveText, t]);\n\n\t// Filter navigation items based on query (client-side)\n\tconst filteredNavItems = useMemo(\n\t\t() => filterItems(navItems, query),\n\t\t[navItems, query],\n\t);\n\n\t// Convert search results to SearchItem format\n\tconst recordItems = useMemo(() => {\n\t\tif (!searchResults?.docs) return [];\n\n\t\tconst collections = admin?.getCollections() ?? {};\n\n\t\treturn searchResults.docs.map((doc): SearchItem => {\n\t\t\tconst collectionName = doc._collection;\n\t\t\tconst collectionConfig = collections[collectionName];\n\t\t\t// Use resolveText for proper localization of collection label\n\t\t\tconst collectionLabel = resolveText((collectionConfig as any)?.label, collectionName);\n\t\t\t// Get icon from collection config (getCollections already extracts .state)\n\t\t\tconst icon = (collectionConfig as any)?.icon || File;\n\n\t\t\treturn {\n\t\t\t\tid: `record-${collectionName}-${doc.id}`,\n\t\t\t\ttype: \"record\",\n\t\t\t\tlabel: doc._search?.indexedTitle || doc.id,\n\t\t\t\tsublabel: collectionLabel,\n\t\t\t\thref: `${basePath}/collections/${collectionName}/${doc.id}`,\n\t\t\t\ticon,\n\t\t\t\thighlights: doc._search?.highlights,\n\t\t\t};\n\t\t});\n\t}, [searchResults, admin, basePath, resolveText]);\n\n\t// Group navigation items by type\n\tconst groupedNavItems = useMemo(() => {\n\t\treturn {\n\t\t\tcollections: filteredNavItems.filter((i) => i.type === \"collection\"),\n\t\t\tglobals: filteredNavItems.filter((i) => i.type === \"global\"),\n\t\t\tactions: filteredNavItems.filter((i) => i.type === \"action\"),\n\t\t};\n\t}, [filteredNavItems]);\n\n\t// Calculate total count and indices\n\tconst allItems = useMemo(() => {\n\t\treturn [\n\t\t\t...groupedNavItems.collections,\n\t\t\t...groupedNavItems.globals,\n\t\t\t...groupedNavItems.actions,\n\t\t\t...recordItems,\n\t\t];\n\t}, [groupedNavItems, recordItems]);\n\n\tconst totalCount = allItems.length;\n\tconst collectionsStartIndex = 0;\n\tconst globalsStartIndex = groupedNavItems.collections.length;\n\tconst actionsStartIndex =\n\t\tgroupedNavItems.collections.length + groupedNavItems.globals.length;\n\tconst recordsStartIndex =\n\t\tgroupedNavItems.collections.length +\n\t\tgroupedNavItems.globals.length +\n\t\tgroupedNavItems.actions.length;\n\n\t// Reset selected index when query changes\n\tuseEffect(() => {\n\t\tsetSelectedIndex(0);\n\t}, [query]);\n\n\t// Reset state when dialog opens\n\tuseEffect(() => {\n\t\tif (isOpen) {\n\t\t\tsetQuery(\"\");\n\t\t\tsetSelectedIndex(0);\n\t\t\t// Focus input after a small delay to ensure dialog is rendered\n\t\t\tsetTimeout(() => inputRef.current?.focus(), 50);\n\t\t}\n\t}, [isOpen]);\n\n\t// Handle selection\n\tconst handleSelect = useCallback(\n\t\t(item: SearchItem) => {\n\t\t\tnavigate(item.href);\n\t\t\tonClose();\n\t\t},\n\t\t[navigate, onClose],\n\t);\n\n\t// Handle keyboard navigation\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent) => {\n\t\t\tswitch (e.key) {\n\t\t\t\tcase \"ArrowDown\":\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tsetSelectedIndex((i) => Math.min(i + 1, totalCount - 1));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"ArrowUp\":\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tsetSelectedIndex((i) => Math.max(i - 1, 0));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Enter\":\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tif (allItems[selectedIndex]) {\n\t\t\t\t\t\thandleSelect(allItems[selectedIndex]);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Escape\":\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tonClose();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t\t[allItems, selectedIndex, totalCount, handleSelect, onClose],\n\t);\n\n\tconst handleHover = useCallback((index: number) => {\n\t\tsetSelectedIndex(index);\n\t}, []);\n\n\tconst hasNavResults =\n\t\tgroupedNavItems.collections.length > 0 ||\n\t\tgroupedNavItems.globals.length > 0 ||\n\t\tgroupedNavItems.actions.length > 0;\n\n\tconst hasRecordResults = recordItems.length > 0;\n\tconst hasResults = hasNavResults || hasRecordResults;\n\n\treturn (\n\t\t<ResponsiveDialog open={isOpen} onOpenChange={(open) => !open && onClose()}>\n\t\t\t<ResponsiveDialogContent className=\"p-0 gap-0 max-w-2xl\">\n\t\t\t\t{/* Search Input */}\n\t\t\t\t<div className=\"flex items-center border-b px-3\">\n\t\t\t\t\t<MagnifyingGlass className=\"mr-2 h-5 w-5 text-muted-foreground shrink-0\" />\n\t\t\t\t\t<input\n\t\t\t\t\t\tref={inputRef}\n\t\t\t\t\t\tclassName=\"flex h-14 w-full rounded-none bg-transparent py-3 text-base outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\"\n\t\t\t\t\t\tplaceholder={t(\"globalSearch.placeholder\")}\n\t\t\t\t\t\tvalue={query}\n\t\t\t\t\t\tonChange={(e) => setQuery(e.target.value)}\n\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\tautoFocus\n\t\t\t\t\t/>\n\t\t\t\t\t<div className=\"flex items-center gap-1 shrink-0\">\n\t\t\t\t\t\t{isSearching && <Spinner className=\"h-4 w-4 animate-spin text-muted-foreground\" />}\n\t\t\t\t\t\t<Kbd>ESC</Kbd>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Results */}\n\t\t\t\t<div className=\"max-h-[60vh] overflow-y-auto p-2\">\n\t\t\t\t\t{hasResults ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{/* Navigation Groups */}\n\t\t\t\t\t\t\t<SearchGroup\n\t\t\t\t\t\t\t\ttitle={t(\"globalSearch.collections\")}\n\t\t\t\t\t\t\t\titems={groupedNavItems.collections}\n\t\t\t\t\t\t\t\tselectedIndex={selectedIndex}\n\t\t\t\t\t\t\t\tstartIndex={collectionsStartIndex}\n\t\t\t\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\t\t\t\tonHover={handleHover}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<SearchGroup\n\t\t\t\t\t\t\t\ttitle={t(\"globalSearch.globals\")}\n\t\t\t\t\t\t\t\titems={groupedNavItems.globals}\n\t\t\t\t\t\t\t\tselectedIndex={selectedIndex}\n\t\t\t\t\t\t\t\tstartIndex={globalsStartIndex}\n\t\t\t\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\t\t\t\tonHover={handleHover}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<SearchGroup\n\t\t\t\t\t\t\t\ttitle={t(\"globalSearch.quickActions\")}\n\t\t\t\t\t\t\t\titems={groupedNavItems.actions}\n\t\t\t\t\t\t\t\tselectedIndex={selectedIndex}\n\t\t\t\t\t\t\t\tstartIndex={actionsStartIndex}\n\t\t\t\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\t\t\t\tonHover={handleHover}\n\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t{/* Record Results */}\n\t\t\t\t\t\t\t{hasRecordResults && (\n\t\t\t\t\t\t\t\t<SearchGroup\n\t\t\t\t\t\t\t\t\ttitle={t(\"globalSearch.records\")}\n\t\t\t\t\t\t\t\t\titems={recordItems}\n\t\t\t\t\t\t\t\t\tselectedIndex={selectedIndex}\n\t\t\t\t\t\t\t\t\tstartIndex={recordsStartIndex}\n\t\t\t\t\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\t\t\t\t\tonHover={handleHover}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"py-8 text-center text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t{isSearching ? (\n\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-center gap-2\">\n\t\t\t\t\t\t\t\t\t<Spinner className=\"h-4 w-4 animate-spin\" />\n\t\t\t\t\t\t\t\t\t<span>{t(\"globalSearch.searching\")}</span>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\tt(\"globalSearch.noResults\")\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Footer with keyboard hints */}\n\t\t\t\t<div className=\"border-t px-3 py-2 flex items-center justify-end gap-4 text-xs text-muted-foreground\">\n\t\t\t\t\t<span className=\"flex items-center gap-1\">\n\t\t\t\t\t\t<Kbd className=\"text-[10px] px-1\">↑</Kbd>\n\t\t\t\t\t\t<Kbd className=\"text-[10px] px-1\">↓</Kbd>\n\t\t\t\t\t\t<span>{t(\"globalSearch.navigate\")}</span>\n\t\t\t\t\t</span>\n\t\t\t\t\t<span className=\"flex items-center gap-1\">\n\t\t\t\t\t\t<Kbd className=\"text-[10px] px-1.5\">↵</Kbd>\n\t\t\t\t\t\t<span>{t(\"globalSearch.select\")}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</ResponsiveDialogContent>\n\t\t</ResponsiveDialog>\n\t);\n}\n","/**\n * AdminSidebar Component\n *\n * Navigation sidebar for the admin UI using shadcn sidebar primitives.\n * Automatically reads from AdminProvider context when props are not provided.\n */\n\nimport {\n\tCaretDownIcon,\n\tCaretUpDown,\n\tCheck,\n\tGlobe,\n\tSignOut,\n\tUser,\n\tUserCircle,\n} from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport type { IconComponent } from \"../../builder/types/common\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuPortal,\n\tDropdownMenuSeparator,\n\tDropdownMenuSub,\n\tDropdownMenuSubContent,\n\tDropdownMenuSubTrigger,\n\tDropdownMenuTrigger,\n} from \"../../components/ui/dropdown-menu\";\nimport {\n\tSidebar,\n\tSidebarContent,\n\tSidebarFooter,\n\tSidebarGroup,\n\tSidebarGroupContent,\n\tSidebarGroupLabel,\n\tSidebarHeader,\n\tSidebarMenu,\n\tSidebarMenuItem,\n\tSidebarSeparator,\n\tuseSidebar,\n} from \"../../components/ui/sidebar\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport {\n\tTooltip,\n\tTooltipContent,\n\tTooltipTrigger,\n} from \"../../components/ui/tooltip\";\nimport { useAuthClientSafe } from \"../../hooks/use-auth\";\nimport { useSessionState } from \"../../hooks/use-current-user\";\nimport { useResolveText, useTranslation } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\nimport {\n\tselectAdmin,\n\tselectBasePath,\n\tselectNavigate,\n\tuseAdminStore,\n} from \"../../runtime/provider\";\nimport type {\n\tNavigationElement,\n\tNavigationGroup,\n\tNavigationItem,\n} from \"../../runtime/routes\";\nimport { getFlagUrl } from \"../../utils/locale-to-flag\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Link component props (router-agnostic)\n */\nexport interface LinkComponentProps {\n\tto: string;\n\tclassName?: string;\n\tchildren: React.ReactNode;\n\tactiveProps?: { className?: string };\n\tactiveOptions?: { exact?: boolean };\n}\n\n/**\n * AdminSidebar props\n */\nexport interface AdminSidebarProps {\n\t/**\n\t * Navigation groups to render.\n\t * If not provided, reads from AdminProvider context.\n\t */\n\tnavigation?: NavigationGroup[];\n\n\t/**\n\t * Link component (router-specific)\n\t */\n\tLinkComponent: React.ComponentType<LinkComponentProps>;\n\n\t/**\n\t * Current active route\n\t */\n\tactiveRoute?: string;\n\n\t/**\n\t * Base path for admin routes\n\t */\n\tbasePath?: string;\n\n\t/**\n\t * Brand name.\n\t * If not provided, reads from AdminProvider context.\n\t */\n\tbrandName?: string;\n\n\t/**\n\t * Custom class for sidebar container\n\t */\n\tclassName?: string;\n\n\t/**\n\t * Render custom brand content\n\t */\n\trenderBrand?: (props: {\n\t\tname: string;\n\t\tcollapsed: boolean;\n\t}) => React.ReactNode;\n\n\t/**\n\t * Render custom nav item\n\t */\n\trenderNavItem?: (params: {\n\t\titem: NavigationItem;\n\t\tisActive: boolean;\n\t\tcollapsed: boolean;\n\t}) => React.ReactNode;\n\n\t/**\n\t * Custom footer content\n\t */\n\tfooter?: React.ReactNode;\n\n\t/**\n\t * Use framework-specific active link props (e.g., TanStack Router's activeProps)\n\t * @default true\n\t */\n\tuseActiveProps?: boolean;\n}\n\n// ============================================================================\n// Internal Hook - Resolve props from store\n// ============================================================================\n\nfunction useSidebarProps(props: {\n\tnavigation?: NavigationGroup[];\n\tbrandName?: string;\n}): { navigation: NavigationGroup[]; brandName: string } {\n\t// Select individual values to avoid object identity issues\n\tconst storeNavigation = useAdminStore((s) => s.navigation);\n\tconst storeBrandName = useAdminStore((s) => s.brandName);\n\n\t// If props provided, use them (props take priority)\n\tif (props.navigation !== undefined && props.brandName !== undefined) {\n\t\treturn {\n\t\t\tnavigation: props.navigation,\n\t\t\tbrandName: props.brandName,\n\t\t};\n\t}\n\n\treturn {\n\t\tnavigation: props.navigation ?? storeNavigation ?? [],\n\t\tbrandName: props.brandName ?? storeBrandName ?? \"Admin\",\n\t};\n}\n\n// ============================================================================\n// Sub-components\n// ============================================================================\n\n/**\n * Render an IconComponent (handles lazy loading)\n */\nfunction RenderIcon(props: { icon: IconComponent; className?: string }) {\n\t// // Handle different icon types\n\t// if (typeof icon === \"function\") {\n\t// \t// Check if it's a lazy component or regular component\n\t// \tconst IconComp = icon as React.ComponentType<{ className?: string }>;\n\t// \treturn (\n\t// \t\t<Suspense fallback={<span className={cn(\"size-4\", className)} />}>\n\t// \t\t\t<IconComp className={cn(\"size-4 shrink-0\", className)} />\n\t// \t\t</Suspense>\n\t// \t);\n\t// }\n\treturn <props.icon className={cn(\"size-4 shrink-0\", props.className)} />;\n}\n\nfunction QuestpieSymbol({ className }: { className?: string }) {\n\treturn (\n\t\t<svg\n\t\t\twidth=\"640\"\n\t\t\theight=\"640\"\n\t\t\tviewBox=\"0 0 640 640\"\n\t\t\tfill=\"none\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\tclassName={cn(\n\t\t\t\t\"size-8 shrink-0 text-[#02012B] dark:text-white\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t<title>QUESTPIE</title>\n\t\t\t<path\n\t\t\t\tfillRule=\"evenodd\"\n\t\t\t\tclipRule=\"evenodd\"\n\t\t\t\td=\"M466.377 350.987C468.486 340.983 469.595 330.611 469.595 319.98C469.595 237.377 402.624 170.406 320.001 170.406C237.378 170.406 170.406 237.377 170.406 319.98C170.406 393.857 223.976 455.23 294.402 467.372V510.268C200.465 497.754 128 417.329 128 319.98C128 213.952 213.962 128 320.001 128C426.04 128 512.002 213.952 512.002 319.98C512.002 344.198 507.517 367.37 499.332 388.708C489.817 374.897 478.748 362.239 466.377 350.987ZM320.002 469.553C381.932 469.553 435.067 431.927 457.799 378.296C468.772 389.602 478.366 402.254 486.309 415.98C453.11 473.357 391.065 511.959 320.002 511.959L320.002 469.553Z\"\n\t\t\t\tfill=\"currentColor\"\n\t\t\t/>\n\t\t\t<path\n\t\t\t\tfillRule=\"evenodd\"\n\t\t\t\tclipRule=\"evenodd\"\n\t\t\t\td=\"M320.002 512H512.004V511.985C512.004 405.958 426.042 320.005 320.003 320.005C320.003 320.005 320.002 320.005 320.002 320.005V512Z\"\n\t\t\t\tfill=\"#B700FF\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n\n/**\n * Check if element is a navigation item (not divider)\n */\nfunction isNavigationItem(\n\telement: NavigationElement,\n): element is NavigationItem {\n\treturn element.type !== \"divider\";\n}\n\nfunction normalizeRoute(route?: string) {\n\treturn route?.replace(/\\/+$/, \"\");\n}\n\nfunction isRouteActive(\n\tactiveRoute: string | undefined,\n\titemHref: string,\n\tbasePath: string,\n) {\n\tif (!activeRoute) {\n\t\treturn false;\n\t}\n\n\tconst normalizedActive = normalizeRoute(activeRoute);\n\tconst normalizedItem = normalizeRoute(itemHref);\n\tconst normalizedBase = normalizeRoute(basePath);\n\n\tif (!normalizedActive || !normalizedItem) {\n\t\treturn false;\n\t}\n\n\tif (normalizedActive === normalizedItem) {\n\t\treturn true;\n\t}\n\n\tif (normalizedItem === normalizedBase) {\n\t\treturn false;\n\t}\n\n\treturn normalizedActive.startsWith(`${normalizedItem}/`);\n}\n\n/**\n * Menu button styles - QUESTPIE design: clean, technical look\n */\nconst menuButtonStyles = cn(\n\t\"flex w-full items-center gap-2.5 px-3 py-2 text-sm font-medium transition-colors duration-150\",\n\t\"text-sidebar-foreground hover:text-sidebar-foreground hover:bg-sidebar-accent\",\n\t\"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sidebar-ring\",\n\t\"group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:px-2 group-data-[collapsible=icon]:size-8\",\n);\n\nconst menuButtonActiveStyles = cn(\n\t\"bg-sidebar-primary/10 text-sidebar-primary border-l-2 border-sidebar-primary\",\n);\n\nfunction NavItem({\n\titem,\n\tisActive,\n\tLinkComponent,\n\trenderNavItem,\n\tuseActiveProps,\n\tclassName,\n}: {\n\titem: NavigationItem;\n\tisActive: boolean;\n\tLinkComponent: React.ComponentType<LinkComponentProps>;\n\trenderNavItem?: AdminSidebarProps[\"renderNavItem\"];\n\tuseActiveProps: boolean;\n\tclassName?: string;\n}) {\n\tconst { state, isMobile, setOpenMobile } = useSidebar();\n\tconst collapsed = state === \"collapsed\";\n\tconst resolveText = useResolveText();\n\n\t// Close sidebar on mobile when navigating\n\tconst handleClick = React.useCallback(() => {\n\t\tif (isMobile) {\n\t\t\tsetOpenMobile(false);\n\t\t}\n\t}, [isMobile, setOpenMobile]);\n\n\tif (renderNavItem) {\n\t\treturn <>{renderNavItem({ item, isActive, collapsed })}</>;\n\t}\n\n\tconst label = resolveText(item.label);\n\n\tconst linkActiveProps = useActiveProps\n\t\t? {\n\t\t\t\tactiveProps: { className: menuButtonActiveStyles },\n\t\t\t\tactiveOptions: { exact: true },\n\t\t\t}\n\t\t: {};\n\n\tconst linkContent = (\n\t\t<LinkComponent\n\t\t\tto={item.href}\n\t\t\tclassName={cn(menuButtonStyles, isActive && menuButtonActiveStyles)}\n\t\t\t{...linkActiveProps}\n\t\t>\n\t\t\t{item.icon && <RenderIcon icon={item.icon} />}\n\t\t\t<span className=\"truncate group-data-[collapsible=icon]:hidden\">\n\t\t\t\t{label}\n\t\t\t</span>\n\t\t</LinkComponent>\n\t);\n\n\t// Show tooltip when collapsed (desktop only)\n\tif (collapsed && !isMobile) {\n\t\treturn (\n\t\t\t<SidebarMenuItem onClickCapture={handleClick}>\n\t\t\t\t<Tooltip>\n\t\t\t\t\t<TooltipTrigger\n\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t<LinkComponent\n\t\t\t\t\t\t\t\tto={item.href}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\tmenuButtonStyles,\n\t\t\t\t\t\t\t\t\tisActive && menuButtonActiveStyles,\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{...linkActiveProps}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{item.icon && <RenderIcon icon={item.icon} />}\n\t\t\t\t\t\t\t\t<span className=\"truncate group-data-[collapsible=icon]:hidden\">\n\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</LinkComponent>\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t\t<TooltipContent side=\"right\" align=\"center\">\n\t\t\t\t\t\t{label}\n\t\t\t\t\t</TooltipContent>\n\t\t\t\t</Tooltip>\n\t\t\t</SidebarMenuItem>\n\t\t);\n\t}\n\n\treturn (\n\t\t<SidebarMenuItem className={className} onClickCapture={handleClick}>\n\t\t\t{linkContent}\n\t\t</SidebarMenuItem>\n\t);\n}\n\nfunction NavGroup({\n\tgroup,\n\tactiveRoute,\n\tLinkComponent,\n\trenderNavItem,\n\tbasePath,\n\tuseActiveProps,\n}: {\n\tgroup: NavigationGroup;\n\tactiveRoute?: string;\n\tLinkComponent: React.ComponentType<LinkComponentProps>;\n\trenderNavItem?: AdminSidebarProps[\"renderNavItem\"];\n\tbasePath: string;\n\tuseActiveProps: boolean;\n}) {\n\t// Track collapsed state for sections that support it\n\tconst [isCollapsed, setIsCollapsed] = React.useState(\n\t\tgroup.collapsed ?? false,\n\t);\n\tconst resolveText = useResolveText();\n\tconst groupLabel = resolveText(group.label);\n\n\treturn (\n\t\t<SidebarGroup>\n\t\t\t{/* Section header with optional icon and collapse toggle */}\n\t\t\t{groupLabel && (\n\t\t\t\t<SidebarGroupLabel\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"gap-2 px-3 mt-2\",\n\t\t\t\t\t\tgroup.collapsed !== undefined &&\n\t\t\t\t\t\t\t\"cursor-pointer hover:text-sidebar-foreground\",\n\t\t\t\t\t)}\n\t\t\t\t\tonClick={\n\t\t\t\t\t\tgroup.collapsed !== undefined\n\t\t\t\t\t\t\t? () => setIsCollapsed(!isCollapsed)\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t{group.icon && <RenderIcon icon={group.icon} className=\"size-3.5\" />}\n\t\t\t\t\t<span className=\"flex-1 font-mono text-left\">{groupLabel}</span>\n\t\t\t\t\t{group.collapsed !== undefined && (\n\t\t\t\t\t\t<CaretDownIcon\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"size-3.5 transition-transform\",\n\t\t\t\t\t\t\t\tisCollapsed && \"-rotate-90\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</SidebarGroupLabel>\n\t\t\t)}\n\n\t\t\t{/* Section items (hidden when collapsed) */}\n\t\t\t{!isCollapsed && (\n\t\t\t\t<SidebarGroupContent>\n\t\t\t\t\t<SidebarMenu>\n\t\t\t\t\t\t{group.items.map((element, elementIndex) => {\n\t\t\t\t\t\t\t// Handle dividers\n\t\t\t\t\t\t\tif (!isNavigationItem(element)) {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<SidebarSeparator\n\t\t\t\t\t\t\t\t\t\tkey={`${group.id ?? groupLabel ?? \"group\"}-divider-${elementIndex}`}\n\t\t\t\t\t\t\t\t\t\tclassName=\"my-2\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Handle navigation items\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<NavItem\n\t\t\t\t\t\t\t\t\tkey={element.id}\n\t\t\t\t\t\t\t\t\titem={element}\n\t\t\t\t\t\t\t\t\tisActive={isRouteActive(activeRoute, element.href, basePath)}\n\t\t\t\t\t\t\t\t\tLinkComponent={LinkComponent}\n\t\t\t\t\t\t\t\t\trenderNavItem={renderNavItem}\n\t\t\t\t\t\t\t\t\tuseActiveProps={useActiveProps}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</SidebarMenu>\n\t\t\t\t</SidebarGroupContent>\n\t\t\t)}\n\t\t</SidebarGroup>\n\t);\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * Loading skeleton for UserFooter\n */\nfunction UserFooterSkeleton({ collapsed }: { collapsed: boolean }) {\n\treturn (\n\t\t<SidebarFooter className=\"border-t border-sidebar-border/50 p-2\">\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex items-center gap-2.5 p-2\",\n\t\t\t\t\tcollapsed && \"justify-center\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<Skeleton className=\"size-8 shrink-0\" />\n\t\t\t\t{!collapsed && (\n\t\t\t\t\t<div className=\"grid flex-1 gap-1\">\n\t\t\t\t\t\t<Skeleton className=\"h-3 w-24\" />\n\t\t\t\t\t\t<Skeleton className=\"h-2 w-32\" />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</SidebarFooter>\n\t);\n}\n\nfunction UserFooter() {\n\tconst { state, isMobile, setOpenMobile } = useSidebar();\n\tconst collapsed = state === \"collapsed\";\n\n\t// Get auth client and session state\n\tconst authClient = useAuthClientSafe();\n\tconst { user, isPending } = useSessionState();\n\tconst navigate = useAdminStore(selectNavigate);\n\tconst basePath = useAdminStore(selectBasePath);\n\tconst admin = useAdminStore(selectAdmin);\n\tconst {\n\t\tt,\n\t\tlocale: uiLocale,\n\t\tsetLocale: setUiLocale,\n\t\tgetLocaleName,\n\t} = useTranslation();\n\n\t// Get available locales from admin config\n\tconst localeConfig = admin.getLocale();\n\tconst uiLocales = localeConfig.supported ?? [\"en\"];\n\tconst hasMultipleUiLocales = uiLocales.length > 1;\n\tconst uiLocaleOptions = uiLocales.map((code) => ({\n\t\tcode,\n\t\tlabel: getLocaleName(code),\n\t}));\n\n\t// Close sidebar on mobile when navigating\n\tconst closeSidebarOnMobile = React.useCallback(() => {\n\t\tif (isMobile) {\n\t\t\tsetOpenMobile(false);\n\t\t}\n\t}, [isMobile, setOpenMobile]);\n\n\t// Handle logout\n\tconst handleLogout = React.useCallback(async () => {\n\t\tif (!authClient) return;\n\t\ttry {\n\t\t\tawait authClient.signOut();\n\t\t\tcloseSidebarOnMobile();\n\t\t\tnavigate(`${basePath}/login`);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Logout failed:\", error);\n\t\t}\n\t}, [authClient, navigate, basePath, closeSidebarOnMobile]);\n\n\t// Handle navigate to user profile\n\tconst handleMyAccount = React.useCallback(() => {\n\t\tif (user?.id) {\n\t\t\tcloseSidebarOnMobile();\n\t\t\tnavigate(`${basePath}/collections/user/${user.id}`);\n\t\t}\n\t}, [navigate, basePath, user?.id, closeSidebarOnMobile]);\n\n\t// Show skeleton while loading\n\tif (isPending) {\n\t\treturn <UserFooterSkeleton collapsed={collapsed} />;\n\t}\n\n\t// If no auth client or no user, don't show footer\n\tif (!authClient || !user) {\n\t\treturn null;\n\t}\n\n\t// Get display values\n\tconst displayName = user.name || user.email?.split(\"@\")[0] || \"User\";\n\tconst displayEmail = user.email || \"\";\n\n\treturn (\n\t\t<SidebarFooter className=\"border-t border-sidebar-border/50 p-2\">\n\t\t\t<SidebarMenu>\n\t\t\t\t{/* User Menu */}\n\t\t\t\t<SidebarMenuItem>\n\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t<DropdownMenuTrigger\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"flex w-full items-center gap-2.5 p-2 text-left transition-colors duration-150\",\n\t\t\t\t\t\t\t\t\"hover:bg-sidebar-accent text-sidebar-foreground\",\n\t\t\t\t\t\t\t\t\"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sidebar-ring\",\n\t\t\t\t\t\t\t\tcollapsed && \"justify-center\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div className=\"flex size-8 shrink-0 items-center justify-center bg-sidebar-primary/10 text-sidebar-primary border border-sidebar-primary/20\">\n\t\t\t\t\t\t\t\t<User className=\"size-4\" weight=\"bold\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{!collapsed && (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<div className=\"grid flex-1 text-left leading-tight\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"truncate text-xs font-medium\">\n\t\t\t\t\t\t\t\t\t\t\t{displayName}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t<span className=\"truncate text-[10px] text-sidebar-foreground/50\">\n\t\t\t\t\t\t\t\t\t\t\t{displayEmail}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<CaretUpDown className=\"ml-auto size-3.5 text-sidebar-foreground/40\" />\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</DropdownMenuTrigger>\n\t\t\t\t\t\t<DropdownMenuContent\n\t\t\t\t\t\t\tside={collapsed ? \"right\" : \"top\"}\n\t\t\t\t\t\t\talign={collapsed ? \"start\" : \"start\"}\n\t\t\t\t\t\t\tclassName=\"w-56\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div className=\"px-2 py-1.5\">\n\t\t\t\t\t\t\t\t<p className=\"text-xs font-medium\">{displayName}</p>\n\t\t\t\t\t\t\t\t<p className=\"text-[10px] text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{displayEmail}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t{user.role && (\n\t\t\t\t\t\t\t\t\t<p className=\"text-[10px] text-muted-foreground capitalize mt-0.5\">\n\t\t\t\t\t\t\t\t\t\t{user.role}\n\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t\t\t{/* My Account - link to user detail */}\n\t\t\t\t\t\t\t<DropdownMenuItem onClick={handleMyAccount}>\n\t\t\t\t\t\t\t\t<UserCircle className=\"size-4\" />\n\t\t\t\t\t\t\t\t{t(\"auth.myAccount\")}\n\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t{/* UI Language Switcher */}\n\t\t\t\t\t\t\t{hasMultipleUiLocales && (\n\t\t\t\t\t\t\t\t<DropdownMenuSub>\n\t\t\t\t\t\t\t\t\t<DropdownMenuSubTrigger>\n\t\t\t\t\t\t\t\t\t\t<Globe />\n\t\t\t\t\t\t\t\t\t\t{t(\"locale.uiLanguage\")}\n\t\t\t\t\t\t\t\t\t</DropdownMenuSubTrigger>\n\t\t\t\t\t\t\t\t\t<DropdownMenuPortal>\n\t\t\t\t\t\t\t\t\t\t<DropdownMenuSubContent>\n\t\t\t\t\t\t\t\t\t\t\t{uiLocaleOptions.map((locale) => (\n\t\t\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={locale.code}\n\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => setUiLocale(locale.code)}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsrc={getFlagUrl(locale.code)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talt={locale.code}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"h-3 w-4 rounded-[2px] object-cover\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonError={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.currentTarget.style.display = \"none\";\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"uppercase text-xs font-medium w-6\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{locale.code}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"flex-1\">{locale.label}</span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{locale.code === uiLocale && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Check className=\"size-4 text-primary\" />\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t</DropdownMenuSubContent>\n\t\t\t\t\t\t\t\t\t</DropdownMenuPortal>\n\t\t\t\t\t\t\t\t</DropdownMenuSub>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<DropdownMenuSeparator />\n\t\t\t\t\t\t\t<DropdownMenuItem variant=\"destructive\" onClick={handleLogout}>\n\t\t\t\t\t\t\t\t<SignOut className=\"size-4\" />\n\t\t\t\t\t\t\t\t{t(\"auth.logout\")}\n\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t</DropdownMenu>\n\t\t\t\t</SidebarMenuItem>\n\t\t\t</SidebarMenu>\n\t\t</SidebarFooter>\n\t);\n}\n\n/**\n * AdminSidebar Component\n *\n * When used inside AdminProvider, navigation and brandName are automatically\n * read from context if not provided as props.\n *\n * @example\n * ```tsx\n * // With AdminProvider (automatic)\n * <AdminProvider admin={admin} client={client}>\n * <SidebarProvider>\n * <AdminSidebar LinkComponent={Link} activeRoute=\"/admin/posts\" />\n * </SidebarProvider>\n * </AdminProvider>\n *\n * // Without AdminProvider (manual)\n * <SidebarProvider>\n * <AdminSidebar\n * navigation={buildNavigation(admin)}\n * LinkComponent={Link}\n * activeRoute=\"/admin/posts\"\n * brandName=\"My CMS\"\n * />\n * </SidebarProvider>\n * ```\n */\nexport function AdminSidebar({\n\tnavigation: navigationProp,\n\tLinkComponent,\n\tactiveRoute,\n\tbasePath = \"/admin\",\n\tbrandName: brandNameProp,\n\tclassName,\n\trenderBrand,\n\trenderNavItem,\n\tfooter,\n\tuseActiveProps = true,\n}: AdminSidebarProps): React.ReactElement {\n\t// Resolve navigation and brandName from props or store\n\tconst { navigation, brandName } = useSidebarProps({\n\t\tnavigation: navigationProp,\n\t\tbrandName: brandNameProp,\n\t});\n\n\tconst { state, isMobile, setOpenMobile } = useSidebar();\n\tconst collapsed = state === \"collapsed\";\n\n\t// Close sidebar on mobile when navigating\n\tconst handleBrandClick = React.useCallback(() => {\n\t\tif (isMobile) {\n\t\t\tsetOpenMobile(false);\n\t\t}\n\t}, [isMobile, setOpenMobile]);\n\n\tconst brandContent = renderBrand ? (\n\t\trenderBrand({ name: brandName, collapsed })\n\t) : (\n\t\t<>\n\t\t\t<QuestpieSymbol />\n\t\t\t{!collapsed && (\n\t\t\t\t<div className=\"grid flex-1 text-left leading-tight\">\n\t\t\t\t\t<span className=\"truncate font-bold tracking-tight\">\n\t\t\t\t\t\t{brandName}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</>\n\t);\n\n\tconst brandLink = (\n\t\t<LinkComponent\n\t\t\tto={basePath}\n\t\t\tclassName={cn(\n\t\t\t\t\"flex items-center gap-2.5 p-2 transition-colors duration-150\",\n\t\t\t\t\"hover:bg-sidebar-accent\",\n\t\t\t\tcollapsed && \"justify-center\",\n\t\t\t)}\n\t\t>\n\t\t\t{brandContent}\n\t\t</LinkComponent>\n\t);\n\n\treturn (\n\t\t<Sidebar collapsible=\"icon\" className={className}>\n\t\t\t{/* Brand Header */}\n\t\t\t<SidebarHeader className=\"p-2 border-b border-sidebar-border/50\">\n\t\t\t\t<SidebarMenu>\n\t\t\t\t\t<SidebarMenuItem onClickCapture={handleBrandClick}>\n\t\t\t\t\t\t{collapsed && !isMobile ? (\n\t\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t\t<TooltipTrigger\n\t\t\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t\t\t<LinkComponent\n\t\t\t\t\t\t\t\t\t\t\tto={basePath}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\"flex items-center gap-2.5 p-2 transition-colors duration-150\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"hover:bg-sidebar-accent\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"justify-center\",\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{renderBrand ? (\n\t\t\t\t\t\t\t\t\t\t\t\trenderBrand({ name: brandName, collapsed: true })\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t<QuestpieSymbol />\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</LinkComponent>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<TooltipContent side=\"right\">{brandName}</TooltipContent>\n\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tbrandLink\n\t\t\t\t\t\t)}\n\t\t\t\t\t</SidebarMenuItem>\n\t\t\t\t</SidebarMenu>\n\t\t\t</SidebarHeader>\n\n\t\t\t{/* Navigation */}\n\t\t\t<SidebarContent>\n\t\t\t\t{navigation.map((group, index) => (\n\t\t\t\t\t<NavGroup\n\t\t\t\t\t\tkey={group.id ?? `group-${index}`}\n\t\t\t\t\t\tgroup={group}\n\t\t\t\t\t\tactiveRoute={activeRoute}\n\t\t\t\t\t\tLinkComponent={LinkComponent}\n\t\t\t\t\t\trenderNavItem={renderNavItem}\n\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\tuseActiveProps={useActiveProps}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</SidebarContent>\n\n\t\t\t{/* Footer */}\n\t\t\t{footer ?? <UserFooter />}\n\t\t</Sidebar>\n\t);\n}\n","import {\n\tCaretDown,\n\tMagnifyingGlassIcon,\n\tMonitorIcon,\n\tMoonIcon,\n\tSunIcon,\n} from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuItem,\n\tDropdownMenuTrigger,\n} from \"../../components/ui/dropdown-menu\";\nimport { Kbd } from \"../../components/ui/kbd\";\nimport { SidebarTrigger } from \"../../components/ui/sidebar\";\nimport type { Breadcrumb } from \"../../contexts/breadcrumb-context\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\n\nexport type Theme = \"light\" | \"dark\" | \"system\";\n\nexport interface AdminTopbarProps {\n\tonSearchOpen: () => void;\n\tbreadcrumbs?: Breadcrumb[];\n\ttheme?: Theme;\n\tsetTheme?: (theme: Theme) => void;\n\tshowThemeToggle?: boolean;\n}\n\nexport function AdminTopbar({\n\tonSearchOpen,\n\tbreadcrumbs = [],\n\ttheme = \"system\",\n\tsetTheme,\n\tshowThemeToggle,\n}: AdminTopbarProps) {\n\tconst resolveText = useResolveText();\n\n\t// Show theme toggle if setTheme is provided and showThemeToggle is not explicitly false\n\tconst shouldShowThemeToggle = setTheme && showThemeToggle !== false;\n\n\treturn (\n\t\t<header className=\"relative sticky top-0 z-30 flex h-16 w-full items-center justify-between border-b border-border/60 bg-background/60 px-4 md:px-6 backdrop-blur-xl after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-gradient-to-r after:from-transparent after:via-primary/15 after:to-transparent\">\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t{/* Sidebar toggle - works for both mobile (opens sheet) and desktop (collapses) */}\n\t\t\t\t<SidebarTrigger />\n\n\t\t\t\t{/* Breadcrumbs */}\n\t\t\t\t<nav className=\"hidden md:flex items-center gap-1.5 text-sm text-muted-foreground\">\n\t\t\t\t\t{breadcrumbs.map((crumb) => {\n\t\t\t\t\t\tconst CrumbIcon = crumb.icon;\n\t\t\t\t\t\tconst crumbLabel = resolveText(crumb.label);\n\t\t\t\t\t\tconst crumbKey = crumb.href ?? crumbLabel;\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<React.Fragment key={crumbKey}>\n\t\t\t\t\t\t\t\t{breadcrumbs[0] !== crumb && (\n\t\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground/40 mx-1\">/</span>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{crumb.menu ? (\n\t\t\t\t\t\t\t\t\t// Breadcrumb with dropdown menu\n\t\t\t\t\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t\t\t\t\t<DropdownMenuTrigger\n\t\t\t\t\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"flex items-center gap-1 hover:text-foreground transition-colors\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreadcrumbs[breadcrumbs.length - 1] === crumb &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"text-foreground font-medium\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{CrumbIcon && <CrumbIcon className=\"size-3.5\" />}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{crumbLabel}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<CaretDown className=\"size-3 opacity-50\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<DropdownMenuContent align=\"start\">\n\t\t\t\t\t\t\t\t\t\t\t{crumb.menu.items.map((item) => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst ItemIcon = item.icon;\n\t\t\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<DropdownMenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={item.href}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twindow.location.href = item.href;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ItemIcon && <ItemIcon className=\"size-3.5\" />}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{resolveText(item.label)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t\t\t\t\t</DropdownMenu>\n\t\t\t\t\t\t\t\t) : crumb.href ? (\n\t\t\t\t\t\t\t\t\t// Breadcrumb with link\n\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\thref={crumb.href}\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center gap-1.5 hover:text-foreground transition-colors\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{CrumbIcon && <CrumbIcon className=\"size-3.5\" />}\n\t\t\t\t\t\t\t\t\t\t{crumbLabel}\n\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t// Static breadcrumb (current page)\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"flex items-center gap-1.5\",\n\t\t\t\t\t\t\t\t\t\t\tbreadcrumbs[breadcrumbs.length - 1] === crumb\n\t\t\t\t\t\t\t\t\t\t\t\t? \"text-foreground font-medium\"\n\t\t\t\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{CrumbIcon && <CrumbIcon className=\"size-3.5\" />}\n\t\t\t\t\t\t\t\t\t\t{crumbLabel}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</nav>\n\t\t\t</div>\n\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tonClick={onSearchOpen}\n\t\t\t\t\tclassName=\"gap-2 w-auto md:w-64 justify-between text-muted-foreground\"\n\t\t\t\t>\n\t\t\t\t\t<span className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<MagnifyingGlassIcon />\n\t\t\t\t\t\t<span className=\"hidden sm:inline\">Search...</span>\n\t\t\t\t\t</span>\n\t\t\t\t\t<Kbd className=\"hidden md:inline-flex\">\n\t\t\t\t\t\t<span className=\"text-xs\">⌘</span>K\n\t\t\t\t\t</Kbd>\n\t\t\t\t</Button>\n\n\t\t\t\t{shouldShowThemeToggle && (\n\t\t\t\t\t<DropdownMenu>\n\t\t\t\t\t\t<DropdownMenuTrigger\n\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t<Button variant=\"ghost\" size=\"icon\">\n\t\t\t\t\t\t\t\t\t<SunIcon className=\"size-4 scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90\" />\n\t\t\t\t\t\t\t\t\t<MoonIcon className=\"absolute size-4 scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0\" />\n\t\t\t\t\t\t\t\t\t<span className=\"sr-only\">Toggle theme</span>\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<DropdownMenuContent align=\"end\">\n\t\t\t\t\t\t\t<DropdownMenuItem onClick={() => setTheme(\"light\")}>\n\t\t\t\t\t\t\t\t<SunIcon className=\"mr-2 size-4\" />\n\t\t\t\t\t\t\t\tLight\n\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t<DropdownMenuItem onClick={() => setTheme(\"dark\")}>\n\t\t\t\t\t\t\t\t<MoonIcon className=\"mr-2 size-4\" />\n\t\t\t\t\t\t\t\tDark\n\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t\t<DropdownMenuItem onClick={() => setTheme(\"system\")}>\n\t\t\t\t\t\t\t\t<MonitorIcon className=\"mr-2 size-4\" />\n\t\t\t\t\t\t\t\tSystem\n\t\t\t\t\t\t\t</DropdownMenuItem>\n\t\t\t\t\t\t</DropdownMenuContent>\n\t\t\t\t\t</DropdownMenu>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</header>\n\t);\n}\n","/**\n * AdminLayout Component\n *\n * Complete admin layout with:\n * - Sidebar navigation (using shadcn sidebar primitives)\n * - Main content area\n * - Optional header/footer\n *\n * Automatically reads from AdminProvider context when props are not provided.\n */\n\nimport * as React from \"react\";\nimport { SidebarInset, SidebarProvider } from \"../../components/ui/sidebar\";\nimport { type AdminToasterProps, Toaster } from \"../../components/ui/sonner\";\nimport {\n\tBreadcrumbProvider,\n\tuseCurrentBreadcrumbs,\n} from \"../../contexts/breadcrumb-context\";\nimport { cn } from \"../../lib/utils\";\nimport { useAdminStore } from \"../../runtime/provider\";\nimport type { NavigationGroup } from \"../../runtime/routes\";\nimport { GlobalSearch } from \"../common\";\nimport { AdminSidebar, type AdminSidebarProps } from \"./admin-sidebar\";\nimport { AdminTopbar } from \"./admin-topbar\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Theme mode for the admin interface\n */\nexport type AdminTheme = \"light\" | \"dark\" | \"system\";\n\n/**\n * Layout mode for content area width\n * - default: max-w-6xl (forms, settings)\n * - wide: max-w-7xl (tables, cards)\n * - full: 100% with padding (kanban, calendar)\n * - immersive: 100% no padding (puck editor)\n */\nexport type LayoutMode = \"default\" | \"wide\" | \"full\" | \"immersive\";\n\n/**\n * Shared layout props that can be passed through AdminLayoutProvider\n * or directly to AdminLayout.\n */\nexport interface AdminLayoutSharedProps {\n\t/**\n\t * Link component (router-specific)\n\t */\n\tLinkComponent: AdminSidebarProps[\"LinkComponent\"];\n\n\t/**\n\t * Current active route\n\t */\n\tactiveRoute?: string;\n\n\t/**\n\t * Base path for admin routes\n\t * @default \"/admin\"\n\t */\n\tbasePath?: string;\n\n\t/**\n\t * Header content\n\t */\n\theader?: React.ReactNode;\n\n\t/**\n\t * Footer content\n\t */\n\tfooter?: React.ReactNode;\n\n\t/**\n\t * Additional sidebar props\n\t */\n\tsidebarProps?: Partial<\n\t\tOmit<AdminSidebarProps, \"navigation\" | \"LinkComponent\">\n\t>;\n\n\t/**\n\t * Current theme.\n\t * Pass from your app's theme context.\n\t * @default \"system\"\n\t */\n\ttheme?: AdminTheme;\n\n\t/**\n\t * Callback to change theme.\n\t * Connect to your app's theme context setTheme function.\n\t */\n\tsetTheme?: (theme: AdminTheme) => void;\n\n\t/**\n\t * Show theme toggle button in the topbar\n\t * @default true (when setTheme is provided)\n\t */\n\tshowThemeToggle?: boolean;\n\n\t/**\n\t * Additional toaster props\n\t */\n\ttoasterProps?: Omit<AdminToasterProps, \"theme\">;\n\n\t/**\n\t * Custom layout className\n\t */\n\tclassName?: string;\n\n\t/**\n\t * Layout mode for content area width\n\t * @default \"default\"\n\t */\n\tlayoutMode?: LayoutMode;\n}\n\nexport interface AdminLayoutProps extends AdminLayoutSharedProps {\n\t/**\n\t * Navigation groups for sidebar.\n\t * If not provided, reads from AdminProvider context.\n\t */\n\tnavigation?: NavigationGroup[];\n\n\t/**\n\t * Brand name for sidebar.\n\t * If not provided, reads from AdminProvider context.\n\t */\n\tbrandName?: string;\n\n\t/**\n\t * Whether sidebar is collapsed\n\t */\n\tsidebarCollapsed?: boolean;\n\n\t/**\n\t * Main content to render\n\t */\n\tchildren: React.ReactNode;\n\n\t/**\n\t * Navigation function (for search/quick actions)\n\t */\n\tnavigate?: (path: string) => void;\n}\n\n// ============================================================================\n// Internal Hook - Resolve props from store\n// ============================================================================\n\nfunction useLayoutProps(props: {\n\tnavigation?: NavigationGroup[];\n\tbrandName?: string;\n\tnavigate?: (path: string) => void;\n}): {\n\tnavigation: NavigationGroup[];\n\tbrandName: string;\n\tnavigate: (path: string) => void;\n} {\n\t// Subscribe to store values reactively (for HMR support)\n\tconst storeNavigation = useAdminStore((s) => s.navigation);\n\tconst storeBrandName = useAdminStore((s) => s.brandName);\n\tconst storeNavigate = useAdminStore((s) => s.navigate);\n\n\treturn {\n\t\tnavigation: props.navigation ?? storeNavigation,\n\t\tbrandName: props.brandName ?? storeBrandName,\n\t\tnavigate: props.navigate ?? storeNavigate,\n\t};\n}\n\n// ============================================================================\n// Internal Components\n// ============================================================================\n\n/**\n * Topbar wrapper that reads breadcrumbs from context\n */\nfunction AdminTopbarWithBreadcrumbs(\n\tprops: Omit<React.ComponentProps<typeof AdminTopbar>, \"breadcrumbs\">,\n) {\n\tconst breadcrumbs = useCurrentBreadcrumbs();\n\treturn <AdminTopbar {...props} breadcrumbs={breadcrumbs} />;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * AdminLayout Component\n *\n * When used inside AdminProvider, navigation and brandName are automatically\n * read from context if not provided as props.\n *\n * @example\n * ```tsx\n * // With AdminProvider (automatic)\n * <AdminProvider admin={admin} client={client}>\n * <AdminLayout LinkComponent={Link} activeRoute=\"/admin/posts\">\n * <Outlet />\n * </AdminLayout>\n * </AdminProvider>\n *\n * // Without AdminProvider (manual)\n * <AdminLayout\n * navigation={buildNavigation(admin)}\n * LinkComponent={Link}\n * activeRoute=\"/admin/posts\"\n * brandName=\"My CMS\"\n * >\n * <Outlet />\n * </AdminLayout>\n * ```\n */\nexport function AdminLayout({\n\tnavigation: navigationProp,\n\tLinkComponent,\n\tactiveRoute,\n\tbasePath = \"/admin\",\n\tbrandName: brandNameProp,\n\tsidebarCollapsed: sidebarCollapsedProp = false,\n\tchildren,\n\tclassName,\n\tsidebarProps,\n\theader,\n\tfooter,\n\tnavigate: navigateProp,\n\ttheme = \"system\",\n\tsetTheme,\n\tshowThemeToggle,\n\ttoasterProps,\n\tlayoutMode = \"default\",\n}: AdminLayoutProps): React.ReactElement {\n\t// Infer show flags from content\n\tconst shouldShowHeader = !!header;\n\tconst shouldShowFooter = !!footer;\n\t// Resolve navigation and brandName from props or store\n\tconst { navigation, brandName, navigate } = useLayoutProps({\n\t\tnavigation: navigationProp,\n\t\tbrandName: brandNameProp,\n\t\tnavigate: navigateProp,\n\t});\n\n\tconst [isSearchOpen, setIsSearchOpen] = React.useState(false);\n\n\t// Keyboard shortcuts for search\n\tReact.useEffect(() => {\n\t\tconst down = (e: KeyboardEvent) => {\n\t\t\tif (e.key === \"k\" && (e.metaKey || e.ctrlKey)) {\n\t\t\t\te.preventDefault();\n\t\t\t\tsetIsSearchOpen(true);\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener(\"keydown\", down);\n\t\treturn () => document.removeEventListener(\"keydown\", down);\n\t}, []);\n\n\treturn (\n\t\t<BreadcrumbProvider>\n\t\t\t<div\n\t\t\t\tclassName={cn(\"min-h-screen bg-background bg-grid-quest\", className)}\n\t\t\t>\n\t\t\t\t{/* <div className=\"fixed inset-0 bg-grid-quest pointer-events-none z-10\" /> */}\n\t\t\t\t<GlobalSearch\n\t\t\t\t\tisOpen={isSearchOpen}\n\t\t\t\t\tonClose={() => setIsSearchOpen(false)}\n\t\t\t\t\tnavigate={navigate}\n\t\t\t\t\tbasePath={basePath}\n\t\t\t\t/>\n\n\t\t\t\t{/* Max-width container for ultrawide monitors - centered with subtle side borders */}\n\t\t\t\t<SidebarProvider\n\t\t\t\t\tdefaultOpen={!sidebarCollapsedProp}\n\t\t\t\t\tclassName=\"mx-auto max-w-[1920px] border-x border-border/40 h-svh overflow-hidden\"\n\t\t\t\t>\n\t\t\t\t\t{/* Sidebar */}\n\t\t\t\t\t<AdminSidebar\n\t\t\t\t\t\tnavigation={navigation}\n\t\t\t\t\t\tLinkComponent={LinkComponent}\n\t\t\t\t\t\tactiveRoute={activeRoute}\n\t\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\t\tbrandName={brandName}\n\t\t\t\t\t\t{...sidebarProps}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{/* Content Area */}\n\t\t\t\t\t<SidebarInset className=\"flex h-svh flex-col\">\n\t\t\t\t\t\t<AdminTopbarWithBreadcrumbs\n\t\t\t\t\t\t\tonSearchOpen={() => setIsSearchOpen(true)}\n\t\t\t\t\t\t\ttheme={theme}\n\t\t\t\t\t\t\tsetTheme={setTheme}\n\t\t\t\t\t\t\tshowThemeToggle={showThemeToggle}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t{/* Header (optional) */}\n\t\t\t\t\t\t{shouldShowHeader && header && (\n\t\t\t\t\t\t\t<header className=\"border-b\">{header}</header>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t<main className=\"flex-1 overflow-y-auto\">\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"mx-auto\",\n\t\t\t\t\t\t\t\t\tlayoutMode === \"default\" && \"max-w-6xl p-5 md:p-8 lg:p-10\",\n\t\t\t\t\t\t\t\t\tlayoutMode === \"wide\" && \"max-w-7xl p-5 md:p-8 lg:p-10\",\n\t\t\t\t\t\t\t\t\tlayoutMode === \"full\" && \"max-w-full p-4 md:p-6\",\n\t\t\t\t\t\t\t\t\tlayoutMode === \"immersive\" && \"max-w-full p-0\",\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</main>\n\n\t\t\t\t\t\t{/* Footer (optional) */}\n\t\t\t\t\t\t{shouldShowFooter && footer && (\n\t\t\t\t\t\t\t<footer className=\"border-t\">{footer}</footer>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</SidebarInset>\n\t\t\t\t</SidebarProvider>\n\n\t\t\t\t{/* Toast notifications */}\n\t\t\t\t<Toaster theme={theme} {...toasterProps} />\n\t\t\t</div>\n\t\t</BreadcrumbProvider>\n\t);\n}\n","/**\n * AdminLayoutProvider Component\n *\n * Universal layout wrapper that works with any router.\n * Provides AdminProvider + AdminLayout and renders children.\n *\n * @example Next.js (App Router)\n * ```tsx\n * // app/admin/layout.tsx\n * export default function AdminLayout({ children }) {\n * return (\n * <AdminLayoutProvider\n * admin={myAdmin}\n * client={cmsClient}\n * authClient={authClient}\n * LinkComponent={Link}\n * >\n * {children}\n * </AdminLayoutProvider>\n * );\n * }\n * ```\n *\n * @example TanStack Router\n * ```tsx\n * // routes/admin.tsx\n * function AdminLayout() {\n * return (\n * <AdminLayoutProvider\n * admin={myAdmin}\n * client={cmsClient}\n * authClient={authClient}\n * LinkComponent={Link}\n * >\n * <Outlet />\n * </AdminLayoutProvider>\n * );\n * }\n * ```\n *\n * @example With Auth Protection\n * ```tsx\n * <AdminLayoutProvider\n * admin={myAdmin}\n * client={cmsClient}\n * authClient={authClient}\n * enableAuthGuard={true}\n * publicPaths={[\"/admin/login\", \"/admin/forgot-password\"]}\n * requiredRole=\"admin\"\n * >\n * {children}\n * </AdminLayoutProvider>\n * ```\n */\n\nimport type { QueryClient } from \"@tanstack/react-query\";\nimport { QueryClientProvider } from \"@tanstack/react-query\";\nimport type { Questpie } from \"questpie\";\nimport type { QuestpieClient } from \"questpie/client\";\nimport type * as React from \"react\";\nimport { Admin, type AdminInput } from \"../../builder/admin\";\nimport type { AdminBuilder } from \"../../builder/admin-builder\";\nimport { AuthGuard } from \"../../components/auth\";\nimport { AdminProvider } from \"../../runtime/provider\";\nimport { AdminLayout, type AdminLayoutSharedProps } from \"./admin-layout\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AdminLayoutProviderProps<\n\tTApp extends Questpie<any> = Questpie<any>,\n> extends AdminLayoutSharedProps {\n\t/**\n\t * Admin configuration - pass your AdminBuilder directly.\n\t * Can also accept an Admin instance for backward compatibility.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Recommended: pass builder directly\n\t * <AdminLayoutProvider admin={admin} ... />\n\t *\n\t * // Also works (backward compatible)\n\t * <AdminLayoutProvider admin={Admin.from(admin)} ... />\n\t * ```\n\t */\n\tadmin: AdminInput<any>;\n\n\t/**\n\t * API client for data fetching\n\t */\n\tclient: QuestpieClient<TApp>;\n\n\t/**\n\t * Auth client for authentication (created via createAdminAuthClient)\n\t */\n\tauthClient?: any;\n\n\t/**\n\t * Optional QueryClient instance (will create one if not provided)\n\t */\n\tqueryClient?: QueryClient;\n\n\t// =========================================================================\n\t// Auth Guard Options\n\t// =========================================================================\n\n\t/**\n\t * Enable authentication guard for protected routes.\n\t * When true, checks if user is authenticated before rendering content.\n\t * @default true if authClient is provided\n\t */\n\tenableAuthGuard?: boolean;\n\n\t/**\n\t * Paths that don't require authentication.\n\t * Use relative paths from basePath (e.g., \"/login\" for \"/admin/login\").\n\t * @default [\"/login\", \"/forgot-password\", \"/reset-password\", \"/accept-invite\"]\n\t */\n\tpublicPaths?: string[];\n\n\t/**\n\t * Required role for accessing protected routes.\n\t * @default \"admin\"\n\t */\n\trequiredRole?: string;\n\n\t/**\n\t * Custom loading component while checking authentication.\n\t */\n\tauthLoadingFallback?: React.ReactNode;\n\n\t/**\n\t * Custom unauthorized component (instead of redirecting to login).\n\t */\n\tauthUnauthorizedFallback?: React.ReactNode;\n\n\t/**\n\t * Children to render inside the layout\n\t * - Next.js: {children} from layout props\n\t * - TanStack Router: <Outlet />\n\t */\n\tchildren: React.ReactNode;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nimport { QueryClient as QueryClientClass } from \"@tanstack/react-query\";\n\nlet cachedQueryClient: QueryClient | undefined;\n\nfunction getDefaultQueryClient(): QueryClient {\n\tif (!cachedQueryClient) {\n\t\tcachedQueryClient = new QueryClientClass({\n\t\t\tdefaultOptions: {\n\t\t\t\tqueries: {\n\t\t\t\t\tstaleTime: 60 * 1000, // 1 minute\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t}\n\treturn cachedQueryClient;\n}\n\n/**\n * Default public paths that don't require authentication\n * These paths also render WITHOUT the admin layout (no sidebar/header)\n */\nconst DEFAULT_PUBLIC_PATHS = [\n\t\"/login\",\n\t\"/forgot-password\",\n\t\"/reset-password\",\n\t\"/accept-invite\",\n\t\"/setup\",\n];\n\n/**\n * Check if current path matches any public path\n */\nfunction isPublicPath(\n\tcurrentPath: string | undefined,\n\tbasePath: string,\n\tpublicPaths: string[],\n): boolean {\n\tif (!currentPath) return false;\n\n\t// Normalize paths\n\tconst normalizedCurrent = currentPath.replace(/\\/+$/, \"\");\n\tconst normalizedBase = basePath.replace(/\\/+$/, \"\");\n\n\tfor (const publicPath of publicPaths) {\n\t\t// Build full public path\n\t\tconst fullPublicPath = `${normalizedBase}${publicPath}`.replace(/\\/+$/, \"\");\n\n\t\t// Check exact match or starts with (for nested routes)\n\t\tif (\n\t\t\tnormalizedCurrent === fullPublicPath ||\n\t\t\tnormalizedCurrent.startsWith(`${fullPublicPath}/`)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * AdminLayoutProvider Component\n *\n * Universal wrapper for admin layout that works with any router.\n * Handles all the provider setup and renders children inside the layout.\n */\nexport function AdminLayoutProvider<TApp extends Questpie<any>>({\n\tadmin: adminInput,\n\tclient,\n\tauthClient,\n\tqueryClient,\n\t// Shared layout props\n\tLinkComponent,\n\tactiveRoute,\n\tbasePath = \"/admin\",\n\theader,\n\tfooter,\n\tsidebarProps,\n\ttheme,\n\tsetTheme,\n\tshowThemeToggle,\n\ttoasterProps,\n\tclassName,\n\t// Auth guard props\n\tenableAuthGuard,\n\tpublicPaths = DEFAULT_PUBLIC_PATHS,\n\trequiredRole = \"admin\",\n\tauthLoadingFallback,\n\tauthUnauthorizedFallback,\n\t// Children\n\tchildren,\n}: AdminLayoutProviderProps<TApp>): React.ReactElement {\n\tconst qc = queryClient ?? getDefaultQueryClient();\n\n\t// Normalize admin input - accepts both AdminBuilder and Admin instance\n\tconst admin = Admin.normalize(adminInput);\n\n\t// Determine if auth guard should be enabled\n\t// Default: enabled if authClient is provided\n\tconst shouldUseAuthGuard = enableAuthGuard ?? authClient != null;\n\n\t// Check if current route is public\n\tconst currentPath =\n\t\tactiveRoute ??\n\t\t(typeof window !== \"undefined\" ? window.location.pathname : undefined);\n\tconst isCurrentPathPublic = isPublicPath(currentPath, basePath, publicPaths);\n\n\t// Determine content based on path type:\n\t// - Public paths (login, setup, etc.): render children directly (no AdminLayout)\n\t// - Protected paths: render with AdminLayout + optional AuthGuard\n\tlet innerContent: React.ReactNode;\n\n\tif (isCurrentPathPublic) {\n\t\t// Public paths render children directly without admin layout (sidebar/header)\n\t\t// Auth pages (login, setup) use their own AuthLayout component\n\t\tinnerContent = children;\n\t} else {\n\t\t// Protected paths get the full admin layout\n\t\tconst layoutContent = (\n\t\t\t<AdminLayout\n\t\t\t\tLinkComponent={LinkComponent}\n\t\t\t\tactiveRoute={activeRoute}\n\t\t\t\tbasePath={basePath}\n\t\t\t\theader={header}\n\t\t\t\tfooter={footer}\n\t\t\t\tsidebarProps={sidebarProps}\n\t\t\t\ttheme={theme}\n\t\t\t\tsetTheme={setTheme}\n\t\t\t\tshowThemeToggle={showThemeToggle}\n\t\t\t\ttoasterProps={toasterProps}\n\t\t\t\tclassName={className}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</AdminLayout>\n\t\t);\n\n\t\t// Optionally wrap with auth guard\n\t\tinnerContent = shouldUseAuthGuard ? (\n\t\t\t<AuthGuard\n\t\t\t\tloginPath={`${basePath}/login`}\n\t\t\t\trequiredRole={requiredRole}\n\t\t\t\tloadingFallback={authLoadingFallback}\n\t\t\t\tunauthorizedFallback={authUnauthorizedFallback}\n\t\t\t>\n\t\t\t\t{layoutContent}\n\t\t\t</AuthGuard>\n\t\t) : (\n\t\t\tlayoutContent\n\t\t);\n\t}\n\n\tconst content = (\n\t\t<AdminProvider admin={admin} client={client} authClient={authClient}>\n\t\t\t{innerContent}\n\t\t</AdminProvider>\n\t);\n\n\t// Always wrap with QueryClientProvider\n\treturn <QueryClientProvider client={qc}>{content}</QueryClientProvider>;\n}\n\nexport default AdminLayoutProvider;\n","/**\n * Invite Form - invite new users to the admin\n */\n\nimport {\n\tEnvelope,\n\tSpinnerGap,\n\tUserPlus,\n\tWarningCircle,\n} from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport { Alert, AlertDescription } from \"../../components/ui/alert\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n\tField,\n\tFieldContent,\n\tFieldDescription,\n\tFieldError,\n\tFieldGroup,\n\tFieldLabel,\n} from \"../../components/ui/field\";\nimport { Input } from \"../../components/ui/input\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"../../components/ui/select\";\nimport { Textarea } from \"../../components/ui/textarea\";\nimport { useResolveText } from \"../../i18n/hooks\";\nimport { cn } from \"../../lib/utils\";\n\nexport type InviteFormValues = {\n\temail: string;\n\trole: string;\n\tmessage?: string;\n};\n\nexport type InviteFormProps = {\n\t/** Called when form is submitted with valid data */\n\tonSubmit: (values: InviteFormValues) => Promise<void>;\n\t/** Available roles for selection */\n\troles?: Array<{ value: string; label: string }>;\n\t/** Default role */\n\tdefaultRole?: string;\n\t/** Show custom message field */\n\tshowMessage?: boolean;\n\t/** Additional class name */\n\tclassName?: string;\n\t/** Error message from auth */\n\terror?: string | null;\n\t/** Success message after invite sent */\n\tsuccess?: string | null;\n};\n\n/**\n * Invite form for admins to invite new users\n *\n * @example\n * ```tsx\n * function InvitePage() {\n * const authClient = useAuthClient()\n * const [error, setError] = useState<string | null>(null)\n * const [success, setSuccess] = useState<string | null>(null)\n *\n * const handleInvite = async (values: InviteFormValues) => {\n * const result = await authClient.admin.createInvitation({\n * email: values.email,\n * role: values.role,\n * })\n * if (result.error) {\n * setError(result.error.message)\n * } else {\n * setSuccess(`Invitation sent to ${values.email}`)\n * }\n * }\n *\n * return (\n * <InviteForm\n * onSubmit={handleInvite}\n * error={error}\n * success={success}\n * />\n * )\n * }\n * ```\n */\nexport function InviteForm({\n\tonSubmit,\n\troles = [\n\t\t{ value: \"admin\", label: \"Admin\" },\n\t\t{ value: \"user\", label: \"User\" },\n\t],\n\tdefaultRole = \"user\",\n\tshowMessage = true,\n\tclassName,\n\terror,\n\tsuccess,\n}: InviteFormProps) {\n\tconst {\n\t\tregister,\n\t\thandleSubmit,\n\t\tsetValue,\n\t\twatch,\n\t\treset,\n\t\tformState: { errors, isSubmitting },\n\t} = useForm<InviteFormValues>({\n\t\tdefaultValues: {\n\t\t\temail: \"\",\n\t\t\trole: defaultRole,\n\t\t\tmessage: \"\",\n\t\t},\n\t});\n\n\tconst selectedRole = watch(\"role\");\n\tconst resolveText = useResolveText();\n\n\tconst handleFormSubmit = handleSubmit(async (values) => {\n\t\tawait onSubmit(values);\n\t\t// Reset form on success\n\t\tif (!error) {\n\t\t\treset();\n\t\t}\n\t});\n\n\treturn (\n\t\t<form onSubmit={handleFormSubmit} className={cn(\"space-y-4\", className)}>\n\t\t\t<FieldGroup>\n\t\t\t\t{/* Email Field */}\n\t\t\t\t<Field data-invalid={!!errors.email}>\n\t\t\t\t\t<FieldLabel htmlFor=\"invite-email\">Email Address</FieldLabel>\n\t\t\t\t\t<FieldContent>\n\t\t\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t\t\t<Envelope\n\t\t\t\t\t\t\t\tclassName=\"text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2\"\n\t\t\t\t\t\t\t\tweight=\"duotone\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\tid=\"invite-email\"\n\t\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\t\tplaceholder=\"user@example.com\"\n\t\t\t\t\t\t\t\tclassName=\"pl-8\"\n\t\t\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\t\t\taria-invalid={!!errors.email}\n\t\t\t\t\t\t\t\t{...register(\"email\", {\n\t\t\t\t\t\t\t\t\trequired: \"Email is required\",\n\t\t\t\t\t\t\t\t\tpattern: {\n\t\t\t\t\t\t\t\t\t\tvalue: /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/,\n\t\t\t\t\t\t\t\t\t\tmessage: \"Invalid email address\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<FieldDescription>\n\t\t\t\t\t\t\tAn invitation link will be sent to this email\n\t\t\t\t\t\t</FieldDescription>\n\t\t\t\t\t\t<FieldError>{errors.email?.message}</FieldError>\n\t\t\t\t\t</FieldContent>\n\t\t\t\t</Field>\n\n\t\t\t\t{/* Role Field */}\n\t\t\t\t<Field data-invalid={!!errors.role}>\n\t\t\t\t\t<FieldLabel htmlFor=\"invite-role\">Role</FieldLabel>\n\t\t\t\t\t<FieldContent>\n\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\tvalue={selectedRole}\n\t\t\t\t\t\t\tonValueChange={(value) => value && setValue(\"role\", value)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SelectTrigger id=\"invite-role\">\n\t\t\t\t\t\t\t\t<SelectValue>\n\t\t\t\t\t\t\t\t\t{roles.find((r) => r.value === selectedRole)?.label\n\t\t\t\t\t\t\t\t\t\t? resolveText(\n\t\t\t\t\t\t\t\t\t\t\t\troles.find((r) => r.value === selectedRole)?.label,\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t: \"Select a role\"}\n\t\t\t\t\t\t\t\t</SelectValue>\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t{roles.map((role) => (\n\t\t\t\t\t\t\t\t\t<SelectItem key={role.value} value={role.value}>\n\t\t\t\t\t\t\t\t\t\t{resolveText(role.label)}\n\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t<FieldDescription>\n\t\t\t\t\t\t\tThe role determines what permissions the user will have\n\t\t\t\t\t\t</FieldDescription>\n\t\t\t\t\t\t<FieldError>{errors.role?.message}</FieldError>\n\t\t\t\t\t</FieldContent>\n\t\t\t\t</Field>\n\n\t\t\t\t{/* Optional Message Field */}\n\t\t\t\t{showMessage && (\n\t\t\t\t\t<Field>\n\t\t\t\t\t\t<FieldLabel htmlFor=\"invite-message\">\n\t\t\t\t\t\t\tPersonal Message (Optional)\n\t\t\t\t\t\t</FieldLabel>\n\t\t\t\t\t\t<FieldContent>\n\t\t\t\t\t\t\t<Textarea\n\t\t\t\t\t\t\t\tid=\"invite-message\"\n\t\t\t\t\t\t\t\tplaceholder=\"Add a personal message to the invitation...\"\n\t\t\t\t\t\t\t\trows={3}\n\t\t\t\t\t\t\t\t{...register(\"message\")}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<FieldDescription>\n\t\t\t\t\t\t\t\tThis message will be included in the invitation email\n\t\t\t\t\t\t\t</FieldDescription>\n\t\t\t\t\t\t</FieldContent>\n\t\t\t\t\t</Field>\n\t\t\t\t)}\n\t\t\t</FieldGroup>\n\n\t\t\t{/* Error Message */}\n\t\t\t{error && (\n\t\t\t\t<Alert variant=\"destructive\">\n\t\t\t\t\t<WarningCircle />\n\t\t\t\t\t<AlertDescription>{error}</AlertDescription>\n\t\t\t\t</Alert>\n\t\t\t)}\n\n\t\t\t{/* Success Message */}\n\t\t\t{success && (\n\t\t\t\t<Alert>\n\t\t\t\t\t<UserPlus />\n\t\t\t\t\t<AlertDescription>{success}</AlertDescription>\n\t\t\t\t</Alert>\n\t\t\t)}\n\n\t\t\t{/* Submit Button */}\n\t\t\t<Button\n\t\t\t\ttype=\"submit\"\n\t\t\t\tclassName=\"w-full\"\n\t\t\t\tsize=\"lg\"\n\t\t\t\tdisabled={isSubmitting}\n\t\t\t>\n\t\t\t\t{isSubmitting ? (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<SpinnerGap className=\"animate-spin\" weight=\"bold\" />\n\t\t\t\t\t\tSending invitation...\n\t\t\t\t\t</>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<UserPlus weight=\"bold\" />\n\t\t\t\t\t\tSend Invitation\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</Button>\n\t\t</form>\n\t);\n}\n","/**\n * Invite Page\n *\n * Page for admins to invite new users.\n * Uses Better Auth's admin plugin for invitations.\n */\n\nimport * as React from \"react\";\nimport { useAuthClient } from \"../../hooks/use-auth\";\nimport {\n selectBasePath,\n selectBrandName,\n useAdminStore,\n} from \"../../runtime/provider\";\nimport { AuthLayout } from \"../auth/auth-layout\";\nimport { InviteForm, type InviteFormValues } from \"../auth/invite-form\";\n\nexport interface InvitePageProps {\n /**\n * Title shown on the invite page\n * @default \"Invite User\"\n */\n title?: string;\n\n /**\n * Description shown below the title\n * @default \"Send an invitation to add a new user\"\n */\n description?: string;\n\n /**\n * Logo component to show above the form\n */\n logo?: React.ReactNode;\n\n /**\n * Available roles for selection\n * @default [{ value: \"admin\", label: \"Admin\" }, { value: \"user\", label: \"User\" }]\n */\n roles?: Array<{ value: string; label: string }>;\n\n /**\n * Default role for new users\n * @default \"user\"\n */\n defaultRole?: string;\n\n /**\n * Show custom message field\n * @default true\n */\n showMessage?: boolean;\n\n /**\n * Callback when invitation is sent successfully\n */\n onSuccess?: (email: string) => void;\n}\n\n/**\n * Default invite page component.\n *\n * Uses authClient from AdminProvider to send invitations.\n * Requires Better Auth admin plugin.\n *\n * @example\n * ```tsx\n * // In your admin config\n * const admin = qa<AppCMS>()\n * .use(adminStarterModule)\n * .pages({\n * invite: page(\"invite\", { component: InvitePage }).path(\"/invite\"),\n * })\n * ```\n */\nexport function InvitePage({\n title = \"Invite User\",\n description = \"Send an invitation to add a new user\",\n logo,\n roles = [\n { value: \"admin\", label: \"Admin\" },\n { value: \"user\", label: \"User\" },\n ],\n defaultRole = \"user\",\n showMessage = true,\n onSuccess,\n}: InvitePageProps) {\n const authClient = useAuthClient();\n const brandName = useAdminStore(selectBrandName);\n\n const [error, setError] = React.useState<string | null>(null);\n const [success, setSuccess] = React.useState<string | null>(null);\n\n const handleSubmit = async (values: InviteFormValues) => {\n setError(null);\n setSuccess(null);\n\n try {\n // Use Better Auth admin plugin to create invitation\n const result = await authClient.admin.createInvitation({\n email: values.email,\n role: values.role,\n });\n\n if (result.error) {\n setError(result.error.message || \"Failed to send invitation\");\n return;\n }\n\n setSuccess(`Invitation sent to ${values.email}`);\n onSuccess?.(values.email);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"An error occurred\");\n }\n };\n\n return (\n <AuthLayout\n title={title}\n description={description}\n logo={logo ?? <DefaultLogo brandName={brandName} />}\n >\n <InviteForm\n onSubmit={handleSubmit}\n roles={roles}\n defaultRole={defaultRole}\n showMessage={showMessage}\n error={error}\n success={success}\n />\n </AuthLayout>\n );\n}\n\nfunction DefaultLogo({ brandName }: { brandName: string }) {\n return (\n <div className=\"text-center\">\n <h1 className=\"text-xl font-bold\">{brandName}</h1>\n </div>\n );\n}\n\nexport default InvitePage;\n","/**\n * Accept Invite Page\n *\n * Page for new users to complete registration after receiving invitation.\n * Uses Better Auth's admin plugin for invitation acceptance.\n */\n\nimport * as React from \"react\";\nimport { useAuthClient } from \"../../hooks/use-auth\";\nimport {\n selectBasePath,\n selectBrandName,\n selectNavigate,\n useAdminStore,\n} from \"../../runtime/provider\";\nimport { AuthLayout } from \"../auth/auth-layout\";\nimport {\n AcceptInviteForm,\n type AcceptInviteFormValues,\n} from \"../auth/accept-invite-form\";\nimport { Alert, AlertDescription } from \"../../components/ui/alert\";\nimport { Button } from \"../../components/ui/button\";\nimport { Spinner } from \"../../components/ui/spinner\";\nimport { WarningCircle } from \"@phosphor-icons/react\";\n\nexport interface AcceptInvitePageProps {\n /**\n * Invitation token from URL\n */\n token: string;\n\n /**\n * Title shown on the page\n * @default \"Complete Registration\"\n */\n title?: string;\n\n /**\n * Description shown below the title\n * @default \"Create your account to get started\"\n */\n description?: string;\n\n /**\n * Logo component to show above the form\n */\n logo?: React.ReactNode;\n\n /**\n * Path to redirect after successful registration\n * @default basePath (e.g., \"/admin\")\n */\n redirectTo?: string;\n\n /**\n * Path to login page (for invalid/expired tokens)\n * @default \"{basePath}/login\"\n */\n loginPath?: string;\n\n /**\n * Minimum password length\n * @default 8\n */\n minPasswordLength?: number;\n}\n\ntype InvitationState =\n | { status: \"loading\" }\n | { status: \"valid\"; email: string; role?: string }\n | { status: \"invalid\"; message: string };\n\n/**\n * Accept invite page component.\n *\n * Validates the invitation token and allows new users to complete registration.\n * Uses authClient from AdminProvider.\n *\n * @example\n * ```tsx\n * // In your router\n * function AcceptInviteRoute() {\n * const { token } = useParams()\n * return <AcceptInvitePage token={token} />\n * }\n * ```\n */\nexport function AcceptInvitePage({\n token,\n title = \"Complete Registration\",\n description = \"Create your account to get started\",\n logo,\n redirectTo,\n loginPath,\n minPasswordLength = 8,\n}: AcceptInvitePageProps) {\n const authClient = useAuthClient();\n const navigate = useAdminStore(selectNavigate);\n const basePath = useAdminStore(selectBasePath);\n const brandName = useAdminStore(selectBrandName);\n\n const [invitation, setInvitation] = React.useState<InvitationState>({\n status: \"loading\",\n });\n const [error, setError] = React.useState<string | null>(null);\n\n // Validate token on mount\n React.useEffect(() => {\n const validateToken = async () => {\n try {\n const result = await authClient.admin.getInvitation({\n query: { token },\n });\n\n if (result.error || !result.data) {\n setInvitation({\n status: \"invalid\",\n message: result.error?.message || \"Invalid or expired invitation\",\n });\n return;\n }\n\n setInvitation({\n status: \"valid\",\n email: result.data.email,\n role: result.data.role,\n });\n } catch (err) {\n setInvitation({\n status: \"invalid\",\n message: \"Invalid or expired invitation\",\n });\n }\n };\n\n validateToken();\n }, [token, authClient]);\n\n const handleSubmit = async (values: AcceptInviteFormValues) => {\n setError(null);\n\n try {\n const result = await authClient.admin.acceptInvitation({\n token,\n name: values.name,\n password: values.password,\n });\n\n if (result.error) {\n setError(result.error.message || \"Failed to create account\");\n return;\n }\n\n // Redirect on success\n navigate(redirectTo ?? basePath);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"An error occurred\");\n }\n };\n\n const handleGoToLogin = () => {\n navigate(loginPath ?? `${basePath}/login`);\n };\n\n // Loading state\n if (invitation.status === \"loading\") {\n return (\n <AuthLayout\n title=\"Validating Invitation\"\n description=\"Please wait...\"\n logo={logo ?? <DefaultLogo brandName={brandName} />}\n >\n <div className=\"flex justify-center py-8\">\n <Spinner className=\"size-8\" />\n </div>\n </AuthLayout>\n );\n }\n\n // Invalid token state\n if (invitation.status === \"invalid\") {\n return (\n <AuthLayout\n title=\"Invalid Invitation\"\n description=\"This invitation link is no longer valid\"\n logo={logo ?? <DefaultLogo brandName={brandName} />}\n >\n <div className=\"space-y-4\">\n <Alert variant=\"destructive\">\n <WarningCircle />\n <AlertDescription>{invitation.message}</AlertDescription>\n </Alert>\n <p className=\"text-muted-foreground text-center text-sm\">\n The invitation may have expired or already been used. Please contact\n your administrator for a new invitation.\n </p>\n <Button\n variant=\"outline\"\n className=\"w-full\"\n onClick={handleGoToLogin}\n >\n Go to Login\n </Button>\n </div>\n </AuthLayout>\n );\n }\n\n // Valid token - show registration form\n return (\n <AuthLayout\n title={title}\n description={description}\n logo={logo ?? <DefaultLogo brandName={brandName} />}\n >\n <AcceptInviteForm\n onSubmit={handleSubmit}\n email={invitation.email}\n error={error}\n minPasswordLength={minPasswordLength}\n />\n </AuthLayout>\n );\n}\n\nfunction DefaultLogo({ brandName }: { brandName: string }) {\n return (\n <div className=\"text-center\">\n <h1 className=\"text-xl font-bold\">{brandName}</h1>\n </div>\n );\n}\n\nexport default AcceptInvitePage;\n","import { Combobox as ComboboxPrimitive } from \"@base-ui/react\";\nimport { CaretDownIcon, CheckIcon, XIcon } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"./button\";\nimport {\n\tInputGroup,\n\tInputGroupAddon,\n\tInputGroupButton,\n\tInputGroupInput,\n} from \"./input-group\";\n\nconst Combobox = ComboboxPrimitive.Root;\n\nfunction ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) {\n\treturn <ComboboxPrimitive.Value data-slot=\"combobox-value\" {...props} />;\n}\n\nfunction ComboboxTrigger({\n\tclassName,\n\tchildren,\n\t...props\n}: ComboboxPrimitive.Trigger.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.Trigger\n\t\t\tdata-slot=\"combobox-trigger\"\n\t\t\tclassName={cn(\"[&_svg:not([class*='size-'])]:size-3.5\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t<CaretDownIcon className=\"text-muted-foreground size-3.5 pointer-events-none\" />\n\t\t</ComboboxPrimitive.Trigger>\n\t);\n}\n\nfunction ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.Clear\n\t\t\tdata-slot=\"combobox-clear\"\n\t\t\trender={<InputGroupButton variant=\"ghost\" size=\"icon-xs\" />}\n\t\t\tclassName={className}\n\t\t\t{...props}\n\t\t>\n\t\t\t<XIcon className=\"pointer-events-none\" />\n\t\t</ComboboxPrimitive.Clear>\n\t);\n}\n\nfunction ComboboxInput({\n\tclassName,\n\tchildren,\n\tdisabled = false,\n\tshowTrigger = true,\n\tshowClear = false,\n\t...props\n}: ComboboxPrimitive.Input.Props & {\n\tshowTrigger?: boolean;\n\tshowClear?: boolean;\n}) {\n\treturn (\n\t\t<InputGroup className={cn(\"w-auto\", className)}>\n\t\t\t<ComboboxPrimitive.Input\n\t\t\t\trender={<InputGroupInput disabled={disabled} />}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t\t<InputGroupAddon align=\"inline-end\">\n\t\t\t\t{showTrigger && (\n\t\t\t\t\t<InputGroupButton\n\t\t\t\t\t\tsize=\"icon-xs\"\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\trender={<ComboboxTrigger />}\n\t\t\t\t\t\tdata-slot=\"input-group-button\"\n\t\t\t\t\t\tclassName=\"group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{showClear && <ComboboxClear disabled={disabled} />}\n\t\t\t</InputGroupAddon>\n\t\t\t{children}\n\t\t</InputGroup>\n\t);\n}\n\nfunction ComboboxContent({\n\tclassName,\n\tside = \"bottom\",\n\tsideOffset = 6,\n\talign = \"start\",\n\talignOffset = 0,\n\tanchor,\n\t...props\n}: ComboboxPrimitive.Popup.Props &\n\tPick<\n\t\tComboboxPrimitive.Positioner.Props,\n\t\t\"side\" | \"align\" | \"sideOffset\" | \"alignOffset\" | \"anchor\"\n\t>) {\n\treturn (\n\t\t<ComboboxPrimitive.Portal>\n\t\t\t<ComboboxPrimitive.Positioner\n\t\t\t\tside={side}\n\t\t\t\tsideOffset={sideOffset}\n\t\t\t\talign={align}\n\t\t\t\talignOffset={alignOffset}\n\t\t\t\tanchor={anchor}\n\t\t\t\tclassName=\"isolate z-50\"\n\t\t\t>\n\t\t\t\t<ComboboxPrimitive.Popup\n\t\t\t\t\tdata-slot=\"combobox-content\"\n\t\t\t\t\tdata-chips={!!anchor}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 *:data-[slot=input-group]:bg-input/20 dark:bg-popover max-h-72 min-w-32 overflow-hidden shadow-md ring-1 duration-100 *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-7 *:data-[slot=input-group]:border-none *:data-[slot=input-group]:shadow-none group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) data-[chips=true]:min-w-(--anchor-width)\",\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\n\t\t\t\t\t{...props}\n\t\t\t\t/>\n\t\t\t</ComboboxPrimitive.Positioner>\n\t\t</ComboboxPrimitive.Portal>\n\t);\n}\n\nfunction ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.List\n\t\t\tdata-slot=\"combobox-list\"\n\t\t\tclassName={cn(\n\t\t\t\t\"no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto p-1 data-empty:p-0 overflow-y-auto overscroll-contain\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction ComboboxItem({\n\tclassName,\n\tchildren,\n\t...props\n}: ComboboxPrimitive.Item.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.Item\n\t\t\tdata-slot=\"combobox-item\"\n\t\t\tclassName={cn(\n\t\t\t\t\"data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground min-h-7 gap-2 px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 relative flex w-full cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t<ComboboxPrimitive.ItemIndicator\n\t\t\t\trender={\n\t\t\t\t\t<span className=\"pointer-events-none absolute right-2 flex items-center justify-center\" />\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t<CheckIcon className=\"pointer-events-none\" />\n\t\t\t</ComboboxPrimitive.ItemIndicator>\n\t\t</ComboboxPrimitive.Item>\n\t);\n}\n\nfunction ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.Group\n\t\t\tdata-slot=\"combobox-group\"\n\t\t\tclassName={className}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction ComboboxLabel({\n\tclassName,\n\t...props\n}: ComboboxPrimitive.GroupLabel.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.GroupLabel\n\t\t\tdata-slot=\"combobox-label\"\n\t\t\tclassName={cn(\"text-muted-foreground px-2 py-1.5 text-xs\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction ComboboxCollection({ ...props }: ComboboxPrimitive.Collection.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.Collection data-slot=\"combobox-collection\" {...props} />\n\t);\n}\n\nfunction ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.Empty\n\t\t\tdata-slot=\"combobox-empty\"\n\t\t\tclassName={cn(\n\t\t\t\t\"text-muted-foreground hidden w-full justify-center py-2 text-center text-xs/relaxed group-data-empty/combobox-content:flex\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction ComboboxSeparator({\n\tclassName,\n\t...props\n}: ComboboxPrimitive.Separator.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.Separator\n\t\t\tdata-slot=\"combobox-separator\"\n\t\t\tclassName={cn(\"bg-border/50 -mx-1 my-1 h-px\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction ComboboxChips({\n\tclassName,\n\t...props\n}: React.ComponentPropsWithRef<typeof ComboboxPrimitive.Chips> &\n\tComboboxPrimitive.Chips.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.Chips\n\t\t\tdata-slot=\"combobox-chips\"\n\t\t\tclassName={cn(\n\t\t\t\t\"bg-input/20 border-input focus-within:border-ring focus-within:ring-ring/30 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive dark:has-aria-invalid:border-destructive/50 flex min-h-7 flex-wrap items-center gap-1 border bg-clip-padding px-2 py-0.5 text-xs/relaxed transition-colors focus-within:ring-[2px] has-aria-invalid:ring-[2px] has-data-[slot=combobox-chip]:px-1\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction ComboboxChip({\n\tclassName,\n\tchildren,\n\tshowRemove = true,\n\t...props\n}: ComboboxPrimitive.Chip.Props & {\n\tshowRemove?: boolean;\n}) {\n\treturn (\n\t\t<ComboboxPrimitive.Chip\n\t\t\tdata-slot=\"combobox-chip\"\n\t\t\tclassName={cn(\n\t\t\t\t\"bg-muted-foreground/10 text-foreground flex h-[calc(--spacing(4.75))] w-fit items-center justify-center gap-1 px-1.5 text-xs/relaxed font-medium whitespace-nowrap has-data-[slot=combobox-chip-remove]:pr-0 has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t{showRemove && (\n\t\t\t\t<ComboboxPrimitive.ChipRemove\n\t\t\t\t\trender={<Button variant=\"ghost\" size=\"icon-xs\" />}\n\t\t\t\t\tclassName=\"-ml-1 opacity-50 hover:opacity-100\"\n\t\t\t\t\tdata-slot=\"combobox-chip-remove\"\n\t\t\t\t>\n\t\t\t\t\t<XIcon className=\"pointer-events-none\" />\n\t\t\t\t</ComboboxPrimitive.ChipRemove>\n\t\t\t)}\n\t\t</ComboboxPrimitive.Chip>\n\t);\n}\n\nfunction ComboboxChipsInput({\n\tclassName,\n\t...props\n}: ComboboxPrimitive.Input.Props) {\n\treturn (\n\t\t<ComboboxPrimitive.Input\n\t\t\tdata-slot=\"combobox-chip-input\"\n\t\t\tclassName={cn(\"min-w-16 flex-1 outline-none\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\nfunction useComboboxAnchor() {\n\treturn React.useRef<HTMLDivElement | null>(null);\n}\n\nexport {\n\tCombobox,\n\tComboboxInput,\n\tComboboxContent,\n\tComboboxList,\n\tComboboxItem,\n\tComboboxGroup,\n\tComboboxLabel,\n\tComboboxCollection,\n\tComboboxEmpty,\n\tComboboxSeparator,\n\tComboboxChips,\n\tComboboxChip,\n\tComboboxChipsInput,\n\tComboboxTrigger,\n\tComboboxValue,\n\tuseComboboxAnchor,\n};\n","/**\n * AdminRouter Component\n *\n * Handles routing for the admin UI based on URL segments.\n * Uses the view registry to resolve list/edit views dynamically.\n *\n * URL Patterns:\n * - /admin -> Dashboard\n * - /admin/collections/:name -> Collection list\n * - /admin/collections/:name/create -> Collection create\n * - /admin/collections/:name/:id -> Collection edit\n * - /admin/globals/:name -> Global edit\n * - /admin/:customPage -> Custom pages\n */\n\nimport { SpinnerGap } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport type {\n\tComponentRegistry,\n\tDashboardConfig,\n\tDefaultViewsConfig,\n\tPageDefinition,\n} from \"../../builder\";\nimport { Card } from \"../../components/index.js\";\nimport { parsePrefillParams } from \"../../hooks/use-prefill-params\";\nimport { useAdminStore } from \"../../runtime/provider\";\nimport FormView from \"../collection/form-view\";\nimport TableView from \"../collection/table-view\";\nimport { DashboardGrid } from \"../dashboard/dashboard-grid\";\nimport GlobalFormView from \"../globals/global-form-view\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Collection config as used by AdminRouter.\n * Compatible with CollectionBuilderState from admin.getCollections().\n */\nexport type CollectionRouterConfig = Record<string, any>;\n\n/**\n * Global config as used by AdminRouter.\n * Compatible with GlobalBuilderState from admin.getGlobals().\n */\nexport type GlobalRouterConfig = Record<string, any>;\n\nexport interface AdminRouterProps {\n\t/**\n\t * Current route segments (parsed from URL after /admin)\n\t * Example: [\"collections\", \"posts\", \"123\"] for /admin/collections/posts/123\n\t */\n\tsegments: string[];\n\n\t/**\n\t * Navigate function (router-specific)\n\t */\n\tnavigate: (path: string) => void;\n\n\t/**\n\t * Base path for admin routes (default: \"/admin\")\n\t */\n\tbasePath?: string;\n\n\t/**\n\t * Current URL search params (for prefill support)\n\t * If not provided, reads from window.location.search\n\t */\n\tsearchParams?: URLSearchParams;\n\n\t/**\n\t * Collection configurations.\n\t * Accepts CollectionBuilderState objects from admin.getCollections()\n\t */\n\tcollections?: Record<string, CollectionRouterConfig>;\n\n\t/**\n\t * Global configurations.\n\t * Accepts GlobalBuilderState objects from admin.getGlobals()\n\t */\n\tglobals?: Record<string, GlobalRouterConfig>;\n\n\t/**\n\t * Custom pages\n\t */\n\tpages?: Record<string, PageDefinition<string>>;\n\n\t/**\n\t * Dashboard component (legacy - use dashboardConfig instead)\n\t */\n\tDashboardComponent?: React.ComponentType;\n\n\t/**\n\t * Dashboard configuration (widgets, title, etc.)\n\t */\n\tdashboardConfig?: DashboardConfig;\n\n\t/**\n\t * Default views configuration\n\t */\n\tdefaultViews?: DefaultViewsConfig;\n\n\t/**\n\t * Custom collection components (override default views)\n\t */\n\tcollectionComponents?: Record<\n\t\tstring,\n\t\t{\n\t\t\tList?: React.ComponentType;\n\t\t\tForm?: React.ComponentType;\n\t\t}\n\t>;\n\n\t/**\n\t * Custom global components\n\t */\n\tglobalComponents?: Record<\n\t\tstring,\n\t\t{\n\t\t\tForm?: React.ComponentType;\n\t\t}\n\t>;\n\n\t/**\n\t * Render custom form fields for collection\n\t */\n\trenderFormFields?: (collection: string) => React.ReactNode;\n\n\t/**\n\t * Component registry\n\t */\n\tregistry?: ComponentRegistry;\n\n\t/**\n\t * Not found component\n\t */\n\tNotFoundComponent?: React.ComponentType;\n}\n\n// ============================================================================\n// Internal Hook - Resolve props from store\n// ============================================================================\n\nfunction useRouterProps(props: {\n\tcollections?: Record<string, CollectionRouterConfig>;\n\tglobals?: Record<string, GlobalRouterConfig>;\n\tpages?: Record<string, PageDefinition<string>>;\n\tdashboardConfig?: DashboardConfig;\n\tDashboardComponent?: React.ComponentType;\n\tdefaultViews?: DefaultViewsConfig;\n}): {\n\tcollections: Record<string, CollectionRouterConfig>;\n\tglobals: Record<string, GlobalRouterConfig>;\n\tpages: Record<string, PageDefinition<string>>;\n\tdashboardConfig?: DashboardConfig;\n\tDashboardComponent?: React.ComponentType;\n\tdefaultViews?: DefaultViewsConfig;\n} {\n\t// Subscribe to admin from store reactively\n\tconst admin = useAdminStore((s) => s.admin);\n\n\tconst storeCollections = admin.getCollections();\n\tconst storeGlobals = admin.getGlobals();\n\tconst storePages = admin.getPages();\n\tconst storeDashboard = admin.getDashboard();\n\tconst storeDefaultViews = admin.getDefaultViews();\n\n\treturn {\n\t\tcollections: props.collections ?? storeCollections,\n\t\tglobals: props.globals ?? storeGlobals,\n\t\tpages: props.pages ?? storePages,\n\t\tdashboardConfig: props.dashboardConfig ?? storeDashboard,\n\t\tDashboardComponent:\n\t\t\tprops.DashboardComponent ?? (storeDashboard as any)?.component,\n\t\tdefaultViews: props.defaultViews ?? storeDefaultViews,\n\t};\n}\n\n// ============================================================================\n// Route Matching\n// ============================================================================\n\ntype RouteMatch =\n\t| { type: \"dashboard\" }\n\t| { type: \"collection-list\"; name: string }\n\t| { type: \"collection-create\"; name: string }\n\t| { type: \"collection-edit\"; name: string; id: string }\n\t| { type: \"global-edit\"; name: string }\n\t| { type: \"page\"; name: string; config: PageDefinition<string> }\n\t| { type: \"not-found\" };\n\nfunction matchRoute(\n\tsegments: string[],\n\t_collections: Record<string, unknown> = {},\n\tglobals: Record<string, unknown> = {},\n\tpages: Record<string, PageDefinition<string>> = {},\n): RouteMatch {\n\tif (segments.length === 0) {\n\t\treturn { type: \"dashboard\" };\n\t}\n\n\tconst [first, second, third] = segments;\n\n\t// Collections: /collections/:name/...\n\tif (first === \"collections\" && second) {\n\t\tif (!third) {\n\t\t\treturn { type: \"collection-list\", name: second };\n\t\t}\n\t\tif (third === \"create\") {\n\t\t\treturn { type: \"collection-create\", name: second };\n\t\t}\n\t\treturn { type: \"collection-edit\", name: second, id: third };\n\t}\n\n\t// Globals: /globals/:name\n\tif (first === \"globals\" && second && globals[second]) {\n\t\treturn { type: \"global-edit\", name: second };\n\t}\n\n\t// Custom pages\n\tfor (const [name, config] of Object.entries(pages)) {\n\t\tif (!config?.path) continue;\n\t\tconst pagePath = config.path.replace(/^\\//, \"\");\n\t\tif (first === pagePath || segments.join(\"/\") === pagePath) {\n\t\t\treturn { type: \"page\", name, config };\n\t\t}\n\t}\n\n\treturn { type: \"not-found\" };\n}\n\n// ============================================================================\n// Sub-components\n// ============================================================================\n\nfunction DefaultDashboard({\n\tconfig,\n}: {\n\tconfig?: DefaultViewsConfig[\"dashboard\"];\n}) {\n\tconst date = new Date().toLocaleDateString(\"en-US\", {\n\t\tweekday: \"long\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"long\",\n\t\tday: \"numeric\",\n\t});\n\n\treturn (\n\t\t<div className=\"container \">\n\t\t\t<div className=\"mb-8 flex items-end justify-between\">\n\t\t\t\t<div>\n\t\t\t\t\t<h1 className=\"text-3xl font-bold tracking-tight\">\n\t\t\t\t\t\t{config?.header?.title || \"Dashboard\"}\n\t\t\t\t\t</h1>\n\t\t\t\t\t{config?.header?.showDate !== false && (\n\t\t\t\t\t\t<p className=\"text-muted-foreground mt-1 font-mono text-xs uppercase tracking-widest\">\n\t\t\t\t\t\t\t{date}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3\">\n\t\t\t\t<Card className=\"relative overflow-hidden p-6\">\n\t\t\t\t\t<div className=\"absolute -right-12 -top-12 h-32 w-32 rounded-full bg-primary/10 blur-3xl\" />\n\t\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t\t<div className=\"mb-4 flex items-center gap-3\">\n\t\t\t\t\t\t\t<div className=\"h-2 w-2 rounded-full bg-primary glow-primary-sm\" />\n\t\t\t\t\t\t\t<h3 className=\"font-mono text-xs font-bold uppercase tracking-widest text-primary\">\n\t\t\t\t\t\t\t\tSystem Status\n\t\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<h2 className=\"mb-2 text-xl font-bold\">\n\t\t\t\t\t\t\t{config?.welcomeCard?.title || \"Welcome back\"}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t\t<p className=\"text-sm leading-relaxed text-muted-foreground\">\n\t\t\t\t\t\t\t{config?.welcomeCard?.description ||\n\t\t\t\t\t\t\t\t\"Select a collection from the sidebar to manage your content.\"}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</Card>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction DefaultNotFound() {\n\treturn (\n\t\t<div className=\"container \">\n\t\t\t<h1 className=\"mb-4 text-2xl font-bold\">Page Not Found</h1>\n\t\t\t<p className=\"text-muted-foreground\">\n\t\t\t\tThe page you're looking for doesn't exist.\n\t\t\t</p>\n\t\t</div>\n\t);\n}\n\nfunction LazyPageRenderer({ config }: { config: PageDefinition<string> }) {\n\tconst [Component, setComponent] = React.useState<React.ComponentType | null>(\n\t\tnull,\n\t);\n\tconst [loading, setLoading] = React.useState(true);\n\tconst [error, setError] = React.useState<Error | null>(null);\n\n\tReact.useEffect(() => {\n\t\tlet mounted = true;\n\n\t\tasync function load() {\n\t\t\ttry {\n\t\t\t\tif (typeof config.component === \"function\") {\n\t\t\t\t\tconst result = (config.component as () => any)();\n\t\t\t\t\tif (result?.then) {\n\t\t\t\t\t\tconst mod = await result;\n\t\t\t\t\t\tif (mounted) {\n\t\t\t\t\t\t\tsetComponent(() => mod.default || mod);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (mounted) {\n\t\t\t\t\t\t\tsetComponent(() => config.component as React.ComponentType);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (config.component) {\n\t\t\t\t\tif (mounted) {\n\t\t\t\t\t\tsetComponent(() => config.component as React.ComponentType);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tif (mounted) {\n\t\t\t\t\tsetError(err instanceof Error ? err : new Error(\"Failed to load\"));\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tif (mounted) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tload();\n\t\treturn () => {\n\t\t\tmounted = false;\n\t\t};\n\t}, [config.component]);\n\n\tif (loading) {\n\t\treturn (\n\t\t\t<div className=\"flex h-64 items-center justify-center text-muted-foreground\">\n\t\t\t\t<SpinnerGap className=\"size-6 animate-spin\" />\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (error) {\n\t\treturn (\n\t\t\t<div className=\"container \">\n\t\t\t\t<h1 className=\"mb-4 text-2xl font-bold text-destructive\">Error</h1>\n\t\t\t\t<p className=\"text-muted-foreground\">{error.message}</p>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn Component ? <Component /> : <DefaultNotFound />;\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * AdminRouter Component\n *\n * Routes to the appropriate view based on URL segments.\n * Uses the view registry to resolve list/edit views dynamically.\n *\n * When used inside AdminProvider, collections/globals/pages are automatically\n * read from context if not provided as props.\n *\n * @example\n * ```tsx\n * // With AdminProvider (automatic)\n * <AdminProvider admin={admin} client={client}>\n * <AdminRouter segments={segments} navigate={navigate} />\n * </AdminProvider>\n *\n * // Without AdminProvider (manual)\n * <AdminRouter\n * segments={segments}\n * navigate={navigate}\n * collections={collections}\n * globals={globals}\n * />\n * ```\n */\nexport function AdminRouter({\n\tsegments,\n\tnavigate,\n\tbasePath = \"/admin\",\n\tsearchParams: searchParamsProp,\n\tcollections: collectionsProp,\n\tglobals: globalsProp,\n\tpages: pagesProp,\n\tDashboardComponent: DashboardComponentProp,\n\tdashboardConfig: dashboardConfigProp,\n\tdefaultViews: defaultViewsProp,\n\tcollectionComponents = {},\n\tglobalComponents = {},\n\trenderFormFields,\n\tregistry,\n\tNotFoundComponent,\n}: AdminRouterProps): React.ReactElement {\n\t// Get search params (from prop or window.location)\n\tconst searchParams = React.useMemo(() => {\n\t\tif (searchParamsProp) return searchParamsProp;\n\t\tif (typeof window !== \"undefined\") {\n\t\t\treturn new URLSearchParams(window.location.search);\n\t\t}\n\t\treturn new URLSearchParams();\n\t}, [searchParamsProp]);\n\n\t// Parse prefill params from URL\n\tconst prefillValues = React.useMemo(\n\t\t() => parsePrefillParams(searchParams),\n\t\t[searchParams],\n\t);\n\n\t// Resolve props from store or use provided values\n\tconst {\n\t\tcollections,\n\t\tglobals,\n\t\tpages,\n\t\tdashboardConfig,\n\t\tDashboardComponent,\n\t\tdefaultViews,\n\t} = useRouterProps({\n\t\tcollections: collectionsProp,\n\t\tglobals: globalsProp,\n\t\tpages: pagesProp,\n\t\tdashboardConfig: dashboardConfigProp,\n\t\tDashboardComponent: DashboardComponentProp,\n\t\tdefaultViews: defaultViewsProp,\n\t});\n\n\tconst route = matchRoute(segments, collections, globals, pages);\n\n\t// Dashboard\n\tif (route.type === \"dashboard\") {\n\t\t// Priority 1: defaultViews.dashboard.component\n\t\tif (defaultViews?.dashboard?.component) {\n\t\t\tconst Component = defaultViews.dashboard.component;\n\t\t\treturn <Component />;\n\t\t}\n\n\t\t// Priority 2: Legacy DashboardComponent prop\n\t\tif (DashboardComponent) {\n\t\t\treturn <DashboardComponent />;\n\t\t}\n\n\t\t// Priority 3: DashboardGrid (if items or widgets exist)\n\t\tif (dashboardConfig?.items?.length || dashboardConfig?.widgets?.length) {\n\t\t\treturn (\n\t\t\t\t<DashboardGrid\n\t\t\t\t\tconfig={dashboardConfig}\n\t\t\t\t\tbasePath={basePath}\n\t\t\t\t\tnavigate={navigate}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\t// Priority 4: Default Dashboard\n\t\treturn <DefaultDashboard config={defaultViews?.dashboard} />;\n\t}\n\n\t// Collection List - use TableView from registry\n\tif (route.type === \"collection-list\") {\n\t\tconst { name } = route;\n\t\tconst config = collections[name];\n\t\tconst custom = collectionComponents[name];\n\n\t\t// Priority 1: Custom component override\n\t\tif (custom?.List) {\n\t\t\treturn <custom.List />;\n\t\t}\n\n\t\t// Priority 2: TableView from registry (default list view)\n\t\t// Key forces remount when collection changes to reset all internal state\n\t\treturn (\n\t\t\t<TableView\n\t\t\t\tkey={name}\n\t\t\t\tcollection={name}\n\t\t\t\tconfig={config}\n\t\t\t\tnavigate={navigate}\n\t\t\t\tbasePath={basePath}\n\t\t\t\tshowSearch={defaultViews?.collectionList?.showSearch}\n\t\t\t\tshowFilters={defaultViews?.collectionList?.showFilters}\n\t\t\t\tshowToolbar={defaultViews?.collectionList?.showToolbar}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Collection Create/Edit - use FormView from registry\n\tif (route.type === \"collection-create\" || route.type === \"collection-edit\") {\n\t\tconst { name } = route;\n\t\tconst id = route.type === \"collection-edit\" ? route.id : undefined;\n\t\tconst config = collections[name];\n\t\tconst custom = collectionComponents[name];\n\t\tconst formDefaults = defaultViews?.collectionForm;\n\n\t\t// Priority 1: Custom component override\n\t\tif (custom?.Form) {\n\t\t\treturn <custom.Form />;\n\t\t}\n\n\t\t// Only apply prefill values when creating (not editing)\n\t\tconst defaultValues =\n\t\t\troute.type === \"collection-create\" &&\n\t\t\tObject.keys(prefillValues).length > 0\n\t\t\t\t? prefillValues\n\t\t\t\t: undefined;\n\n\t\t// Priority 2: FormView from registry (default edit view)\n\t\t// Key forces remount when collection/id changes to reset all internal state\n\t\treturn (\n\t\t\t<FormView\n\t\t\t\tkey={`${name}-${id ?? \"create\"}`}\n\t\t\t\tcollection={name}\n\t\t\t\tid={id}\n\t\t\t\tconfig={config}\n\t\t\t\tnavigate={navigate}\n\t\t\t\tbasePath={basePath}\n\t\t\t\tdefaultValues={defaultValues}\n\t\t\t\tregistry={registry}\n\t\t\t\tallCollectionsConfig={collections}\n\t\t\t\tshowMeta={formDefaults?.showMeta}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Global Edit\n\tif (route.type === \"global-edit\") {\n\t\tconst { name } = route;\n\t\tconst config = globals[name];\n\t\tconst custom = globalComponents[name];\n\n\t\tif (custom?.Form) {\n\t\t\treturn <custom.Form />;\n\t\t}\n\n\t\t// Key forces remount when global changes to reset all internal state\n\t\treturn (\n\t\t\t<GlobalFormView\n\t\t\t\tkey={name}\n\t\t\t\tglobal={name}\n\t\t\t\tconfig={config}\n\t\t\t\tnavigate={navigate}\n\t\t\t\tbasePath={basePath}\n\t\t\t\tregistry={registry}\n\t\t\t\tallGlobalsConfig={globals}\n\t\t\t/>\n\t\t);\n\t}\n\n\t// Custom Page\n\tif (route.type === \"page\") {\n\t\treturn <LazyPageRenderer config={route.config} />;\n\t}\n\n\t// Not Found\n\tconst NotFound = NotFoundComponent || DefaultNotFound;\n\treturn <NotFound />;\n}\n","/**\n * Block Scope Context\n *\n * Provides block context for field path resolution in preview mode.\n * Allows PreviewField components to auto-resolve full scoped paths\n * like \"content._values.{blockId}.title\" from simple field names.\n */\n\n\"use client\";\n\nimport * as React from \"react\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type BlockScopeContextValue = {\n\t/** Current block ID */\n\tblockId: string;\n\t/** Field path prefix (e.g., \"content._values.abc123\") */\n\tfieldPrefix: string;\n};\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst BlockScopeContext = React.createContext<BlockScopeContextValue | null>(\n\tnull,\n);\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport type BlockScopeProviderProps = {\n\t/** Block ID for this scope */\n\tblockId: string;\n\t/** Base path for blocks field (e.g., \"content._values\") */\n\tbasePath?: string;\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provides block scope context for field path resolution.\n *\n * Automatically wraps each block in BlockRenderer to enable\n * PreviewField components to resolve full scoped paths.\n *\n * @example\n * ```tsx\n * <BlockScopeProvider blockId=\"abc123\" basePath=\"content._values\">\n * <PreviewField field=\"title\">\n * {/* Auto-resolves to: content._values.abc123.title *\\/}\n * </PreviewField>\n * </BlockScopeProvider>\n * ```\n */\nexport function BlockScopeProvider({\n\tblockId,\n\tbasePath = \"content._values\",\n\tchildren,\n}: BlockScopeProviderProps) {\n\tconst parentScope = React.useContext(BlockScopeContext);\n\n\t// Build field prefix based on parent scope\n\tconst fieldPrefix = React.useMemo(() => {\n\t\tif (parentScope) {\n\t\t\t// Nested block: append to parent prefix\n\t\t\treturn `${parentScope.fieldPrefix}.${blockId}`;\n\t\t}\n\t\t// Top-level block: use basePath\n\t\treturn `${basePath}.${blockId}`;\n\t}, [parentScope, basePath, blockId]);\n\n\tconst value = React.useMemo<BlockScopeContextValue>(\n\t\t() => ({\n\t\t\tblockId,\n\t\t\tfieldPrefix,\n\t\t}),\n\t\t[blockId, fieldPrefix],\n\t);\n\n\treturn (\n\t\t<BlockScopeContext.Provider value={value}>\n\t\t\t{children}\n\t\t</BlockScopeContext.Provider>\n\t);\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Get current block scope context.\n *\n * Returns null if not inside a BlockScopeProvider.\n *\n * @example\n * ```tsx\n * const scope = useBlockScope();\n * if (scope) {\n * console.log(scope.blockId); // \"abc123\"\n * console.log(scope.fieldPrefix); // \"content._values.abc123\"\n * }\n * ```\n */\nexport function useBlockScope(): BlockScopeContextValue | null {\n\treturn React.useContext(BlockScopeContext);\n}\n\n/**\n * Resolve a field name to its full scoped path.\n *\n * If inside a BlockScopeProvider, prepends the field prefix.\n * Otherwise, returns the field name as-is.\n *\n * @example\n * ```tsx\n * // Inside BlockScopeProvider with blockId=\"abc123\"\n * const fullPath = useResolveFieldPath(\"title\");\n * // Returns: \"content._values.abc123.title\"\n *\n * // Outside BlockScopeProvider\n * const fullPath = useResolveFieldPath(\"title\");\n * // Returns: \"title\"\n * ```\n */\nexport function useResolveFieldPath(fieldName: string): string {\n\tconst scope = useBlockScope();\n\n\treturn React.useMemo(() => {\n\t\tif (!scope) {\n\t\t\treturn fieldName;\n\t\t}\n\t\treturn `${scope.fieldPrefix}.${fieldName}`;\n\t}, [scope, fieldName]);\n}\n","/**\n * BlockRenderer Component\n *\n * Renders a tree of blocks using registered block definitions.\n * Each block type has a renderer component that receives the block's values.\n *\n * @example\n * ```tsx\n * import { BlockRenderer } from \"@questpie/admin/client\";\n * import { blocks } from \"~/admin/blocks\";\n *\n * function PageContent({ page }) {\n * return (\n * <BlockRenderer\n * content={page.content}\n * blocks={blocks}\n * />\n * );\n * }\n * ```\n */\n\nimport type * as React from \"react\";\nimport type { BlockDefinition } from \"../builder/block/types\";\nimport type { BlockContent, BlockNode } from \"./types\";\nimport { BlockScopeProvider } from \"../preview/block-scope-context.js\";\n\n/**\n * Props for BlockRenderer component.\n */\nexport type BlockRendererProps = {\n\t/** Block content from API (tree + values) */\n\tcontent: BlockContent;\n\t/** Registered block definitions */\n\tblocks: Record<string, BlockDefinition>;\n\t/** Prefetched data by block ID (optional, for SSR) */\n\tdata?: Record<string, unknown>;\n\t/** Currently selected block ID (for editor mode) */\n\tselectedBlockId?: string | null;\n\t/** Block click handler (for editor mode) */\n\tonBlockClick?: (blockId: string) => void;\n\t/** Custom class name for the container */\n\tclassName?: string;\n};\n\n/**\n * Renders a tree of blocks.\n *\n * Iterates through the block tree and renders each block using its\n * registered renderer component. Layout blocks receive their rendered\n * children as the `children` prop.\n */\nexport function BlockRenderer({\n\tcontent,\n\tblocks,\n\tdata = {},\n\tselectedBlockId,\n\tonBlockClick,\n\tclassName,\n}: BlockRendererProps) {\n\t/**\n\t * Recursively render a block node.\n\t */\n\tfunction renderBlock(node: BlockNode): React.ReactNode {\n\t\tconst blockDef = blocks[node.type];\n\n\t\tif (!blockDef?.renderer) {\n\t\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[BlockRenderer] Block type \"${node.type}\" not found or has no renderer`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\tconst Component = blockDef.renderer;\n\t\tconst values = content._values[node.id] || {};\n\t\tconst blockData = data[node.id];\n\t\tconst isSelected = selectedBlockId === node.id;\n\n\t\t// Render children for layout blocks\n\t\tconst renderedChildren =\n\t\t\tnode.children.length > 0 ? node.children.map(renderBlock) : undefined;\n\n\t\tconst handleClick = onBlockClick\n\t\t\t? (e: React.MouseEvent) => {\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\tonBlockClick(node.id);\n\t\t\t\t}\n\t\t\t: undefined;\n\n\t\tconst blockElement = (\n\t\t\t<BlockScopeProvider blockId={node.id} basePath=\"content._values\">\n\t\t\t\t<Component\n\t\t\t\t\tid={node.id}\n\t\t\t\t\tvalues={values}\n\t\t\t\t\tdata={blockData}\n\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\tisPreview={false}\n\t\t\t\t>\n\t\t\t\t\t{renderedChildren}\n\t\t\t\t</Component>\n\t\t\t</BlockScopeProvider>\n\t\t);\n\n\t\t// Wrap in interactive container when in editor mode\n\t\tif (handleClick) {\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tkey={node.id}\n\t\t\t\t\tdata-block-id={node.id}\n\t\t\t\t\tdata-block-type={node.type}\n\t\t\t\t\tonClick={handleClick}\n\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\tif (e.key === \"Enter\" || e.key === \" \") {\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\tonBlockClick?.(node.id);\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\ttabIndex={0}\n\t\t\t\t\tclassName=\"cursor-pointer\"\n\t\t\t\t>\n\t\t\t\t\t{blockElement}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<div key={node.id} data-block-id={node.id} data-block-type={node.type}>\n\t\t\t\t{blockElement}\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!content?._tree?.length) {\n\t\treturn null;\n\t}\n\n\treturn <div className={className}>{content._tree.map(renderBlock)}</div>;\n}\n\nexport default BlockRenderer;\n","/**\n * Block Prefetch Utilities\n *\n * SSR data prefetching for blocks that need external data.\n * Allows blocks to declare prefetch functions that are executed\n * in route loaders on the server.\n *\n * @example\n * ```ts\n * // In route loader (TanStack Start, Next.js, Hono, etc.)\n * const blockData = await prefetchBlockData(page.content, blocks, {\n * locale: \"en\",\n * defaultLocale: \"en\",\n * cms: cmsClient,\n * });\n *\n * // Pass to BlockRenderer\n * <BlockRenderer content={page.content} blocks={blocks} data={blockData} />\n * ```\n */\n\nimport type { BlockDefinition } from \"../builder/block/types.js\";\nimport type { BlockContent, BlockNode } from \"./types.js\";\n\n/**\n * Context passed to block prefetch functions.\n * Provides access to CMS client, locale info, and request context.\n */\nexport type BlockPrefetchContext<TCms = unknown> = {\n\t/** CMS client for data fetching */\n\tcms: TCms;\n\t/** Current locale for the request */\n\tlocale: string;\n\t/** Default/fallback locale */\n\tdefaultLocale: string;\n\t/** Original request object (for headers, cookies, auth) */\n\trequest?: Request;\n};\n\n/**\n * Extended context passed to individual block prefetch functions.\n * Includes block-specific values in addition to the base context.\n */\nexport type BlockPrefetchParams<TCms = unknown> = BlockPrefetchContext<TCms> & {\n\t/** Block instance ID */\n\tid: string;\n\t/** Block field values */\n\tvalues: Record<string, unknown>;\n};\n\n/**\n * Result map from prefetchBlockData.\n * Keys are block IDs, values are the data returned by each block's prefetch.\n */\nexport type BlockPrefetchResult = Record<string, unknown>;\n\n/**\n * Internal type for tracking prefetch requirements.\n */\ntype PrefetchRequirement = {\n\tblockId: string;\n\tblockType: string;\n\tprefetch: (params: BlockPrefetchParams<unknown>) => Promise<unknown>;\n\tvalues: Record<string, unknown>;\n};\n\n/**\n * Recursively collect all blocks with prefetch functions.\n */\nfunction collectPrefetchRequirements(\n\tnodes: BlockNode[],\n\tblocks: Record<string, BlockDefinition>,\n\tvalues: Record<string, Record<string, unknown>>,\n\trequirements: PrefetchRequirement[],\n): void {\n\tfor (const node of nodes) {\n\t\tconst blockDef = blocks[node.type];\n\n\t\tif (blockDef?.prefetch) {\n\t\t\trequirements.push({\n\t\t\t\tblockId: node.id,\n\t\t\t\tblockType: node.type,\n\t\t\t\tprefetch: blockDef.prefetch as (\n\t\t\t\t\tparams: BlockPrefetchParams<unknown>,\n\t\t\t\t) => Promise<unknown>,\n\t\t\t\tvalues: values[node.id] || {},\n\t\t\t});\n\t\t}\n\n\t\t// Process children recursively\n\t\tif (node.children?.length) {\n\t\t\tcollectPrefetchRequirements(node.children, blocks, values, requirements);\n\t\t}\n\t}\n}\n\n/**\n * Prefetch data for all blocks that have prefetch functions.\n *\n * This function should be called in your route loader (server-side) to\n * fetch all data needed by blocks before rendering. It executes all\n * prefetch functions in parallel for optimal performance.\n *\n * @param content - Block content from the collection (contains _tree and _values)\n * @param blocks - Registered block definitions (with optional prefetch functions)\n * @param context - Prefetch context with CMS client, locale, and optional request\n *\n * @returns Promise resolving to a map of block ID -> prefetched data\n *\n * @example\n * ```ts\n * // TanStack Start loader\n * export const Route = createFileRoute(\"/$locale/pages/$slug\")({\n * loader: async ({ params, context }) => {\n * const page = await context.cms.pages.findOne({ where: { slug: params.slug } });\n *\n * const blockData = await prefetchBlockData(page.content, blocks, {\n * cms: context.cms,\n * locale: params.locale,\n * defaultLocale: \"en\",\n * });\n *\n * return { page, blockData };\n * },\n * });\n * ```\n *\n * @example\n * ```ts\n * // Next.js App Router\n * export default async function Page({ params }) {\n * const page = await cms.pages.findOne({ where: { slug: params.slug } });\n *\n * const blockData = await prefetchBlockData(page.content, blocks, {\n * cms,\n * locale: params.locale,\n * defaultLocale: \"en\",\n * });\n *\n * return <PageContent page={page} blockData={blockData} />;\n * }\n * ```\n */\nexport async function prefetchBlockData<TCms = unknown>(\n\tcontent: BlockContent | null | undefined,\n\tblocks: Record<string, BlockDefinition>,\n\tcontext: BlockPrefetchContext<TCms>,\n): Promise<BlockPrefetchResult> {\n\t// Handle empty or invalid content\n\tif (!content?._tree?.length) {\n\t\treturn {};\n\t}\n\n\t// Collect all blocks with prefetch functions\n\tconst requirements: PrefetchRequirement[] = [];\n\tcollectPrefetchRequirements(\n\t\tcontent._tree,\n\t\tblocks,\n\t\tcontent._values,\n\t\trequirements,\n\t);\n\n\t// No prefetch needed\n\tif (requirements.length === 0) {\n\t\treturn {};\n\t}\n\n\t// Execute all prefetch functions in parallel\n\tconst results = await Promise.allSettled(\n\t\trequirements.map(async ({ blockId, blockType, prefetch, values }) => {\n\t\t\ttry {\n\t\t\t\tconst data = await prefetch({\n\t\t\t\t\t...context,\n\t\t\t\t\tid: blockId,\n\t\t\t\t\tvalues,\n\t\t\t\t});\n\t\t\t\treturn { blockId, data };\n\t\t\t} catch (error) {\n\t\t\t\t// Re-throw with block context for better debugging\n\t\t\t\tthrow new BlockPrefetchError(blockId, blockType, error);\n\t\t\t}\n\t\t}),\n\t);\n\n\t// Build result map, logging errors but not failing the entire page\n\tconst prefetchResult: BlockPrefetchResult = {};\n\n\tfor (const result of results) {\n\t\tif (result.status === \"fulfilled\") {\n\t\t\tprefetchResult[result.value.blockId] = result.value.data;\n\t\t} else {\n\t\t\t// Log error but continue - block will render without data\n\t\t\tif (process.env.NODE_ENV !== \"production\") {\n\t\t\t\tconsole.error(\"[prefetchBlockData]\", result.reason);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn prefetchResult;\n}\n\n/**\n * Error thrown when a block's prefetch function fails.\n * Includes block context for easier debugging.\n */\nexport class BlockPrefetchError extends Error {\n\tconstructor(\n\t\tpublic readonly blockId: string,\n\t\tpublic readonly blockType: string,\n\t\tpublic readonly cause: unknown,\n\t) {\n\t\tconst message =\n\t\t\tcause instanceof Error ? cause.message : \"Unknown prefetch error\";\n\t\tsuper(`Block prefetch failed for \"${blockType}\" (${blockId}): ${message}`);\n\t\tthis.name = \"BlockPrefetchError\";\n\t}\n}\n\n/**\n * Type helper for creating typed prefetch functions.\n *\n * @example\n * ```ts\n * type PostsData = { posts: Post[] };\n *\n * const prefetchPosts: TypedBlockPrefetch<PostsData, CMSClient> = async ({\n * cms,\n * values,\n * locale,\n * }) => {\n * const posts = await cms.posts.find({ limit: values.count, locale });\n * return { posts };\n * };\n * ```\n */\nexport type TypedBlockPrefetch<TData, TCms = unknown> = (\n\tparams: BlockPrefetchParams<TCms>,\n) => Promise<TData>;\n","/**\n * FormWithPreview Component\n *\n * Wrapper that renders a form alongside a live preview panel.\n * Used by FormView when a collection has preview configured.\n */\n\n\"use client\";\n\nimport { ArrowsOutSimple, X } from \"@phosphor-icons/react\";\nimport * as React from \"react\";\nimport type { PreviewConfig } from \"../../builder/collection/types.js\";\nimport {\n\tFocusProvider,\n\ttype FocusState,\n\tparsePreviewFieldPath,\n\tscrollFieldIntoView,\n} from \"../../context/focus-context.js\";\nimport { useIsMobile } from \"../../hooks/use-media-query.js\";\nimport { cn } from \"../../lib/utils.js\";\nimport { Button } from \"../ui/button.js\";\nimport { PreviewPane } from \"./preview-pane.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type FormWithPreviewProps = {\n\t/** Form content to render */\n\tchildren: React.ReactNode;\n\t/** Preview configuration from collection */\n\tpreviewConfig: PreviewConfig;\n\t/** Current form values (for preview URL and data) */\n\tvalues: Record<string, unknown>;\n\t/** Current content locale */\n\tlocale: string;\n\t/** Callback when a field is clicked in preview */\n\tonFieldClick?: (fieldPath: string) => void;\n\t/** Callback when a block is clicked in preview */\n\tonBlockClick?: (blockId: string) => void;\n\t/** Callback when a relation field is clicked in preview */\n\tonRelationClick?: (fieldPath: string, targetCollection?: string) => void;\n\t/** Custom class name */\n\tclassName?: string;\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function FormWithPreview({\n\tchildren,\n\tpreviewConfig,\n\tvalues,\n\tlocale,\n\tonFieldClick,\n\tonBlockClick,\n\tonRelationClick,\n\tclassName,\n}: FormWithPreviewProps) {\n\tconst isMobile = useIsMobile();\n\tconst [isPreviewVisible, setIsPreviewVisible] = React.useState(!isMobile);\n\tconst [isPreviewFullscreen, setIsPreviewFullscreen] = React.useState(false);\n\n\t// Generate preview URL\n\tconst previewUrl = React.useMemo(() => {\n\t\ttry {\n\t\t\treturn previewConfig.url(values, locale);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}, [previewConfig, values, locale]);\n\n\t// Handle focus changes from preview\n\tconst handleFocusChange = React.useCallback(\n\t\t(state: FocusState) => {\n\t\t\tswitch (state.type) {\n\t\t\t\tcase \"field\":\n\t\t\t\t\tscrollFieldIntoView(state.fieldPath);\n\t\t\t\t\tonFieldClick?.(state.fieldPath);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"block\":\n\t\t\t\t\tonBlockClick?.(state.blockId);\n\t\t\t\t\tif (state.fieldPath) {\n\t\t\t\t\t\tconst fullPath = `content._values.${state.blockId}.${state.fieldPath}`;\n\t\t\t\t\t\tsetTimeout(() => scrollFieldIntoView(fullPath), 100);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"relation\":\n\t\t\t\t\tonRelationClick?.(state.fieldPath, state.targetCollection);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t\t[onFieldClick, onBlockClick, onRelationClick],\n\t);\n\n\t// Handle field click from preview iframe\n\tconst handlePreviewFieldClick = React.useCallback(\n\t\t(\n\t\t\tfieldPath: string,\n\t\t\tcontext?: {\n\t\t\t\tblockId?: string;\n\t\t\t\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t\t\t},\n\t\t) => {\n\t\t\tconst focusState = parsePreviewFieldPath(fieldPath, context);\n\t\t\thandleFocusChange(focusState);\n\t\t},\n\t\t[handleFocusChange],\n\t);\n\n\t// Handle block click from preview iframe\n\tconst handlePreviewBlockClick = React.useCallback(\n\t\t(blockId: string) => {\n\t\t\tonBlockClick?.(blockId);\n\t\t},\n\t\t[onBlockClick],\n\t);\n\n\t// Width calculation\n\tconst previewWidth = previewConfig.defaultWidth ?? 50;\n\n\t// Mobile: Show toggle button and fullscreen preview\n\tif (isMobile) {\n\t\treturn (\n\t\t\t<FocusProvider onFocusChange={handleFocusChange}>\n\t\t\t\t<div className={cn(\"relative\", className)} data-preview-form-scope>\n\t\t\t\t\t{/* Form content */}\n\t\t\t\t\t{children}\n\n\t\t\t\t\t{/* Preview toggle button (fixed) */}\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"default\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tclassName=\"fixed bottom-4 right-4 z-50 shadow-lg\"\n\t\t\t\t\t\tonClick={() => setIsPreviewVisible(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowsOutSimple className=\"mr-2 h-4 w-4\" />\n\t\t\t\t\t\tPreview\n\t\t\t\t\t</Button>\n\n\t\t\t\t\t{/* Fullscreen preview overlay */}\n\t\t\t\t\t{isPreviewVisible && previewUrl && (\n\t\t\t\t\t\t<div className=\"fixed inset-0 z-50 bg-background\">\n\t\t\t\t\t\t\t<div className=\"flex h-full flex-col\">\n\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-between border-b px-4 py-2\">\n\t\t\t\t\t\t\t\t\t<span className=\"font-medium\">Preview</span>\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => setIsPreviewVisible(false)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<X className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"flex-1\">\n\t\t\t\t\t\t\t\t\t<PreviewPane\n\t\t\t\t\t\t\t\t\t\turl={previewUrl}\n\t\t\t\t\t\t\t\t\t\tonFieldClick={handlePreviewFieldClick}\n\t\t\t\t\t\t\t\t\t\tonBlockClick={handlePreviewBlockClick}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</FocusProvider>\n\t\t);\n\t}\n\n\t// Desktop: Side-by-side split\n\treturn (\n\t\t<FocusProvider onFocusChange={handleFocusChange}>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex h-full\",\n\t\t\t\t\tpreviewConfig.position === \"bottom\" ? \"flex-col\" : \"flex-row\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{/* Form panel */}\n\t\t\t\t<div\n\t\t\t\t\tdata-preview-form-scope\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"overflow-auto\",\n\t\t\t\t\t\tpreviewConfig.position === \"bottom\"\n\t\t\t\t\t\t\t? \"flex-1\"\n\t\t\t\t\t\t\t: isPreviewVisible\n\t\t\t\t\t\t\t\t? `w-[${100 - previewWidth}%]`\n\t\t\t\t\t\t\t\t: \"w-full\",\n\t\t\t\t\t)}\n\t\t\t\t\tstyle={\n\t\t\t\t\t\tisPreviewVisible && previewConfig.position !== \"bottom\"\n\t\t\t\t\t\t\t? { width: `${100 - previewWidth}%` }\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Preview panel */}\n\t\t\t\t{isPreviewVisible && previewUrl && !isPreviewFullscreen && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{/* Divider */}\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"bg-border flex-shrink-0\",\n\t\t\t\t\t\t\t\tpreviewConfig.position === \"bottom\" ? \"h-px\" : \"w-px\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t{/* Preview */}\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"relative overflow-hidden bg-muted/30\",\n\t\t\t\t\t\t\t\tpreviewConfig.position === \"bottom\" ? \"h-[400px]\" : \"\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\tpreviewConfig.position !== \"bottom\"\n\t\t\t\t\t\t\t\t\t? { width: `${previewWidth}%` }\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{/* Preview header */}\n\t\t\t\t\t\t\t<div className=\"absolute top-0 right-0 left-0 z-10 flex items-center justify-between border-b bg-background/95 px-3 py-1.5 backdrop-blur\">\n\t\t\t\t\t\t\t\t<span className=\"text-xs font-medium text-muted-foreground\">\n\t\t\t\t\t\t\t\t\tLive Preview\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<div className=\"flex gap-1\">\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => setIsPreviewFullscreen(true)}\n\t\t\t\t\t\t\t\t\t\ttitle=\"Fullscreen\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ArrowsOutSimple className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-6 w-6\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => setIsPreviewVisible(false)}\n\t\t\t\t\t\t\t\t\t\ttitle=\"Close preview\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<X className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{/* Preview content */}\n\t\t\t\t\t\t\t<div className=\"h-full pt-8\">\n\t\t\t\t\t\t\t\t<PreviewPane\n\t\t\t\t\t\t\t\t\turl={previewUrl}\n\t\t\t\t\t\t\t\t\tonFieldClick={handlePreviewFieldClick}\n\t\t\t\t\t\t\t\t\tonBlockClick={handlePreviewBlockClick}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\n\t\t\t\t{/* Preview toggle when hidden */}\n\t\t\t\t{!isPreviewVisible && (\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tclassName=\"absolute top-2 right-2\"\n\t\t\t\t\t\tonClick={() => setIsPreviewVisible(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\tShow Preview\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\n\t\t\t\t{/* Fullscreen preview overlay */}\n\t\t\t\t{isPreviewFullscreen && previewUrl && (\n\t\t\t\t\t<div className=\"fixed inset-0 z-50 bg-background\">\n\t\t\t\t\t\t<div className=\"flex h-full flex-col\">\n\t\t\t\t\t\t\t<div className=\"flex items-center justify-between border-b px-4 py-2\">\n\t\t\t\t\t\t\t\t<span className=\"font-medium\">Preview</span>\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\tonClick={() => setIsPreviewFullscreen(false)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"flex-1\">\n\t\t\t\t\t\t\t\t<PreviewPane\n\t\t\t\t\t\t\t\t\turl={previewUrl}\n\t\t\t\t\t\t\t\t\tonFieldClick={handlePreviewFieldClick}\n\t\t\t\t\t\t\t\t\tonBlockClick={handlePreviewBlockClick}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</FocusProvider>\n\t);\n}\n\n// ============================================================================\n// Preview Toggle for Form Header\n// ============================================================================\n\nexport type PreviewToggleProps = {\n\tisVisible: boolean;\n\tonToggle: () => void;\n\tclassName?: string;\n};\n\nexport function PreviewToggle({\n\tisVisible,\n\tonToggle,\n\tclassName,\n}: PreviewToggleProps) {\n\treturn (\n\t\t<Button\n\t\t\tvariant={isVisible ? \"default\" : \"outline\"}\n\t\t\tsize=\"sm\"\n\t\t\tonClick={onToggle}\n\t\t\tclassName={className}\n\t\t>\n\t\t\t<ArrowsOutSimple className=\"mr-2 h-4 w-4\" />\n\t\t\t{isVisible ? \"Hide Preview\" : \"Show Preview\"}\n\t\t</Button>\n\t);\n}\n","/**\n * PreviewField Component\n *\n * Wrapper component that makes fields clickable in preview mode.\n * When clicked, signals to admin to focus that field in the form.\n */\n\n\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../lib/utils.js\";\nimport { useBlockScope, useResolveFieldPath } from \"./block-scope-context.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type PreviewFieldProps = {\n\t/** Field name (for click-to-focus) - will be resolved with block scope if available */\n\tfield: string;\n\t/** Field type for routing (regular, block, or relation) */\n\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t/** Content to render */\n\tchildren: React.ReactNode;\n\t/** HTML element type */\n\tas?: React.ElementType;\n\t/** Additional class names */\n\tclassName?: string;\n\t/** Click handler (uses context by default) */\n\tonClick?: (\n\t\tfieldPath: string,\n\t\tcontext?: {\n\t\t\tblockId?: string;\n\t\t\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t\t},\n\t) => void;\n};\n\n// ============================================================================\n// Context\n// ============================================================================\n\ntype PreviewContextValue = {\n\tisPreviewMode: boolean;\n\thandleFieldClick: (\n\t\tfieldPath: string,\n\t\tcontext?: {\n\t\t\tblockId?: string;\n\t\t\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t\t},\n\t) => void;\n\tfocusedField: string | null;\n};\n\nconst PreviewContext = React.createContext<PreviewContextValue | null>(null);\n\n/**\n * Provider for preview mode context.\n * Use this at the root of your preview page.\n */\nexport function PreviewProvider({\n\tisPreviewMode,\n\tfocusedField,\n\tonFieldClick,\n\tchildren,\n}: {\n\tisPreviewMode: boolean;\n\tfocusedField: string | null;\n\tonFieldClick: (\n\t\tfieldPath: string,\n\t\tcontext?: {\n\t\t\tblockId?: string;\n\t\t\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t\t},\n\t) => void;\n\tchildren: React.ReactNode;\n}) {\n\tconst value = React.useMemo(\n\t\t() => ({\n\t\t\tisPreviewMode,\n\t\t\tfocusedField,\n\t\t\thandleFieldClick: onFieldClick,\n\t\t}),\n\t\t[isPreviewMode, focusedField, onFieldClick],\n\t);\n\n\treturn (\n\t\t<PreviewContext.Provider value={value}>{children}</PreviewContext.Provider>\n\t);\n}\n\n/**\n * Hook to access preview context.\n */\nexport function usePreviewContext(): PreviewContextValue | null {\n\treturn React.useContext(PreviewContext);\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Wrapper that makes a field clickable in preview mode.\n *\n * When clicked in preview, signals to admin to focus that field in the form.\n * Automatically resolves field paths using block scope context if available.\n *\n * @example\n * ```tsx\n * // Regular field\n * <PreviewField field=\"title\" as=\"h1\" className=\"text-4xl\">\n * {data.title}\n * </PreviewField>\n *\n * // Relation field\n * <PreviewField field=\"author\" fieldType=\"relation\">\n * {data.author.name}\n * </PreviewField>\n *\n * // Inside a block (auto-resolves to content._values.{blockId}.title)\n * <PreviewField field=\"title\">\n * {values.title}\n * </PreviewField>\n * ```\n */\nexport function PreviewField({\n\tfield,\n\tfieldType = \"regular\",\n\tchildren,\n\tas: Component = \"div\",\n\tclassName,\n\tonClick,\n}: PreviewFieldProps) {\n\tconst context = usePreviewContext();\n\tconst blockScope = useBlockScope();\n\tconst fullPath = useResolveFieldPath(field);\n\n\t// If no context or not in preview mode, just render normally\n\tif (!context?.isPreviewMode) {\n\t\treturn <Component className={className}>{children}</Component>;\n\t}\n\n\tconst { handleFieldClick, focusedField } = context;\n\tconst isFocused = focusedField === fullPath;\n\n\tconst handleClick = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tif (onClick) {\n\t\t\tonClick(fullPath, {\n\t\t\t\tblockId: blockScope?.blockId,\n\t\t\t\tfieldType,\n\t\t\t});\n\t\t} else {\n\t\t\thandleFieldClick(fullPath, {\n\t\t\t\tblockId: blockScope?.blockId,\n\t\t\t\tfieldType,\n\t\t\t});\n\t\t}\n\t};\n\n\treturn (\n\t\t<Component\n\t\t\tdata-preview-field={fullPath}\n\t\t\tdata-block-id={blockScope?.blockId}\n\t\t\tdata-field-type={fieldType}\n\t\t\tonClick={handleClick}\n\t\t\tclassName={cn(\n\t\t\t\tclassName,\n\t\t\t\t\"group relative cursor-pointer transition-all duration-150\",\n\t\t\t\t\"hover:outline hover:outline-2 hover:outline-dashed hover:outline-primary/60 hover:outline-offset-2 hover:rounded-sm\",\n\t\t\t\tisFocused &&\n\t\t\t\t\t\"outline outline-2 outline-primary outline-offset-2 rounded-sm\",\n\t\t\t)}\n\t\t>\n\t\t\t{children}\n\t\t</Component>\n\t);\n}\n\n/**\n * Standalone PreviewField that works without context.\n * Useful when you can't use PreviewProvider.\n */\nexport function StandalonePreviewField({\n\tfield,\n\tfieldType = \"regular\",\n\tchildren,\n\tas: Component = \"div\",\n\tclassName,\n\tisPreviewMode,\n\tisFocused,\n\tonFieldClick,\n}: PreviewFieldProps & {\n\tisPreviewMode: boolean;\n\tisFocused?: boolean;\n\tonFieldClick: (\n\t\tfieldPath: string,\n\t\tcontext?: {\n\t\t\tblockId?: string;\n\t\t\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t\t},\n\t) => void;\n}) {\n\tconst blockScope = useBlockScope();\n\tconst fullPath = useResolveFieldPath(field);\n\n\tif (!isPreviewMode) {\n\t\treturn <Component className={className}>{children}</Component>;\n\t}\n\n\tconst handleClick = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tonFieldClick(fullPath, {\n\t\t\tblockId: blockScope?.blockId,\n\t\t\tfieldType,\n\t\t});\n\t};\n\n\treturn (\n\t\t<Component\n\t\t\tdata-preview-field={fullPath}\n\t\t\tdata-block-id={blockScope?.blockId}\n\t\t\tdata-field-type={fieldType}\n\t\t\tonClick={handleClick}\n\t\t\tclassName={cn(\n\t\t\t\tclassName,\n\t\t\t\t\"group relative cursor-pointer transition-all duration-150\",\n\t\t\t\t\"hover:outline hover:outline-2 hover:outline-dashed hover:outline-primary/60 hover:outline-offset-2 hover:rounded-sm\",\n\t\t\t\tisFocused &&\n\t\t\t\t\t\"outline outline-2 outline-primary outline-offset-2 rounded-sm\",\n\t\t\t)}\n\t\t>\n\t\t\t{children}\n\t\t</Component>\n\t);\n}\n","/**\n * Preview Banner Component\n *\n * Displayed at the top of preview pages when in draft mode.\n * Allows users to exit preview mode (clear __draft_mode cookie).\n */\n\n\"use client\";\n\nimport * as React from \"react\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type PreviewBannerProps = {\n\t/** Whether we're in preview mode */\n\tisPreviewMode: boolean;\n\t/** Custom class name */\n\tclassName?: string;\n\t/** Custom exit preview URL (default: /api/preview?disable=true) */\n\texitPreviewUrl?: string;\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Preview mode banner with exit button.\n *\n * Shows a sticky banner at the top of the page when in draft/preview mode.\n * Clicking \"Exit Preview\" clears the draft mode cookie.\n *\n * @example\n * ```tsx\n * export default function RootLayout({ children }) {\n * const { isPreviewMode } = useCollectionPreview({ ... });\n *\n * return (\n * <>\n * <PreviewBanner isPreviewMode={isPreviewMode} />\n * {children}\n * </>\n * );\n * }\n * ```\n */\nexport function PreviewBanner({\n\tisPreviewMode,\n\tclassName,\n\texitPreviewUrl = \"/api/preview?disable=true\",\n}: PreviewBannerProps) {\n\tif (!isPreviewMode) return null;\n\n\treturn (\n\t\t<div\n\t\t\tclassName={className}\n\t\t\tstyle={{\n\t\t\t\tposition: \"sticky\",\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0,\n\t\t\t\tright: 0,\n\t\t\t\tzIndex: 9999,\n\t\t\t\tbackgroundColor: \"hsl(var(--primary))\",\n\t\t\t\tcolor: \"hsl(var(--primary-foreground))\",\n\t\t\t\tpadding: \"0.5rem 1rem\",\n\t\t\t\tdisplay: \"flex\",\n\t\t\t\talignItems: \"center\",\n\t\t\t\tjustifyContent: \"space-between\",\n\t\t\t\tgap: \"1rem\",\n\t\t\t\tfontSize: \"0.875rem\",\n\t\t\t\tfontWeight: 500,\n\t\t\t\tboxShadow: \"0 2px 8px rgba(0, 0, 0, 0.1)\",\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\tgap: \"0.5rem\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\twidth=\"16\"\n\t\t\t\t\theight=\"16\"\n\t\t\t\t\tviewBox=\"0 0 256 256\"\n\t\t\t\t\tfill=\"currentColor\"\n\t\t\t\t>\n\t\t\t\t\t<title>Eye icon</title>\n\t\t\t\t\t<path d=\"M247.31,124.76c-.35-.79-8.82-19.58-27.65-38.41C194.57,61.26,162.88,48,128,48S61.43,61.26,36.34,86.35C17.51,105.18,9,124,8.69,124.76a8,8,0,0,0,0,6.5c.35.79,8.82,19.57,27.65,38.4C61.43,194.74,93.12,208,128,208s66.57-13.26,91.66-38.34c18.83-18.83,27.3-37.61,27.65-38.4A8,8,0,0,0,247.31,124.76ZM128,192c-30.78,0-57.67-11.19-79.93-33.25A133.47,133.47,0,0,1,25,128,133.33,133.33,0,0,1,48.07,97.25C70.33,75.19,97.22,64,128,64s57.67,11.19,79.93,33.25A133.46,133.46,0,0,1,231.05,128C223.84,141.46,192.43,192,128,192Zm0-112a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Z\" />\n\t\t\t\t</svg>\n\t\t\t\t<span>Preview Mode</span>\n\t\t\t</div>\n\n\t\t\t<a\n\t\t\t\thref={exitPreviewUrl}\n\t\t\t\tstyle={{\n\t\t\t\t\tpadding: \"0.25rem 0.75rem\",\n\t\t\t\t\tbackgroundColor: \"rgba(255, 255, 255, 0.2)\",\n\t\t\t\t\tborder: \"1px solid rgba(255, 255, 255, 0.3)\",\n\t\t\t\t\tborderRadius: \"4px\",\n\t\t\t\t\tcolor: \"inherit\",\n\t\t\t\t\ttextDecoration: \"none\",\n\t\t\t\t\tfontWeight: 600,\n\t\t\t\t\tfontSize: \"0.875rem\",\n\t\t\t\t\tcursor: \"pointer\",\n\t\t\t\t\ttransition: \"background-color 0.2s\",\n\t\t\t\t}}\n\t\t\t\tonMouseEnter={(e) => {\n\t\t\t\t\te.currentTarget.style.backgroundColor = \"rgba(255, 255, 255, 0.3)\";\n\t\t\t\t}}\n\t\t\t\tonMouseLeave={(e) => {\n\t\t\t\t\te.currentTarget.style.backgroundColor = \"rgba(255, 255, 255, 0.2)\";\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\tExit Preview\n\t\t\t</a>\n\t\t</div>\n\t);\n}\n","/**\n * useCollectionPreview Hook\n *\n * Hook for frontend pages to receive live preview data from admin.\n * Handles postMessage communication with the admin iframe parent.\n */\n\n\"use client\";\n\nimport * as React from \"react\";\nimport type { AdminToPreviewMessage } from \"./types.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type UseCollectionPreviewOptions<TData> = {\n\t/** Server-loaded data (from loader/SSR) */\n\tinitialData: TData;\n\t/**\n\t * Callback to refresh data (e.g., router.invalidate()).\n\t * Required for preview functionality.\n\t */\n\tonRefresh: () => void | Promise<void>;\n};\n\nexport type UseCollectionPreviewResult<TData> = {\n\t/** Current data (from initialData, refreshed via onRefresh) */\n\tdata: TData;\n\t/** Whether we're in preview mode (inside admin iframe) */\n\tisPreviewMode: boolean;\n\t/** Currently selected block ID */\n\tselectedBlockId: string | null;\n\t/** Focused field path */\n\tfocusedField: string | null;\n\t/** Call when a field is clicked in preview */\n\thandleFieldClick: (\n\t\tfieldPath: string,\n\t\tcontext?: {\n\t\t\tblockId?: string;\n\t\t\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t\t},\n\t) => void;\n\t/** Call when a block is clicked in preview */\n\thandleBlockClick: (blockId: string) => void;\n};\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook for receiving live preview data from admin.\n *\n * Use this in your frontend page components to enable live preview.\n *\n * @example\n * ```tsx\n * function PageRoute() {\n * const loaderData = Route.useLoaderData();\n * const router = useRouter();\n *\n * const { data, isPreviewMode, selectedBlockId, handleBlockClick } =\n * useCollectionPreview({\n * initialData: loaderData.page,\n * onRefresh: () => router.invalidate(),\n * });\n *\n * return (\n * <article>\n * <PreviewField field=\"title\" as=\"h1\">{data.title}</PreviewField>\n * <BlockRenderer\n * content={data.content}\n * blocks={blocks}\n * selectedBlockId={selectedBlockId}\n * onBlockClick={handleBlockClick}\n * />\n * </article>\n * );\n * }\n * ```\n */\nexport function useCollectionPreview<TData extends Record<string, unknown>>({\n\tinitialData,\n\tonRefresh,\n}: UseCollectionPreviewOptions<TData>): UseCollectionPreviewResult<TData> {\n\tconst [selectedBlockId, setSelectedBlockId] = React.useState<string | null>(\n\t\tnull,\n\t);\n\tconst [focusedField, setFocusedField] = React.useState<string | null>(null);\n\n\t// Check if we're in an iframe (preview mode)\n\tconst isPreviewMode = React.useMemo(() => {\n\t\tif (typeof window === \"undefined\") return false;\n\t\ttry {\n\t\t\treturn window.self !== window.top;\n\t\t} catch {\n\t\t\t// Cross-origin iframe - assume we're in preview mode\n\t\t\treturn true;\n\t\t}\n\t}, []);\n\n\t// Keep onRefresh in a ref to avoid stale closures while maintaining stable reference\n\tconst onRefreshRef = React.useRef(onRefresh);\n\tReact.useEffect(() => {\n\t\tonRefreshRef.current = onRefresh;\n\t}, [onRefresh]);\n\n\t// Set up postMessage listener\n\tReact.useEffect(() => {\n\t\tif (!isPreviewMode) return;\n\n\t\t// Signal that preview is ready\n\t\twindow.parent.postMessage({ type: \"PREVIEW_READY\" }, \"*\");\n\n\t\tconst handleMessage = async (\n\t\t\tevent: MessageEvent<AdminToPreviewMessage>,\n\t\t) => {\n\t\t\t// In production, validate origin here\n\t\t\tconst message = event.data;\n\n\t\t\tif (!message || typeof message !== \"object\" || !message.type) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tswitch (message.type) {\n\t\t\t\tcase \"PREVIEW_REFRESH\": {\n\t\t\t\t\tawait onRefreshRef.current();\n\t\t\t\t\twindow.parent.postMessage(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"REFRESH_COMPLETE\",\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"*\",\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"SELECT_BLOCK\":\n\t\t\t\t\tsetSelectedBlockId(message.blockId);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"FOCUS_FIELD\": {\n\t\t\t\t\tsetFocusedField(message.fieldPath);\n\t\t\t\t\t// Scroll field into view (with delay to ensure React render)\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tconst element = document.querySelector(\n\t\t\t\t\t\t\t`[data-preview-field=\"${message.fieldPath}\"]`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (element) {\n\t\t\t\t\t\t\telement.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 150);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener(\"message\", handleMessage);\n\t\treturn () => window.removeEventListener(\"message\", handleMessage);\n\t}, [isPreviewMode]);\n\n\t// Field click handler\n\tconst handleFieldClick = React.useCallback(\n\t\t(\n\t\t\tfieldPath: string,\n\t\t\tcontext?: {\n\t\t\t\tblockId?: string;\n\t\t\t\tfieldType?: \"regular\" | \"block\" | \"relation\";\n\t\t\t},\n\t\t) => {\n\t\t\tif (isPreviewMode) {\n\t\t\t\twindow.parent.postMessage(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"FIELD_CLICKED\",\n\t\t\t\t\t\tfieldPath,\n\t\t\t\t\t\tblockId: context?.blockId,\n\t\t\t\t\t\tfieldType: context?.fieldType,\n\t\t\t\t\t},\n\t\t\t\t\t\"*\",\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[isPreviewMode],\n\t);\n\n\t// Block click handler\n\tconst handleBlockClick = React.useCallback(\n\t\t(blockId: string) => {\n\t\t\tif (isPreviewMode) {\n\t\t\t\twindow.parent.postMessage({ type: \"BLOCK_CLICKED\", blockId }, \"*\");\n\t\t\t}\n\t\t},\n\t\t[isPreviewMode],\n\t);\n\n\treturn {\n\t\tdata: initialData,\n\t\tisPreviewMode,\n\t\tselectedBlockId,\n\t\tfocusedField,\n\t\thandleFieldClick,\n\t\thandleBlockClick,\n\t};\n}\n"],"mappings":"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,UAAU;KACV,WAAW,GACV,yFACA,sGACA;MACA;KACG;IACU;GACR;;;;;ACnRZ,SAAgB,UAAU,EACzB,MACA,OACA,aACA,aACA,UACA,UACA,WACA,QACA,SACA,WACA,SACA,SACA,oBACkB;AAGlB,QACC,oBAAC;EACM;EACN,SALsB,mBAAmB,QAAQ;EAMjD,SAAS,EAAE,gBAAO,iBAAiB;GAElC,MAAM,YACLC,QAAM,iBAAiB,OACpBA,QAAM,QACNA,QAAM,QACL,IAAI,KAAKA,QAAM,MAAM,GACrB;AAEL,UACC,oBAAC;IACM;IACC;IACM;IACH;IACA;IACC;IACH;IACR,OAAO,WAAW,OAAO;cAEzB,oBAAC;KACA,IAAI;KACJ,OAAO;KACP,UAAUA,QAAM;KACP;KACA;KACT,QAAQC;KACK;KACH;KACV,gBAAc,CAAC,CAAC,WAAW;KAChB;MACV;KACY;;GAGhB;;;;;ACxDJ,SAAgB,cAAc,EAC7B,MACA,OACA,aACA,aACA,UACA,UACA,WACA,QACA,SACA,WACA,SACA,SACA,kBACA,aACsB;AAGtB,QACC,oBAAC;EACM;EACN,SALsB,mBAAmB,QAAQ;EAMjD,SAAS,EAAE,gBAAO,iBAAiB;GAElC,MAAM,YACLC,QAAM,iBAAiB,OACpBA,QAAM,QACNA,QAAM,QACL,IAAI,KAAKA,QAAM,MAAM,GACrB;AAEL,UACC,oBAAC;IACM;IACC;IACM;IACH;IACA;IACC;IACH;IACR,OAAO,WAAW,OAAO;cAEzB,oBAAC;KACA,IAAI;KACJ,OAAO;KACP,UAAUA,QAAM;KACP;KACA;KACT,QAAQC;KACG;KACE;KACH;KACV,gBAAc,CAAC,CAAC,WAAW;KAChB;MACV;KACY;;GAGhB;;;;;;;;;;;;;;;;;;;;;AC5CJ,SAAgB,UAAU,EACzB,OACA,UACA,OAAO,QACP,aACA,UACA,UACA,WACA,cACA,WACA,IACA,gBAAgB,eACE;AAGlB,QACC,oBAAC;EACI;EACE;EACC;EACP,WAAW,MAAM,SAAS,EAAE,OAAO,MAAM;EACzC,aARkB,gBAAgB,CAQT,YAAY;EAC3B;EACA;EACC;EACG;EACd,gBA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CA,UACA,WACA,QACA,SACA,aACqB;AAGrB,QACC,oBAAC;EACM;EACN,SALsB,mBAAmB,QAAQ;EAMjD,SAAS,EAAE,gBAAO,iBACjB,oBAAC;GACM;GACC;GACM;GACH;GACA;GACC;GACH;GACR,OAAO,WAAW,OAAO;aAEzB,oBAAC;IACA,IAAI;IACJ,OAAO,CAAC,CAACC,QAAM;IACf,UAAUA,QAAM;IACN;IACV,gBAAc,CAAC,CAAC,WAAW;IAChB;KACV;IACY;GAEf;;;;;ACtCJ,SAAgB,UAAU,EACzB,MACA,OACA,aACA,aACA,UACA,UACA,WACA,QACA,SACA,WACA,OAAO,QACP,WACA,gBACkB;AAGlB,QACC,oBAAC;EACM;EACN,SALsB,mBAAmB,QAAQ;EAMjD,SAAS,EAAE,gBAAO,iBACjB,oBAAC;GACM;GACC;GACM;GACH;GACA;GACC;GACH;GACR,OAAO,WAAW,OAAO;aAEzB,oBAAC;IACA,IAAI;IACJ,OAAOC,QAAM,SAAS;IACtB,UAAUA,QAAM;IACV;IACO;IACH;IACC;IACG;IACd,gBAAc,CAAC,CAAC,WAAW;IAChB;KACV;IACY;GAEf;;;;;;;;;;;;;;;;;;;;ACjCJ,SAAgB,cAAc,EAC7B,OACA,UACA,OAAO,GACP,WACA,aACA,UACA,UACA,WACA,IACA,gBAAgB,eACM;AAGtB,QACC,oBAAC;EACI;EACG;EACP,WAAW,MAAM,SAAS,EAAE,OAAO,MAAM;EACnC;EACK;EACX,aATkB,gBAAgB,CAST,YAAY;EAC3B;EACA;EACV,gBAAc;EACH;GACV;;;;;ACvCJ,SAAgB,cAAc,EAC7B,MACA,OACA,aACA,aACA,UACA,UACA,WACA,QACA,SACA,WACA,MACA,WACA,cACsB;AAGtB,QACC,oBAAC;EACM;EACN,SALsB,mBAAmB,QAAQ;EAMjD,SAAS,EAAE,gBAAO,iBACjB,oBAAC;GACM;GACC;GACM;GACH;GACA;GACC;GACH;GACR,OAAO,WAAW,OAAO;aAEzB,oBAAC;IACA,IAAI;IACJ,OAAOC,QAAM,SAAS;IACtB,UAAUA,QAAM;IACH;IACH;IACJ;IACK;IACC;IACZ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"}
|