@momentumcms/admin 0.1.8 → 0.1.10
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-BZva87Sh.mjs +316 -0
- package/fesm2022/momentumcms-admin-array-field.component-BZva87Sh.mjs.map +1 -0
- package/fesm2022/momentumcms-admin-blocks-field.component-CIxpyKAV.mjs +362 -0
- package/fesm2022/momentumcms-admin-blocks-field.component-CIxpyKAV.mjs.map +1 -0
- package/fesm2022/momentumcms-admin-collapsible-field.component-BpmaUKom.mjs +126 -0
- package/fesm2022/momentumcms-admin-collapsible-field.component-BpmaUKom.mjs.map +1 -0
- package/fesm2022/{momentumcms-admin-global-edit.page-DFDV-uh3.mjs → momentumcms-admin-global-edit.page-976NlNjw.mjs} +2 -2
- package/fesm2022/{momentumcms-admin-global-edit.page-DFDV-uh3.mjs.map → momentumcms-admin-global-edit.page-976NlNjw.mjs.map} +1 -1
- package/fesm2022/momentumcms-admin-group-field.component-Bgy_tQOG.mjs +184 -0
- package/fesm2022/momentumcms-admin-group-field.component-Bgy_tQOG.mjs.map +1 -0
- package/fesm2022/{momentumcms-admin-momentumcms-admin-z82jXEsP.mjs → momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs} +9680 -12243
- package/fesm2022/momentumcms-admin-momentumcms-admin-TvEIOeYg.mjs.map +1 -0
- package/fesm2022/momentumcms-admin-relationship-field.component-s46Lu33u.mjs +473 -0
- package/fesm2022/momentumcms-admin-relationship-field.component-s46Lu33u.mjs.map +1 -0
- package/fesm2022/momentumcms-admin-rich-text-field.component-Djv7tDS2.mjs +813 -0
- package/fesm2022/momentumcms-admin-rich-text-field.component-Djv7tDS2.mjs.map +1 -0
- package/fesm2022/momentumcms-admin-row-field.component-Dc5vqRQ8.mjs +98 -0
- package/fesm2022/momentumcms-admin-row-field.component-Dc5vqRQ8.mjs.map +1 -0
- package/fesm2022/momentumcms-admin-tabs-field.component-CdZoCrvw.mjs +127 -0
- package/fesm2022/momentumcms-admin-tabs-field.component-CdZoCrvw.mjs.map +1 -0
- package/fesm2022/momentumcms-admin.mjs +1 -1
- package/package.json +1 -1
- package/types/momentumcms-admin.d.ts +79 -13
- package/fesm2022/momentumcms-admin-momentumcms-admin-z82jXEsP.mjs.map +0 -1
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { moveItemInArray, CdkDropList, CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
|
|
4
|
+
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
5
|
+
import { heroBars2, heroTrash, heroPlus } from '@ng-icons/heroicons/outline';
|
|
6
|
+
import { Card, CardHeader, CardTitle, CardContent, CardFooter, Button } from '@momentumcms/ui';
|
|
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';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Array field renderer.
|
|
12
|
+
*
|
|
13
|
+
* Renders an array of rows, each row displayed as a card with sub-fields.
|
|
14
|
+
* Supports add/remove rows and drag-drop reordering via CDK DragDrop.
|
|
15
|
+
* Respects minRows/maxRows constraints.
|
|
16
|
+
*
|
|
17
|
+
* Data container pattern: passes row sub-field FieldTree nodes via
|
|
18
|
+
* getSubNode(getSubNode(formNode, rowIndex), subFieldName).
|
|
19
|
+
* Array mutations use nodeState.value.set(newArray).
|
|
20
|
+
*/
|
|
21
|
+
class ArrayFieldRenderer {
|
|
22
|
+
/** Field definition (must be an ArrayField) */
|
|
23
|
+
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
24
|
+
/** Signal forms FieldTree node for this array */
|
|
25
|
+
formNode = input(null, ...(ngDevMode ? [{ debugName: "formNode" }] : []));
|
|
26
|
+
/** Root signal forms FieldTree (for layout fields that look up child nodes) */
|
|
27
|
+
formTree = input(null, ...(ngDevMode ? [{ debugName: "formTree" }] : []));
|
|
28
|
+
/** Form model data (for condition evaluation and relationship filterOptions) */
|
|
29
|
+
formModel = input({}, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
|
|
30
|
+
/** Form mode */
|
|
31
|
+
mode = input('create', ...(ngDevMode ? [{ debugName: "mode" }] : []));
|
|
32
|
+
/** Field path (e.g., "features") */
|
|
33
|
+
path = input.required(...(ngDevMode ? [{ debugName: "path" }] : []));
|
|
34
|
+
/** Bridge: extract FieldState from formNode */
|
|
35
|
+
nodeState = computed(() => getFieldNodeState(this.formNode()), ...(ngDevMode ? [{ debugName: "nodeState" }] : []));
|
|
36
|
+
/** Computed label */
|
|
37
|
+
label = computed(() => this.field().label || humanizeFieldName(this.field().name), ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
38
|
+
/** Computed description */
|
|
39
|
+
description = computed(() => this.field().description || '', ...(ngDevMode ? [{ debugName: "description" }] : []));
|
|
40
|
+
/** Sub-fields from the array definition */
|
|
41
|
+
subFields = computed(() => {
|
|
42
|
+
const f = this.field();
|
|
43
|
+
if (f.type === 'array') {
|
|
44
|
+
return f.fields.filter((sf) => !sf.admin?.hidden);
|
|
45
|
+
}
|
|
46
|
+
return [];
|
|
47
|
+
}, ...(ngDevMode ? [{ debugName: "subFields" }] : []));
|
|
48
|
+
/** Min rows constraint */
|
|
49
|
+
minRows = computed(() => {
|
|
50
|
+
const f = this.field();
|
|
51
|
+
return f.type === 'array' ? (f.minRows ?? 0) : 0;
|
|
52
|
+
}, ...(ngDevMode ? [{ debugName: "minRows" }] : []));
|
|
53
|
+
/** Max rows constraint */
|
|
54
|
+
maxRows = computed(() => {
|
|
55
|
+
const f = this.field();
|
|
56
|
+
return f.type === 'array' ? f.maxRows : undefined;
|
|
57
|
+
}, ...(ngDevMode ? [{ debugName: "maxRows" }] : []));
|
|
58
|
+
/** Current rows as array of objects (read from FieldState) */
|
|
59
|
+
rows = computed(() => {
|
|
60
|
+
const state = this.nodeState();
|
|
61
|
+
if (!state)
|
|
62
|
+
return [];
|
|
63
|
+
const val = state.value();
|
|
64
|
+
if (Array.isArray(val)) {
|
|
65
|
+
return val.map((item) => (isRecord(item) ? item : {}));
|
|
66
|
+
}
|
|
67
|
+
return [];
|
|
68
|
+
}, ...(ngDevMode ? [{ debugName: "rows" }] : []));
|
|
69
|
+
/** Whether the field is disabled (view mode) */
|
|
70
|
+
isDisabled = computed(() => this.mode() === 'view', ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
71
|
+
/** Whether a new row can be added */
|
|
72
|
+
canAddRow = computed(() => {
|
|
73
|
+
if (this.isDisabled())
|
|
74
|
+
return false;
|
|
75
|
+
const max = this.maxRows();
|
|
76
|
+
return max === undefined || this.rows().length < max;
|
|
77
|
+
}, ...(ngDevMode ? [{ debugName: "canAddRow" }] : []));
|
|
78
|
+
/** Whether rows can be removed */
|
|
79
|
+
canRemoveRow = computed(() => {
|
|
80
|
+
if (this.isDisabled())
|
|
81
|
+
return false;
|
|
82
|
+
return this.rows().length > this.minRows();
|
|
83
|
+
}, ...(ngDevMode ? [{ debugName: "canRemoveRow" }] : []));
|
|
84
|
+
/** Get a FieldTree sub-node for a row's sub-field */
|
|
85
|
+
getRowSubNode(rowIndex, subFieldName) {
|
|
86
|
+
const rowNode = getSubNode(this.formNode(), rowIndex);
|
|
87
|
+
return getSubNode(rowNode, subFieldName);
|
|
88
|
+
}
|
|
89
|
+
/** Get the full path for a row's sub-field */
|
|
90
|
+
getRowSubFieldPath(rowIndex, subFieldName) {
|
|
91
|
+
return `${this.path()}.${rowIndex}.${subFieldName}`;
|
|
92
|
+
}
|
|
93
|
+
/** Handle drag-drop reorder */
|
|
94
|
+
onDrop(event) {
|
|
95
|
+
const state = this.nodeState();
|
|
96
|
+
if (!state)
|
|
97
|
+
return;
|
|
98
|
+
const rows = [...this.rows()];
|
|
99
|
+
moveItemInArray(rows, event.previousIndex, event.currentIndex);
|
|
100
|
+
state.value.set(rows);
|
|
101
|
+
}
|
|
102
|
+
/** Add a new empty row */
|
|
103
|
+
addRow() {
|
|
104
|
+
const state = this.nodeState();
|
|
105
|
+
if (!state)
|
|
106
|
+
return;
|
|
107
|
+
const rows = [...this.rows()];
|
|
108
|
+
const newRow = {};
|
|
109
|
+
for (const field of this.subFields()) {
|
|
110
|
+
newRow[field.name] = getFieldDefaultValue(field);
|
|
111
|
+
}
|
|
112
|
+
rows.push(newRow);
|
|
113
|
+
state.value.set(rows);
|
|
114
|
+
}
|
|
115
|
+
/** Remove a row at the given index */
|
|
116
|
+
removeRow(index) {
|
|
117
|
+
const state = this.nodeState();
|
|
118
|
+
if (!state)
|
|
119
|
+
return;
|
|
120
|
+
const rows = this.rows().filter((_, i) => i !== index);
|
|
121
|
+
state.value.set(rows);
|
|
122
|
+
}
|
|
123
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ArrayFieldRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
124
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ArrayFieldRenderer, isStandalone: true, selector: "mcms-array-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 } }, providers: [provideIcons({ heroPlus, heroTrash, heroBars2 })], ngImport: i0, template: `
|
|
125
|
+
<mcms-card>
|
|
126
|
+
<mcms-card-header>
|
|
127
|
+
<div class="flex items-center justify-between">
|
|
128
|
+
<div>
|
|
129
|
+
<mcms-card-title>{{ label() }}</mcms-card-title>
|
|
130
|
+
@if (description()) {
|
|
131
|
+
<p class="text-sm text-muted-foreground mt-1">{{ description() }}</p>
|
|
132
|
+
}
|
|
133
|
+
</div>
|
|
134
|
+
<span class="text-sm text-muted-foreground">
|
|
135
|
+
{{ rows().length }}{{ maxRows() ? ' / ' + maxRows() : '' }} rows
|
|
136
|
+
</span>
|
|
137
|
+
</div>
|
|
138
|
+
</mcms-card-header>
|
|
139
|
+
<mcms-card-content>
|
|
140
|
+
@if (rows().length === 0) {
|
|
141
|
+
<p class="text-sm text-muted-foreground py-4 text-center">
|
|
142
|
+
No items yet. Click "Add Row" to get started.
|
|
143
|
+
</p>
|
|
144
|
+
} @else {
|
|
145
|
+
<div
|
|
146
|
+
cdkDropList
|
|
147
|
+
(cdkDropListDropped)="onDrop($event)"
|
|
148
|
+
class="space-y-3"
|
|
149
|
+
role="list"
|
|
150
|
+
aria-label="Array rows"
|
|
151
|
+
>
|
|
152
|
+
@for (row of rows(); track $index; let i = $index) {
|
|
153
|
+
<div
|
|
154
|
+
cdkDrag
|
|
155
|
+
class="border rounded-lg p-4 bg-card flex gap-3 items-start"
|
|
156
|
+
[cdkDragDisabled]="isDisabled()"
|
|
157
|
+
>
|
|
158
|
+
<div
|
|
159
|
+
cdkDragHandle
|
|
160
|
+
class="cursor-grab pt-1 text-muted-foreground hover:text-foreground"
|
|
161
|
+
[class.hidden]="isDisabled()"
|
|
162
|
+
role="button"
|
|
163
|
+
tabindex="0"
|
|
164
|
+
[attr.aria-label]="'Reorder row ' + (i + 1)"
|
|
165
|
+
aria-roledescription="sortable"
|
|
166
|
+
>
|
|
167
|
+
<ng-icon name="heroBars2" size="16" aria-hidden="true" />
|
|
168
|
+
</div>
|
|
169
|
+
<div class="flex-1 space-y-3">
|
|
170
|
+
@for (subField of subFields(); track subField.name) {
|
|
171
|
+
<mcms-field-renderer
|
|
172
|
+
[field]="subField"
|
|
173
|
+
[formNode]="getRowSubNode(i, subField.name)"
|
|
174
|
+
[formTree]="formTree()"
|
|
175
|
+
[formModel]="formModel()"
|
|
176
|
+
[mode]="mode()"
|
|
177
|
+
[path]="getRowSubFieldPath(i, subField.name)"
|
|
178
|
+
/>
|
|
179
|
+
}
|
|
180
|
+
</div>
|
|
181
|
+
@if (canRemoveRow()) {
|
|
182
|
+
<button
|
|
183
|
+
mcms-button
|
|
184
|
+
variant="ghost"
|
|
185
|
+
size="icon"
|
|
186
|
+
class="shrink-0 text-destructive hover:text-destructive"
|
|
187
|
+
(click)="removeRow(i)"
|
|
188
|
+
[attr.aria-label]="'Remove row ' + (i + 1)"
|
|
189
|
+
>
|
|
190
|
+
<ng-icon name="heroTrash" size="16" aria-hidden="true" />
|
|
191
|
+
</button>
|
|
192
|
+
}
|
|
193
|
+
</div>
|
|
194
|
+
}
|
|
195
|
+
</div>
|
|
196
|
+
}
|
|
197
|
+
</mcms-card-content>
|
|
198
|
+
@if (canAddRow()) {
|
|
199
|
+
<mcms-card-footer>
|
|
200
|
+
<button mcms-button variant="outline" (click)="addRow()">
|
|
201
|
+
<ng-icon name="heroPlus" size="16" aria-hidden="true" />
|
|
202
|
+
Add Row
|
|
203
|
+
</button>
|
|
204
|
+
</mcms-card-footer>
|
|
205
|
+
}
|
|
206
|
+
</mcms-card>
|
|
207
|
+
`, isInline: true, dependencies: [{ kind: "component", type: Card, selector: "mcms-card" }, { kind: "component", type: CardHeader, selector: "mcms-card-header" }, { kind: "component", type: CardTitle, selector: "mcms-card-title" }, { kind: "component", type: CardContent, selector: "mcms-card-content" }, { kind: "component", type: CardFooter, selector: "mcms-card-footer" }, { kind: "component", type: Button, selector: "button[mcms-button], a[mcms-button]", inputs: ["variant", "size", "disabled", "loading", "ariaLabel", "class"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: FieldRenderer, selector: "mcms-field-renderer", inputs: ["field", "formNode", "formTree", "formModel", "mode", "path"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
208
|
+
}
|
|
209
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ArrayFieldRenderer, decorators: [{
|
|
210
|
+
type: Component,
|
|
211
|
+
args: [{
|
|
212
|
+
selector: 'mcms-array-field-renderer',
|
|
213
|
+
imports: [
|
|
214
|
+
Card,
|
|
215
|
+
CardHeader,
|
|
216
|
+
CardTitle,
|
|
217
|
+
CardContent,
|
|
218
|
+
CardFooter,
|
|
219
|
+
Button,
|
|
220
|
+
NgIcon,
|
|
221
|
+
CdkDropList,
|
|
222
|
+
CdkDrag,
|
|
223
|
+
CdkDragHandle,
|
|
224
|
+
FieldRenderer,
|
|
225
|
+
],
|
|
226
|
+
providers: [provideIcons({ heroPlus, heroTrash, heroBars2 })],
|
|
227
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
228
|
+
template: `
|
|
229
|
+
<mcms-card>
|
|
230
|
+
<mcms-card-header>
|
|
231
|
+
<div class="flex items-center justify-between">
|
|
232
|
+
<div>
|
|
233
|
+
<mcms-card-title>{{ label() }}</mcms-card-title>
|
|
234
|
+
@if (description()) {
|
|
235
|
+
<p class="text-sm text-muted-foreground mt-1">{{ description() }}</p>
|
|
236
|
+
}
|
|
237
|
+
</div>
|
|
238
|
+
<span class="text-sm text-muted-foreground">
|
|
239
|
+
{{ rows().length }}{{ maxRows() ? ' / ' + maxRows() : '' }} rows
|
|
240
|
+
</span>
|
|
241
|
+
</div>
|
|
242
|
+
</mcms-card-header>
|
|
243
|
+
<mcms-card-content>
|
|
244
|
+
@if (rows().length === 0) {
|
|
245
|
+
<p class="text-sm text-muted-foreground py-4 text-center">
|
|
246
|
+
No items yet. Click "Add Row" to get started.
|
|
247
|
+
</p>
|
|
248
|
+
} @else {
|
|
249
|
+
<div
|
|
250
|
+
cdkDropList
|
|
251
|
+
(cdkDropListDropped)="onDrop($event)"
|
|
252
|
+
class="space-y-3"
|
|
253
|
+
role="list"
|
|
254
|
+
aria-label="Array rows"
|
|
255
|
+
>
|
|
256
|
+
@for (row of rows(); track $index; let i = $index) {
|
|
257
|
+
<div
|
|
258
|
+
cdkDrag
|
|
259
|
+
class="border rounded-lg p-4 bg-card flex gap-3 items-start"
|
|
260
|
+
[cdkDragDisabled]="isDisabled()"
|
|
261
|
+
>
|
|
262
|
+
<div
|
|
263
|
+
cdkDragHandle
|
|
264
|
+
class="cursor-grab pt-1 text-muted-foreground hover:text-foreground"
|
|
265
|
+
[class.hidden]="isDisabled()"
|
|
266
|
+
role="button"
|
|
267
|
+
tabindex="0"
|
|
268
|
+
[attr.aria-label]="'Reorder row ' + (i + 1)"
|
|
269
|
+
aria-roledescription="sortable"
|
|
270
|
+
>
|
|
271
|
+
<ng-icon name="heroBars2" size="16" aria-hidden="true" />
|
|
272
|
+
</div>
|
|
273
|
+
<div class="flex-1 space-y-3">
|
|
274
|
+
@for (subField of subFields(); track subField.name) {
|
|
275
|
+
<mcms-field-renderer
|
|
276
|
+
[field]="subField"
|
|
277
|
+
[formNode]="getRowSubNode(i, subField.name)"
|
|
278
|
+
[formTree]="formTree()"
|
|
279
|
+
[formModel]="formModel()"
|
|
280
|
+
[mode]="mode()"
|
|
281
|
+
[path]="getRowSubFieldPath(i, subField.name)"
|
|
282
|
+
/>
|
|
283
|
+
}
|
|
284
|
+
</div>
|
|
285
|
+
@if (canRemoveRow()) {
|
|
286
|
+
<button
|
|
287
|
+
mcms-button
|
|
288
|
+
variant="ghost"
|
|
289
|
+
size="icon"
|
|
290
|
+
class="shrink-0 text-destructive hover:text-destructive"
|
|
291
|
+
(click)="removeRow(i)"
|
|
292
|
+
[attr.aria-label]="'Remove row ' + (i + 1)"
|
|
293
|
+
>
|
|
294
|
+
<ng-icon name="heroTrash" size="16" aria-hidden="true" />
|
|
295
|
+
</button>
|
|
296
|
+
}
|
|
297
|
+
</div>
|
|
298
|
+
}
|
|
299
|
+
</div>
|
|
300
|
+
}
|
|
301
|
+
</mcms-card-content>
|
|
302
|
+
@if (canAddRow()) {
|
|
303
|
+
<mcms-card-footer>
|
|
304
|
+
<button mcms-button variant="outline" (click)="addRow()">
|
|
305
|
+
<ng-icon name="heroPlus" size="16" aria-hidden="true" />
|
|
306
|
+
Add Row
|
|
307
|
+
</button>
|
|
308
|
+
</mcms-card-footer>
|
|
309
|
+
}
|
|
310
|
+
</mcms-card>
|
|
311
|
+
`,
|
|
312
|
+
}]
|
|
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
|
+
|
|
315
|
+
export { ArrayFieldRenderer };
|
|
316
|
+
//# sourceMappingURL=momentumcms-admin-array-field.component-BZva87Sh.mjs.map
|
|
@@ -0,0 +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":";;;;;;;;;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;;;;;"}
|