@momentumcms/admin 0.1.10 → 0.2.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.
Files changed (26) hide show
  1. package/fesm2022/{momentumcms-admin-array-field.component-BZva87Sh.mjs → momentumcms-admin-array-field.component-CT5NlIEv.mjs} +2 -2
  2. package/fesm2022/{momentumcms-admin-array-field.component-BZva87Sh.mjs.map → momentumcms-admin-array-field.component-CT5NlIEv.mjs.map} +1 -1
  3. package/fesm2022/{momentumcms-admin-blocks-field.component-CIxpyKAV.mjs → momentumcms-admin-blocks-field.component-Cz7HmuBK.mjs} +2 -2
  4. package/fesm2022/{momentumcms-admin-blocks-field.component-CIxpyKAV.mjs.map → momentumcms-admin-blocks-field.component-Cz7HmuBK.mjs.map} +1 -1
  5. package/fesm2022/{momentumcms-admin-collapsible-field.component-BpmaUKom.mjs → momentumcms-admin-collapsible-field.component-CtwrGQvg.mjs} +3 -9
  6. package/fesm2022/momentumcms-admin-collapsible-field.component-CtwrGQvg.mjs.map +1 -0
  7. package/fesm2022/{momentumcms-admin-global-edit.page-976NlNjw.mjs → momentumcms-admin-global-edit.page-BBUtWCSl.mjs} +2 -2
  8. package/fesm2022/{momentumcms-admin-global-edit.page-976NlNjw.mjs.map → momentumcms-admin-global-edit.page-BBUtWCSl.mjs.map} +1 -1
  9. package/fesm2022/{momentumcms-admin-group-field.component-Bgy_tQOG.mjs → momentumcms-admin-group-field.component-BZeG8Oqy.mjs} +2 -2
  10. package/fesm2022/momentumcms-admin-group-field.component-BZeG8Oqy.mjs.map +1 -0
  11. package/fesm2022/{momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs → momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs} +30 -20
  12. package/fesm2022/momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs.map +1 -0
  13. package/fesm2022/{momentumcms-admin-relationship-field.component-s46Lu33u.mjs → momentumcms-admin-relationship-field.component-BuxtRs2_.mjs} +2 -2
  14. package/fesm2022/{momentumcms-admin-relationship-field.component-s46Lu33u.mjs.map → momentumcms-admin-relationship-field.component-BuxtRs2_.mjs.map} +1 -1
  15. package/fesm2022/{momentumcms-admin-rich-text-field.component-Djv7tDS2.mjs → momentumcms-admin-rich-text-field.component-DKQ6pwp7.mjs} +2 -2
  16. package/fesm2022/{momentumcms-admin-rich-text-field.component-Djv7tDS2.mjs.map → momentumcms-admin-rich-text-field.component-DKQ6pwp7.mjs.map} +1 -1
  17. package/fesm2022/{momentumcms-admin-row-field.component-Dc5vqRQ8.mjs → momentumcms-admin-row-field.component-ks3FXd4B.mjs} +2 -2
  18. package/fesm2022/{momentumcms-admin-row-field.component-Dc5vqRQ8.mjs.map → momentumcms-admin-row-field.component-ks3FXd4B.mjs.map} +1 -1
  19. package/fesm2022/{momentumcms-admin-tabs-field.component-CdZoCrvw.mjs → momentumcms-admin-tabs-field.component-mZ4dpZoD.mjs} +73 -11
  20. package/fesm2022/momentumcms-admin-tabs-field.component-mZ4dpZoD.mjs.map +1 -0
  21. package/fesm2022/momentumcms-admin.mjs +1 -1
  22. package/package.json +1 -1
  23. package/fesm2022/momentumcms-admin-collapsible-field.component-BpmaUKom.mjs.map +0 -1
  24. package/fesm2022/momentumcms-admin-group-field.component-Bgy_tQOG.mjs.map +0 -1
  25. package/fesm2022/momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs.map +0 -1
  26. package/fesm2022/momentumcms-admin-tabs-field.component-CdZoCrvw.mjs.map +0 -1
@@ -5,7 +5,7 @@ import { NgIcon, provideIcons } from '@ng-icons/core';
5
5
  import { heroBars2, heroTrash, heroPlus } from '@ng-icons/heroicons/outline';
6
6
  import { Card, CardHeader, CardTitle, CardContent, CardFooter, Button } from '@momentumcms/ui';
7
7
  import { humanizeFieldName } from '@momentumcms/core';
