@momentumcms/admin 0.5.10 → 0.5.11
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/fesm2022/{momentumcms-admin-array-field.component-CfbBjPVd.mjs → momentumcms-admin-array-field.component-6pmL6KAy.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-array-field.component-CfbBjPVd.mjs.map → momentumcms-admin-array-field.component-6pmL6KAy.mjs.map} +1 -1
- package/fesm2022/{momentumcms-admin-blocks-field.component-QZ8tLEg6.mjs → momentumcms-admin-blocks-field.component-CB935QxV.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-blocks-field.component-QZ8tLEg6.mjs.map → momentumcms-admin-blocks-field.component-CB935QxV.mjs.map} +1 -1
- package/fesm2022/{momentumcms-admin-collapsible-field.component-BclQc85b.mjs → momentumcms-admin-collapsible-field.component-BeE6OYCo.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-collapsible-field.component-BclQc85b.mjs.map → momentumcms-admin-collapsible-field.component-BeE6OYCo.mjs.map} +1 -1
- package/fesm2022/{momentumcms-admin-global-edit.page-BrSh7EBY.mjs → momentumcms-admin-global-edit.page-DJecoi_H.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-global-edit.page-BrSh7EBY.mjs.map → momentumcms-admin-global-edit.page-DJecoi_H.mjs.map} +1 -1
- package/fesm2022/{momentumcms-admin-group-field.component-BmWE2N0v.mjs → momentumcms-admin-group-field.component-BsA6jGL8.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-group-field.component-BmWE2N0v.mjs.map → momentumcms-admin-group-field.component-BsA6jGL8.mjs.map} +1 -1
- package/fesm2022/{momentumcms-admin-momentumcms-admin-BKepTX-n.mjs → momentumcms-admin-momentumcms-admin-Dm9Ab3iA.mjs} +16 -12
- package/fesm2022/momentumcms-admin-momentumcms-admin-Dm9Ab3iA.mjs.map +1 -0
- package/fesm2022/{momentumcms-admin-relationship-field.component-DQySS2uK.mjs → momentumcms-admin-relationship-field.component-C-qCFaZr.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-relationship-field.component-DQySS2uK.mjs.map → momentumcms-admin-relationship-field.component-C-qCFaZr.mjs.map} +1 -1
- package/fesm2022/{momentumcms-admin-rich-text-field.component-BtPq7BWT.mjs → momentumcms-admin-rich-text-field.component-mX0v9MFC.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-rich-text-field.component-BtPq7BWT.mjs.map → momentumcms-admin-rich-text-field.component-mX0v9MFC.mjs.map} +1 -1
- package/fesm2022/{momentumcms-admin-row-field.component-CDU2ukTM.mjs → momentumcms-admin-row-field.component-JYBMoZRu.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-row-field.component-CDU2ukTM.mjs.map → momentumcms-admin-row-field.component-JYBMoZRu.mjs.map} +1 -1
- package/fesm2022/{momentumcms-admin-tabs-field.component-Dj65PyBW.mjs → momentumcms-admin-tabs-field.component-Df-V5Rex.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-tabs-field.component-Dj65PyBW.mjs.map → momentumcms-admin-tabs-field.component-Df-V5Rex.mjs.map} +1 -1
- package/fesm2022/momentumcms-admin.mjs +1 -1
- package/package.json +1 -1
- package/types/momentumcms-admin.d.ts +1 -0
- package/fesm2022/momentumcms-admin-momentumcms-admin-BKepTX-n.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-
|
|
8
|
+
import { a as getFieldNodeState, i as isRecord, b as getSubNode, c as getFieldDefaultValue, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-Dm9Ab3iA.mjs';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Array field renderer.
|
|
@@ -313,4 +313,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", 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-
|
|
316
|
+
//# sourceMappingURL=momentumcms-admin-array-field.component-6pmL6KAy.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"momentumcms-admin-array-field.component-CfbBjPVd.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-6pmL6KAy.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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"}
|
|
@@ -5,7 +5,7 @@ import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
|
5
5
|
import { heroChevronDown, heroChevronRight, 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-
|
|
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-Dm9Ab3iA.mjs';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Blocks field renderer.
|
|
@@ -448,4 +448,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
448
448
|
}], 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 }] }] } });
|
|
449
449
|
|
|
450
450
|
export { BlocksFieldRenderer };
|
|
451
|
-
//# sourceMappingURL=momentumcms-admin-blocks-field.component-
|
|
451
|
+
//# sourceMappingURL=momentumcms-admin-blocks-field.component-CB935QxV.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"momentumcms-admin-blocks-field.component-QZ8tLEg6.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\tsignal,\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 {\n\theroPlus,\n\theroTrash,\n\theroBars2,\n\theroChevronRight,\n\theroChevronDown,\n} 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, heroChevronRight, heroChevronDown })],\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<button\n\t\t\t\t\t\t\t\t\t\tclass=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground transition-colors\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"toggleBlockCollapse(i)\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"isBlockCollapsed(i) ? 'Expand block' : 'Collapse block'\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-expanded]=\"!isBlockCollapsed(i)\"\n\t\t\t\t\t\t\t\t\t\tdata-testid=\"block-collapse-toggle\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ng-icon\n\t\t\t\t\t\t\t\t\t\t\t[name]=\"isBlockCollapsed(i) ? 'heroChevronRight' : 'heroChevronDown'\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"14\"\n\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t/>\n\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\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@if (!isBlockCollapsed(i)) {\n\t\t\t\t\t\t\t\t\t<div class=\"p-4 space-y-3\" data-testid=\"block-fields\">\n\t\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\t<mcms-field-renderer\n\t\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\t[formNode]=\"getBlockSubNode(i, subField.name)\"\n\t\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\t[formModel]=\"formModel()\"\n\t\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\t[path]=\"getBlockSubFieldPath(i, subField.name)\"\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</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}\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/** Tracks which block indices are collapsed */\n\tprivate readonly collapsedBlocks = signal(new Set<number>());\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/** Whether a block at the given index is collapsed */\n\tisBlockCollapsed(index: number): boolean {\n\t\treturn this.collapsedBlocks().has(index);\n\t}\n\n\t/** Toggle the collapsed state of a block */\n\ttoggleBlockCollapse(index: number): void {\n\t\tconst next = new Set(this.collapsedBlocks());\n\t\tif (next.has(index)) {\n\t\t\tnext.delete(index);\n\t\t} else {\n\t\t\tnext.add(index);\n\t\t}\n\t\tthis.collapsedBlocks.set(next);\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\tthis.remapCollapsedIndicesOnReorder(event.previousIndex, event.currentIndex);\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\tthis.removeCollapsedIndex(index);\n\t}\n\n\t/** Remove an index from collapsedBlocks and shift higher indices down */\n\tprivate removeCollapsedIndex(removedIndex: number): void {\n\t\tconst prev = this.collapsedBlocks();\n\t\tconst next = new Set<number>();\n\t\tfor (const idx of prev) {\n\t\t\tif (idx < removedIndex) {\n\t\t\t\tnext.add(idx);\n\t\t\t} else if (idx > removedIndex) {\n\t\t\t\tnext.add(idx - 1);\n\t\t\t}\n\t\t\t// idx === removedIndex is dropped\n\t\t}\n\t\tthis.collapsedBlocks.set(next);\n\t}\n\n\t/** Remap collapsed indices after a drag-drop reorder */\n\tprivate remapCollapsedIndicesOnReorder(from: number, to: number): void {\n\t\tconst prev = this.collapsedBlocks();\n\t\tconst next = new Set<number>();\n\t\tfor (const idx of prev) {\n\t\t\tif (idx === from) {\n\t\t\t\tnext.add(to);\n\t\t\t} else {\n\t\t\t\tlet mapped = idx;\n\t\t\t\tif (from < to) {\n\t\t\t\t\t// Moved forward: items between (from, to] shift down by 1\n\t\t\t\t\tif (idx > from && idx <= to) mapped = idx - 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Moved backward: items between [to, from) shift up by 1\n\t\t\t\t\tif (idx >= to && idx < from) mapped = idx + 1;\n\t\t\t\t}\n\t\t\t\tnext.add(mapped);\n\t\t\t}\n\t\t}\n\t\tthis.collapsedBlocks.set(next);\n\t}\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"momentumcms-admin-blocks-field.component-CB935QxV.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\tsignal,\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 {\n\theroPlus,\n\theroTrash,\n\theroBars2,\n\theroChevronRight,\n\theroChevronDown,\n} 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, heroChevronRight, heroChevronDown })],\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<button\n\t\t\t\t\t\t\t\t\t\tclass=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:text-foreground transition-colors\"\n\t\t\t\t\t\t\t\t\t\t(click)=\"toggleBlockCollapse(i)\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"isBlockCollapsed(i) ? 'Expand block' : 'Collapse block'\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-expanded]=\"!isBlockCollapsed(i)\"\n\t\t\t\t\t\t\t\t\t\tdata-testid=\"block-collapse-toggle\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<ng-icon\n\t\t\t\t\t\t\t\t\t\t\t[name]=\"isBlockCollapsed(i) ? 'heroChevronRight' : 'heroChevronDown'\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"14\"\n\t\t\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\t\t/>\n\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\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@if (!isBlockCollapsed(i)) {\n\t\t\t\t\t\t\t\t\t<div class=\"p-4 space-y-3\" data-testid=\"block-fields\">\n\t\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\t<mcms-field-renderer\n\t\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\t[formNode]=\"getBlockSubNode(i, subField.name)\"\n\t\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\t[formModel]=\"formModel()\"\n\t\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\t[path]=\"getBlockSubFieldPath(i, subField.name)\"\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</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}\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/** Tracks which block indices are collapsed */\n\tprivate readonly collapsedBlocks = signal(new Set<number>());\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/** Whether a block at the given index is collapsed */\n\tisBlockCollapsed(index: number): boolean {\n\t\treturn this.collapsedBlocks().has(index);\n\t}\n\n\t/** Toggle the collapsed state of a block */\n\ttoggleBlockCollapse(index: number): void {\n\t\tconst next = new Set(this.collapsedBlocks());\n\t\tif (next.has(index)) {\n\t\t\tnext.delete(index);\n\t\t} else {\n\t\t\tnext.add(index);\n\t\t}\n\t\tthis.collapsedBlocks.set(next);\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\tthis.remapCollapsedIndicesOnReorder(event.previousIndex, event.currentIndex);\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\tthis.removeCollapsedIndex(index);\n\t}\n\n\t/** Remove an index from collapsedBlocks and shift higher indices down */\n\tprivate removeCollapsedIndex(removedIndex: number): void {\n\t\tconst prev = this.collapsedBlocks();\n\t\tconst next = new Set<number>();\n\t\tfor (const idx of prev) {\n\t\t\tif (idx < removedIndex) {\n\t\t\t\tnext.add(idx);\n\t\t\t} else if (idx > removedIndex) {\n\t\t\t\tnext.add(idx - 1);\n\t\t\t}\n\t\t\t// idx === removedIndex is dropped\n\t\t}\n\t\tthis.collapsedBlocks.set(next);\n\t}\n\n\t/** Remap collapsed indices after a drag-drop reorder */\n\tprivate remapCollapsedIndicesOnReorder(from: number, to: number): void {\n\t\tconst prev = this.collapsedBlocks();\n\t\tconst next = new Set<number>();\n\t\tfor (const idx of prev) {\n\t\t\tif (idx === from) {\n\t\t\t\tnext.add(to);\n\t\t\t} else {\n\t\t\t\tlet mapped = idx;\n\t\t\t\tif (from < to) {\n\t\t\t\t\t// Moved forward: items between (from, to] shift down by 1\n\t\t\t\t\tif (idx > from && idx <= to) mapped = idx - 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Moved backward: items between [to, from) shift up by 1\n\t\t\t\t\tif (idx >= to && idx < from) mapped = idx + 1;\n\t\t\t\t}\n\t\t\t\tnext.add(mapped);\n\t\t\t}\n\t\t}\n\t\tthis.collapsedBlocks.set(next);\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-
|
|
5
|
+
import { b as getSubNode, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-Dm9Ab3iA.mjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Collapsible layout field renderer.
|
|
@@ -117,4 +117,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
117
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 }] }] } });
|
|
118
118
|
|
|
119
119
|
export { CollapsibleFieldRenderer };
|
|
120
|
-
//# sourceMappingURL=momentumcms-admin-collapsible-field.component-
|
|
120
|
+
//# sourceMappingURL=momentumcms-admin-collapsible-field.component-BeE6OYCo.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"momentumcms-admin-collapsible-field.component-
|
|
1
|
+
{"version":3,"file":"momentumcms-admin-collapsible-field.component-BeE6OYCo.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-
|
|
5
|
+
import { g as getGlobalsFromRouteData, E as EntityFormWidget } from './momentumcms-admin-momentumcms-admin-Dm9Ab3iA.mjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Global Edit Page
|
|
@@ -87,4 +87,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", 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-
|
|
90
|
+
//# sourceMappingURL=momentumcms-admin-global-edit.page-DJecoi_H.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"momentumcms-admin-global-edit.page-
|
|
1
|
+
{"version":3,"file":"momentumcms-admin-global-edit.page-DJecoi_H.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-
|
|
5
|
+
import { b as getSubNode, F as FieldRenderer } from './momentumcms-admin-momentumcms-admin-Dm9Ab3iA.mjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Group field renderer.
|
|
@@ -181,4 +181,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", 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-
|
|
184
|
+
//# sourceMappingURL=momentumcms-admin-group-field.component-BsA6jGL8.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"momentumcms-admin-group-field.component-
|
|
1
|
+
{"version":3,"file":"momentumcms-admin-group-field.component-BsA6jGL8.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":"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"}
|
|
@@ -1193,7 +1193,7 @@ function momentumAdminRoutes(configOrOptions) {
|
|
|
1193
1193
|
loadComponent: () => Promise.resolve().then(function () { return adminPageResolver_component; }).then((m) => m.AdminPageResolver),
|
|
1194
1194
|
data: {
|
|
1195
1195
|
adminPageKey: 'global-edit',
|
|
1196
|
-
adminPageFallback: () => import('./momentumcms-admin-global-edit.page-
|
|
1196
|
+
adminPageFallback: () => import('./momentumcms-admin-global-edit.page-DJecoi_H.mjs').then((m) => m.GlobalEditPage),
|
|
1197
1197
|
},
|
|
1198
1198
|
canDeactivate: [unsavedChangesGuard],
|
|
1199
1199
|
},
|
|
@@ -2869,7 +2869,7 @@ class McmsThemeService {
|
|
|
2869
2869
|
setTheme(theme) {
|
|
2870
2870
|
this.theme.set(theme);
|
|
2871
2871
|
if (this.isBrowser) {
|
|
2872
|
-
this.
|
|
2872
|
+
this.getStorage()?.setItem(THEME_STORAGE_KEY, theme);
|
|
2873
2873
|
this.document.cookie = `${THEME_STORAGE_KEY}=${theme}; path=/; max-age=31536000; SameSite=Lax`;
|
|
2874
2874
|
}
|
|
2875
2875
|
}
|
|
@@ -2881,6 +2881,10 @@ class McmsThemeService {
|
|
|
2881
2881
|
const current = this.resolvedTheme();
|
|
2882
2882
|
this.setTheme(current === 'dark' ? 'light' : 'dark');
|
|
2883
2883
|
}
|
|
2884
|
+
getStorage() {
|
|
2885
|
+
const storage = this.document.defaultView?.localStorage;
|
|
2886
|
+
return storage && typeof storage.getItem === 'function' ? storage : null;
|
|
2887
|
+
}
|
|
2884
2888
|
/**
|
|
2885
2889
|
* Loads theme from localStorage or defaults to 'system'.
|
|
2886
2890
|
*/
|
|
@@ -2888,7 +2892,7 @@ class McmsThemeService {
|
|
|
2888
2892
|
if (!this.isBrowser) {
|
|
2889
2893
|
return 'system';
|
|
2890
2894
|
}
|
|
2891
|
-
const stored = this.
|
|
2895
|
+
const stored = this.getStorage()?.getItem(THEME_STORAGE_KEY) ?? null;
|
|
2892
2896
|
if (stored === 'light' || stored === 'dark' || stored === 'system') {
|
|
2893
2897
|
return stored;
|
|
2894
2898
|
}
|
|
@@ -14810,18 +14814,18 @@ function provideMomentumFieldRenderers() {
|
|
|
14810
14814
|
registry.register('checkbox', () => Promise.resolve().then(function () { return checkboxField_component; }).then((m) => m.CheckboxFieldRenderer));
|
|
14811
14815
|
registry.register('date', () => Promise.resolve().then(function () { return dateField_component; }).then((m) => m.DateFieldRenderer));
|
|
14812
14816
|
registry.register('upload', () => Promise.resolve().then(function () { return uploadField_component; }).then((m) => m.UploadFieldRenderer));
|
|
14813
|
-
registry.register('richText', () => import('./momentumcms-admin-rich-text-field.component-
|
|
14817
|
+
registry.register('richText', () => import('./momentumcms-admin-rich-text-field.component-mX0v9MFC.mjs').then((m) => m.RichTextFieldRenderer));
|
|
14814
14818
|
// Layout field renderers (support nested field rendering)
|
|
14815
|
-
registry.register('group', () => import('./momentumcms-admin-group-field.component-
|
|
14816
|
-
registry.register('array', () => import('./momentumcms-admin-array-field.component-
|
|
14817
|
-
registry.register('blocks', () => import('./momentumcms-admin-blocks-field.component-
|
|
14819
|
+
registry.register('group', () => import('./momentumcms-admin-group-field.component-BsA6jGL8.mjs').then((m) => m.GroupFieldRenderer));
|
|
14820
|
+
registry.register('array', () => import('./momentumcms-admin-array-field.component-6pmL6KAy.mjs').then((m) => m.ArrayFieldRenderer));
|
|
14821
|
+
registry.register('blocks', () => import('./momentumcms-admin-blocks-field.component-CB935QxV.mjs').then((m) => m.BlocksFieldRenderer));
|
|
14818
14822
|
// Visual block editor variant (blocks field with admin.editor === 'visual')
|
|
14819
14823
|
registry.register('blocks-visual', () => Promise.resolve().then(function () { return visualBlockEditor_component; }).then((m) => m.VisualBlockEditorComponent));
|
|
14820
|
-
registry.register('relationship', () => import('./momentumcms-admin-relationship-field.component-
|
|
14824
|
+
registry.register('relationship', () => import('./momentumcms-admin-relationship-field.component-C-qCFaZr.mjs').then((m) => m.RelationshipFieldRenderer));
|
|
14821
14825
|
// Layout-only renderers (tabs, collapsible, row)
|
|
14822
|
-
registry.register('tabs', () => import('./momentumcms-admin-tabs-field.component-
|
|
14823
|
-
registry.register('collapsible', () => import('./momentumcms-admin-collapsible-field.component-
|
|
14824
|
-
registry.register('row', () => import('./momentumcms-admin-row-field.component-
|
|
14826
|
+
registry.register('tabs', () => import('./momentumcms-admin-tabs-field.component-Df-V5Rex.mjs').then((m) => m.TabsFieldRenderer));
|
|
14827
|
+
registry.register('collapsible', () => import('./momentumcms-admin-collapsible-field.component-BeE6OYCo.mjs').then((m) => m.CollapsibleFieldRenderer));
|
|
14828
|
+
registry.register('row', () => import('./momentumcms-admin-row-field.component-JYBMoZRu.mjs').then((m) => m.RowFieldRenderer));
|
|
14825
14829
|
};
|
|
14826
14830
|
},
|
|
14827
14831
|
},
|
|
@@ -16699,4 +16703,4 @@ var uploadField_component = /*#__PURE__*/Object.freeze({
|
|
|
16699
16703
|
*/
|
|
16700
16704
|
|
|
16701
16705
|
export { UploadService as $, AdminComponentRegistry as A, BlockEditDialog as B, CheckboxFieldRenderer as C, DashboardPage as D, EntityFormWidget as E, FieldRenderer as F, ForgotPasswordPage as G, LoginPage as H, MOMENTUM_API_CONTEXT as I, McmsThemeService as J, MediaLibraryPage as K, LivePreviewComponent as L, MOMENTUM_API as M, MediaPickerDialog as N, MediaPreviewComponent as O, MomentumApiService as P, MomentumAuthService as Q, NumberFieldRenderer as R, PublishControlsWidget as S, ResetPasswordFormComponent as T, ResetPasswordPage as U, SHEET_QUERY_PARAMS as V, SKIP_AUTO_TOAST as W, SelectFieldRenderer as X, SetupPage as Y, TextFieldRenderer as Z, UploadFieldRenderer as _, getFieldNodeState as a, VersionHistoryWidget as a0, VersionService as a1, VisualBlockEditorComponent as a2, adminGuard as a3, authGuard as a4, collectionAccessGuard as a5, crudToastInterceptor as a6, guestGuard as a7, injectHasAnyRole as a8, injectHasRole as a9, injectIsAdmin as aa, injectIsAuthenticated as ab, injectMomentumAPI as ac, injectTypedMomentumAPI as ad, injectUser as ae, injectUserRole as af, injectVersionService as ag, momentumAdminRoutes as ah, provideAdminComponent as ai, provideAdminSlot as aj, provideFieldRenderer as ak, provideMomentumAPI as al, provideMomentumFieldRenderers as am, registerConfigComponents as an, setupGuard as ao, unsavedChangesGuard as ap, getSubNode as b, getFieldDefaultValue as c, EntitySheetService as d, getTitleField as e, AdminPageResolver as f, getGlobalsFromRouteData as g, AdminShellComponent as h, isRecord as i, AdminSidebarWidget as j, AdminSlotOutlet as k, AdminSlotRegistry as l, BlockInserterComponent as m, normalizeBlockDefaults as n, BlockWrapperComponent as o, CollectionAccessService as p, CollectionCardWidget as q, CollectionEditPage as r, CollectionListPage as s, CollectionViewPage as t, DateFieldRenderer as u, EntityListWidget as v, EntityViewWidget as w, FeedbackService as x, FieldRendererRegistry as y, ForgotPasswordFormComponent as z };
|
|
16702
|
-
//# sourceMappingURL=momentumcms-admin-momentumcms-admin-
|
|
16706
|
+
//# sourceMappingURL=momentumcms-admin-momentumcms-admin-Dm9Ab3iA.mjs.map
|