@aglyn/plugins-forms 1.0.0-beta.246 → 1.0.0-beta.249
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/package.json +14 -14
- package/src/lib/components/form.d.ts +9 -0
- package/src/lib/components/form.js +138 -90
- package/src/lib/components/form.js.map +1 -1
- package/src/lib/model/form-field-elements.d.ts +132 -0
- package/src/lib/model/form-field-elements.js +511 -0
- package/src/lib/model/form-field-elements.js.map +1 -0
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /*
|
|
17
|
+
* ONE ALL-IN-ONE FORM FIELD, REBUILT FROM MUI'S SEPARATE FORM ELEMENTS.
|
|
18
|
+
*
|
|
19
|
+
* Every piece of a field is its own Besigner element now (a Form Control
|
|
20
|
+
* holding a Form Label and an Input, a Select of Select Options, a Radio Group
|
|
21
|
+
* of Radios in Choice Labels, Checkboxes in Choice Labels, a Rating), so an
|
|
22
|
+
* author selects and styles each piece with the ordinary Styles panel. The
|
|
23
|
+
* all-in-one `formField` is still registered so a document nobody has migrated
|
|
24
|
+
* keeps drawing, and this module is how each one is moved off it: the seeds,
|
|
25
|
+
* the presets and `tools/scripts/backfill-formfield-elements.mjs` all build the
|
|
26
|
+
* same tree from the same rules.
|
|
27
|
+
*
|
|
28
|
+
* What must survive the move, exactly:
|
|
29
|
+
*
|
|
30
|
+
* - **The field's id.** It stays on the Form Control wrapper, so a parent's
|
|
31
|
+
* `nodes` list, a reveal target and every placement override keyed by it
|
|
32
|
+
* still find the field. The wrapper takes the field's `sx` with it.
|
|
33
|
+
* - **The name it submits under.** Contact-field mappings, dataset bindings
|
|
34
|
+
* and the consent field all key on it, so it is copied verbatim.
|
|
35
|
+
* - **Everything a placement overrode.** A placed form's `attrOverrides`
|
|
36
|
+
* named the field's id and a prop of the all-in-one element; the slice is
|
|
37
|
+
* re-keyed onto the piece that now owns that prop.
|
|
38
|
+
*
|
|
39
|
+
* It lives with the forms plugin, which owns the all-in-one element, rather
|
|
40
|
+
* than in core: a form's vocabulary is the plugin's domain (docs/PACKAGES.md
|
|
41
|
+
* rule 3).
|
|
42
|
+
*
|
|
43
|
+
* Pure and dependency-free (no imports at all) on purpose: the backfill is a
|
|
44
|
+
* plain Node script that imports this file directly from its TypeScript
|
|
45
|
+
* source, and an import here would drag a package graph into it.
|
|
46
|
+
*/ /** A node as it is stored: a flat map entry with its children by id. */ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
47
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
48
|
+
/** The all-in-one element this module migrates away from. Persisted; never rename. */ export const LEGACY_FORM_FIELD_COMPONENT_ID = 'formField';
|
|
49
|
+
/** The bundle that registers every element a field is rebuilt from. */ export const FORM_FIELD_ELEMENTS_PLUGIN_ID = 'mui';
|
|
50
|
+
/**
|
|
51
|
+
* MUI's form elements, by persisted component id — restated rather than
|
|
52
|
+
* imported (see the module note; a plugin never imports another plugin).
|
|
53
|
+
* `form-field-elements.spec.ts` holds this table equal to core's
|
|
54
|
+
* `FORM_INPUT_ELEMENT_IDS` in `forms.ts`.
|
|
55
|
+
*/ export const FORM_FIELD_ELEMENT_IDS = {
|
|
56
|
+
formControl: 'muiFormControl',
|
|
57
|
+
formLabel: 'muiFormLabel',
|
|
58
|
+
input: 'muiInput',
|
|
59
|
+
select: 'muiSelect',
|
|
60
|
+
selectOption: 'muiSelectOption',
|
|
61
|
+
radioGroup: 'muiRadioGroup',
|
|
62
|
+
radio: 'muiRadio',
|
|
63
|
+
checkbox: 'muiCheckbox',
|
|
64
|
+
choiceLabel: 'muiFormControlLabel',
|
|
65
|
+
rating: 'muiRating'
|
|
66
|
+
};
|
|
67
|
+
const LEGACY_FIELD_TYPES = new Set([
|
|
68
|
+
'text',
|
|
69
|
+
'email',
|
|
70
|
+
'textarea',
|
|
71
|
+
'select',
|
|
72
|
+
'radio',
|
|
73
|
+
'checkbox',
|
|
74
|
+
'rating'
|
|
75
|
+
]);
|
|
76
|
+
/** The props the all-in-one element read; anything else rode onto its root. */ const LEGACY_FIELD_PROPS = new Set([
|
|
77
|
+
'fieldName',
|
|
78
|
+
'datasetFieldId',
|
|
79
|
+
'label',
|
|
80
|
+
'placeholder',
|
|
81
|
+
'fieldType',
|
|
82
|
+
'options',
|
|
83
|
+
'required'
|
|
84
|
+
]);
|
|
85
|
+
/**
|
|
86
|
+
* A choice list as the all-in-one element split it: newline- or
|
|
87
|
+
* comma-separated, trimmed, empties dropped (its own `parseFieldOptions`).
|
|
88
|
+
*/ export function parseLegacyFieldOptions(options) {
|
|
89
|
+
return (typeof options === 'string' ? options : '').split(/[\n,]/).map((entry)=>entry.trim()).filter(Boolean);
|
|
90
|
+
}
|
|
91
|
+
/** Child ids of a stored node, in order. */ const childIds = (node)=>Array.isArray(node == null ? void 0 : node.nodes) ? node == null ? void 0 : node.nodes : [];
|
|
92
|
+
/**
|
|
93
|
+
* The all-in-one `formField` node `node`, rebuilt as MUI's separate form
|
|
94
|
+
* elements — or `null` when it is not one.
|
|
95
|
+
*
|
|
96
|
+
* `nodes` is the tree it sits in, read only so a new id never collides with
|
|
97
|
+
* one already there. New ids are derived from the field's own
|
|
98
|
+
* (`<id>-label`, `<id>-input`, `<id>-opt-0`, `<id>-opt-0-input`), so a
|
|
99
|
+
* second run over the same field mints the same tree.
|
|
100
|
+
*/ export function formFieldToElements(node, nodes = {}) {
|
|
101
|
+
var _node_$id, _node_props, _props_fieldType;
|
|
102
|
+
if (!node || node.componentId !== LEGACY_FORM_FIELD_COMPONENT_ID) return null;
|
|
103
|
+
const id = String((_node_$id = node.$id) != null ? _node_$id : '');
|
|
104
|
+
if (!id) return null;
|
|
105
|
+
const props = (_node_props = node.props) != null ? _node_props : {};
|
|
106
|
+
const rawName = props['fieldName'];
|
|
107
|
+
// Exactly what the element submitted under: `fieldName || 'field'`.
|
|
108
|
+
const name = rawName === undefined || rawName === null || rawName === '' ? 'field' : String(rawName);
|
|
109
|
+
const label = String(props['label'] || '') || String(rawName || '') || 'Field';
|
|
110
|
+
const rawType = String((_props_fieldType = props['fieldType']) != null ? _props_fieldType : 'text');
|
|
111
|
+
const fieldType = LEGACY_FIELD_TYPES.has(rawType) ? rawType : 'text';
|
|
112
|
+
const placeholder = typeof props['placeholder'] === 'string' && props['placeholder'].trim() ? props['placeholder'] : undefined;
|
|
113
|
+
const required = Boolean(props['required']);
|
|
114
|
+
const datasetFieldId = typeof props['datasetFieldId'] === 'string' && props['datasetFieldId'].trim() ? props['datasetFieldId'] : undefined;
|
|
115
|
+
const options = parseLegacyFieldOptions(props['options']);
|
|
116
|
+
// Whatever else the author's props held rode onto the element's root, so
|
|
117
|
+
// it rides onto the wrapper.
|
|
118
|
+
const rest = {};
|
|
119
|
+
for (const [key, value] of Object.entries(props)){
|
|
120
|
+
if (!LEGACY_FIELD_PROPS.has(key)) rest[key] = value;
|
|
121
|
+
}
|
|
122
|
+
const taken = new Set(Object.keys(nodes));
|
|
123
|
+
taken.delete(id);
|
|
124
|
+
const mint = (base)=>{
|
|
125
|
+
let candidate = base;
|
|
126
|
+
for(let n = 2; taken.has(candidate); n += 1)candidate = `${base}-${n}`;
|
|
127
|
+
taken.add(candidate);
|
|
128
|
+
return candidate;
|
|
129
|
+
};
|
|
130
|
+
const out = {};
|
|
131
|
+
const typed = node.type !== undefined ? {
|
|
132
|
+
type: node.type
|
|
133
|
+
} : {};
|
|
134
|
+
const add = (nodeId, parentId, componentId, nodeProps)=>{
|
|
135
|
+
out[nodeId] = _extends({
|
|
136
|
+
$id: nodeId
|
|
137
|
+
}, typed, {
|
|
138
|
+
componentId,
|
|
139
|
+
pluginId: FORM_FIELD_ELEMENTS_PLUGIN_ID,
|
|
140
|
+
parentId,
|
|
141
|
+
props: nodeProps
|
|
142
|
+
});
|
|
143
|
+
const parent = out[parentId];
|
|
144
|
+
if (parent) parent.nodes = [
|
|
145
|
+
...childIds(parent),
|
|
146
|
+
nodeId
|
|
147
|
+
];
|
|
148
|
+
return nodeId;
|
|
149
|
+
};
|
|
150
|
+
const mapping = datasetFieldId ? {
|
|
151
|
+
datasetFieldId
|
|
152
|
+
} : {};
|
|
153
|
+
const req = required ? {
|
|
154
|
+
required: true
|
|
155
|
+
} : {};
|
|
156
|
+
const fullWidth = fieldType === 'text' || fieldType === 'email' || fieldType === 'textarea' || fieldType === 'select';
|
|
157
|
+
const { nodes: _ownChildren, props: _props } = node, shell = _object_without_properties_loose(node, [
|
|
158
|
+
"nodes",
|
|
159
|
+
"props"
|
|
160
|
+
]);
|
|
161
|
+
out[id] = _extends({}, shell, {
|
|
162
|
+
componentId: FORM_FIELD_ELEMENT_IDS.formControl,
|
|
163
|
+
pluginId: FORM_FIELD_ELEMENTS_PLUGIN_ID,
|
|
164
|
+
props: _extends({}, rest, fullWidth ? {
|
|
165
|
+
fullWidth: true
|
|
166
|
+
} : {}, req),
|
|
167
|
+
nodes: []
|
|
168
|
+
});
|
|
169
|
+
const layout = {
|
|
170
|
+
rootId: id,
|
|
171
|
+
answerIds: [],
|
|
172
|
+
placeholderIds: [],
|
|
173
|
+
requiredIds: []
|
|
174
|
+
};
|
|
175
|
+
const addLabel = ()=>{
|
|
176
|
+
layout.labelId = add(mint(`${id}-label`), id, FORM_FIELD_ELEMENT_IDS.formLabel, {
|
|
177
|
+
children: label
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
switch(fieldType){
|
|
181
|
+
case 'select':
|
|
182
|
+
{
|
|
183
|
+
addLabel();
|
|
184
|
+
const select = add(mint(`${id}-input`), id, FORM_FIELD_ELEMENT_IDS.select, _extends({
|
|
185
|
+
name
|
|
186
|
+
}, placeholder ? {
|
|
187
|
+
placeholder
|
|
188
|
+
} : {}, req, {
|
|
189
|
+
fullWidth: true
|
|
190
|
+
}, mapping));
|
|
191
|
+
options.forEach((option, index)=>{
|
|
192
|
+
add(mint(`${id}-opt-${index}`), select, FORM_FIELD_ELEMENT_IDS.selectOption, {
|
|
193
|
+
children: option
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
layout.answerIds.push(select);
|
|
197
|
+
layout.placeholderIds.push(select);
|
|
198
|
+
layout.requiredIds.push(select);
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
case 'radio':
|
|
202
|
+
{
|
|
203
|
+
addLabel();
|
|
204
|
+
const group = add(mint(`${id}-input`), id, FORM_FIELD_ELEMENT_IDS.radioGroup, _extends({
|
|
205
|
+
name
|
|
206
|
+
}, mapping));
|
|
207
|
+
options.forEach((option, index)=>{
|
|
208
|
+
const choice = add(mint(`${id}-opt-${index}`), group, FORM_FIELD_ELEMENT_IDS.choiceLabel, {
|
|
209
|
+
label: option
|
|
210
|
+
});
|
|
211
|
+
const radio = add(mint(`${id}-opt-${index}-input`), choice, FORM_FIELD_ELEMENT_IDS.radio, _extends({
|
|
212
|
+
value: option
|
|
213
|
+
}, req));
|
|
214
|
+
layout.requiredIds.push(radio);
|
|
215
|
+
});
|
|
216
|
+
layout.answerIds.push(group);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case 'checkbox':
|
|
220
|
+
{
|
|
221
|
+
// A lone box is its own question: the words beside it say it all. A
|
|
222
|
+
// group of boxes keeps the question above them.
|
|
223
|
+
if (options.length !== 1) addLabel();
|
|
224
|
+
options.forEach((option, index)=>{
|
|
225
|
+
const choice = add(mint(`${id}-opt-${index}`), id, FORM_FIELD_ELEMENT_IDS.choiceLabel, {
|
|
226
|
+
label: option
|
|
227
|
+
});
|
|
228
|
+
// `value` is the option text, as the all-in-one element posted it —
|
|
229
|
+
// which is also what makes a single-option marketing consent box
|
|
230
|
+
// read as ticked (`isConsentCheckboxTicked`). `required` only on a
|
|
231
|
+
// lone box: on a group it meant "at least one", which a box of its
|
|
232
|
+
// own cannot say.
|
|
233
|
+
const box = add(mint(`${id}-opt-${index}-input`), choice, FORM_FIELD_ELEMENT_IDS.checkbox, _extends({
|
|
234
|
+
name,
|
|
235
|
+
value: option
|
|
236
|
+
}, options.length === 1 ? req : {}, mapping));
|
|
237
|
+
layout.answerIds.push(box);
|
|
238
|
+
if (options.length === 1) layout.requiredIds.push(box);
|
|
239
|
+
});
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case 'rating':
|
|
243
|
+
{
|
|
244
|
+
addLabel();
|
|
245
|
+
const rating = add(mint(`${id}-input`), id, FORM_FIELD_ELEMENT_IDS.rating, _extends({
|
|
246
|
+
name
|
|
247
|
+
}, mapping));
|
|
248
|
+
layout.answerIds.push(rating);
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
default:
|
|
252
|
+
{
|
|
253
|
+
addLabel();
|
|
254
|
+
const input = add(mint(`${id}-input`), id, FORM_FIELD_ELEMENT_IDS.input, _extends({
|
|
255
|
+
name,
|
|
256
|
+
type: fieldType === 'email' ? 'email' : 'text'
|
|
257
|
+
}, fieldType === 'textarea' ? {
|
|
258
|
+
multiline: true,
|
|
259
|
+
minRows: 3
|
|
260
|
+
} : {}, placeholder ? {
|
|
261
|
+
placeholder
|
|
262
|
+
} : {}, req, {
|
|
263
|
+
fullWidth: true
|
|
264
|
+
}, mapping));
|
|
265
|
+
layout.answerIds.push(input);
|
|
266
|
+
layout.placeholderIds.push(input);
|
|
267
|
+
layout.requiredIds.push(input);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// A self-closing field never had children, but one that somehow did keeps
|
|
271
|
+
// them rather than orphaning them.
|
|
272
|
+
const wrapper = out[id];
|
|
273
|
+
wrapper.nodes = [
|
|
274
|
+
...childIds(wrapper),
|
|
275
|
+
...childIds(node)
|
|
276
|
+
];
|
|
277
|
+
return _extends({}, layout, {
|
|
278
|
+
nodes: out
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Every all-in-one field in a tree, rebuilt — or `null` when the tree holds
|
|
283
|
+
* none. The tree is not mutated; the result is a new map with each field
|
|
284
|
+
* replaced in place (same id) and its new pieces added.
|
|
285
|
+
*/ export function migrateFormFieldNodes(nodes) {
|
|
286
|
+
if (!nodes || typeof nodes !== 'object') return null;
|
|
287
|
+
const next = _extends({}, nodes);
|
|
288
|
+
const converted = [];
|
|
289
|
+
for (const [key, node] of Object.entries(nodes)){
|
|
290
|
+
var _node_$id;
|
|
291
|
+
if (!node || node.componentId !== LEGACY_FORM_FIELD_COMPONENT_ID) continue;
|
|
292
|
+
const elements = formFieldToElements(_extends({}, node, {
|
|
293
|
+
$id: (_node_$id = node.$id) != null ? _node_$id : key
|
|
294
|
+
}), next);
|
|
295
|
+
if (!elements) continue;
|
|
296
|
+
Object.assign(next, elements.nodes);
|
|
297
|
+
converted.push(key);
|
|
298
|
+
}
|
|
299
|
+
return converted.length ? {
|
|
300
|
+
nodes: next,
|
|
301
|
+
converted
|
|
302
|
+
} : null;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Which piece owns each prop of the field at `id` in a DEFINITION tree,
|
|
306
|
+
* whether that tree still holds the all-in-one element or already holds its
|
|
307
|
+
* replacement — so re-keying a placement works before and after the design
|
|
308
|
+
* itself was migrated, and a re-run never double-moves anything.
|
|
309
|
+
*/ export function formFieldLayoutIn(definition, id) {
|
|
310
|
+
const node = definition[id];
|
|
311
|
+
if (!node) return null;
|
|
312
|
+
if (node.componentId === LEGACY_FORM_FIELD_COMPONENT_ID) {
|
|
313
|
+
var _node_$id;
|
|
314
|
+
const elements = formFieldToElements(_extends({}, node, {
|
|
315
|
+
$id: (_node_$id = node.$id) != null ? _node_$id : id
|
|
316
|
+
}), definition);
|
|
317
|
+
if (!elements) return null;
|
|
318
|
+
const { nodes: _nodes } = elements, layout = _object_without_properties_loose(elements, [
|
|
319
|
+
"nodes"
|
|
320
|
+
]);
|
|
321
|
+
return layout;
|
|
322
|
+
}
|
|
323
|
+
if (node.componentId !== FORM_FIELD_ELEMENT_IDS.formControl) return null;
|
|
324
|
+
const layout = {
|
|
325
|
+
rootId: id,
|
|
326
|
+
answerIds: [],
|
|
327
|
+
placeholderIds: [],
|
|
328
|
+
requiredIds: []
|
|
329
|
+
};
|
|
330
|
+
const checkboxes = [];
|
|
331
|
+
const stack = [
|
|
332
|
+
...childIds(node)
|
|
333
|
+
].reverse();
|
|
334
|
+
const seen = new Set([
|
|
335
|
+
id
|
|
336
|
+
]);
|
|
337
|
+
while(stack.length){
|
|
338
|
+
const childId = stack.pop();
|
|
339
|
+
if (seen.has(childId)) continue;
|
|
340
|
+
seen.add(childId);
|
|
341
|
+
const child = definition[childId];
|
|
342
|
+
if (!child) continue;
|
|
343
|
+
switch(child.componentId){
|
|
344
|
+
case FORM_FIELD_ELEMENT_IDS.formLabel:
|
|
345
|
+
if (!layout.labelId && child.parentId === id) layout.labelId = childId;
|
|
346
|
+
break;
|
|
347
|
+
case FORM_FIELD_ELEMENT_IDS.input:
|
|
348
|
+
case FORM_FIELD_ELEMENT_IDS.select:
|
|
349
|
+
layout.answerIds.push(childId);
|
|
350
|
+
layout.placeholderIds.push(childId);
|
|
351
|
+
layout.requiredIds.push(childId);
|
|
352
|
+
break;
|
|
353
|
+
case FORM_FIELD_ELEMENT_IDS.radioGroup:
|
|
354
|
+
case FORM_FIELD_ELEMENT_IDS.rating:
|
|
355
|
+
layout.answerIds.push(childId);
|
|
356
|
+
break;
|
|
357
|
+
case FORM_FIELD_ELEMENT_IDS.radio:
|
|
358
|
+
layout.requiredIds.push(childId);
|
|
359
|
+
break;
|
|
360
|
+
case FORM_FIELD_ELEMENT_IDS.checkbox:
|
|
361
|
+
layout.answerIds.push(childId);
|
|
362
|
+
checkboxes.push(childId);
|
|
363
|
+
break;
|
|
364
|
+
default:
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
const children = childIds(child);
|
|
368
|
+
for(let index = children.length - 1; index >= 0; index -= 1){
|
|
369
|
+
stack.push(children[index]);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (checkboxes.length === 1) layout.requiredIds.push(checkboxes[0]);
|
|
373
|
+
return layout;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* A placement's `attrOverrides` re-keyed for MUI's separate form elements, or
|
|
377
|
+
* `null` when nothing in it named an all-in-one field's props.
|
|
378
|
+
*
|
|
379
|
+
* `overrides` is keyed by DEFINITION node ids (a placed form's design, a
|
|
380
|
+
* reusable component's definition). A slice keyed by a field's id moves:
|
|
381
|
+
* `label` onto the Form Label (as its text), `placeholder` onto the Input or
|
|
382
|
+
* Select, `fieldName` onto every answer element (as `name`), `required` onto
|
|
383
|
+
* the elements that enforce it and the wrapper, `datasetFieldId` onto the
|
|
384
|
+
* answer elements. Anything else in the slice (`sx` among it) stays on the
|
|
385
|
+
* field's id, which is the wrapper. `fieldType` and `options` re-shape the
|
|
386
|
+
* field itself and have no single new home; they are dropped and returned so
|
|
387
|
+
* the caller can report them.
|
|
388
|
+
*/ export function rekeyFormFieldOverrides(overrides, definition) {
|
|
389
|
+
if (!overrides || typeof overrides !== 'object' || Array.isArray(overrides)) return null;
|
|
390
|
+
if (!definition) return null;
|
|
391
|
+
const source = overrides;
|
|
392
|
+
const next = {};
|
|
393
|
+
for (const [key, slice] of Object.entries(source)){
|
|
394
|
+
if (slice && typeof slice === 'object' && !Array.isArray(slice)) {
|
|
395
|
+
next[key] = _extends({}, slice);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
const put = (targetId, prop, value)=>{
|
|
399
|
+
var _next_targetId;
|
|
400
|
+
next[targetId] = _extends({}, (_next_targetId = next[targetId]) != null ? _next_targetId : {}, {
|
|
401
|
+
[prop]: value
|
|
402
|
+
});
|
|
403
|
+
};
|
|
404
|
+
let moved = 0;
|
|
405
|
+
const dropped = [];
|
|
406
|
+
for (const [key, slice] of Object.entries(source)){
|
|
407
|
+
var _next_key;
|
|
408
|
+
if (!slice || typeof slice !== 'object' || Array.isArray(slice)) continue;
|
|
409
|
+
const own = slice;
|
|
410
|
+
if (!Object.keys(own).some((prop)=>LEGACY_FIELD_PROPS.has(prop))) continue;
|
|
411
|
+
const layout = formFieldLayoutIn(definition, key);
|
|
412
|
+
if (!layout) continue;
|
|
413
|
+
const kept = {};
|
|
414
|
+
for (const [prop, value] of Object.entries(own)){
|
|
415
|
+
switch(prop){
|
|
416
|
+
case 'label':
|
|
417
|
+
if (layout.labelId) put(layout.labelId, 'children', value);
|
|
418
|
+
else dropped.push({
|
|
419
|
+
key,
|
|
420
|
+
prop
|
|
421
|
+
});
|
|
422
|
+
break;
|
|
423
|
+
case 'placeholder':
|
|
424
|
+
if (layout.placeholderIds.length) {
|
|
425
|
+
for (const target of layout.placeholderIds)put(target, 'placeholder', value);
|
|
426
|
+
} else dropped.push({
|
|
427
|
+
key,
|
|
428
|
+
prop
|
|
429
|
+
});
|
|
430
|
+
break;
|
|
431
|
+
case 'fieldName':
|
|
432
|
+
if (layout.answerIds.length) {
|
|
433
|
+
for (const target of layout.answerIds)put(target, 'name', value);
|
|
434
|
+
} else dropped.push({
|
|
435
|
+
key,
|
|
436
|
+
prop
|
|
437
|
+
});
|
|
438
|
+
break;
|
|
439
|
+
case 'datasetFieldId':
|
|
440
|
+
if (layout.answerIds.length) {
|
|
441
|
+
for (const target of layout.answerIds)put(target, 'datasetFieldId', value);
|
|
442
|
+
} else dropped.push({
|
|
443
|
+
key,
|
|
444
|
+
prop
|
|
445
|
+
});
|
|
446
|
+
break;
|
|
447
|
+
case 'required':
|
|
448
|
+
kept['required'] = value;
|
|
449
|
+
for (const target of layout.requiredIds)put(target, 'required', value);
|
|
450
|
+
break;
|
|
451
|
+
case 'fieldType':
|
|
452
|
+
case 'options':
|
|
453
|
+
dropped.push({
|
|
454
|
+
key,
|
|
455
|
+
prop
|
|
456
|
+
});
|
|
457
|
+
break;
|
|
458
|
+
default:
|
|
459
|
+
kept[prop] = value;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
moved += 1;
|
|
463
|
+
// The wrapper's slice is rebuilt from what stayed, merged over anything
|
|
464
|
+
// a re-key of ANOTHER field put there (none can — ids are per field —
|
|
465
|
+
// but the merge keeps the rule obvious).
|
|
466
|
+
const _ref = (_next_key = next[key]) != null ? _next_key : {}, { label: _l, placeholder: _p, fieldName: _f, datasetFieldId: _d, fieldType: _t, options: _o, required: _r } = _ref, others = _object_without_properties_loose(_ref, [
|
|
467
|
+
"label",
|
|
468
|
+
"placeholder",
|
|
469
|
+
"fieldName",
|
|
470
|
+
"datasetFieldId",
|
|
471
|
+
"fieldType",
|
|
472
|
+
"options",
|
|
473
|
+
"required"
|
|
474
|
+
]);
|
|
475
|
+
const wrapper = _extends({}, others, kept);
|
|
476
|
+
if (Object.keys(wrapper).length) next[key] = wrapper;
|
|
477
|
+
else delete next[key];
|
|
478
|
+
}
|
|
479
|
+
return moved ? {
|
|
480
|
+
attrOverrides: next,
|
|
481
|
+
moved,
|
|
482
|
+
dropped
|
|
483
|
+
} : null;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* The MUI class names a stored `sx` (or a style override slice) selects, such
|
|
487
|
+
* as `& .MuiInputLabel-root` or `& .MuiOutlinedInput-notchedOutline`.
|
|
488
|
+
*
|
|
489
|
+
* The all-in-one element drew a TextField, so an author's styles could reach
|
|
490
|
+
* into its inner classes. After the move a field is separate elements whose
|
|
491
|
+
* own classes differ (`MuiFormLabel`, not `MuiInputLabel`), so such a
|
|
492
|
+
* selector may match nothing; the backfill lists every one for a person to
|
|
493
|
+
* restate on the right element.
|
|
494
|
+
*/ export function muiClassSelectorsIn(sx) {
|
|
495
|
+
const found = new Set();
|
|
496
|
+
const visit = (value, depth)=>{
|
|
497
|
+
if (!value || typeof value !== 'object' || depth > 8) return;
|
|
498
|
+
for (const [key, entry] of Object.entries(value)){
|
|
499
|
+
for (const match of key.matchAll(/Mui[A-Z][A-Za-z]*(?:-[A-Za-z]+)?/g)){
|
|
500
|
+
found.add(match[0]);
|
|
501
|
+
}
|
|
502
|
+
visit(entry, depth + 1);
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
visit(sx, 0);
|
|
506
|
+
return [
|
|
507
|
+
...found
|
|
508
|
+
].sort();
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
//# sourceMappingURL=form-field-elements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/forms/src/lib/model/form-field-elements.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*\n * ONE ALL-IN-ONE FORM FIELD, REBUILT FROM MUI'S SEPARATE FORM ELEMENTS.\n *\n * Every piece of a field is its own Besigner element now (a Form Control\n * holding a Form Label and an Input, a Select of Select Options, a Radio Group\n * of Radios in Choice Labels, Checkboxes in Choice Labels, a Rating), so an\n * author selects and styles each piece with the ordinary Styles panel. The\n * all-in-one `formField` is still registered so a document nobody has migrated\n * keeps drawing, and this module is how each one is moved off it: the seeds,\n * the presets and `tools/scripts/backfill-formfield-elements.mjs` all build the\n * same tree from the same rules.\n *\n * What must survive the move, exactly:\n *\n * - **The field's id.** It stays on the Form Control wrapper, so a parent's\n * `nodes` list, a reveal target and every placement override keyed by it\n * still find the field. The wrapper takes the field's `sx` with it.\n * - **The name it submits under.** Contact-field mappings, dataset bindings\n * and the consent field all key on it, so it is copied verbatim.\n * - **Everything a placement overrode.** A placed form's `attrOverrides`\n * named the field's id and a prop of the all-in-one element; the slice is\n * re-keyed onto the piece that now owns that prop.\n *\n * It lives with the forms plugin, which owns the all-in-one element, rather\n * than in core: a form's vocabulary is the plugin's domain (docs/PACKAGES.md\n * rule 3).\n *\n * Pure and dependency-free (no imports at all) on purpose: the backfill is a\n * plain Node script that imports this file directly from its TypeScript\n * source, and an import here would drag a package graph into it.\n */\n\n/** A node as it is stored: a flat map entry with its children by id. */\nexport interface StoredFormNode {\n $id?: string\n componentId?: string\n pluginId?: string\n parentId?: string | null\n props?: Record<string, unknown>\n nodes?: string[]\n sx?: unknown\n [key: string]: unknown\n}\n\n/** The all-in-one element this module migrates away from. Persisted; never rename. */\nexport const LEGACY_FORM_FIELD_COMPONENT_ID = 'formField'\n\n/** The bundle that registers every element a field is rebuilt from. */\nexport const FORM_FIELD_ELEMENTS_PLUGIN_ID = 'mui'\n\n/**\n * MUI's form elements, by persisted component id — restated rather than\n * imported (see the module note; a plugin never imports another plugin).\n * `form-field-elements.spec.ts` holds this table equal to core's\n * `FORM_INPUT_ELEMENT_IDS` in `forms.ts`.\n */\nexport const FORM_FIELD_ELEMENT_IDS = {\n formControl: 'muiFormControl',\n formLabel: 'muiFormLabel',\n input: 'muiInput',\n select: 'muiSelect',\n selectOption: 'muiSelectOption',\n radioGroup: 'muiRadioGroup',\n radio: 'muiRadio',\n checkbox: 'muiCheckbox',\n choiceLabel: 'muiFormControlLabel',\n rating: 'muiRating',\n} as const\n\n/** The all-in-one element's types; anything else drew as a one-line text box. */\ntype LegacyFieldType =\n | 'text'\n | 'email'\n | 'textarea'\n | 'select'\n | 'radio'\n | 'checkbox'\n | 'rating'\n\nconst LEGACY_FIELD_TYPES = new Set<string>([\n 'text',\n 'email',\n 'textarea',\n 'select',\n 'radio',\n 'checkbox',\n 'rating',\n])\n\n/** The props the all-in-one element read; anything else rode onto its root. */\nconst LEGACY_FIELD_PROPS = new Set<string>([\n 'fieldName',\n 'datasetFieldId',\n 'label',\n 'placeholder',\n 'fieldType',\n 'options',\n 'required',\n])\n\n/**\n * A choice list as the all-in-one element split it: newline- or\n * comma-separated, trimmed, empties dropped (its own `parseFieldOptions`).\n */\nexport function parseLegacyFieldOptions(options: unknown): string[] {\n return (typeof options === 'string' ? options : '')\n .split(/[\\n,]/)\n .map((entry) => entry.trim())\n .filter(Boolean)\n}\n\n/** Which new node owns each prop the all-in-one element had. */\nexport interface FormFieldElementsLayout {\n /** The Form Control; the field's own id. */\n rootId: string\n /** The Form Label, when the field has one (not a lone checkbox). */\n labelId?: string\n /** Every node that submits the answer and carries `name`. */\n answerIds: string[]\n /** The nodes a placeholder belongs on (Input, Select). */\n placeholderIds: string[]\n /** The nodes `required` is enforced on. */\n requiredIds: string[]\n}\n\nexport interface FormFieldElements extends FormFieldElementsLayout {\n /** The wrapper and every new node under it, keyed by id. */\n nodes: Record<string, StoredFormNode>\n}\n\n/** Child ids of a stored node, in order. */\nconst childIds = (node: StoredFormNode | undefined): string[] =>\n Array.isArray(node?.nodes) ? (node?.nodes as string[]) : []\n\n/**\n * The all-in-one `formField` node `node`, rebuilt as MUI's separate form\n * elements — or `null` when it is not one.\n *\n * `nodes` is the tree it sits in, read only so a new id never collides with\n * one already there. New ids are derived from the field's own\n * (`<id>-label`, `<id>-input`, `<id>-opt-0`, `<id>-opt-0-input`), so a\n * second run over the same field mints the same tree.\n */\nexport function formFieldToElements(\n node: StoredFormNode | undefined | null,\n nodes: Record<string, StoredFormNode | undefined> = {},\n): FormFieldElements | null {\n if (!node || node.componentId !== LEGACY_FORM_FIELD_COMPONENT_ID) return null\n const id = String(node.$id ?? '')\n if (!id) return null\n\n const props = (node.props ?? {}) as Record<string, unknown>\n const rawName = props['fieldName']\n // Exactly what the element submitted under: `fieldName || 'field'`.\n const name = rawName === undefined || rawName === null || rawName === ''\n ? 'field'\n : String(rawName)\n const label =\n String(props['label'] || '') || String(rawName || '') || 'Field'\n const rawType = String(props['fieldType'] ?? 'text')\n const fieldType = (\n LEGACY_FIELD_TYPES.has(rawType) ? rawType : 'text'\n ) as LegacyFieldType\n const placeholder =\n typeof props['placeholder'] === 'string' && props['placeholder'].trim()\n ? (props['placeholder'] as string)\n : undefined\n const required = Boolean(props['required'])\n const datasetFieldId =\n typeof props['datasetFieldId'] === 'string' && props['datasetFieldId'].trim()\n ? (props['datasetFieldId'] as string)\n : undefined\n const options = parseLegacyFieldOptions(props['options'])\n\n // Whatever else the author's props held rode onto the element's root, so\n // it rides onto the wrapper.\n const rest: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(props)) {\n if (!LEGACY_FIELD_PROPS.has(key)) rest[key] = value\n }\n\n const taken = new Set<string>(Object.keys(nodes))\n taken.delete(id)\n const mint = (base: string): string => {\n let candidate = base\n for (let n = 2; taken.has(candidate); n += 1) candidate = `${base}-${n}`\n taken.add(candidate)\n return candidate\n }\n\n const out: Record<string, StoredFormNode> = {}\n const typed = node.type !== undefined ? { type: node.type } : {}\n const add = (\n nodeId: string,\n parentId: string,\n componentId: string,\n nodeProps: Record<string, unknown>,\n ): string => {\n out[nodeId] = {\n $id: nodeId,\n ...typed,\n componentId,\n pluginId: FORM_FIELD_ELEMENTS_PLUGIN_ID,\n parentId,\n props: nodeProps,\n }\n const parent = out[parentId]\n if (parent) parent.nodes = [...childIds(parent), nodeId]\n return nodeId\n }\n const mapping = datasetFieldId ? { datasetFieldId } : {}\n const req = required ? { required: true } : {}\n\n const fullWidth =\n fieldType === 'text' ||\n fieldType === 'email' ||\n fieldType === 'textarea' ||\n fieldType === 'select'\n const { nodes: _ownChildren, props: _props, ...shell } = node\n out[id] = {\n ...shell,\n componentId: FORM_FIELD_ELEMENT_IDS.formControl,\n pluginId: FORM_FIELD_ELEMENTS_PLUGIN_ID,\n props: {\n ...rest,\n ...(fullWidth ? { fullWidth: true } : {}),\n ...req,\n },\n nodes: [],\n }\n\n const layout: FormFieldElementsLayout = {\n rootId: id,\n answerIds: [],\n placeholderIds: [],\n requiredIds: [],\n }\n const addLabel = () => {\n layout.labelId = add(mint(`${id}-label`), id, FORM_FIELD_ELEMENT_IDS.formLabel, {\n children: label,\n })\n }\n\n switch (fieldType) {\n case 'select': {\n addLabel()\n const select = add(mint(`${id}-input`), id, FORM_FIELD_ELEMENT_IDS.select, {\n name,\n ...(placeholder ? { placeholder } : {}),\n ...req,\n fullWidth: true,\n ...mapping,\n })\n options.forEach((option, index) => {\n add(mint(`${id}-opt-${index}`), select, FORM_FIELD_ELEMENT_IDS.selectOption, {\n children: option,\n })\n })\n layout.answerIds.push(select)\n layout.placeholderIds.push(select)\n layout.requiredIds.push(select)\n break\n }\n case 'radio': {\n addLabel()\n const group = add(mint(`${id}-input`), id, FORM_FIELD_ELEMENT_IDS.radioGroup, {\n name,\n ...mapping,\n })\n options.forEach((option, index) => {\n const choice = add(\n mint(`${id}-opt-${index}`),\n group,\n FORM_FIELD_ELEMENT_IDS.choiceLabel,\n { label: option },\n )\n const radio = add(mint(`${id}-opt-${index}-input`), choice, FORM_FIELD_ELEMENT_IDS.radio, {\n value: option,\n ...req,\n })\n layout.requiredIds.push(radio)\n })\n layout.answerIds.push(group)\n break\n }\n case 'checkbox': {\n // A lone box is its own question: the words beside it say it all. A\n // group of boxes keeps the question above them.\n if (options.length !== 1) addLabel()\n options.forEach((option, index) => {\n const choice = add(\n mint(`${id}-opt-${index}`),\n id,\n FORM_FIELD_ELEMENT_IDS.choiceLabel,\n { label: option },\n )\n // `value` is the option text, as the all-in-one element posted it —\n // which is also what makes a single-option marketing consent box\n // read as ticked (`isConsentCheckboxTicked`). `required` only on a\n // lone box: on a group it meant \"at least one\", which a box of its\n // own cannot say.\n const box = add(mint(`${id}-opt-${index}-input`), choice, FORM_FIELD_ELEMENT_IDS.checkbox, {\n name,\n value: option,\n ...(options.length === 1 ? req : {}),\n ...mapping,\n })\n layout.answerIds.push(box)\n if (options.length === 1) layout.requiredIds.push(box)\n })\n break\n }\n case 'rating': {\n addLabel()\n const rating = add(mint(`${id}-input`), id, FORM_FIELD_ELEMENT_IDS.rating, {\n name,\n ...mapping,\n })\n layout.answerIds.push(rating)\n break\n }\n default: {\n addLabel()\n const input = add(mint(`${id}-input`), id, FORM_FIELD_ELEMENT_IDS.input, {\n name,\n type: fieldType === 'email' ? 'email' : 'text',\n ...(fieldType === 'textarea' ? { multiline: true, minRows: 3 } : {}),\n ...(placeholder ? { placeholder } : {}),\n ...req,\n fullWidth: true,\n ...mapping,\n })\n layout.answerIds.push(input)\n layout.placeholderIds.push(input)\n layout.requiredIds.push(input)\n }\n }\n\n // A self-closing field never had children, but one that somehow did keeps\n // them rather than orphaning them.\n const wrapper = out[id] as StoredFormNode\n wrapper.nodes = [...childIds(wrapper), ...childIds(node)]\n return { ...layout, nodes: out }\n}\n\n/**\n * Every all-in-one field in a tree, rebuilt — or `null` when the tree holds\n * none. The tree is not mutated; the result is a new map with each field\n * replaced in place (same id) and its new pieces added.\n */\nexport function migrateFormFieldNodes(\n nodes: Record<string, StoredFormNode | undefined> | null | undefined,\n): { nodes: Record<string, StoredFormNode>; converted: string[] } | null {\n if (!nodes || typeof nodes !== 'object') return null\n const next: Record<string, StoredFormNode> = { ...(nodes as Record<string, StoredFormNode>) }\n const converted: string[] = []\n for (const [key, node] of Object.entries(nodes)) {\n if (!node || node.componentId !== LEGACY_FORM_FIELD_COMPONENT_ID) continue\n const elements = formFieldToElements({ ...node, $id: node.$id ?? key }, next)\n if (!elements) continue\n Object.assign(next, elements.nodes)\n converted.push(key)\n }\n return converted.length ? { nodes: next, converted } : null\n}\n\n/**\n * Which piece owns each prop of the field at `id` in a DEFINITION tree,\n * whether that tree still holds the all-in-one element or already holds its\n * replacement — so re-keying a placement works before and after the design\n * itself was migrated, and a re-run never double-moves anything.\n */\nexport function formFieldLayoutIn(\n definition: Record<string, StoredFormNode | undefined>,\n id: string,\n): FormFieldElementsLayout | null {\n const node = definition[id]\n if (!node) return null\n if (node.componentId === LEGACY_FORM_FIELD_COMPONENT_ID) {\n const elements = formFieldToElements({ ...node, $id: node.$id ?? id }, definition)\n if (!elements) return null\n const { nodes: _nodes, ...layout } = elements\n return layout\n }\n if (node.componentId !== FORM_FIELD_ELEMENT_IDS.formControl) return null\n\n const layout: FormFieldElementsLayout = {\n rootId: id,\n answerIds: [],\n placeholderIds: [],\n requiredIds: [],\n }\n const checkboxes: string[] = []\n const stack = [...childIds(node)].reverse()\n const seen = new Set<string>([id])\n while (stack.length) {\n const childId = stack.pop() as string\n if (seen.has(childId)) continue\n seen.add(childId)\n const child = definition[childId]\n if (!child) continue\n switch (child.componentId) {\n case FORM_FIELD_ELEMENT_IDS.formLabel:\n if (!layout.labelId && child.parentId === id) layout.labelId = childId\n break\n case FORM_FIELD_ELEMENT_IDS.input:\n case FORM_FIELD_ELEMENT_IDS.select:\n layout.answerIds.push(childId)\n layout.placeholderIds.push(childId)\n layout.requiredIds.push(childId)\n break\n case FORM_FIELD_ELEMENT_IDS.radioGroup:\n case FORM_FIELD_ELEMENT_IDS.rating:\n layout.answerIds.push(childId)\n break\n case FORM_FIELD_ELEMENT_IDS.radio:\n layout.requiredIds.push(childId)\n break\n case FORM_FIELD_ELEMENT_IDS.checkbox:\n layout.answerIds.push(childId)\n checkboxes.push(childId)\n break\n default:\n break\n }\n const children = childIds(child)\n for (let index = children.length - 1; index >= 0; index -= 1) {\n stack.push(children[index] as string)\n }\n }\n if (checkboxes.length === 1) layout.requiredIds.push(checkboxes[0] as string)\n return layout\n}\n\n/** A placement override that had nowhere to go, reported rather than kept. */\nexport interface DroppedFormFieldOverride {\n key: string\n prop: string\n}\n\n/**\n * A placement's `attrOverrides` re-keyed for MUI's separate form elements, or\n * `null` when nothing in it named an all-in-one field's props.\n *\n * `overrides` is keyed by DEFINITION node ids (a placed form's design, a\n * reusable component's definition). A slice keyed by a field's id moves:\n * `label` onto the Form Label (as its text), `placeholder` onto the Input or\n * Select, `fieldName` onto every answer element (as `name`), `required` onto\n * the elements that enforce it and the wrapper, `datasetFieldId` onto the\n * answer elements. Anything else in the slice (`sx` among it) stays on the\n * field's id, which is the wrapper. `fieldType` and `options` re-shape the\n * field itself and have no single new home; they are dropped and returned so\n * the caller can report them.\n */\nexport function rekeyFormFieldOverrides(\n overrides: unknown,\n definition: Record<string, StoredFormNode | undefined> | null | undefined,\n): {\n attrOverrides: Record<string, Record<string, unknown>>\n moved: number\n dropped: DroppedFormFieldOverride[]\n} | null {\n if (!overrides || typeof overrides !== 'object' || Array.isArray(overrides)) return null\n if (!definition) return null\n const source = overrides as Record<string, unknown>\n const next: Record<string, Record<string, unknown>> = {}\n for (const [key, slice] of Object.entries(source)) {\n if (slice && typeof slice === 'object' && !Array.isArray(slice)) {\n next[key] = { ...(slice as Record<string, unknown>) }\n }\n }\n const put = (targetId: string, prop: string, value: unknown) => {\n next[targetId] = { ...(next[targetId] ?? {}), [prop]: value }\n }\n let moved = 0\n const dropped: DroppedFormFieldOverride[] = []\n for (const [key, slice] of Object.entries(source)) {\n if (!slice || typeof slice !== 'object' || Array.isArray(slice)) continue\n const own = slice as Record<string, unknown>\n if (!Object.keys(own).some((prop) => LEGACY_FIELD_PROPS.has(prop))) continue\n const layout = formFieldLayoutIn(definition, key)\n if (!layout) continue\n const kept: Record<string, unknown> = {}\n for (const [prop, value] of Object.entries(own)) {\n switch (prop) {\n case 'label':\n if (layout.labelId) put(layout.labelId, 'children', value)\n else dropped.push({ key, prop })\n break\n case 'placeholder':\n if (layout.placeholderIds.length) {\n for (const target of layout.placeholderIds) put(target, 'placeholder', value)\n } else dropped.push({ key, prop })\n break\n case 'fieldName':\n if (layout.answerIds.length) {\n for (const target of layout.answerIds) put(target, 'name', value)\n } else dropped.push({ key, prop })\n break\n case 'datasetFieldId':\n if (layout.answerIds.length) {\n for (const target of layout.answerIds) put(target, 'datasetFieldId', value)\n } else dropped.push({ key, prop })\n break\n case 'required':\n kept['required'] = value\n for (const target of layout.requiredIds) put(target, 'required', value)\n break\n case 'fieldType':\n case 'options':\n dropped.push({ key, prop })\n break\n default:\n kept[prop] = value\n }\n }\n moved += 1\n // The wrapper's slice is rebuilt from what stayed, merged over anything\n // a re-key of ANOTHER field put there (none can — ids are per field —\n // but the merge keeps the rule obvious).\n const { label: _l, placeholder: _p, fieldName: _f, datasetFieldId: _d, fieldType: _t, options: _o, required: _r, ...others } =\n next[key] ?? {}\n const wrapper = { ...others, ...kept }\n if (Object.keys(wrapper).length) next[key] = wrapper\n else delete next[key]\n }\n return moved ? { attrOverrides: next, moved, dropped } : null\n}\n\n/**\n * The MUI class names a stored `sx` (or a style override slice) selects, such\n * as `& .MuiInputLabel-root` or `& .MuiOutlinedInput-notchedOutline`.\n *\n * The all-in-one element drew a TextField, so an author's styles could reach\n * into its inner classes. After the move a field is separate elements whose\n * own classes differ (`MuiFormLabel`, not `MuiInputLabel`), so such a\n * selector may match nothing; the backfill lists every one for a person to\n * restate on the right element.\n */\nexport function muiClassSelectorsIn(sx: unknown): string[] {\n const found = new Set<string>()\n const visit = (value: unknown, depth: number) => {\n if (!value || typeof value !== 'object' || depth > 8) return\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n for (const match of key.matchAll(/Mui[A-Z][A-Za-z]*(?:-[A-Za-z]+)?/g)) {\n found.add(match[0])\n }\n visit(entry, depth + 1)\n }\n }\n visit(sx, 0)\n return [...found].sort()\n}\n"],"names":["LEGACY_FORM_FIELD_COMPONENT_ID","FORM_FIELD_ELEMENTS_PLUGIN_ID","FORM_FIELD_ELEMENT_IDS","formControl","formLabel","input","select","selectOption","radioGroup","radio","checkbox","choiceLabel","rating","LEGACY_FIELD_TYPES","Set","LEGACY_FIELD_PROPS","parseLegacyFieldOptions","options","split","map","entry","trim","filter","Boolean","childIds","node","Array","isArray","nodes","formFieldToElements","props","componentId","id","String","$id","rawName","name","undefined","label","rawType","fieldType","has","placeholder","required","datasetFieldId","rest","key","value","Object","entries","taken","keys","delete","mint","base","candidate","n","add","out","typed","type","nodeId","parentId","nodeProps","pluginId","parent","mapping","req","fullWidth","_ownChildren","_props","shell","layout","rootId","answerIds","placeholderIds","requiredIds","addLabel","labelId","children","forEach","option","index","push","group","choice","length","box","multiline","minRows","wrapper","migrateFormFieldNodes","next","converted","elements","assign","formFieldLayoutIn","definition","_nodes","checkboxes","stack","reverse","seen","childId","pop","child","rekeyFormFieldOverrides","overrides","source","slice","put","targetId","prop","moved","dropped","own","some","kept","target","_l","_p","fieldName","_f","_d","_t","_o","_r","others","attrOverrides","muiClassSelectorsIn","sx","found","visit","depth","match","matchAll","sort"],"mappings":"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"}
|