8
- import { a as getFieldNodeState, i as isRecord, b as getSubNode, c as getFieldDefaultValue, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs';
8
+ import { a as getFieldNodeState, i as isRecord, b as getSubNode, c as getFieldDefaultValue, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs';
9
9
 
10
10
  /**
11
11
  * Array field renderer.
@@ -313,4 +313,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
313
313
  }], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], formNode: [{ type: i0.Input, args: [{ isSignal: true, alias: "formNode", required: false }] }], formTree: [{ type: i0.Input, args: [{ isSignal: true, alias: "formTree", required: false }] }], formModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "formModel", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "path", required: true }] }] } });
314
314
 
315
315
  export { ArrayFieldRenderer };
316
- //# sourceMappingURL=momentumcms-admin-array-field.component-BZva87Sh.mjs.map
316
+ //# sourceMappingURL=momentumcms-admin-array-field.component-CT5NlIEv.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"momentumcms-admin-array-field.component-BZva87Sh.mjs","sources":["../../../../libs/admin/src/lib/widgets/entity-form/field-renderers/array-field.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport {\n\tCdkDropList,\n\tCdkDrag,\n\tCdkDragHandle,\n\ttype CdkDragDrop,\n\tmoveItemInArray,\n} from '@angular/cdk/drag-drop';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroPlus, heroTrash, heroBars2 } from '@ng-icons/heroicons/outline';\nimport { Card, CardHeader, CardTitle, CardContent, CardFooter, Button } from '@momentumcms/ui';\nimport { humanizeFieldName } from '@momentumcms/core';\nimport type { Field } from '@momentumcms/core';\nimport type { EntityFormMode } from '../entity-form.types';\nimport {\n\tgetFieldNodeState,\n\tgetSubNode,\n\tisRecord,\n\tgetFieldDefaultValue,\n} from '../entity-form.types';\nimport { FieldRenderer } from './field-renderer.component';\n\n/**\n * Array field renderer.\n *\n * Renders an array of rows, each row displayed as a card with sub-fields.\n * Supports add/remove rows and drag-drop reordering via CDK DragDrop.\n * Respects minRows/maxRows constraints.\n *\n * Data container pattern: passes row sub-field FieldTree nodes via\n * getSubNode(getSubNode(formNode, rowIndex), subFieldName).\n * Array mutations use nodeState.value.set(newArray).\n */\n@Component({\n\tselector: 'mcms-array-field-renderer',\n\timports: [\n\t\tCard,\n\t\tCardHeader,\n\t\tCardTitle,\n\t\tCardContent,\n\t\tCardFooter,\n\t\tButton,\n\t\tNgIcon,\n\t\tCdkDropList,\n\t\tCdkDrag,\n\t\tCdkDragHandle,\n\t\tFieldRenderer,\n\t],\n\tproviders: [provideIcons({ heroPlus, heroTrash, heroBars2 })],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplate: `\n\t\t<mcms-card>\n\t\t\t<mcms-card-header>\n\t\t\t\t<div class=\"flex items-center justify-between\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<mcms-card-title>{{ label() }}</mcms-card-title>\n\t\t\t\t\t\t@if (description()) {\n\t\t\t\t\t\t\t<p class=\"text-sm text-muted-foreground mt-1\">{{ description() }}</p>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t\t<span class=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t{{ rows().length }}{{ maxRows() ? ' / ' + maxRows() : '' }} rows\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</mcms-card-header>\n\t\t\t<mcms-card-content>\n\t\t\t\t@if (rows().length === 0) {\n\t\t\t\t\t<p class=\"text-sm text-muted-foreground py-4 text-center\">\n\t\t\t\t\t\tNo items yet. Click \"Add Row\" to get started.\n\t\t\t\t\t</p>\n\t\t\t\t} @else {\n\t\t\t\t\t<div\n\t\t\t\t\t\tcdkDropList\n\t\t\t\t\t\t(cdkDropListDropped)=\"onDrop($event)\"\n\t\t\t\t\t\tclass=\"space-y-3\"\n\t\t\t\t\t\trole=\"list\"\n\t\t\t\t\t\taria-label=\"Array rows\"\n\t\t\t\t\t>\n\t\t\t\t\t\t@for (row of rows(); track $index; let i = $index) {\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tcdkDrag\n\t\t\t\t\t\t\t\tclass=\"border rounded-lg p-4 bg-card flex gap-3 items-start\"\n\t\t\t\t\t\t\t\t[cdkDragDisabled]=\"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\tcdkDragHandle\n\t\t\t\t\t\t\t\t\tclass=\"cursor-grab pt-1 text-muted-foreground hover:text-foreground\"\n\t\t\t\t\t\t\t\t\t[class.hidden]=\"isDisabled()\"\n\t\t\t\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\t\t\t\ttabindex=\"0\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'Reorder row ' + (i + 1)\"\n\t\t\t\t\t\t\t\t\taria-roledescription=\"sortable\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ng-icon name=\"heroBars2\" size=\"16\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"flex-1 space-y-3\">\n\t\t\t\t\t\t\t\t\t@for (subField of subFields(); track subField.name) {\n\t\t\t\t\t\t\t\t\t\t<mcms-field-renderer\n\t\t\t\t\t\t\t\t\t\t\t[field]=\"subField\"\n\t\t\t\t\t\t\t\t\t\t\t[formNode]=\"getRowSubNode(i, subField.name)\"\n\t\t\t\t\t\t\t\t\t\t\t[formTree]=\"formTree()\"\n\t\t\t\t\t\t\t\t\t\t\t[formModel]=\"formModel()\"\n\t\t\t\t\t\t\t\t\t\t\t[mode]=\"mode()\"\n\t\t\t\t\t\t\t\t\t\t\t[path]=\"getRowSubFieldPath(i, subField.name)\"\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</div>\n\t\t\t\t\t\t\t\t@if (canRemoveRow()) {\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\tmcms-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\tclass=\"shrink-0 text-destructive hover:text-destructive\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"removeRow(i)\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'Remove row ' + (i + 1)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ng-icon name=\"heroTrash\" size=\"16\" aria-hidden=\"true\" />\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</div>\n\t\t\t\t}\n\t\t\t</mcms-card-content>\n\t\t\t@if (canAddRow()) {\n\t\t\t\t<mcms-card-footer>\n\t\t\t\t\t<button mcms-button variant=\"outline\" (click)=\"addRow()\">\n\t\t\t\t\t\t<ng-icon name=\"heroPlus\" size=\"16\" aria-hidden=\"true\" />\n\t\t\t\t\t\tAdd Row\n\t\t\t\t\t</button>\n\t\t\t\t</mcms-card-footer>\n\t\t\t}\n\t\t</mcms-card>\n\t`,\n})\nexport class ArrayFieldRenderer {\n\t/** Field definition (must be an ArrayField) */\n\treadonly field = input.required<Field>();\n\n\t/** Signal forms FieldTree node for this array */\n\treadonly formNode = input<unknown>(null);\n\n\t/** Root signal forms FieldTree (for layout fields that look up child nodes) */\n\treadonly formTree = input<unknown>(null);\n\n\t/** Form model data (for condition evaluation and relationship filterOptions) */\n\treadonly formModel = input<Record<string, unknown>>({});\n\n\t/** Form mode */\n\treadonly mode = input<EntityFormMode>('create');\n\n\t/** Field path (e.g., \"features\") */\n\treadonly path = input.required<string>();\n\n\t/** Bridge: extract FieldState from formNode */\n\tprivate readonly nodeState = computed(() => getFieldNodeState(this.formNode()));\n\n\t/** Computed label */\n\treadonly label = computed(() => this.field().label || humanizeFieldName(this.field().name));\n\n\t/** Computed description */\n\treadonly description = computed(() => this.field().description || '');\n\n\t/** Sub-fields from the array definition */\n\treadonly subFields = computed((): Field[] => {\n\t\tconst f = this.field();\n\t\tif (f.type === 'array') {\n\t\t\treturn f.fields.filter((sf) => !sf.admin?.hidden);\n\t\t}\n\t\treturn [];\n\t});\n\n\t/** Min rows constraint */\n\treadonly minRows = computed((): number => {\n\t\tconst f = this.field();\n\t\treturn f.type === 'array' ? (f.minRows ?? 0) : 0;\n\t});\n\n\t/** Max rows constraint */\n\treadonly maxRows = computed((): number | undefined => {\n\t\tconst f = this.field();\n\t\treturn f.type === 'array' ? f.maxRows : undefined;\n\t});\n\n\t/** Current rows as array of objects (read from FieldState) */\n\treadonly rows = computed((): Record<string, unknown>[] => {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return [];\n\t\tconst val = state.value();\n\t\tif (Array.isArray(val)) {\n\t\t\treturn val.map((item) => (isRecord(item) ? item : {}));\n\t\t}\n\t\treturn [];\n\t});\n\n\t/** Whether the field is disabled (view mode) */\n\treadonly isDisabled = computed(() => this.mode() === 'view');\n\n\t/** Whether a new row can be added */\n\treadonly canAddRow = computed((): boolean => {\n\t\tif (this.isDisabled()) return false;\n\t\tconst max = this.maxRows();\n\t\treturn max === undefined || this.rows().length < max;\n\t});\n\n\t/** Whether rows can be removed */\n\treadonly canRemoveRow = computed((): boolean => {\n\t\tif (this.isDisabled()) return false;\n\t\treturn this.rows().length > this.minRows();\n\t});\n\n\t/** Get a FieldTree sub-node for a row's sub-field */\n\tgetRowSubNode(rowIndex: number, subFieldName: string): unknown {\n\t\tconst rowNode = getSubNode(this.formNode(), rowIndex);\n\t\treturn getSubNode(rowNode, subFieldName);\n\t}\n\n\t/** Get the full path for a row's sub-field */\n\tgetRowSubFieldPath(rowIndex: number, subFieldName: string): string {\n\t\treturn `${this.path()}.${rowIndex}.${subFieldName}`;\n\t}\n\n\t/** Handle drag-drop reorder */\n\tonDrop(event: CdkDragDrop<unknown>): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst rows = [...this.rows()];\n\t\tmoveItemInArray(rows, event.previousIndex, event.currentIndex);\n\t\tstate.value.set(rows);\n\t}\n\n\t/** Add a new empty row */\n\taddRow(): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst rows = [...this.rows()];\n\t\tconst newRow: Record<string, unknown> = {};\n\t\tfor (const field of this.subFields()) {\n\t\t\tnewRow[field.name] = getFieldDefaultValue(field);\n\t\t}\n\t\trows.push(newRow);\n\t\tstate.value.set(rows);\n\t}\n\n\t/** Remove a row at the given index */\n\tremoveRow(index: number): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst rows = this.rows().filter((_, i) => i !== index);\n\t\tstate.value.set(rows);\n\t}\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"momentumcms-admin-array-field.component-CT5NlIEv.mjs","sources":["../../../../libs/admin/src/lib/widgets/entity-form/field-renderers/array-field.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport {\n\tCdkDropList,\n\tCdkDrag,\n\tCdkDragHandle,\n\ttype CdkDragDrop,\n\tmoveItemInArray,\n} from '@angular/cdk/drag-drop';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroPlus, heroTrash, heroBars2 } from '@ng-icons/heroicons/outline';\nimport { Card, CardHeader, CardTitle, CardContent, CardFooter, Button } from '@momentumcms/ui';\nimport { humanizeFieldName } from '@momentumcms/core';\nimport type { Field } from '@momentumcms/core';\nimport type { EntityFormMode } from '../entity-form.types';\nimport {\n\tgetFieldNodeState,\n\tgetSubNode,\n\tisRecord,\n\tgetFieldDefaultValue,\n} from '../entity-form.types';\nimport { FieldRenderer } from './field-renderer.component';\n\n/**\n * Array field renderer.\n *\n * Renders an array of rows, each row displayed as a card with sub-fields.\n * Supports add/remove rows and drag-drop reordering via CDK DragDrop.\n * Respects minRows/maxRows constraints.\n *\n * Data container pattern: passes row sub-field FieldTree nodes via\n * getSubNode(getSubNode(formNode, rowIndex), subFieldName).\n * Array mutations use nodeState.value.set(newArray).\n */\n@Component({\n\tselector: 'mcms-array-field-renderer',\n\timports: [\n\t\tCard,\n\t\tCardHeader,\n\t\tCardTitle,\n\t\tCardContent,\n\t\tCardFooter,\n\t\tButton,\n\t\tNgIcon,\n\t\tCdkDropList,\n\t\tCdkDrag,\n\t\tCdkDragHandle,\n\t\tFieldRenderer,\n\t],\n\tproviders: [provideIcons({ heroPlus, heroTrash, heroBars2 })],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplate: `\n\t\t<mcms-card>\n\t\t\t<mcms-card-header>\n\t\t\t\t<div class=\"flex items-center justify-between\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<mcms-card-title>{{ label() }}</mcms-card-title>\n\t\t\t\t\t\t@if (description()) {\n\t\t\t\t\t\t\t<p class=\"text-sm text-muted-foreground mt-1\">{{ description() }}</p>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t\t<span class=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t{{ rows().length }}{{ maxRows() ? ' / ' + maxRows() : '' }} rows\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</mcms-card-header>\n\t\t\t<mcms-card-content>\n\t\t\t\t@if (rows().length === 0) {\n\t\t\t\t\t<p class=\"text-sm text-muted-foreground py-4 text-center\">\n\t\t\t\t\t\tNo items yet. Click \"Add Row\" to get started.\n\t\t\t\t\t</p>\n\t\t\t\t} @else {\n\t\t\t\t\t<div\n\t\t\t\t\t\tcdkDropList\n\t\t\t\t\t\t(cdkDropListDropped)=\"onDrop($event)\"\n\t\t\t\t\t\tclass=\"space-y-3\"\n\t\t\t\t\t\trole=\"list\"\n\t\t\t\t\t\taria-label=\"Array rows\"\n\t\t\t\t\t>\n\t\t\t\t\t\t@for (row of rows(); track $index; let i = $index) {\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tcdkDrag\n\t\t\t\t\t\t\t\tclass=\"border rounded-lg p-4 bg-card flex gap-3 items-start\"\n\t\t\t\t\t\t\t\t[cdkDragDisabled]=\"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\tcdkDragHandle\n\t\t\t\t\t\t\t\t\tclass=\"cursor-grab pt-1 text-muted-foreground hover:text-foreground\"\n\t\t\t\t\t\t\t\t\t[class.hidden]=\"isDisabled()\"\n\t\t\t\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\t\t\t\ttabindex=\"0\"\n\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'Reorder row ' + (i + 1)\"\n\t\t\t\t\t\t\t\t\taria-roledescription=\"sortable\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<ng-icon name=\"heroBars2\" size=\"16\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"flex-1 space-y-3\">\n\t\t\t\t\t\t\t\t\t@for (subField of subFields(); track subField.name) {\n\t\t\t\t\t\t\t\t\t\t<mcms-field-renderer\n\t\t\t\t\t\t\t\t\t\t\t[field]=\"subField\"\n\t\t\t\t\t\t\t\t\t\t\t[formNode]=\"getRowSubNode(i, subField.name)\"\n\t\t\t\t\t\t\t\t\t\t\t[formTree]=\"formTree()\"\n\t\t\t\t\t\t\t\t\t\t\t[formModel]=\"formModel()\"\n\t\t\t\t\t\t\t\t\t\t\t[mode]=\"mode()\"\n\t\t\t\t\t\t\t\t\t\t\t[path]=\"getRowSubFieldPath(i, subField.name)\"\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</div>\n\t\t\t\t\t\t\t\t@if (canRemoveRow()) {\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\tmcms-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\tclass=\"shrink-0 text-destructive hover:text-destructive\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"removeRow(i)\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'Remove row ' + (i + 1)\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ng-icon name=\"heroTrash\" size=\"16\" aria-hidden=\"true\" />\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</div>\n\t\t\t\t}\n\t\t\t</mcms-card-content>\n\t\t\t@if (canAddRow()) {\n\t\t\t\t<mcms-card-footer>\n\t\t\t\t\t<button mcms-button variant=\"outline\" (click)=\"addRow()\">\n\t\t\t\t\t\t<ng-icon name=\"heroPlus\" size=\"16\" aria-hidden=\"true\" />\n\t\t\t\t\t\tAdd Row\n\t\t\t\t\t</button>\n\t\t\t\t</mcms-card-footer>\n\t\t\t}\n\t\t</mcms-card>\n\t`,\n})\nexport class ArrayFieldRenderer {\n\t/** Field definition (must be an ArrayField) */\n\treadonly field = input.required<Field>();\n\n\t/** Signal forms FieldTree node for this array */\n\treadonly formNode = input<unknown>(null);\n\n\t/** Root signal forms FieldTree (for layout fields that look up child nodes) */\n\treadonly formTree = input<unknown>(null);\n\n\t/** Form model data (for condition evaluation and relationship filterOptions) */\n\treadonly formModel = input<Record<string, unknown>>({});\n\n\t/** Form mode */\n\treadonly mode = input<EntityFormMode>('create');\n\n\t/** Field path (e.g., \"features\") */\n\treadonly path = input.required<string>();\n\n\t/** Bridge: extract FieldState from formNode */\n\tprivate readonly nodeState = computed(() => getFieldNodeState(this.formNode()));\n\n\t/** Computed label */\n\treadonly label = computed(() => this.field().label || humanizeFieldName(this.field().name));\n\n\t/** Computed description */\n\treadonly description = computed(() => this.field().description || '');\n\n\t/** Sub-fields from the array definition */\n\treadonly subFields = computed((): Field[] => {\n\t\tconst f = this.field();\n\t\tif (f.type === 'array') {\n\t\t\treturn f.fields.filter((sf) => !sf.admin?.hidden);\n\t\t}\n\t\treturn [];\n\t});\n\n\t/** Min rows constraint */\n\treadonly minRows = computed((): number => {\n\t\tconst f = this.field();\n\t\treturn f.type === 'array' ? (f.minRows ?? 0) : 0;\n\t});\n\n\t/** Max rows constraint */\n\treadonly maxRows = computed((): number | undefined => {\n\t\tconst f = this.field();\n\t\treturn f.type === 'array' ? f.maxRows : undefined;\n\t});\n\n\t/** Current rows as array of objects (read from FieldState) */\n\treadonly rows = computed((): Record<string, unknown>[] => {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return [];\n\t\tconst val = state.value();\n\t\tif (Array.isArray(val)) {\n\t\t\treturn val.map((item) => (isRecord(item) ? item : {}));\n\t\t}\n\t\treturn [];\n\t});\n\n\t/** Whether the field is disabled (view mode) */\n\treadonly isDisabled = computed(() => this.mode() === 'view');\n\n\t/** Whether a new row can be added */\n\treadonly canAddRow = computed((): boolean => {\n\t\tif (this.isDisabled()) return false;\n\t\tconst max = this.maxRows();\n\t\treturn max === undefined || this.rows().length < max;\n\t});\n\n\t/** Whether rows can be removed */\n\treadonly canRemoveRow = computed((): boolean => {\n\t\tif (this.isDisabled()) return false;\n\t\treturn this.rows().length > this.minRows();\n\t});\n\n\t/** Get a FieldTree sub-node for a row's sub-field */\n\tgetRowSubNode(rowIndex: number, subFieldName: string): unknown {\n\t\tconst rowNode = getSubNode(this.formNode(), rowIndex);\n\t\treturn getSubNode(rowNode, subFieldName);\n\t}\n\n\t/** Get the full path for a row's sub-field */\n\tgetRowSubFieldPath(rowIndex: number, subFieldName: string): string {\n\t\treturn `${this.path()}.${rowIndex}.${subFieldName}`;\n\t}\n\n\t/** Handle drag-drop reorder */\n\tonDrop(event: CdkDragDrop<unknown>): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst rows = [...this.rows()];\n\t\tmoveItemInArray(rows, event.previousIndex, event.currentIndex);\n\t\tstate.value.set(rows);\n\t}\n\n\t/** Add a new empty row */\n\taddRow(): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst rows = [...this.rows()];\n\t\tconst newRow: Record<string, unknown> = {};\n\t\tfor (const field of this.subFields()) {\n\t\t\tnewRow[field.name] = getFieldDefaultValue(field);\n\t\t}\n\t\trows.push(newRow);\n\t\tstate.value.set(rows);\n\t}\n\n\t/** Remove a row at the given index */\n\tremoveRow(index: number): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst rows = this.rows().filter((_, i) => i !== index);\n\t\tstate.value.set(rows);\n\t}\n}\n"],"names":[],"mappings":";;;;;;;;;AAsBA;;;;;;;;;;AAUG;MAuGU,kBAAkB,CAAA;;AAErB,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,gDAAS;;AAG/B,IAAA,QAAQ,GAAG,KAAK,CAAU,IAAI,oDAAC;;AAG/B,IAAA,QAAQ,GAAG,KAAK,CAAU,IAAI,oDAAC;;AAG/B,IAAA,SAAS,GAAG,KAAK,CAA0B,EAAE,qDAAC;;AAG9C,IAAA,IAAI,GAAG,KAAK,CAAiB,QAAQ,gDAAC;;AAGtC,IAAA,IAAI,GAAG,KAAK,CAAC,QAAQ,+CAAU;;AAGvB,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAM,iBAAiB,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,qDAAC;;IAGtE,KAAK,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;;AAGlF,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,WAAW,IAAI,EAAE,uDAAC;;AAG5D,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAc;AAC3C,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE;AACtB,QAAA,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE;AACvB,YAAA,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;QAClD;AACA,QAAA,OAAO,EAAE;AACV,IAAA,CAAC,qDAAC;;AAGO,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAa;AACxC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE;AACtB,QAAA,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC;AACjD,IAAA,CAAC,mDAAC;;AAGO,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAyB;AACpD,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE;AACtB,QAAA,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,GAAG,CAAC,CAAC,OAAO,GAAG,SAAS;AAClD,IAAA,CAAC,mDAAC;;AAGO,IAAA,IAAI,GAAG,QAAQ,CAAC,MAAgC;AACxD,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;AAC9B,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,EAAE;AACrB,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,EAAE;AACzB,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACvB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;QACvD;AACA,QAAA,OAAO,EAAE;AACV,IAAA,CAAC,gDAAC;;AAGO,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,KAAK,MAAM,sDAAC;;AAGnD,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAc;QAC3C,IAAI,IAAI,CAAC,UAAU,EAAE;AAAE,YAAA,OAAO,KAAK;AACnC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE;AAC1B,QAAA,OAAO,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,GAAG;AACrD,IAAA,CAAC,qDAAC;;AAGO,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAc;QAC9C,IAAI,IAAI,CAAC,UAAU,EAAE;AAAE,YAAA,OAAO,KAAK;QACnC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE;AAC3C,IAAA,CAAC,wDAAC;;IAGF,aAAa,CAAC,QAAgB,EAAE,YAAoB,EAAA;QACnD,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC;AACrD,QAAA,OAAO,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC;IACzC;;IAGA,kBAAkB,CAAC,QAAgB,EAAE,YAAoB,EAAA;QACxD,OAAO,CAAA,EAAG,IAAI,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAA,CAAA,EAAI,YAAY,CAAA,CAAE;IACpD;;AAGA,IAAA,MAAM,CAAC,KAA2B,EAAA;AACjC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;AAC9B,QAAA,IAAI,CAAC,KAAK;YAAE;QACZ,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7B,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC;AAC9D,QAAA,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;IACtB;;IAGA,MAAM,GAAA;AACL,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;AAC9B,QAAA,IAAI,CAAC,KAAK;YAAE;QACZ,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,MAAM,GAA4B,EAAE;QAC1C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE;YACrC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,KAAK,CAAC;QACjD;AACA,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;AACjB,QAAA,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;IACtB;;AAGA,IAAA,SAAS,CAAC,KAAa,EAAA;AACtB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE;AAC9B,QAAA,IAAI,CAAC,KAAK;YAAE;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;AACtD,QAAA,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;IACtB;uGAnHY,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAvFnB,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmFT,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAjGA,IAAI,sDACJ,UAAU,EAAA,QAAA,EAAA,kBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,SAAS,EAAA,QAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACT,WAAW,8DACX,UAAU,EAAA,QAAA,EAAA,kBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,MAAM,EAAA,QAAA,EAAA,qCAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,WAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACN,MAAM,6GACN,WAAW,EAAA,QAAA,EAAA,8BAAA,EAAA,MAAA,EAAA,CAAA,wBAAA,EAAA,iBAAA,EAAA,wBAAA,EAAA,IAAA,EAAA,qBAAA,EAAA,qBAAA,EAAA,4BAAA,EAAA,2BAAA,EAAA,0BAAA,EAAA,+BAAA,EAAA,2BAAA,EAAA,6BAAA,EAAA,sBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,oBAAA,EAAA,oBAAA,EAAA,mBAAA,EAAA,mBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,OAAO,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,iBAAA,EAAA,oBAAA,EAAA,iBAAA,EAAA,mBAAA,EAAA,yBAAA,EAAA,iBAAA,EAAA,0BAAA,EAAA,qBAAA,EAAA,yBAAA,EAAA,cAAA,CAAA,EAAA,OAAA,EAAA,CAAA,gBAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,gBAAA,EAAA,cAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACP,aAAa,+FACb,aAAa,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,UAAA,EAAA,UAAA,EAAA,WAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAyFF,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAtG9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,QAAQ,EAAE,2BAA2B;AACrC,oBAAA,OAAO,EAAE;wBACR,IAAI;wBACJ,UAAU;wBACV,SAAS;wBACT,WAAW;wBACX,UAAU;wBACV,MAAM;wBACN,MAAM;wBACN,WAAW;wBACX,OAAO;wBACP,aAAa;wBACb,aAAa;AACb,qBAAA;AACD,oBAAA,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;oBAC7D,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmFT,CAAA,CAAA;AACD,iBAAA;;;;;"}
@@ -5,7 +5,7 @@ import { NgIcon, provideIcons } from '@ng-icons/core';
5
5
  import { heroBars2, heroTrash, heroPlus } from '@ng-icons/heroicons/outline';
6
6
  import { Card, CardHeader, CardTitle, CardContent, CardFooter, Button, Badge } from '@momentumcms/ui';
7
7
  import { humanizeFieldName } from '@momentumcms/core';
8
- import { a as getFieldNodeState, i as isRecord, n as normalizeBlockDefaults, b as getSubNode, c as getFieldDefaultValue, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs';
8
+ import { a as getFieldNodeState, i as isRecord, n as normalizeBlockDefaults, b as getSubNode, c as getFieldDefaultValue, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs';
9
9
 
10
10
  /**
11
11
  * Blocks field renderer.
@@ -359,4 +359,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
359
359
  }], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], formNode: [{ type: i0.Input, args: [{ isSignal: true, alias: "formNode", required: false }] }], formTree: [{ type: i0.Input, args: [{ isSignal: true, alias: "formTree", required: false }] }], formModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "formModel", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "path", required: true }] }] } });
360
360
 
361
361
  export { BlocksFieldRenderer };
362
- //# sourceMappingURL=momentumcms-admin-blocks-field.component-CIxpyKAV.mjs.map
362
+ //# sourceMappingURL=momentumcms-admin-blocks-field.component-Cz7HmuBK.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"momentumcms-admin-blocks-field.component-CIxpyKAV.mjs","sources":["../../../../libs/admin/src/lib/widgets/entity-form/field-renderers/blocks-field.component.ts"],"sourcesContent":["import {\n\tChangeDetectionStrategy,\n\tComponent,\n\tcomputed,\n\teffect,\n\tinput,\n\tuntracked,\n} from '@angular/core';\nimport {\n\tCdkDropList,\n\tCdkDrag,\n\tCdkDragHandle,\n\ttype CdkDragDrop,\n\tmoveItemInArray,\n} from '@angular/cdk/drag-drop';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroPlus, heroTrash, heroBars2 } from '@ng-icons/heroicons/outline';\nimport {\n\tCard,\n\tCardHeader,\n\tCardTitle,\n\tCardContent,\n\tCardFooter,\n\tButton,\n\tBadge,\n} from '@momentumcms/ui';\nimport { humanizeFieldName } from '@momentumcms/core';\nimport type { Field, BlockConfig } from '@momentumcms/core';\nimport type { EntityFormMode } from '../entity-form.types';\nimport {\n\tgetFieldNodeState,\n\tgetSubNode,\n\tisRecord,\n\tgetFieldDefaultValue,\n\tnormalizeBlockDefaults,\n} from '../entity-form.types';\nimport { FieldRenderer } from './field-renderer.component';\n\n/** Shape of a block item in the stored data */\ninterface BlockItem {\n\tblockType: string;\n\t[key: string]: unknown;\n}\n\n/**\n * Blocks field renderer.\n *\n * Renders a list of typed blocks. Each block has a `blockType` discriminator\n * and type-specific fields. Users can add, remove, and reorder blocks.\n * A dropdown allows selecting which block type to add.\n *\n * Data container pattern: passes block sub-field FieldTree nodes via\n * getSubNode(getSubNode(formNode, blockIndex), subFieldName).\n * Block mutations use nodeState.value.set(newArray).\n */\n@Component({\n\tselector: 'mcms-blocks-field-renderer',\n\timports: [\n\t\tCard,\n\t\tCardHeader,\n\t\tCardTitle,\n\t\tCardContent,\n\t\tCardFooter,\n\t\tButton,\n\t\tBadge,\n\t\tNgIcon,\n\t\tCdkDropList,\n\t\tCdkDrag,\n\t\tCdkDragHandle,\n\t\tFieldRenderer,\n\t],\n\tproviders: [provideIcons({ heroPlus, heroTrash, heroBars2 })],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplate: `\n\t\t<mcms-card>\n\t\t\t<mcms-card-header>\n\t\t\t\t<div class=\"flex items-center justify-between\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<mcms-card-title>{{ label() }}</mcms-card-title>\n\t\t\t\t\t\t@if (description()) {\n\t\t\t\t\t\t\t<p class=\"text-sm text-muted-foreground mt-1\">{{ description() }}</p>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t\t<span class=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t{{ blocks().length }}{{ maxRows() ? ' / ' + maxRows() : '' }} blocks\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</mcms-card-header>\n\t\t\t<mcms-card-content>\n\t\t\t\t@if (blocks().length === 0) {\n\t\t\t\t\t<p class=\"text-sm text-muted-foreground py-4 text-center\">\n\t\t\t\t\t\tNo blocks yet. Add a block to get started.\n\t\t\t\t\t</p>\n\t\t\t\t} @else {\n\t\t\t\t\t<div\n\t\t\t\t\t\tcdkDropList\n\t\t\t\t\t\t(cdkDropListDropped)=\"onDrop($event)\"\n\t\t\t\t\t\tclass=\"space-y-3\"\n\t\t\t\t\t\trole=\"list\"\n\t\t\t\t\t\taria-label=\"Content blocks\"\n\t\t\t\t\t>\n\t\t\t\t\t\t@for (block of blocks(); track $index; let i = $index) {\n\t\t\t\t\t\t\t<div cdkDrag class=\"border rounded-lg bg-card\" [cdkDragDisabled]=\"isDisabled()\">\n\t\t\t\t\t\t\t\t<div class=\"flex items-center gap-3 px-4 py-2 border-b bg-muted/50 rounded-t-lg\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tcdkDragHandle\n\t\t\t\t\t\t\t\t\t\tclass=\"cursor-grab text-muted-foreground hover:text-foreground\"\n\t\t\t\t\t\t\t\t\t\t[class.hidden]=\"isDisabled()\"\n\t\t\t\t\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\t\t\t\t\ttabindex=\"0\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'Reorder ' + getBlockLabel(block.blockType) + ' block'\"\n\t\t\t\t\t\t\t\t\t\taria-roledescription=\"sortable\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ng-icon name=\"heroBars2\" size=\"16\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<mcms-badge>{{ getBlockLabel(block.blockType) }}</mcms-badge>\n\t\t\t\t\t\t\t\t\t<div class=\"flex-1\"></div>\n\t\t\t\t\t\t\t\t\t@if (canRemoveBlock()) {\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\tmcms-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\tclass=\"h-7 w-7 text-destructive hover:text-destructive\"\n\t\t\t\t\t\t\t\t\t\t\t(click)=\"removeBlock(i)\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'Remove ' + getBlockLabel(block.blockType) + ' block'\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ng-icon name=\"heroTrash\" size=\"14\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t\t\t</button>\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<div class=\"p-4 space-y-3\">\n\t\t\t\t\t\t\t\t\t@for (subField of getBlockFields(block.blockType); track subField.name) {\n\t\t\t\t\t\t\t\t\t\t<mcms-field-renderer\n\t\t\t\t\t\t\t\t\t\t\t[field]=\"subField\"\n\t\t\t\t\t\t\t\t\t\t\t[formNode]=\"getBlockSubNode(i, subField.name)\"\n\t\t\t\t\t\t\t\t\t\t\t[formTree]=\"formTree()\"\n\t\t\t\t\t\t\t\t\t\t\t[formModel]=\"formModel()\"\n\t\t\t\t\t\t\t\t\t\t\t[mode]=\"mode()\"\n\t\t\t\t\t\t\t\t\t\t\t[path]=\"getBlockSubFieldPath(i, subField.name)\"\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</div>\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}\n\t\t\t</mcms-card-content>\n\t\t\t@if (canAddBlock()) {\n\t\t\t\t<mcms-card-footer>\n\t\t\t\t\t<div class=\"flex gap-2\">\n\t\t\t\t\t\t@for (blockDef of blockDefinitions(); track blockDef.slug) {\n\t\t\t\t\t\t\t<button mcms-button variant=\"outline\" (click)=\"addBlock(blockDef.slug)\">\n\t\t\t\t\t\t\t\t<ng-icon name=\"heroPlus\" size=\"16\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t{{ blockDef.labels?.singular || blockDef.slug }}\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</mcms-card-footer>\n\t\t\t}\n\t\t</mcms-card>\n\t`,\n})\nexport class BlocksFieldRenderer {\n\t/** Field definition (must be a BlocksField) */\n\treadonly field = input.required<Field>();\n\n\t/** Signal forms FieldTree node for this blocks array */\n\treadonly formNode = input<unknown>(null);\n\n\t/** Root signal forms FieldTree (for layout fields that look up child nodes) */\n\treadonly formTree = input<unknown>(null);\n\n\t/** Form model data (for condition evaluation and relationship filterOptions) */\n\treadonly formModel = input<Record<string, unknown>>({});\n\n\t/** Form mode */\n\treadonly mode = input<EntityFormMode>('create');\n\n\t/** Field path (e.g., \"content\") */\n\treadonly path = input.required<string>();\n\n\t/** Bridge: extract FieldState from formNode */\n\tprivate readonly nodeState = computed(() => getFieldNodeState(this.formNode()));\n\n\t/** Computed label */\n\treadonly label = computed(() => this.field().label || humanizeFieldName(this.field().name));\n\n\t/** Computed description */\n\treadonly description = computed(() => this.field().description || '');\n\n\t/** Block type definitions from the field */\n\treadonly blockDefinitions = computed((): BlockConfig[] => {\n\t\tconst f = this.field();\n\t\tif (f.type === 'blocks') {\n\t\t\treturn f.blocks;\n\t\t}\n\t\treturn [];\n\t});\n\n\t/** Min rows constraint */\n\treadonly minRows = computed((): number => {\n\t\tconst f = this.field();\n\t\treturn f.type === 'blocks' ? (f.minRows ?? 0) : 0;\n\t});\n\n\t/** Max rows constraint */\n\treadonly maxRows = computed((): number | undefined => {\n\t\tconst f = this.field();\n\t\treturn f.type === 'blocks' ? f.maxRows : undefined;\n\t});\n\n\t/** Current blocks as typed items (read from FieldState) */\n\treadonly blocks = computed((): BlockItem[] => {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return [];\n\t\tconst val = state.value();\n\t\tif (Array.isArray(val)) {\n\t\t\treturn val.filter(\n\t\t\t\t(item): item is BlockItem => isRecord(item) && typeof item['blockType'] === 'string',\n\t\t\t);\n\t\t}\n\t\treturn [];\n\t});\n\n\t/**\n\t * Normalize loaded blocks: ensure every block has defaults for all definition fields.\n\t * Blocks saved before new fields were added won't have those keys, and\n\t * signal-forms only creates controls for keys present in the model.\n\t */\n\tprivate readonly _normalizeBlocks = effect(() => {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst val = state.value();\n\t\tif (!Array.isArray(val)) return;\n\n\t\tconst { normalized, changed } = normalizeBlockDefaults(val, this.blockDefMap());\n\t\tif (changed) {\n\t\t\tuntracked(() => state.value.set(normalized));\n\t\t}\n\t});\n\n\t/** Whether the field is disabled (view mode) */\n\treadonly isDisabled = computed(() => this.mode() === 'view');\n\n\t/** Whether a new block can be added */\n\treadonly canAddBlock = computed((): boolean => {\n\t\tif (this.isDisabled()) return false;\n\t\tconst max = this.maxRows();\n\t\treturn max === undefined || this.blocks().length < max;\n\t});\n\n\t/** Whether blocks can be removed */\n\treadonly canRemoveBlock = computed((): boolean => {\n\t\tif (this.isDisabled()) return false;\n\t\treturn this.blocks().length > this.minRows();\n\t});\n\n\t/** Block definition lookup cache */\n\tprivate readonly blockDefMap = computed((): Map<string, BlockConfig> => {\n\t\tconst map = new Map<string, BlockConfig>();\n\t\tfor (const def of this.blockDefinitions()) {\n\t\t\tmap.set(def.slug, def);\n\t\t}\n\t\treturn map;\n\t});\n\n\t/** Get display label for a block type */\n\tgetBlockLabel(blockType: string): string {\n\t\tconst def = this.blockDefMap().get(blockType);\n\t\treturn def?.labels?.singular || blockType;\n\t}\n\n\t/** Get fields for a block type */\n\tgetBlockFields(blockType: string): Field[] {\n\t\tconst def = this.blockDefMap().get(blockType);\n\t\treturn def?.fields.filter((f) => !f.admin?.hidden) ?? [];\n\t}\n\n\t/** Get a FieldTree sub-node for a block's sub-field */\n\tgetBlockSubNode(blockIndex: number, subFieldName: string): unknown {\n\t\tconst blockNode = getSubNode(this.formNode(), blockIndex);\n\t\treturn getSubNode(blockNode, subFieldName);\n\t}\n\n\t/** Get the full path for a block's sub-field */\n\tgetBlockSubFieldPath(blockIndex: number, subFieldName: string): string {\n\t\treturn `${this.path()}.${blockIndex}.${subFieldName}`;\n\t}\n\n\t/** Handle drag-drop reorder */\n\tonDrop(event: CdkDragDrop<unknown>): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst blocks = [...this.blocks()];\n\t\tmoveItemInArray(blocks, event.previousIndex, event.currentIndex);\n\t\tstate.value.set(blocks);\n\t}\n\n\t/** Add a new block of the given type */\n\taddBlock(blockType: string): void {\n\t\tconst def = this.blockDefMap().get(blockType);\n\t\tif (!def) return;\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\n\t\tconst newBlock: BlockItem = { blockType };\n\t\tfor (const field of def.fields) {\n\t\t\tnewBlock[field.name] = getFieldDefaultValue(field);\n\t\t}\n\n\t\tconst blocks = [...this.blocks(), newBlock];\n\t\tstate.value.set(blocks);\n\t}\n\n\t/** Remove a block at the given index */\n\tremoveBlock(index: number): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst blocks = this.blocks().filter((_, i) => i !== index);\n\t\tstate.value.set(blocks);\n\t}\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"momentumcms-admin-blocks-field.component-Cz7HmuBK.mjs","sources":["../../../../libs/admin/src/lib/widgets/entity-form/field-renderers/blocks-field.component.ts"],"sourcesContent":["import {\n\tChangeDetectionStrategy,\n\tComponent,\n\tcomputed,\n\teffect,\n\tinput,\n\tuntracked,\n} from '@angular/core';\nimport {\n\tCdkDropList,\n\tCdkDrag,\n\tCdkDragHandle,\n\ttype CdkDragDrop,\n\tmoveItemInArray,\n} from '@angular/cdk/drag-drop';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { heroPlus, heroTrash, heroBars2 } from '@ng-icons/heroicons/outline';\nimport {\n\tCard,\n\tCardHeader,\n\tCardTitle,\n\tCardContent,\n\tCardFooter,\n\tButton,\n\tBadge,\n} from '@momentumcms/ui';\nimport { humanizeFieldName } from '@momentumcms/core';\nimport type { Field, BlockConfig } from '@momentumcms/core';\nimport type { EntityFormMode } from '../entity-form.types';\nimport {\n\tgetFieldNodeState,\n\tgetSubNode,\n\tisRecord,\n\tgetFieldDefaultValue,\n\tnormalizeBlockDefaults,\n} from '../entity-form.types';\nimport { FieldRenderer } from './field-renderer.component';\n\n/** Shape of a block item in the stored data */\ninterface BlockItem {\n\tblockType: string;\n\t[key: string]: unknown;\n}\n\n/**\n * Blocks field renderer.\n *\n * Renders a list of typed blocks. Each block has a `blockType` discriminator\n * and type-specific fields. Users can add, remove, and reorder blocks.\n * A dropdown allows selecting which block type to add.\n *\n * Data container pattern: passes block sub-field FieldTree nodes via\n * getSubNode(getSubNode(formNode, blockIndex), subFieldName).\n * Block mutations use nodeState.value.set(newArray).\n */\n@Component({\n\tselector: 'mcms-blocks-field-renderer',\n\timports: [\n\t\tCard,\n\t\tCardHeader,\n\t\tCardTitle,\n\t\tCardContent,\n\t\tCardFooter,\n\t\tButton,\n\t\tBadge,\n\t\tNgIcon,\n\t\tCdkDropList,\n\t\tCdkDrag,\n\t\tCdkDragHandle,\n\t\tFieldRenderer,\n\t],\n\tproviders: [provideIcons({ heroPlus, heroTrash, heroBars2 })],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplate: `\n\t\t<mcms-card>\n\t\t\t<mcms-card-header>\n\t\t\t\t<div class=\"flex items-center justify-between\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<mcms-card-title>{{ label() }}</mcms-card-title>\n\t\t\t\t\t\t@if (description()) {\n\t\t\t\t\t\t\t<p class=\"text-sm text-muted-foreground mt-1\">{{ description() }}</p>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t\t<span class=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t{{ blocks().length }}{{ maxRows() ? ' / ' + maxRows() : '' }} blocks\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</mcms-card-header>\n\t\t\t<mcms-card-content>\n\t\t\t\t@if (blocks().length === 0) {\n\t\t\t\t\t<p class=\"text-sm text-muted-foreground py-4 text-center\">\n\t\t\t\t\t\tNo blocks yet. Add a block to get started.\n\t\t\t\t\t</p>\n\t\t\t\t} @else {\n\t\t\t\t\t<div\n\t\t\t\t\t\tcdkDropList\n\t\t\t\t\t\t(cdkDropListDropped)=\"onDrop($event)\"\n\t\t\t\t\t\tclass=\"space-y-3\"\n\t\t\t\t\t\trole=\"list\"\n\t\t\t\t\t\taria-label=\"Content blocks\"\n\t\t\t\t\t>\n\t\t\t\t\t\t@for (block of blocks(); track $index; let i = $index) {\n\t\t\t\t\t\t\t<div cdkDrag class=\"border rounded-lg bg-card\" [cdkDragDisabled]=\"isDisabled()\">\n\t\t\t\t\t\t\t\t<div class=\"flex items-center gap-3 px-4 py-2 border-b bg-muted/50 rounded-t-lg\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tcdkDragHandle\n\t\t\t\t\t\t\t\t\t\tclass=\"cursor-grab text-muted-foreground hover:text-foreground\"\n\t\t\t\t\t\t\t\t\t\t[class.hidden]=\"isDisabled()\"\n\t\t\t\t\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\t\t\t\t\ttabindex=\"0\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'Reorder ' + getBlockLabel(block.blockType) + ' block'\"\n\t\t\t\t\t\t\t\t\t\taria-roledescription=\"sortable\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ng-icon name=\"heroBars2\" size=\"16\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<mcms-badge>{{ getBlockLabel(block.blockType) }}</mcms-badge>\n\t\t\t\t\t\t\t\t\t<div class=\"flex-1\"></div>\n\t\t\t\t\t\t\t\t\t@if (canRemoveBlock()) {\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\tmcms-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\tclass=\"h-7 w-7 text-destructive hover:text-destructive\"\n\t\t\t\t\t\t\t\t\t\t\t(click)=\"removeBlock(i)\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"'Remove ' + getBlockLabel(block.blockType) + ' block'\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ng-icon name=\"heroTrash\" size=\"14\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t\t\t</button>\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<div class=\"p-4 space-y-3\">\n\t\t\t\t\t\t\t\t\t@for (subField of getBlockFields(block.blockType); track subField.name) {\n\t\t\t\t\t\t\t\t\t\t<mcms-field-renderer\n\t\t\t\t\t\t\t\t\t\t\t[field]=\"subField\"\n\t\t\t\t\t\t\t\t\t\t\t[formNode]=\"getBlockSubNode(i, subField.name)\"\n\t\t\t\t\t\t\t\t\t\t\t[formTree]=\"formTree()\"\n\t\t\t\t\t\t\t\t\t\t\t[formModel]=\"formModel()\"\n\t\t\t\t\t\t\t\t\t\t\t[mode]=\"mode()\"\n\t\t\t\t\t\t\t\t\t\t\t[path]=\"getBlockSubFieldPath(i, subField.name)\"\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</div>\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}\n\t\t\t</mcms-card-content>\n\t\t\t@if (canAddBlock()) {\n\t\t\t\t<mcms-card-footer>\n\t\t\t\t\t<div class=\"flex gap-2\">\n\t\t\t\t\t\t@for (blockDef of blockDefinitions(); track blockDef.slug) {\n\t\t\t\t\t\t\t<button mcms-button variant=\"outline\" (click)=\"addBlock(blockDef.slug)\">\n\t\t\t\t\t\t\t\t<ng-icon name=\"heroPlus\" size=\"16\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t{{ blockDef.labels?.singular || blockDef.slug }}\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</mcms-card-footer>\n\t\t\t}\n\t\t</mcms-card>\n\t`,\n})\nexport class BlocksFieldRenderer {\n\t/** Field definition (must be a BlocksField) */\n\treadonly field = input.required<Field>();\n\n\t/** Signal forms FieldTree node for this blocks array */\n\treadonly formNode = input<unknown>(null);\n\n\t/** Root signal forms FieldTree (for layout fields that look up child nodes) */\n\treadonly formTree = input<unknown>(null);\n\n\t/** Form model data (for condition evaluation and relationship filterOptions) */\n\treadonly formModel = input<Record<string, unknown>>({});\n\n\t/** Form mode */\n\treadonly mode = input<EntityFormMode>('create');\n\n\t/** Field path (e.g., \"content\") */\n\treadonly path = input.required<string>();\n\n\t/** Bridge: extract FieldState from formNode */\n\tprivate readonly nodeState = computed(() => getFieldNodeState(this.formNode()));\n\n\t/** Computed label */\n\treadonly label = computed(() => this.field().label || humanizeFieldName(this.field().name));\n\n\t/** Computed description */\n\treadonly description = computed(() => this.field().description || '');\n\n\t/** Block type definitions from the field */\n\treadonly blockDefinitions = computed((): BlockConfig[] => {\n\t\tconst f = this.field();\n\t\tif (f.type === 'blocks') {\n\t\t\treturn f.blocks;\n\t\t}\n\t\treturn [];\n\t});\n\n\t/** Min rows constraint */\n\treadonly minRows = computed((): number => {\n\t\tconst f = this.field();\n\t\treturn f.type === 'blocks' ? (f.minRows ?? 0) : 0;\n\t});\n\n\t/** Max rows constraint */\n\treadonly maxRows = computed((): number | undefined => {\n\t\tconst f = this.field();\n\t\treturn f.type === 'blocks' ? f.maxRows : undefined;\n\t});\n\n\t/** Current blocks as typed items (read from FieldState) */\n\treadonly blocks = computed((): BlockItem[] => {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return [];\n\t\tconst val = state.value();\n\t\tif (Array.isArray(val)) {\n\t\t\treturn val.filter(\n\t\t\t\t(item): item is BlockItem => isRecord(item) && typeof item['blockType'] === 'string',\n\t\t\t);\n\t\t}\n\t\treturn [];\n\t});\n\n\t/**\n\t * Normalize loaded blocks: ensure every block has defaults for all definition fields.\n\t * Blocks saved before new fields were added won't have those keys, and\n\t * signal-forms only creates controls for keys present in the model.\n\t */\n\tprivate readonly _normalizeBlocks = effect(() => {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst val = state.value();\n\t\tif (!Array.isArray(val)) return;\n\n\t\tconst { normalized, changed } = normalizeBlockDefaults(val, this.blockDefMap());\n\t\tif (changed) {\n\t\t\tuntracked(() => state.value.set(normalized));\n\t\t}\n\t});\n\n\t/** Whether the field is disabled (view mode) */\n\treadonly isDisabled = computed(() => this.mode() === 'view');\n\n\t/** Whether a new block can be added */\n\treadonly canAddBlock = computed((): boolean => {\n\t\tif (this.isDisabled()) return false;\n\t\tconst max = this.maxRows();\n\t\treturn max === undefined || this.blocks().length < max;\n\t});\n\n\t/** Whether blocks can be removed */\n\treadonly canRemoveBlock = computed((): boolean => {\n\t\tif (this.isDisabled()) return false;\n\t\treturn this.blocks().length > this.minRows();\n\t});\n\n\t/** Block definition lookup cache */\n\tprivate readonly blockDefMap = computed((): Map<string, BlockConfig> => {\n\t\tconst map = new Map<string, BlockConfig>();\n\t\tfor (const def of this.blockDefinitions()) {\n\t\t\tmap.set(def.slug, def);\n\t\t}\n\t\treturn map;\n\t});\n\n\t/** Get display label for a block type */\n\tgetBlockLabel(blockType: string): string {\n\t\tconst def = this.blockDefMap().get(blockType);\n\t\treturn def?.labels?.singular || blockType;\n\t}\n\n\t/** Get fields for a block type */\n\tgetBlockFields(blockType: string): Field[] {\n\t\tconst def = this.blockDefMap().get(blockType);\n\t\treturn def?.fields.filter((f) => !f.admin?.hidden) ?? [];\n\t}\n\n\t/** Get a FieldTree sub-node for a block's sub-field */\n\tgetBlockSubNode(blockIndex: number, subFieldName: string): unknown {\n\t\tconst blockNode = getSubNode(this.formNode(), blockIndex);\n\t\treturn getSubNode(blockNode, subFieldName);\n\t}\n\n\t/** Get the full path for a block's sub-field */\n\tgetBlockSubFieldPath(blockIndex: number, subFieldName: string): string {\n\t\treturn `${this.path()}.${blockIndex}.${subFieldName}`;\n\t}\n\n\t/** Handle drag-drop reorder */\n\tonDrop(event: CdkDragDrop<unknown>): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst blocks = [...this.blocks()];\n\t\tmoveItemInArray(blocks, event.previousIndex, event.currentIndex);\n\t\tstate.value.set(blocks);\n\t}\n\n\t/** Add a new block of the given type */\n\taddBlock(blockType: string): void {\n\t\tconst def = this.blockDefMap().get(blockType);\n\t\tif (!def) return;\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\n\t\tconst newBlock: BlockItem = { blockType };\n\t\tfor (const field of def.fields) {\n\t\t\tnewBlock[field.name] = getFieldDefaultValue(field);\n\t\t}\n\n\t\tconst blocks = [...this.blocks(), newBlock];\n\t\tstate.value.set(blocks);\n\t}\n\n\t/** Remove a block at the given index */\n\tremoveBlock(index: number): void {\n\t\tconst state = this.nodeState();\n\t\tif (!state) return;\n\t\tconst blocks = this.blocks().filter((_, i) => i !== index);\n\t\tstate.value.set(blocks);\n\t}\n}\n"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { input, signal, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@momentumcms/ui';
4
4
  import { humanizeFieldName } from '@momentumcms/core';
5
- import { b as getSubNode, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs';
5
+ import { b as getSubNode, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs';
6
6
 
7
7
  /**
8
8
  * Collapsible layout field renderer.
@@ -84,13 +84,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
84
84
  type: Component,
85
85
  args: [{
86
86
  selector: 'mcms-collapsible-field-renderer',
87
- imports: [
88
- Accordion,
89
- AccordionItem,
90
- AccordionTrigger,
91
- AccordionContent,
92
- FieldRenderer,
93
- ],
87
+ imports: [Accordion, AccordionItem, AccordionTrigger, AccordionContent, FieldRenderer],
94
88
  changeDetection: ChangeDetectionStrategy.OnPush,
95
89
  host: { class: 'block' },
96
90
  template: `
@@ -123,4 +117,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
123
117
  }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], formTree: [{ type: i0.Input, args: [{ isSignal: true, alias: "formTree", required: false }] }], formModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "formModel", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "path", required: true }] }] } });
124
118
 
125
119
  export { CollapsibleFieldRenderer };
126
- //# sourceMappingURL=momentumcms-admin-collapsible-field.component-BpmaUKom.mjs.map
120
+ //# sourceMappingURL=momentumcms-admin-collapsible-field.component-CtwrGQvg.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"momentumcms-admin-collapsible-field.component-CtwrGQvg.mjs","sources":["../../../../libs/admin/src/lib/widgets/entity-form/field-renderers/collapsible-field.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, effect, input, signal } from '@angular/core';\nimport { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@momentumcms/ui';\nimport { humanizeFieldName } from '@momentumcms/core';\nimport type { Field } from '@momentumcms/core';\nimport type { EntityFormMode } from '../entity-form.types';\nimport { getSubNode } from '../entity-form.types';\nimport { FieldRenderer } from './field-renderer.component';\n\n/**\n * Collapsible layout field renderer.\n *\n * Wraps child fields in an expandable/collapsible accordion section.\n * This is a layout-only field; it does not store data itself.\n * Child field FieldTree nodes are looked up from the root formTree\n * using flat field names.\n */\n@Component({\n\tselector: 'mcms-collapsible-field-renderer',\n\timports: [Accordion, AccordionItem, AccordionTrigger, AccordionContent, FieldRenderer],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\thost: { class: 'block' },\n\ttemplate: `\n\t\t<mcms-accordion>\n\t\t\t<mcms-accordion-item>\n\t\t\t\t<mcms-accordion-trigger [panelId]=\"panelId()\" [(expanded)]=\"isExpanded\">\n\t\t\t\t\t{{ label() }}\n\t\t\t\t</mcms-accordion-trigger>\n\t\t\t\t<mcms-accordion-content [panelId]=\"panelId()\">\n\t\t\t\t\t@if (description()) {\n\t\t\t\t\t\t<p class=\"text-sm text-muted-foreground mb-4\">{{ description() }}</p>\n\t\t\t\t\t}\n\t\t\t\t\t<div class=\"space-y-4 py-4\">\n\t\t\t\t\t\t@for (subField of subFields(); track subField.name) {\n\t\t\t\t\t\t\t<mcms-field-renderer\n\t\t\t\t\t\t\t\t[field]=\"subField\"\n\t\t\t\t\t\t\t\t[formNode]=\"getChildFormNode(subField.name)\"\n\t\t\t\t\t\t\t\t[formTree]=\"formTree()\"\n\t\t\t\t\t\t\t\t[formModel]=\"formModel()\"\n\t\t\t\t\t\t\t\t[mode]=\"mode()\"\n\t\t\t\t\t\t\t\t[path]=\"subField.name\"\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</mcms-accordion-content>\n\t\t\t</mcms-accordion-item>\n\t\t</mcms-accordion>\n\t`,\n})\nexport class CollapsibleFieldRenderer {\n\t/** Field definition (must be a CollapsibleField) */\n\treadonly field = input.required<Field>();\n\n\t/** Root signal forms FieldTree (for looking up child field nodes) */\n\treadonly formTree = input<unknown>(null);\n\n\t/** Form model data (for condition evaluation and relationship filterOptions) */\n\treadonly formModel = input<Record<string, unknown>>({});\n\n\t/** Form mode */\n\treadonly mode = input<EntityFormMode>('create');\n\n\t/** Field path (unused for layout fields, kept for interface consistency) */\n\treadonly path = input.required<string>();\n\n\t/** Whether the accordion is expanded */\n\treadonly isExpanded = signal(false);\n\n\t/** Unique panel ID for accordion aria linkage */\n\treadonly panelId = computed(() => `collapsible-${this.path().replace(/\\./g, '-')}`);\n\n\t/** Computed label */\n\treadonly label = computed(() => this.field().label || humanizeFieldName(this.field().name));\n\n\t/** Computed description */\n\treadonly description = computed(() => this.field().description || '');\n\n\t/** Child fields */\n\treadonly subFields = computed((): Field[] => {\n\t\tconst f = this.field();\n\t\tif (f.type === 'collapsible') {\n\t\t\treturn f.fields.filter((sf) => !sf.admin?.hidden);\n\t\t}\n\t\treturn [];\n\t});\n\n\tconstructor() {\n\t\t// Set initial expanded state from field config once input is available\n\t\teffect(() => {\n\t\t\tconst f = this.field();\n\t\t\tif (f.type === 'collapsible' && f.defaultOpen) {\n\t\t\t\tthis.isExpanded.set(true);\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Get a FieldTree sub-node for a child field (flat path from root tree) */\n\tgetChildFormNode(fieldName: string): unknown {\n\t\treturn getSubNode(this.formTree(), fieldName);\n\t}\n}\n"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { inject, viewChild, computed, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { ActivatedRoute } from '@angular/router';
4
4
  import { humanizeFieldName } from '@momentumcms/core';
5
- import { g as getGlobalsFromRouteData, E as EntityFormWidget } from './momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs';
5
+ import { g as getGlobalsFromRouteData, E as EntityFormWidget } from './momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs';
6
6
 
7
7
  /**
8
8
  * Global Edit Page
@@ -87,4 +87,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
87
87
  }], propDecorators: { entityFormRef: [{ type: i0.ViewChild, args: ['entityForm', { isSignal: true }] }] } });
88
88
 
89
89
  export { GlobalEditPage };
90
- //# sourceMappingURL=momentumcms-admin-global-edit.page-976NlNjw.mjs.map
90
+ //# sourceMappingURL=momentumcms-admin-global-edit.page-BBUtWCSl.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"momentumcms-admin-global-edit.page-976NlNjw.mjs","sources":["../../../../libs/admin/src/lib/pages/global-edit/global-edit.page.ts"],"sourcesContent":["import { Component, ChangeDetectionStrategy, inject, computed, viewChild } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\nimport type { CollectionConfig, GlobalConfig } from '@momentumcms/core';\nimport { humanizeFieldName } from '@momentumcms/core';\nimport { getGlobalsFromRouteData } from '../../utils/route-data';\nimport { EntityFormWidget } from '../../widgets/entity-form/entity-form.component';\nimport type { HasUnsavedChanges } from '../../guards/unsaved-changes.guard';\n\n/**\n * Global Edit Page\n *\n * Renders the EntityFormWidget in global (singleton) mode for editing a global document.\n * The global config is converted to a CollectionConfig shape and passed with isGlobal=true.\n */\n@Component({\n\tselector: 'mcms-global-edit',\n\timports: [EntityFormWidget],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\thost: { class: 'block' },\n\ttemplate: `\n\t\t@if (collectionConfig(); as col) {\n\t\t\t<mcms-entity-form\n\t\t\t\t#entityForm\n\t\t\t\t[collection]=\"col\"\n\t\t\t\t[mode]=\"'edit'\"\n\t\t\t\t[basePath]=\"'/admin/globals'\"\n\t\t\t\t[showBreadcrumbs]=\"true\"\n\t\t\t\t[isGlobal]=\"true\"\n\t\t\t\t[globalSlug]=\"globalSlug()\"\n\t\t\t/>\n\t\t} @else {\n\t\t\t<div class=\"p-12 text-center text-muted-foreground\">Global not found</div>\n\t\t}\n\t`,\n})\nexport class GlobalEditPage implements HasUnsavedChanges {\n\tprivate readonly route = inject(ActivatedRoute);\n\n\tprivate readonly entityFormRef = viewChild<EntityFormWidget>('entityForm');\n\n\treadonly globalSlug = computed((): string => {\n\t\treturn this.route.snapshot.paramMap.get('slug') ?? '';\n\t});\n\n\treadonly globalConfig = computed((): GlobalConfig | undefined => {\n\t\tconst slug = this.globalSlug();\n\t\tconst globals = getGlobalsFromRouteData(this.route.parent?.snapshot.data);\n\t\treturn globals.find((g) => g.slug === slug);\n\t});\n\n\t/** Convert GlobalConfig to CollectionConfig shape for EntityFormWidget */\n\treadonly collectionConfig = computed((): CollectionConfig | undefined => {\n\t\tconst global = this.globalConfig();\n\t\tif (!global) return undefined;\n\n\t\treturn {\n\t\t\tslug: global.slug,\n\t\t\tfields: global.fields,\n\t\t\tlabels: {\n\t\t\t\tsingular: global.label ?? humanizeFieldName(global.slug),\n\t\t\t\tplural: global.label ?? humanizeFieldName(global.slug),\n\t\t\t},\n\t\t\tadmin: global.admin,\n\t\t\taccess: global.access\n\t\t\t\t? { read: global.access.read, update: global.access.update }\n\t\t\t\t: undefined,\n\t\t\thooks: global.hooks,\n\t\t\tversions: global.versions,\n\t\t};\n\t});\n\n\thasUnsavedChanges(): boolean {\n\t\treturn this.entityFormRef()?.isDirty() ?? false;\n\t}\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"momentumcms-admin-global-edit.page-BBUtWCSl.mjs","sources":["../../../../libs/admin/src/lib/pages/global-edit/global-edit.page.ts"],"sourcesContent":["import { Component, ChangeDetectionStrategy, inject, computed, viewChild } from '@angular/core';\nimport { ActivatedRoute } from '@angular/router';\nimport type { CollectionConfig, GlobalConfig } from '@momentumcms/core';\nimport { humanizeFieldName } from '@momentumcms/core';\nimport { getGlobalsFromRouteData } from '../../utils/route-data';\nimport { EntityFormWidget } from '../../widgets/entity-form/entity-form.component';\nimport type { HasUnsavedChanges } from '../../guards/unsaved-changes.guard';\n\n/**\n * Global Edit Page\n *\n * Renders the EntityFormWidget in global (singleton) mode for editing a global document.\n * The global config is converted to a CollectionConfig shape and passed with isGlobal=true.\n */\n@Component({\n\tselector: 'mcms-global-edit',\n\timports: [EntityFormWidget],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\thost: { class: 'block' },\n\ttemplate: `\n\t\t@if (collectionConfig(); as col) {\n\t\t\t<mcms-entity-form\n\t\t\t\t#entityForm\n\t\t\t\t[collection]=\"col\"\n\t\t\t\t[mode]=\"'edit'\"\n\t\t\t\t[basePath]=\"'/admin/globals'\"\n\t\t\t\t[showBreadcrumbs]=\"true\"\n\t\t\t\t[isGlobal]=\"true\"\n\t\t\t\t[globalSlug]=\"globalSlug()\"\n\t\t\t/>\n\t\t} @else {\n\t\t\t<div class=\"p-12 text-center text-muted-foreground\">Global not found</div>\n\t\t}\n\t`,\n})\nexport class GlobalEditPage implements HasUnsavedChanges {\n\tprivate readonly route = inject(ActivatedRoute);\n\n\tprivate readonly entityFormRef = viewChild<EntityFormWidget>('entityForm');\n\n\treadonly globalSlug = computed((): string => {\n\t\treturn this.route.snapshot.paramMap.get('slug') ?? '';\n\t});\n\n\treadonly globalConfig = computed((): GlobalConfig | undefined => {\n\t\tconst slug = this.globalSlug();\n\t\tconst globals = getGlobalsFromRouteData(this.route.parent?.snapshot.data);\n\t\treturn globals.find((g) => g.slug === slug);\n\t});\n\n\t/** Convert GlobalConfig to CollectionConfig shape for EntityFormWidget */\n\treadonly collectionConfig = computed((): CollectionConfig | undefined => {\n\t\tconst global = this.globalConfig();\n\t\tif (!global) return undefined;\n\n\t\treturn {\n\t\t\tslug: global.slug,\n\t\t\tfields: global.fields,\n\t\t\tlabels: {\n\t\t\t\tsingular: global.label ?? humanizeFieldName(global.slug),\n\t\t\t\tplural: global.label ?? humanizeFieldName(global.slug),\n\t\t\t},\n\t\t\tadmin: global.admin,\n\t\t\taccess: global.access\n\t\t\t\t? { read: global.access.read, update: global.access.update }\n\t\t\t\t: undefined,\n\t\t\thooks: global.hooks,\n\t\t\tversions: global.versions,\n\t\t};\n\t});\n\n\thasUnsavedChanges(): boolean {\n\t\treturn this.entityFormRef()?.isDirty() ?? false;\n\t}\n}\n"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { input, signal, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { Card, CardHeader, CardTitle, CardContent, Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@momentumcms/ui';
4
4
  import { humanizeFieldName } from '@momentumcms/core';
5
- import { b as getSubNode, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs';
5
+ import { b as getSubNode, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs';
6
6
 
7
7
  /**
8
8
  * Group field renderer.
@@ -181,4 +181,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
181
181
  }], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], formNode: [{ type: i0.Input, args: [{ isSignal: true, alias: "formNode", required: false }] }], formTree: [{ type: i0.Input, args: [{ isSignal: true, alias: "formTree", required: false }] }], formModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "formModel", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "path", required: true }] }] } });
182
182
 
183
183
  export { GroupFieldRenderer };
184
- //# sourceMappingURL=momentumcms-admin-group-field.component-Bgy_tQOG.mjs.map
184
+ //# sourceMappingURL=momentumcms-admin-group-field.component-BZeG8Oqy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"momentumcms-admin-group-field.component-BZeG8Oqy.mjs","sources":["../../../../libs/admin/src/lib/widgets/entity-form/field-renderers/group-field.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, effect, input, signal } from '@angular/core';\nimport {\n\tCard,\n\tCardHeader,\n\tCardTitle,\n\tCardContent,\n\tAccordion,\n\tAccordionItem,\n\tAccordionTrigger,\n\tAccordionContent,\n} from '@momentumcms/ui';\nimport { humanizeFieldName } from '@momentumcms/core';\nimport type { Field } from '@momentumcms/core';\nimport type { EntityFormMode } from '../entity-form.types';\nimport { getSubNode } from '../entity-form.types';\nimport { FieldRenderer } from './field-renderer.component';\n\n/**\n * Group field renderer.\n *\n * Renders a group of sub-fields inside a bordered card section.\n * When `admin.collapsible` is true, renders as an accordion instead.\n * Data container pattern: passes sub-field FieldTree nodes via getSubNode().\n */\n@Component({\n\tselector: 'mcms-group-field-renderer',\n\timports: [\n\t\tCard,\n\t\tCardHeader,\n\t\tCardTitle,\n\t\tCardContent,\n\t\tAccordion,\n\t\tAccordionItem,\n\t\tAccordionTrigger,\n\t\tAccordionContent,\n\t\tFieldRenderer,\n\t],\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\ttemplate: `\n\t\t@if (collapsible()) {\n\t\t\t<mcms-accordion>\n\t\t\t\t<mcms-accordion-item>\n\t\t\t\t\t<mcms-accordion-trigger [panelId]=\"panelId()\" [(expanded)]=\"isExpanded\">\n\t\t\t\t\t\t{{ label() }}\n\t\t\t\t\t</mcms-accordion-trigger>\n\t\t\t\t\t<mcms-accordion-content [panelId]=\"panelId()\">\n\t\t\t\t\t\t@if (description()) {\n\t\t\t\t\t\t\t<p class=\"text-sm text-muted-foreground mb-4\">{{ description() }}</p>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t<div class=\"space-y-4 py-4\">\n\t\t\t\t\t\t\t@for (subField of subFields(); track subField.name) {\n\t\t\t\t\t\t\t\t<mcms-field-renderer\n\t\t\t\t\t\t\t\t\t[field]=\"subField\"\n\t\t\t\t\t\t\t\t\t[formNode]=\"getSubFormNode(subField.name)\"\n\t\t\t\t\t\t\t\t\t[formTree]=\"formTree()\"\n\t\t\t\t\t\t\t\t\t[formModel]=\"formModel()\"\n\t\t\t\t\t\t\t\t\t[mode]=\"mode()\"\n\t\t\t\t\t\t\t\t\t[path]=\"getSubFieldPath(subField.name)\"\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</mcms-accordion-content>\n\t\t\t\t</mcms-accordion-item>\n\t\t\t</mcms-accordion>\n\t\t} @else {\n\t\t\t<mcms-card>\n\t\t\t\t<mcms-card-header>\n\t\t\t\t\t<mcms-card-title>{{ label() }}</mcms-card-title>\n\t\t\t\t\t@if (description()) {\n\t\t\t\t\t\t<p class=\"text-sm text-muted-foreground\">{{ description() }}</p>\n\t\t\t\t\t}\n\t\t\t\t</mcms-card-header>\n\t\t\t\t<mcms-card-content>\n\t\t\t\t\t<div class=\"space-y-4\">\n\t\t\t\t\t\t@for (subField of subFields(); track subField.name) {\n\t\t\t\t\t\t\t<mcms-field-renderer\n\t\t\t\t\t\t\t\t[field]=\"subField\"\n\t\t\t\t\t\t\t\t[formNode]=\"getSubFormNode(subField.name)\"\n\t\t\t\t\t\t\t\t[formTree]=\"formTree()\"\n\t\t\t\t\t\t\t\t[formModel]=\"formModel()\"\n\t\t\t\t\t\t\t\t[mode]=\"mode()\"\n\t\t\t\t\t\t\t\t[path]=\"getSubFieldPath(subField.name)\"\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</mcms-card-content>\n\t\t\t</mcms-card>\n\t\t}\n\t`,\n})\nexport class GroupFieldRenderer {\n\t/** Field definition (must be a GroupField) */\n\treadonly field = input.required<Field>();\n\n\t/** Signal forms FieldTree node for this group */\n\treadonly formNode = input<unknown>(null);\n\n\t/** Root signal forms FieldTree (for layout fields that look up child nodes) */\n\treadonly formTree = input<unknown>(null);\n\n\t/** Form model data (for condition evaluation and relationship filterOptions) */\n\treadonly formModel = input<Record<string, unknown>>({});\n\n\t/** Form mode */\n\treadonly mode = input<EntityFormMode>('create');\n\n\t/** Field path (e.g., \"seo\") */\n\treadonly path = input.required<string>();\n\n\t/** Whether the accordion is expanded (only used in collapsible mode) */\n\treadonly isExpanded = signal(false);\n\n\t/** Whether this group should render as collapsible accordion */\n\treadonly collapsible = computed(() => !!this.field().admin?.collapsible);\n\n\t/** Unique panel ID for accordion aria linkage */\n\treadonly panelId = computed(() => `group-${this.path().replace(/\\./g, '-')}`);\n\n\t/** Computed label */\n\treadonly label = computed(() => this.field().label || humanizeFieldName(this.field().name));\n\n\t/** Computed description */\n\treadonly description = computed(() => this.field().description || '');\n\n\t/** Sub-fields from the group definition */\n\treadonly subFields = computed((): Field[] => {\n\t\tconst f = this.field();\n\t\tif (f.type === 'group') {\n\t\t\treturn f.fields.filter((sf) => !sf.admin?.hidden);\n\t\t}\n\t\treturn [];\n\t});\n\n\tconstructor() {\n\t\teffect(() => {\n\t\t\tif (this.collapsible() && this.field().admin?.defaultOpen) {\n\t\t\t\tthis.isExpanded.set(true);\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Get a FieldTree sub-node for a sub-field */\n\tgetSubFormNode(subFieldName: string): unknown {\n\t\treturn getSubNode(this.formNode(), subFieldName);\n\t}\n\n\t/** Get the full path for a sub-field (e.g., \"seo.metaTitle\") */\n\tgetSubFieldPath(subFieldName: string): string {\n\t\treturn `${this.path()}.${subFieldName}`;\n\t}\n}\n"],"names":[],"mappings":";;;;;;AAiBA;;;;;;AAMG;MAmEU,kBAAkB,CAAA;;AAErB,IAAA,KAAK,GAAG,KAAK,CAAC,QAAQ,gDAAS;;AAG/B,IAAA,QAAQ,GAAG,KAAK,CAAU,IAAI,oDAAC;;AAG/B,IAAA,QAAQ,GAAG,KAAK,CAAU,IAAI,oDAAC;;AAG/B,IAAA,SAAS,GAAG,KAAK,CAA0B,EAAE,qDAAC;;AAG9C,IAAA,IAAI,GAAG,KAAK,CAAiB,QAAQ,gDAAC;;AAGtC,IAAA,IAAI,GAAG,KAAK,CAAC,QAAQ,+CAAU;;AAG/B,IAAA,UAAU,GAAG,MAAM,CAAC,KAAK,sDAAC;;AAG1B,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,uDAAC;;IAG/D,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAA,MAAA,EAAS,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA,CAAE,mDAAC;;IAGpE,KAAK,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;;AAGlF,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,WAAW,IAAI,EAAE,uDAAC;;AAG5D,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAc;AAC3C,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE;AACtB,QAAA,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE;AACvB,YAAA,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;QAClD;AACA,QAAA,OAAO,EAAE;AACV,IAAA,CAAC,qDAAC;AAEF,IAAA,WAAA,GAAA;QACC,MAAM,CAAC,MAAK;AACX,YAAA,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE;AAC1D,gBAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;YAC1B;AACD,QAAA,CAAC,CAAC;IACH;;AAGA,IAAA,cAAc,CAAC,YAAoB,EAAA;QAClC,OAAO,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,YAAY,CAAC;IACjD;;AAGA,IAAA,eAAe,CAAC,YAAoB,EAAA;QACnC,OAAO,CAAA,EAAG,IAAI,CAAC,IAAI,EAAE,CAAA,CAAA,EAAI,YAAY,EAAE;IACxC;uGA3DY,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAlB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EApDpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDT,CAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EA7DA,IAAI,EAAA,QAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACJ,UAAU,EAAA,QAAA,EAAA,kBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACV,SAAS,4DACT,WAAW,EAAA,QAAA,EAAA,mBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,SAAS,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,iBAAA,EAAA,UAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACT,aAAa,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACb,gBAAgB,EAAA,QAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,UAAA,EAAA,UAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,gBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAChB,gBAAgB,iGAChB,aAAa,EAAA,QAAA,EAAA,qBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,UAAA,EAAA,UAAA,EAAA,WAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAuDF,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAlE9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,QAAQ,EAAE,2BAA2B;AACrC,oBAAA,OAAO,EAAE;wBACR,IAAI;wBACJ,UAAU;wBACV,SAAS;wBACT,WAAW;wBACX,SAAS;wBACT,aAAa;wBACb,gBAAgB;wBAChB,gBAAgB;wBAChB,aAAa;AACb,qBAAA;oBACD,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDT,CAAA,CAAA;AACD,iBAAA;;;;;"}
@@ -1135,7 +1135,7 @@ function momentumAdminRoutes(configOrOptions) {
1135
1135
  // Global edit
1136
1136
  {
1137
1137
  path: 'globals/:slug',
1138
- loadComponent: () => import('./momentumcms-admin-global-edit.page-976NlNjw.mjs').then((m) => m.GlobalEditPage),
1138
+ loadComponent: () => import('./momentumcms-admin-global-edit.page-BBUtWCSl.mjs').then((m) => m.GlobalEditPage),
1139
1139
  canDeactivate: [unsavedChangesGuard],
1140
1140
  },
1141
1141
  // Plugin-registered routes
@@ -3530,15 +3530,20 @@ class FieldRenderer {
3530
3530
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: FieldRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
3531
3531
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: FieldRenderer, isStandalone: true, selector: "mcms-field-renderer", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, formNode: { classPropertyName: "formNode", publicName: "formNode", isSignal: true, isRequired: false, transformFunction: null }, formTree: { classPropertyName: "formTree", publicName: "formTree", isSignal: true, isRequired: false, transformFunction: null }, formModel: { classPropertyName: "formModel", publicName: "formModel", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, path: { classPropertyName: "path", publicName: "path", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "block" }, ngImport: i0, template: `
3532
3532
  @if (resolvedComponent()) {
3533
- <ng-container
3534
- *ngComponentOutlet="resolvedComponent(); inputs: rendererInputs()"
3535
- />
3533
+ <ng-container *ngComponentOutlet="resolvedComponent(); inputs: rendererInputs()" />
3536
3534
  } @else if (loadError()) {
3537
- <div role="alert" class="rounded-md border border-destructive/50 bg-destructive/10 p-2 text-sm text-destructive">
3535
+ <div
3536
+ role="alert"
3537
+ class="rounded-md border border-destructive/50 bg-destructive/10 p-2 text-sm text-destructive"
3538
+ >
3538
3539
  Failed to load field renderer
3539
3540
  </div>
3540
3541
  } @else {
3541
- <div role="status" aria-label="Loading field" class="h-10 animate-pulse rounded-md bg-muted"></div>
3542
+ <div
3543
+ role="status"
3544
+ aria-label="Loading field"
3545
+ class="h-10 animate-pulse rounded-md bg-muted"
3546
+ ></div>
3542
3547
  }
3543
3548
  `, isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3544
3549
  }
@@ -3551,15 +3556,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
3551
3556
  host: { class: 'block' },
3552
3557
  template: `
3553
3558
  @if (resolvedComponent()) {
3554
- <ng-container
3555
- *ngComponentOutlet="resolvedComponent(); inputs: rendererInputs()"
3556
- />
3559
+ <ng-container *ngComponentOutlet="resolvedComponent(); inputs: rendererInputs()" />
3557
3560
  } @else if (loadError()) {
3558
- <div role="alert" class="rounded-md border border-destructive/50 bg-destructive/10 p-2 text-sm text-destructive">
3561
+ <div
3562
+ role="alert"
3563
+ class="rounded-md border border-destructive/50 bg-destructive/10 p-2 text-sm text-destructive"
3564
+ >
3559
3565
  Failed to load field renderer
3560
3566
  </div>
3561
3567
  } @else {
3562
- <div role="status" aria-label="Loading field" class="h-10 animate-pulse rounded-md bg-muted"></div>
3568
+ <div
3569
+ role="status"
3570
+ aria-label="Loading field"
3571
+ class="h-10 animate-pulse rounded-md bg-muted"
3572
+ ></div>
3563
3573
  }
3564
3574
  `,
3565
3575
  }]
@@ -12593,18 +12603,18 @@ function provideMomentumFieldRenderers() {
12593
12603
  registry.register('checkbox', () => Promise.resolve().then(function () { return checkboxField_component; }).then((m) => m.CheckboxFieldRenderer));
12594
12604
  registry.register('date', () => Promise.resolve().then(function () { return dateField_component; }).then((m) => m.DateFieldRenderer));
12595
12605
  registry.register('upload', () => Promise.resolve().then(function () { return uploadField_component; }).then((m) => m.UploadFieldRenderer));
12596
- registry.register('richText', () => import('./momentumcms-admin-rich-text-field.component-Djv7tDS2.mjs').then((m) => m.RichTextFieldRenderer));
12606
+ registry.register('richText', () => import('./momentumcms-admin-rich-text-field.component-DKQ6pwp7.mjs').then((m) => m.RichTextFieldRenderer));
12597
12607
  // Layout field renderers (support nested field rendering)
12598
- registry.register('group', () => import('./momentumcms-admin-group-field.component-Bgy_tQOG.mjs').then((m) => m.GroupFieldRenderer));
12599
- registry.register('array', () => import('./momentumcms-admin-array-field.component-BZva87Sh.mjs').then((m) => m.ArrayFieldRenderer));
12600
- registry.register('blocks', () => import('./momentumcms-admin-blocks-field.component-CIxpyKAV.mjs').then((m) => m.BlocksFieldRenderer));
12608
+ registry.register('group', () => import('./momentumcms-admin-group-field.component-BZeG8Oqy.mjs').then((m) => m.GroupFieldRenderer));
12609
+ registry.register('array', () => import('./momentumcms-admin-array-field.component-CT5NlIEv.mjs').then((m) => m.ArrayFieldRenderer));
12610
+ registry.register('blocks', () => import('./momentumcms-admin-blocks-field.component-Cz7HmuBK.mjs').then((m) => m.BlocksFieldRenderer));
12601
12611
  // Visual block editor variant (blocks field with admin.editor === 'visual')
12602
12612
  registry.register('blocks-visual', () => Promise.resolve().then(function () { return visualBlockEditor_component; }).then((m) => m.VisualBlockEditorComponent));
12603
- registry.register('relationship', () => import('./momentumcms-admin-relationship-field.component-s46Lu33u.mjs').then((m) => m.RelationshipFieldRenderer));
12613
+ registry.register('relationship', () => import('./momentumcms-admin-relationship-field.component-BuxtRs2_.mjs').then((m) => m.RelationshipFieldRenderer));
12604
12614
  // Layout-only renderers (tabs, collapsible, row)
12605
- registry.register('tabs', () => import('./momentumcms-admin-tabs-field.component-CdZoCrvw.mjs').then((m) => m.TabsFieldRenderer));
12606
- registry.register('collapsible', () => import('./momentumcms-admin-collapsible-field.component-BpmaUKom.mjs').then((m) => m.CollapsibleFieldRenderer));
12607
- registry.register('row', () => import('./momentumcms-admin-row-field.component-Dc5vqRQ8.mjs').then((m) => m.RowFieldRenderer));
12615
+ registry.register('tabs', () => import('./momentumcms-admin-tabs-field.component-mZ4dpZoD.mjs').then((m) => m.TabsFieldRenderer));
12616
+ registry.register('collapsible', () => import('./momentumcms-admin-collapsible-field.component-CtwrGQvg.mjs').then((m) => m.CollapsibleFieldRenderer));
12617
+ registry.register('row', () => import('./momentumcms-admin-row-field.component-ks3FXd4B.mjs').then((m) => m.RowFieldRenderer));
12608
12618
  };
12609
12619
  },
12610
12620
  },
@@ -14320,4 +14330,4 @@ var uploadField_component = /*#__PURE__*/Object.freeze({
14320
14330
  */
14321
14331
 
14322
14332
  export { adminGuard as $, AdminShellComponent as A, BlockEditDialog as B, CheckboxFieldRenderer as C, DashboardPage as D, EntityFormWidget as E, FieldRenderer as F, MediaLibraryPage as G, MediaPickerDialog as H, MediaPreviewComponent as I, MomentumApiService as J, MomentumAuthService as K, LivePreviewComponent as L, MOMENTUM_API as M, NumberFieldRenderer as N, ResetPasswordPage as O, PublishControlsWidget as P, SKIP_AUTO_TOAST as Q, ResetPasswordFormComponent as R, SHEET_QUERY_PARAMS as S, SelectFieldRenderer as T, SetupPage as U, TextFieldRenderer as V, UploadFieldRenderer as W, UploadService as X, VersionHistoryWidget as Y, VersionService as Z, VisualBlockEditorComponent as _, getFieldNodeState as a, authGuard as a0, collectionAccessGuard as a1, crudToastInterceptor as a2, guestGuard as a3, injectHasAnyRole as a4, injectHasRole as a5, injectIsAdmin as a6, injectIsAuthenticated as a7, injectMomentumAPI as a8, injectTypedMomentumAPI as a9, injectUser as aa, injectUserRole as ab, injectVersionService as ac, momentumAdminRoutes as ad, provideFieldRenderer as ae, provideMomentumAPI as af, provideMomentumFieldRenderers as ag, setupGuard as ah, unsavedChangesGuard as ai, getSubNode as b, getFieldDefaultValue as c, EntitySheetService as d, getTitleField as e, AdminSidebarWidget as f, getGlobalsFromRouteData as g, BlockInserterComponent as h, isRecord as i, BlockWrapperComponent as j, CollectionAccessService as k, CollectionCardWidget as l, CollectionEditPage as m, normalizeBlockDefaults as n, CollectionListPage as o, CollectionViewPage as p, DateFieldRenderer as q, EntityListWidget as r, EntityViewWidget as s, FeedbackService as t, FieldRendererRegistry as u, ForgotPasswordFormComponent as v, ForgotPasswordPage as w, LoginPage as x, MOMENTUM_API_CONTEXT as y, McmsThemeService as z };
14323
- //# sourceMappingURL=momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs.map
14333
+ //# sourceMappingURL=momentumcms-admin-momentumcms-admin-o0FbJXZN.mjs.map