@netlisian/softconfig 0.1.4 → 0.1.5

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.
@@ -76,12 +76,18 @@ __export(puck_exports, {
76
76
  Header: () => Header,
77
77
  Modal: () => Modal,
78
78
  SoftConfigProvider: () => SoftConfigProvider,
79
+ applyMapping: () => applyMapping,
79
80
  confirm: () => confirm,
80
81
  createActionCallback: () => createActionCallback,
81
82
  createSoftConfigStore: () => createSoftConfigStore,
82
83
  createUseSoftConfig: () => createUseSoftConfig,
84
+ filterToOptionsForFrom: () => filterToOptionsForFrom,
85
+ getArrayBasePath: () => getArrayBasePath,
86
+ getArrayItemSubPath: () => getArrayItemSubPath,
87
+ isArrayMappingPath: () => isArrayMappingPath,
83
88
  notify: () => notify,
84
89
  resolveSoftConfig: () => resolveSoftConfig,
90
+ resolveValueByPath: () => resolveValueByPath,
85
91
  setConfirmHandler: () => setConfirmHandler,
86
92
  setNotificationHandler: () => setNotificationHandler,
87
93
  useBuild: () => useBuild,
@@ -107,63 +113,358 @@ var import_puck4 = require("@measured/puck");
107
113
  var getRootProps = (appState) => appState.data.root.props;
108
114
 
109
115
  // src/puck/lib/builder/root-config.tsx
116
+ var import_react2 = require("react");
117
+ var import_react_fast_compare2 = __toESM(require("react-fast-compare"));
110
118
  var import_puck2 = require("@measured/puck");
111
119
 
112
120
  // src/puck/lib/get-field-settings.tsx
113
121
  var import_puck = require("@measured/puck");
122
+
123
+ // src/puck/lib/get-settings-by-path.ts
124
+ function getFieldSettingsByPath(fieldSettings, path) {
125
+ return path.split(".").reduce((o, key) => o ? o[key] : void 0, fieldSettings);
126
+ }
127
+
128
+ // src/puck/lib/array-field-utils.ts
129
+ var primitiveFieldTypes = /* @__PURE__ */ new Set([
130
+ "text",
131
+ "textarea",
132
+ "number",
133
+ "select",
134
+ "radio",
135
+ "reference"
136
+ ]);
137
+ var isPrimitiveValue = (value) => ["string", "number", "boolean"].includes(typeof value);
138
+ var getFallbackValueForField = (type) => {
139
+ switch (type) {
140
+ case "number":
141
+ return 0;
142
+ case "array":
143
+ return [];
144
+ case "object":
145
+ return {};
146
+ default:
147
+ return "";
148
+ }
149
+ };
150
+ var resolveExpressionSummary = (item, index, expression) => {
151
+ if (!expression) return "";
152
+ let isValid = true;
153
+ const result = expression.replace(/\{([^}]+)\}/g, (_match, token) => {
154
+ if (token === "index") {
155
+ return String(index);
156
+ }
157
+ if (token.startsWith("item.")) {
158
+ const value = getFieldSettingsByPath(item, token.slice(5));
159
+ if (isPrimitiveValue(value)) {
160
+ return String(value);
161
+ }
162
+ }
163
+ isValid = false;
164
+ return "";
165
+ });
166
+ return isValid ? result : "";
167
+ };
168
+ var isPrimitiveFieldType = (type) => primitiveFieldTypes.has(type);
169
+ var buildArrayDefaultItemProps = (subFields = [], subFieldSettings = {}) => {
170
+ if (!subFields.length) return void 0;
171
+ const item = {};
172
+ let hasValue = false;
173
+ subFields.forEach((subField) => {
174
+ const settings = subFieldSettings[subField.name];
175
+ if (settings && Object.prototype.hasOwnProperty.call(settings, "defaultValue") && settings.defaultValue !== void 0) {
176
+ item[subField.name] = settings.defaultValue;
177
+ hasValue = true;
178
+ return;
179
+ }
180
+ item[subField.name] = getFallbackValueForField(subField.type);
181
+ hasValue = true;
182
+ });
183
+ return hasValue ? item : void 0;
184
+ };
185
+ var buildArrayDefaultValue = (subFields = [], subFieldSettings = {}) => {
186
+ const item = buildArrayDefaultItemProps(subFields, subFieldSettings);
187
+ return item ? [item] : [];
188
+ };
189
+ var getArrayItemSummary = (item, index = 0, settings) => {
190
+ if ((settings == null ? void 0 : settings.summary) === "field" && settings.summaryField) {
191
+ const value = getFieldSettingsByPath(item, settings.summaryField);
192
+ if (isPrimitiveValue(value) && String(value).length > 0) {
193
+ return String(value);
194
+ }
195
+ return `Item ${(index || 0) + 1}`;
196
+ }
197
+ if ((settings == null ? void 0 : settings.summary) === "expression") {
198
+ const summary = resolveExpressionSummary(
199
+ item,
200
+ index,
201
+ settings.summaryExpression
202
+ );
203
+ return summary || `Item ${(index || 0) + 1}`;
204
+ }
205
+ return `Item ${(index || 0) + 1}`;
206
+ };
207
+ var isArrayMappingPath = (path) => {
208
+ return typeof path === "string" && /^[^.]+\[\]\.[^.]+$/.test(path);
209
+ };
210
+ var getArrayBasePath = (arrayPath) => {
211
+ if (!isArrayMappingPath(arrayPath)) return null;
212
+ const match = arrayPath.match(/^([^.]+)\[\]\./);
213
+ return match ? match[1] : null;
214
+ };
215
+ var getArrayItemSubPath = (arrayPath) => {
216
+ if (!isArrayMappingPath(arrayPath)) return null;
217
+ const match = arrayPath.match(/\[\]\.(.+)$/);
218
+ return match ? match[1] : null;
219
+ };
220
+
221
+ // src/puck/lib/custom-fields.ts
222
+ var builtInSoftFieldTypes = /* @__PURE__ */ new Set([
223
+ "text",
224
+ "textarea",
225
+ "number",
226
+ "select",
227
+ "radio",
228
+ "array",
229
+ "object",
230
+ "reference"
231
+ ]);
232
+ var warnedMessages = /* @__PURE__ */ new Set();
233
+ var warnOnce = (message) => {
234
+ if (warnedMessages.has(message)) {
235
+ return;
236
+ }
237
+ warnedMessages.add(message);
238
+ console.warn(message);
239
+ };
240
+ var isBuiltInSoftFieldType = (fieldType) => {
241
+ return builtInSoftFieldTypes.has(fieldType);
242
+ };
243
+ var resolveCustomFieldDefinition = (fieldType, customFields) => {
244
+ if (isBuiltInSoftFieldType(fieldType)) {
245
+ return void 0;
246
+ }
247
+ return customFields == null ? void 0 : customFields[fieldType];
248
+ };
249
+ var resolveCustomFieldReturnType = (fieldType, customFields) => {
250
+ const customField = resolveCustomFieldDefinition(fieldType, customFields);
251
+ if (!customField) {
252
+ return null;
253
+ }
254
+ if (!customField.returnType) {
255
+ warnOnce(
256
+ `[soft-config] Custom field "${fieldType}" is missing a required returnType and will be skipped from mapping options.`
257
+ );
258
+ return null;
259
+ }
260
+ return customField.returnType;
261
+ };
262
+ var resolveCustomFieldSchema = (fieldType, customFields) => {
263
+ const customField = resolveCustomFieldDefinition(fieldType, customFields);
264
+ if (!customField) {
265
+ return null;
266
+ }
267
+ const returnType = resolveCustomFieldReturnType(fieldType, customFields);
268
+ if (!returnType) {
269
+ return null;
270
+ }
271
+ if (returnType !== "array" && returnType !== "object") {
272
+ return null;
273
+ }
274
+ const subFields = customField.subFields || [];
275
+ if (!subFields.length) {
276
+ warnOnce(
277
+ `[soft-config] Custom field "${fieldType}" returns ${returnType} but does not define subFields. It will be skipped from mapping options.`
278
+ );
279
+ return null;
280
+ }
281
+ return {
282
+ subFields,
283
+ subFieldSettings: customField.subFieldSettings || {}
284
+ };
285
+ };
286
+ var getCustomFieldTypeOptions = (customFields) => {
287
+ if (!customFields) {
288
+ return [];
289
+ }
290
+ return Object.entries(customFields).filter(([fieldType]) => !isBuiltInSoftFieldType(fieldType)).map(([fieldType, definition]) => ({
291
+ label: typeof definition.field.label === "string" && definition.field.label ? definition.field.label : fieldType,
292
+ value: fieldType
293
+ }));
294
+ };
295
+ var mapCustomReturnTypeToMappingType = (returnType) => {
296
+ switch (returnType) {
297
+ case "string":
298
+ return "textarea";
299
+ case "number":
300
+ return "number";
301
+ case "boolean":
302
+ return "select";
303
+ case "array":
304
+ return "array";
305
+ case "object":
306
+ return "object";
307
+ default:
308
+ return "textarea";
309
+ }
310
+ };
311
+
312
+ // src/puck/lib/get-field-settings.tsx
114
313
  var import_jsx_runtime = require("react/jsx-runtime");
115
- var getFieldSettings = (_fields, _fieldSettings, deep) => {
314
+ var buildPuckField = (field, fieldSettings, customFields) => {
315
+ const customFieldDefinition = resolveCustomFieldDefinition(
316
+ field.type,
317
+ customFields
318
+ );
319
+ const customReturnType = resolveCustomFieldReturnType(field.type, customFields);
320
+ if (customFieldDefinition && customReturnType) {
321
+ return __spreadProps(__spreadValues({}, customFieldDefinition.field), {
322
+ type: "custom",
323
+ label: customFieldDefinition.field.label || field.name
324
+ });
325
+ }
326
+ const resolvedType = field.type;
327
+ switch (resolvedType) {
328
+ case "text":
329
+ case "textarea":
330
+ return { type: resolvedType, label: field.name };
331
+ case "number":
332
+ return {
333
+ type: resolvedType,
334
+ label: field.name,
335
+ min: fieldSettings == null ? void 0 : fieldSettings.min,
336
+ max: fieldSettings == null ? void 0 : fieldSettings.max,
337
+ step: fieldSettings == null ? void 0 : fieldSettings.step
338
+ };
339
+ case "select":
340
+ case "radio":
341
+ return {
342
+ type: resolvedType,
343
+ label: field.name,
344
+ options: (fieldSettings == null ? void 0 : fieldSettings.options) || []
345
+ };
346
+ case "array": {
347
+ const subFields = (fieldSettings == null ? void 0 : fieldSettings.subFields) || [];
348
+ const subFieldSettings = (fieldSettings == null ? void 0 : fieldSettings.subFieldSettings) || {};
349
+ return {
350
+ type: "array",
351
+ label: field.name,
352
+ min: fieldSettings == null ? void 0 : fieldSettings.min,
353
+ max: fieldSettings == null ? void 0 : fieldSettings.max,
354
+ arrayFields: buildDefaultEditorFields(
355
+ subFields,
356
+ subFieldSettings,
357
+ customFields
358
+ ),
359
+ defaultItemProps: buildArrayDefaultItemProps(subFields, subFieldSettings),
360
+ getItemSummary(item, index) {
361
+ return getArrayItemSummary(item, index, fieldSettings);
362
+ }
363
+ };
364
+ }
365
+ case "object":
366
+ return {
367
+ type: "object",
368
+ label: field.name,
369
+ objectFields: buildDefaultEditorFields(
370
+ (fieldSettings == null ? void 0 : fieldSettings.subFields) || [],
371
+ (fieldSettings == null ? void 0 : fieldSettings.subFieldSettings) || {},
372
+ customFields
373
+ )
374
+ };
375
+ default:
376
+ return { type: "text", label: field.name };
377
+ }
378
+ };
379
+ var buildDefaultEditorFields = (fields = [], fieldSettings = {}, customFields) => {
380
+ return fields.reduce((acc, field) => {
381
+ acc[field.name] = buildPuckField(
382
+ field,
383
+ fieldSettings[field.name],
384
+ customFields
385
+ );
386
+ return acc;
387
+ }, {});
388
+ };
389
+ var getFieldSettings = (_fields, _fieldSettings, customFields, deep) => {
390
+ const customTypeOptions = getCustomFieldTypeOptions(customFields);
116
391
  return (_fields || []).reduce((fields, field) => {
117
392
  const fieldSettings = {
118
393
  // placeholder: { type: "text", label: "Placeholder" },
119
394
  };
120
395
  const currentFieldSettings = _fieldSettings == null ? void 0 : _fieldSettings[field.name];
121
- switch (field.type) {
396
+ const customFieldDefinition = resolveCustomFieldDefinition(
397
+ field.type,
398
+ customFields
399
+ );
400
+ const customReturnType = resolveCustomFieldReturnType(
401
+ field.type,
402
+ customFields
403
+ );
404
+ const resolvedType = field.type;
405
+ const customSchema = resolveCustomFieldSchema(field.type, customFields);
406
+ const resolvedSubFields = (customSchema == null ? void 0 : customSchema.subFields) || (currentFieldSettings == null ? void 0 : currentFieldSettings.subFields) || [];
407
+ const resolvedSubFieldSettings = (customSchema == null ? void 0 : customSchema.subFieldSettings) || (currentFieldSettings == null ? void 0 : currentFieldSettings.subFieldSettings) || {};
408
+ const customDefaultValueField = customFieldDefinition && customReturnType ? __spreadProps(__spreadValues({}, customFieldDefinition.field), {
409
+ type: "custom",
410
+ label: customFieldDefinition.field.label || "Default Value"
411
+ }) : null;
412
+ if (customDefaultValueField) {
413
+ fieldSettings.defaultValue = customDefaultValueField;
414
+ }
415
+ switch (resolvedType) {
122
416
  case "text":
123
417
  case "textarea":
124
- fieldSettings.defaultValue = {
125
- type: field.type,
126
- label: "Default Value"
127
- };
418
+ if (!customDefaultValueField) {
419
+ fieldSettings.defaultValue = {
420
+ type: resolvedType,
421
+ label: "Default Value"
422
+ };
423
+ }
128
424
  break;
129
425
  case "number":
130
- fieldSettings.defaultValue = {
131
- type: field.type,
132
- label: "Default Value"
133
- };
426
+ if (!customDefaultValueField) {
427
+ fieldSettings.defaultValue = {
428
+ type: resolvedType,
429
+ label: "Default Value"
430
+ };
431
+ }
134
432
  fieldSettings.min = {
135
- type: field.type,
433
+ type: resolvedType,
136
434
  label: "Minimum Value"
137
435
  };
138
436
  fieldSettings.max = {
139
- type: field.type,
437
+ type: resolvedType,
140
438
  label: "Maximum Value"
141
439
  };
142
440
  fieldSettings.step = {
143
- type: field.type,
441
+ type: resolvedType,
144
442
  label: "Step Size"
145
443
  };
146
444
  break;
147
445
  case "radio":
148
- case "select":
149
- fieldSettings.defaultValue = {
150
- type: "custom",
151
- label: "Default Value",
152
- render: ({ value, onChange, id }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
153
- import_puck.AutoField,
154
- {
155
- field: {
156
- type: field.type,
157
- label: "Default Value",
158
- options: (currentFieldSettings == null ? void 0 : currentFieldSettings.options) || []
159
- },
160
- value,
161
- onChange,
162
- readOnly: false,
163
- id
164
- }
165
- )
166
- };
446
+ case "select": {
447
+ const selectOptions = (currentFieldSettings == null ? void 0 : currentFieldSettings.options) || [];
448
+ if (!customDefaultValueField) {
449
+ fieldSettings.defaultValue = {
450
+ type: "custom",
451
+ label: "Default Value",
452
+ render: ({ value, onChange, id }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
453
+ import_puck.AutoField,
454
+ {
455
+ field: {
456
+ type: resolvedType,
457
+ label: "Default Value",
458
+ options: selectOptions
459
+ },
460
+ value,
461
+ onChange,
462
+ readOnly: false,
463
+ id
464
+ }
465
+ )
466
+ };
467
+ }
167
468
  fieldSettings.options = {
168
469
  type: "array",
169
470
  label: "Options",
@@ -183,21 +484,8 @@ var getFieldSettings = (_fields, _fieldSettings, deep) => {
183
484
  }
184
485
  };
185
486
  break;
487
+ }
186
488
  case "array":
187
- fieldSettings.summary = {
188
- type: "select",
189
- label: "Summary Field",
190
- options: [
191
- {
192
- label: "Default Numbering",
193
- value: ""
194
- },
195
- ...((currentFieldSettings == null ? void 0 : currentFieldSettings.subFields) || []).map((f) => ({
196
- label: f.name,
197
- value: f.name
198
- }))
199
- ]
200
- };
201
489
  case "object":
202
490
  fieldSettings.subFields = {
203
491
  type: "array",
@@ -226,7 +514,8 @@ var getFieldSettings = (_fields, _fieldSettings, deep) => {
226
514
  {
227
515
  label: "Radio",
228
516
  value: "radio"
229
- }
517
+ },
518
+ ...customTypeOptions
230
519
  ] : [
231
520
  {
232
521
  label: "Text",
@@ -255,7 +544,8 @@ var getFieldSettings = (_fields, _fieldSettings, deep) => {
255
544
  {
256
545
  label: "Reference",
257
546
  value: "reference"
258
- }
547
+ },
548
+ ...customTypeOptions
259
549
  ]
260
550
  }
261
551
  },
@@ -267,44 +557,99 @@ var getFieldSettings = (_fields, _fieldSettings, deep) => {
267
557
  fieldSettings.subFieldSettings = {
268
558
  type: "object",
269
559
  label: "Sub Field Settings",
270
- objectFields: (currentFieldSettings == null ? void 0 : currentFieldSettings.subFields) ? getFieldSettings(
271
- currentFieldSettings.subFields,
272
- currentFieldSettings.subFieldSettings,
560
+ objectFields: resolvedSubFields ? getFieldSettings(
561
+ resolvedSubFields,
562
+ resolvedSubFieldSettings,
563
+ customFields,
273
564
  true
274
565
  ) : {}
275
566
  };
567
+ if (resolvedType === "array") {
568
+ if (!customDefaultValueField) {
569
+ fieldSettings.defaultValue = {
570
+ type: "array",
571
+ label: "Default Items",
572
+ arrayFields: buildDefaultEditorFields(
573
+ resolvedSubFields,
574
+ resolvedSubFieldSettings,
575
+ customFields
576
+ ),
577
+ defaultItemProps: buildArrayDefaultItemProps(
578
+ resolvedSubFields,
579
+ resolvedSubFieldSettings
580
+ ),
581
+ getItemSummary(item, index) {
582
+ return getArrayItemSummary(item, index, currentFieldSettings);
583
+ }
584
+ };
585
+ }
586
+ fieldSettings.min = {
587
+ type: "number",
588
+ label: "Minimum Items"
589
+ };
590
+ fieldSettings.max = {
591
+ type: "number",
592
+ label: "Maximum Items"
593
+ };
594
+ fieldSettings.summary = {
595
+ type: "select",
596
+ label: "Summary",
597
+ options: [
598
+ {
599
+ label: "Default Numbering / Count",
600
+ value: "count"
601
+ },
602
+ {
603
+ label: "Field",
604
+ value: "field"
605
+ },
606
+ {
607
+ label: "Expression",
608
+ value: "expression"
609
+ }
610
+ ]
611
+ };
612
+ if ((currentFieldSettings == null ? void 0 : currentFieldSettings.summary) === "field") {
613
+ fieldSettings.summaryField = {
614
+ type: "select",
615
+ label: "Summary Field",
616
+ options: [
617
+ {
618
+ label: "Select a field",
619
+ value: ""
620
+ },
621
+ ...resolvedSubFields.filter((subField) => isPrimitiveFieldType(subField.type)).map((subField) => ({
622
+ label: subField.name,
623
+ value: subField.name
624
+ }))
625
+ ]
626
+ };
627
+ }
628
+ if ((currentFieldSettings == null ? void 0 : currentFieldSettings.summary) === "expression") {
629
+ fieldSettings.summaryExpression = {
630
+ type: "text",
631
+ label: "Summary Expression"
632
+ };
633
+ }
634
+ }
276
635
  break;
277
636
  }
637
+ const overriddenFieldSettings = (customFieldDefinition == null ? void 0 : customFieldDefinition.fieldSettingsOverride) ? customFieldDefinition.fieldSettingsOverride({
638
+ fieldName: field.name,
639
+ fieldType: field.type,
640
+ fieldSettings: currentFieldSettings,
641
+ originalFieldSettings: fieldSettings
642
+ }) : fieldSettings;
278
643
  fields[field.name] = {
279
644
  type: "object",
280
645
  label: field.name,
281
- objectFields: fieldSettings
646
+ objectFields: overriddenFieldSettings
282
647
  };
283
648
  return fields;
284
649
  }, {});
285
650
  };
286
651
  var get_field_settings_default = getFieldSettings;
287
652
 
288
- // src/puck/lib/get-settings-by-path.ts
289
- function getFieldSettingsByPath(fieldSettings, path) {
290
- return path.split(".").reduce((o, key) => o ? o[key] : void 0, fieldSettings);
291
- }
292
-
293
- // src/puck/lib/set-prop-by-path.ts
294
- function setPropertyByPath(props, path, value) {
295
- const parts = path.split(".");
296
- const last = parts.pop();
297
- let cur = props;
298
- for (const p of parts) {
299
- if (typeof cur[p] !== "object" || cur[p] === null) cur[p] = {};
300
- cur = cur[p];
301
- }
302
- cur[last] = value;
303
- }
304
-
305
- // src/puck/lib/builder/root-config.tsx
306
- var import_react2 = require("react");
307
-
308
653
  // src/puck/context/useStore.ts
309
654
  var import_react = require("react");
310
655
  var import_zustand = require("zustand");
@@ -325,224 +670,356 @@ var createUseSoftConfig = () => {
325
670
  };
326
671
  var useSoftConfig = createUseSoftConfig();
327
672
 
328
- // src/puck/lib/builder/root-config.tsx
329
- var import_use_debounce = require("use-debounce");
330
- var import_jsx_runtime2 = require("react/jsx-runtime");
331
- var useCustomPuck = (0, import_puck2.createUsePuck)();
332
- var breakVersion = (version) => {
333
- const [major, minor, patch] = version.split(".").map((v) => parseInt(v));
334
- return [major, minor, patch];
335
- };
336
- var updateVersion = (version, increment) => {
337
- let [major, minor, patch] = breakVersion(version);
338
- if (increment === "major") {
339
- major += 1;
340
- minor = 0;
341
- patch = 0;
342
- } else if (increment === "minor") {
343
- minor += 1;
344
- patch = 0;
345
- } else {
346
- patch += 1;
673
+ // src/puck/lib/apply-mapping.ts
674
+ var import_react_fast_compare = __toESM(require("react-fast-compare"));
675
+
676
+ // src/puck/lib/set-prop-by-path.ts
677
+ function setPropertyByPath(props, path, value) {
678
+ const parts = path.split(".");
679
+ const last = parts.pop();
680
+ let cur = props;
681
+ for (const p of parts) {
682
+ if (typeof cur[p] !== "object" || cur[p] === null) cur[p] = {};
683
+ cur = cur[p];
684
+ }
685
+ cur[last] = value;
686
+ }
687
+
688
+ // src/puck/lib/apply-mapping.ts
689
+ var resolveValueByPath = (source, path) => {
690
+ if (!path) return source;
691
+ const segments = path.split(".");
692
+ const resolveSegments = (current, index) => {
693
+ if (current === null || current === void 0) return void 0;
694
+ if (index >= segments.length) return current;
695
+ const segment = segments[index];
696
+ if (segment.endsWith("[]")) {
697
+ const arrayKey = segment.slice(0, -2);
698
+ const arraySource = arrayKey ? current == null ? void 0 : current[arrayKey] : current;
699
+ const resolvedArray = Array.isArray(arraySource) ? arraySource : Array.isArray(arraySource == null ? void 0 : arraySource.defaultValue) ? arraySource.defaultValue : void 0;
700
+ if (!resolvedArray) return void 0;
701
+ if (index === segments.length - 1) return resolvedArray;
702
+ return resolvedArray.map((item) => resolveSegments(item, index + 1));
703
+ }
704
+ return resolveSegments(current[segment], index + 1);
705
+ };
706
+ return resolveSegments(source, 0);
707
+ };
708
+ var resolveFieldSettingEntryByPath = (settings, path) => {
709
+ if (!path) return void 0;
710
+ const segments = path.split(".");
711
+ let currentSettings = settings;
712
+ let currentEntry;
713
+ for (const segmentWithArraySuffix of segments) {
714
+ const segment = segmentWithArraySuffix.endsWith("[]") ? segmentWithArraySuffix.slice(0, -2) : segmentWithArraySuffix;
715
+ if (!currentSettings || typeof currentSettings !== "object") {
716
+ return void 0;
717
+ }
718
+ currentEntry = currentSettings[segment];
719
+ if (currentEntry === void 0) {
720
+ return void 0;
721
+ }
722
+ currentSettings = currentEntry == null ? void 0 : currentEntry.subFieldSettings;
347
723
  }
348
- return `${major}.${minor}.${patch}`;
724
+ return currentEntry;
349
725
  };
350
- var builderRootConfig = (config, overrides, editingComponent, showVersionFields = true) => ({
351
- fields: __spreadValues({
352
- _name: overrides.name || {
353
- type: "text",
354
- label: "Soft Component Name"
355
- },
356
- _category: overrides.categories || {
357
- type: "select",
358
- label: "Category",
359
- options: [
360
- ...Object.keys(config.categories || {}).map((cat) => {
361
- var _a;
362
- return {
363
- label: ((_a = config.categories) == null ? void 0 : _a[cat].title) || cat,
364
- value: cat
365
- };
366
- }) || [],
367
- {
368
- label: Object.keys(config.categories || {}).length ? "Other" : "Uncategorized",
369
- value: void 0
726
+ function applyMapping(props, fieldSettings, map, resolveInput = "fieldSettings", options) {
727
+ var _a, _b, _c;
728
+ const newProps = __spreadValues({}, props);
729
+ const sourceProps = (_a = options == null ? void 0 : options.sourceProps) != null ? _a : props;
730
+ const mappedArrayPaths = /* @__PURE__ */ new Set();
731
+ let changed = false;
732
+ const changedArrayBases = /* @__PURE__ */ new Set();
733
+ for (const entry of map) {
734
+ const { from, to, transform } = entry;
735
+ if (!from || !to) continue;
736
+ const fromPaths = Array.isArray(from) ? from : [from];
737
+ const toPaths = Array.isArray(to) ? to : [to];
738
+ const hasInvalidPair = fromPaths.some((fp, idx) => {
739
+ const tp = toPaths[idx] || toPaths[0];
740
+ if (typeof fp !== "string" || typeof tp !== "string") return false;
741
+ return isArrayMappingPath(fp) && !isArrayMappingPath(tp);
742
+ });
743
+ if (hasInvalidPair) continue;
744
+ const inputValues = fromPaths.map((f) => {
745
+ if (resolveInput === "propsFirst") {
746
+ const propVal = resolveValueByPath(sourceProps, f);
747
+ if (propVal !== void 0) return propVal;
748
+ const setting = resolveValueByPath(fieldSettings, f);
749
+ if (setting && Object.prototype.hasOwnProperty.call(setting, "defaultValue")) {
750
+ return setting.defaultValue;
370
751
  }
371
- ]
372
- },
373
- _fields: {
374
- type: "array",
375
- label: "Fields",
376
- defaultItemProps: {
377
- name: "New Field",
378
- type: "text"
379
- },
380
- getItemSummary(item, index) {
381
- return item.name || `Field ${(index || 0) + 1}`;
382
- },
383
- arrayFields: {
384
- name: { type: "text", label: "Name" },
385
- type: {
386
- type: "select",
387
- label: "Type",
388
- options: [
389
- { label: "Text", value: "text" },
390
- { label: "Textarea", value: "textarea" },
391
- { label: "Number", value: "number" },
392
- { label: "Select", value: "select" },
393
- { label: "Radio", value: "radio" },
394
- { label: "Array", value: "array" },
395
- { label: "Object", value: "object" }
396
- // { label: "Reference", value: "reference" },
397
- ]
752
+ return propVal;
753
+ }
754
+ const directValue = resolveValueByPath(fieldSettings, f);
755
+ if (directValue !== void 0) {
756
+ return directValue;
757
+ }
758
+ return resolveFieldSettingEntryByPath(fieldSettings, f);
759
+ });
760
+ const resolvedInputs = inputValues.map(
761
+ (v) => resolveInput === "fieldSettings" ? v == null ? void 0 : v.defaultValue : v
762
+ );
763
+ let result = transform ? transform(resolvedInputs, newProps) : inputValues[0];
764
+ if (resolveInput === "fieldSettings" && !transform && result !== void 0 && typeof result === "object" && result !== null && "defaultValue" in result) {
765
+ result = result.defaultValue;
766
+ }
767
+ const isSingleArrayTarget = toPaths.length === 1 && typeof toPaths[0] === "string" && isArrayMappingPath(toPaths[0]);
768
+ if (isSingleArrayTarget) {
769
+ const toPath = toPaths[0];
770
+ const arrayBase = getArrayBasePath(toPath);
771
+ const subProp = getArrayItemSubPath(toPath) || "";
772
+ if (!arrayBase) continue;
773
+ const defaultArray = Array.isArray((_b = options == null ? void 0 : options.arrayDefaults) == null ? void 0 : _b[arrayBase]) ? (_c = options == null ? void 0 : options.arrayDefaults) == null ? void 0 : _c[arrayBase] : [];
774
+ const currentArrayAtPath = resolveValueByPath(newProps, arrayBase);
775
+ const currentArray = Array.isArray(currentArrayAtPath) ? currentArrayAtPath : [];
776
+ const isFromArrayPath = typeof fromPaths[0] === "string" && isArrayMappingPath(fromPaths[0]);
777
+ const sourceArray = isFromArrayPath ? Array.isArray(result) ? result : result !== void 0 ? [result] : [] : Array.isArray(result) ? result : defaultArray.map(() => result);
778
+ let defaults = entry.unmappedArrayItemDefaultValues || entry.defaultOverrides || {};
779
+ if (typeof defaults === "string") {
780
+ try {
781
+ defaults = JSON.parse(defaults);
782
+ } catch (e) {
783
+ defaults = {};
398
784
  }
399
785
  }
786
+ const targetLength = sourceArray.length;
787
+ const constructed = Array.from({ length: targetLength }).map((_, idx) => {
788
+ const mappedValue = sourceArray[idx];
789
+ const defaultItem = defaultArray[idx] && typeof defaultArray[idx] === "object" ? defaultArray[idx] : {};
790
+ const currentItem = currentArray[idx] && typeof currentArray[idx] === "object" ? currentArray[idx] : {};
791
+ const item = __spreadValues(__spreadValues(__spreadValues({}, defaultItem), defaults), currentItem);
792
+ if (subProp && mappedValue !== void 0) {
793
+ setPropertyByPath(item, subProp, mappedValue);
794
+ }
795
+ return item;
796
+ });
797
+ const originalArray = resolveValueByPath(newProps, arrayBase);
798
+ if (!(0, import_react_fast_compare.default)(originalArray, constructed)) {
799
+ setPropertyByPath(newProps, arrayBase, constructed);
800
+ changedArrayBases.add(arrayBase);
801
+ }
802
+ mappedArrayPaths.add(arrayBase);
803
+ } else if (toPaths.length === 1 && Array.isArray(result) && toPaths[0].includes("array")) {
804
+ const toPath = toPaths[0];
805
+ const original = resolveValueByPath(newProps, toPath);
806
+ if (!(0, import_react_fast_compare.default)(original, result)) {
807
+ setPropertyByPath(newProps, toPath, result);
808
+ changed = true;
809
+ }
810
+ } else if (Array.isArray(result) && toPaths.length > 1) {
811
+ result.forEach((val, idx) => {
812
+ if (toPaths[idx]) {
813
+ const orig = resolveValueByPath(newProps, toPaths[idx]);
814
+ if (!(0, import_react_fast_compare.default)(orig, val)) {
815
+ setPropertyByPath(newProps, toPaths[idx], val);
816
+ changed = true;
817
+ }
818
+ }
819
+ });
820
+ } else if (toPaths[0]) {
821
+ const finalValue = result;
822
+ const originalValue = resolveValueByPath(newProps, toPaths[0]);
823
+ if (!(0, import_react_fast_compare.default)(originalValue, finalValue)) {
824
+ setPropertyByPath(newProps, toPaths[0], finalValue);
825
+ changed = true;
826
+ }
400
827
  }
401
- }, overrides.additionalRootFields || {}),
402
- resolveFields({ props: data }, { fields, changed }) {
403
- var _a, _b;
404
- if (!(data == null ? void 0 : data._fields) || changed._fields || changed._fieldSettings)
405
- if ((_a = data == null ? void 0 : data._fields) == null ? void 0 : _a.length)
406
- fields._fieldSettings = {
407
- type: "object",
408
- label: "Field Settings",
409
- objectFields: get_field_settings_default(
410
- data._fields || [],
411
- data._fieldSettings || {}
412
- )
413
- };
414
- else delete fields._fieldSettings;
415
- if (showVersionFields && ((_b = data == null ? void 0 : data._versions) == null ? void 0 : _b.length)) {
416
- const latestVersion = data._versions[data._versions.length - 1] || "1.0.0";
417
- delete fields._version;
418
- fields._version = {
828
+ }
829
+ const hasNetArrayChanges = Array.from(changedArrayBases).some(
830
+ (arrayBase) => !(0, import_react_fast_compare.default)(resolveValueByPath(props, arrayBase), resolveValueByPath(newProps, arrayBase))
831
+ );
832
+ return { newProps, mappedArrayPaths, changed: changed || hasNetArrayChanges };
833
+ }
834
+
835
+ // src/puck/lib/builder/root-config.tsx
836
+ var import_jsx_runtime2 = require("react/jsx-runtime");
837
+ var useCustomPuck = (0, import_puck2.createUsePuck)();
838
+ var getSerializableProps = (props) => {
839
+ const cleanProps = {
840
+ id: props.id
841
+ };
842
+ for (const key in props) {
843
+ const value = props[key];
844
+ if (["children", "puck", "editMode"].includes(key)) continue;
845
+ if (value && typeof value === "object" && value.$$typeof) continue;
846
+ if (typeof value === "function") continue;
847
+ cleanProps[key] = value;
848
+ }
849
+ return cleanProps;
850
+ };
851
+ var builderRootConfig = (config, overrides, editingComponent, showVersionFields = true, customFields) => {
852
+ const customTypeOptions = getCustomFieldTypeOptions(customFields);
853
+ return {
854
+ fields: __spreadValues({
855
+ _name: overrides.name || {
856
+ type: "text",
857
+ label: "Soft Component Name"
858
+ },
859
+ _category: overrides.categories || {
419
860
  type: "select",
420
- label: "Version",
861
+ label: "Category",
421
862
  options: [
422
- ...data._versions.map((v) => ({ label: v, value: v })),
423
- {
424
- label: `${updateVersion(latestVersion, "patch")} (Patch)`,
425
- value: updateVersion(latestVersion, "patch")
426
- },
427
- {
428
- label: `${updateVersion(latestVersion, "minor")} (Minor)`,
429
- value: updateVersion(latestVersion, "minor")
430
- },
863
+ ...Object.keys(config.categories || {}).map((cat) => {
864
+ var _a;
865
+ return {
866
+ label: ((_a = config.categories) == null ? void 0 : _a[cat].title) || cat,
867
+ value: cat
868
+ };
869
+ }) || [],
431
870
  {
432
- label: `${updateVersion(latestVersion, "major")} (Major)`,
433
- value: updateVersion(latestVersion, "major")
871
+ label: Object.keys(config.categories || {}).length ? "Other" : "Uncategorized",
872
+ value: void 0
434
873
  }
435
874
  ]
436
- };
437
- } else {
438
- delete fields._version;
439
- }
440
- return fields;
441
- },
442
- resolveData: (props, params) => {
443
- if (overrides.resolveRootData) {
444
- return overrides.resolveRootData(props, params, { editingComponent });
445
- }
446
- let result = {
447
- props,
448
- readOnly: void 0
449
- };
450
- return result;
451
- },
452
- render: (props) => {
453
- const fieldSettings = props == null ? void 0 : props._fieldSettings;
454
- const data = useCustomPuck((s) => s.appState.data);
455
- const dispatch = useCustomPuck((s) => s.dispatch);
456
- const getSelectorForId = useCustomPuck((s) => s.getSelectorForId);
457
- const setVersion = useSoftConfig((s) => s.builder.setVersion);
458
- const state = useSoftConfig((s) => s.state);
459
- const [debouncedFieldSettings] = (0, import_use_debounce.useDebounce)(fieldSettings, 500);
460
- (0, import_react2.useEffect)(() => {
461
- if (!debouncedFieldSettings || Object.keys(debouncedFieldSettings).length === 0) return;
462
- (0, import_puck2.walkTree)(
463
- data,
464
- {
465
- components: config.components
875
+ },
876
+ _fields: {
877
+ type: "array",
878
+ label: "Fields",
879
+ defaultItemProps: {
880
+ name: "New Field",
881
+ type: "text"
466
882
  },
467
- (content) => content.map((child) => {
468
- var _a;
469
- const map = ((_a = child.props) == null ? void 0 : _a._map) || [];
470
- if (map.length) {
471
- map.forEach(({ from, to, transform }) => {
472
- if (!from || !to) return;
473
- const fromPaths = Array.isArray(from) ? from : [from];
474
- const toPaths = Array.isArray(to) ? to : [to];
475
- const inputValues = fromPaths.map(
476
- (f) => getFieldSettingsByPath(props._fieldSettings || {}, f)
477
- );
478
- let value = transform ? transform(
479
- inputValues.map((v) => v == null ? void 0 : v.defaultValue),
480
- child.props
481
- ) : inputValues[0];
482
- if (Array.isArray(value)) {
483
- value.forEach((val, i) => {
484
- if (toPaths[i]) {
485
- const originalValue = getFieldSettingsByPath(
486
- child.props,
487
- toPaths[i]
488
- );
489
- if (originalValue !== val) {
490
- const itemSelector = getSelectorForId(child.props.id);
491
- if (!itemSelector) return;
492
- setPropertyByPath(child.props, toPaths[i], val);
493
- dispatch({
494
- type: "replace",
495
- data: child,
496
- destinationIndex: itemSelector == null ? void 0 : itemSelector.index,
497
- destinationZone: itemSelector == null ? void 0 : itemSelector.zone
498
- });
499
- }
500
- }
501
- });
502
- } else if (toPaths[0]) {
503
- const setting = getFieldSettingsByPath(
504
- debouncedFieldSettings,
505
- fromPaths.length === 1 ? fromPaths[0] : fromPaths.join(".")
506
- );
507
- const defaultValue = setting == null ? void 0 : setting.defaultValue;
508
- const originalValue = getFieldSettingsByPath(
509
- child.props,
510
- toPaths[0]
511
- );
512
- const finalValue = transform !== void 0 && value !== void 0 ? value : defaultValue !== void 0 ? defaultValue : value;
513
- if (originalValue !== finalValue) {
514
- const itemSelector = getSelectorForId(child.props.id);
515
- if (!itemSelector) return;
516
- setPropertyByPath(child.props, toPaths[0], finalValue);
517
- dispatch({
518
- type: "replace",
519
- data: child,
520
- destinationIndex: itemSelector == null ? void 0 : itemSelector.index,
521
- destinationZone: itemSelector == null ? void 0 : itemSelector.zone
522
- });
523
- }
524
- }
525
- });
883
+ getItemSummary(item, index) {
884
+ return item.name || `Field ${(index || 0) + 1}`;
885
+ },
886
+ arrayFields: {
887
+ name: { type: "text", label: "Name" },
888
+ type: {
889
+ type: "select",
890
+ label: "Type",
891
+ options: [
892
+ { label: "Text", value: "text" },
893
+ { label: "Textarea", value: "textarea" },
894
+ { label: "Number", value: "number" },
895
+ { label: "Select", value: "select" },
896
+ { label: "Radio", value: "radio" },
897
+ { label: "Array", value: "array" },
898
+ { label: "Object", value: "object" },
899
+ // { label: "Reference", value: "reference" },
900
+ ...customTypeOptions
901
+ ]
526
902
  }
527
- return child;
528
- })
529
- );
530
- }, [debouncedFieldSettings, data, dispatch, getSelectorForId, props._fieldSettings]);
531
- (0, import_react2.useEffect)(() => {
532
- var _a;
533
- if (state !== "remodeling") return;
534
- if (!(props == null ? void 0 : props._version) || !(props == null ? void 0 : props._name)) return;
535
- const currentVersion = props == null ? void 0 : props._version;
536
- if (((_a = props._versions) == null ? void 0 : _a.includes(currentVersion)) && props._versions.length > 1) {
537
- setVersion(props._name, currentVersion, props, dispatch);
903
+ }
538
904
  }
539
- }, [props == null ? void 0 : props._version]);
540
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: props.children });
541
- }
542
- });
905
+ }, overrides.additionalRootFields || {}),
906
+ resolveFields({ props: data }, { fields, changed }) {
907
+ const newFields = __spreadValues({}, fields);
908
+ const rootFields = Array.isArray(
909
+ data == null ? void 0 : data._fields
910
+ ) ? (data == null ? void 0 : data._fields) || [] : [];
911
+ const rootFieldSettings = (data == null ? void 0 : data._fieldSettings) || {};
912
+ if (changed._fields || changed._fieldSettings) {
913
+ if (rootFields.length) {
914
+ newFields._fieldSettings = {
915
+ type: "object",
916
+ label: "Field Settings",
917
+ objectFields: get_field_settings_default(
918
+ rootFields,
919
+ rootFieldSettings,
920
+ customFields
921
+ )
922
+ };
923
+ } else {
924
+ delete newFields._fieldSettings;
925
+ }
926
+ }
927
+ return newFields;
928
+ },
929
+ // resolveData: (props, params) => {
930
+ // if (overrides.resolveRootData) {
931
+ // return overrides.resolveRootData(props, params, { editingComponent });
932
+ // }
933
+ // const result: {
934
+ // props: RootData<AsFieldProps<WithChildren<BuilderRootConfig>>>;
935
+ // readOnly: Readonly<Record<string, boolean>> | undefined;
936
+ // } = {
937
+ // props,
938
+ // readOnly: undefined,
939
+ // };
940
+ // return result;
941
+ // },
942
+ render: (props) => {
943
+ const fieldSettings = props == null ? void 0 : props._fieldSettings;
944
+ const data = useCustomPuck((s) => s.appState.data);
945
+ const dispatch = useCustomPuck((s) => s.dispatch);
946
+ const getSelectorForId = useCustomPuck((s) => s.getSelectorForId);
947
+ const setVersion = useSoftConfig((s) => s.builder.setVersion);
948
+ const state = useSoftConfig((s) => s.state);
949
+ (0, import_react2.useEffect)(() => {
950
+ if (!fieldSettings || Object.keys(fieldSettings).length === 0) return;
951
+ const replacements = [];
952
+ (0, import_puck2.walkTree)(
953
+ {
954
+ content: (data == null ? void 0 : data.content) || [],
955
+ root: (data == null ? void 0 : data.root) || {}
956
+ },
957
+ {
958
+ components: config.components
959
+ },
960
+ (content) => content.map((child) => {
961
+ var _a;
962
+ const map = ((_a = child.props) == null ? void 0 : _a._map) || [];
963
+ if (!map.length) return child;
964
+ const cleanProps = getSerializableProps(child.props);
965
+ const { newProps, changed } = applyMapping(
966
+ cleanProps,
967
+ fieldSettings,
968
+ map,
969
+ "fieldSettings"
970
+ );
971
+ if (!changed || (0, import_react_fast_compare2.default)(cleanProps, newProps)) return child;
972
+ replacements.push({
973
+ id: child.props.id,
974
+ data: __spreadProps(__spreadValues({}, child), { props: newProps })
975
+ });
976
+ return child;
977
+ })
978
+ );
979
+ if (!replacements.length) return;
980
+ replacements.forEach((replacement) => {
981
+ const itemSelector = getSelectorForId(replacement.id);
982
+ if (!itemSelector) return;
983
+ dispatch({
984
+ type: "replace",
985
+ data: replacement.data,
986
+ destinationIndex: itemSelector.index,
987
+ destinationZone: itemSelector.zone
988
+ });
989
+ });
990
+ }, [fieldSettings, data, dispatch, getSelectorForId]);
991
+ (0, import_react2.useEffect)(() => {
992
+ var _a;
993
+ if (state !== "remodeling" || !(props == null ? void 0 : props._version) || !(props == null ? void 0 : props._name)) return;
994
+ const currentVersion = props._version;
995
+ if (((_a = props._versions) == null ? void 0 : _a.includes(currentVersion)) && props._versions.length > 1) {
996
+ setVersion(props._name, currentVersion, props, dispatch);
997
+ }
998
+ }, [props == null ? void 0 : props._version]);
999
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: props.children });
1000
+ }
1001
+ };
1002
+ };
543
1003
 
544
1004
  // src/puck/lib/builder/generate-field-options.ts
545
- function generateFieldOptions(fields, selectedFields, prefix = "") {
1005
+ var hasArrayMappingPath = (value) => value.includes("[]");
1006
+ var isBareArrayPath = (value) => !hasArrayMappingPath(value) && !value.includes(".");
1007
+ function filterToOptionsForFrom(fromPath, toOptions) {
1008
+ if (!fromPath) return toOptions;
1009
+ const fromHasArrayMapping = hasArrayMappingPath(fromPath);
1010
+ const fromIsBareArray = isBareArrayPath(fromPath);
1011
+ return toOptions.filter((option) => {
1012
+ const optionHasArrayMapping = hasArrayMappingPath(option.value);
1013
+ if (fromHasArrayMapping) {
1014
+ return optionHasArrayMapping;
1015
+ }
1016
+ if (fromIsBareArray) {
1017
+ return isBareArrayPath(option.value);
1018
+ }
1019
+ return !optionHasArrayMapping;
1020
+ });
1021
+ }
1022
+ function generateFieldOptions(fields, prefix = "") {
546
1023
  const opts = [];
547
1024
  function recurse(current, prefix2) {
548
1025
  Object.entries(current).forEach(([key, fld]) => {
@@ -550,36 +1027,68 @@ function generateFieldOptions(fields, selectedFields, prefix = "") {
550
1027
  if (key === "_map") return;
551
1028
  if (key === "_slotEnabled") return;
552
1029
  const path = prefix2 ? `${prefix2}.${key}` : key;
553
- if (selectedFields.includes(path)) {
554
- return;
555
- }
556
- opts.push({ label: path, value: path, type: fld.type });
557
1030
  if (fld.type === "object" && fld.objectFields) {
558
1031
  recurse(fld.objectFields, path);
559
- }
560
- if (fld.type === "array" && fld.arrayFields) {
561
- recurse(fld.arrayFields, path);
1032
+ } else if (fld.type === "array" && fld.arrayFields) {
1033
+ recurse(
1034
+ fld.arrayFields,
1035
+ path + "[]"
1036
+ );
1037
+ } else {
1038
+ opts.push({ label: path, value: path, type: fld.type });
562
1039
  }
563
1040
  });
564
1041
  }
565
1042
  recurse(fields, prefix);
566
1043
  return opts;
567
1044
  }
568
- function generateDynamicFieldOptions(_fields, _fieldSettings, prefix = "") {
1045
+ function generateDynamicFieldOptions(_fields, _fieldSettings, customFields, prefix = "") {
569
1046
  const opts = [];
570
- if (!_fields || !_fieldSettings) return opts;
1047
+ if (!_fields) return opts;
571
1048
  function recurse(fields, fieldSettings, currentPrefix) {
572
1049
  fields.forEach((field) => {
573
1050
  var _a;
574
1051
  const settings = fieldSettings[field.name];
1052
+ const customReturnType = resolveCustomFieldReturnType(
1053
+ field.type,
1054
+ customFields
1055
+ );
575
1056
  const path = currentPrefix ? `${currentPrefix}.${field.name}` : field.name;
576
- opts.push({ label: path, value: path, type: field.type });
1057
+ if (customReturnType) {
1058
+ if (customReturnType === "array" || customReturnType === "object") {
1059
+ const customSchema = resolveCustomFieldSchema(field.type, customFields);
1060
+ if (!customSchema) {
1061
+ return;
1062
+ }
1063
+ recurse(
1064
+ customSchema.subFields,
1065
+ customSchema.subFieldSettings,
1066
+ path + (customReturnType === "array" ? "[]" : "")
1067
+ );
1068
+ return;
1069
+ }
1070
+ opts.push({
1071
+ label: path,
1072
+ value: path,
1073
+ type: mapCustomReturnTypeToMappingType(customReturnType)
1074
+ });
1075
+ return;
1076
+ }
1077
+ if (!isBuiltInSoftFieldType(field.type)) {
1078
+ return;
1079
+ }
577
1080
  if ((_a = settings == null ? void 0 : settings.subFields) == null ? void 0 : _a.length) {
578
- recurse(settings.subFields, settings.subFieldSettings || {}, path);
1081
+ recurse(
1082
+ settings.subFields,
1083
+ settings.subFieldSettings || {},
1084
+ path + (field.type === "array" ? "[]" : "")
1085
+ );
1086
+ } else if (field.type !== "array" && field.type !== "object") {
1087
+ opts.push({ label: path, value: path, type: field.type });
579
1088
  }
580
1089
  });
581
1090
  }
582
- recurse(_fields, _fieldSettings, prefix);
1091
+ recurse(_fields, _fieldSettings || {}, prefix);
583
1092
  return opts;
584
1093
  }
585
1094
 
@@ -671,8 +1180,14 @@ var ErrorBoundary = class extends import_react3.Component {
671
1180
 
672
1181
  // src/puck/lib/builder/builder-config.tsx
673
1182
  var import_jsx_runtime4 = require("react/jsx-runtime");
674
- var builderConfig = (config, overrides, editingComponent, showVersionFields = true, dependents) => ({
675
- root: builderRootConfig(config, overrides, editingComponent, showVersionFields),
1183
+ var builderConfig = (config, overrides, editingComponent, showVersionFields = true, dependents, customFields) => ({
1184
+ root: builderRootConfig(
1185
+ config,
1186
+ overrides,
1187
+ editingComponent,
1188
+ showVersionFields,
1189
+ customFields
1190
+ ),
676
1191
  components: Object.entries(__spreadValues({}, config.components)).reduce(
677
1192
  (acc, [name, component]) => {
678
1193
  const tempComponent = __spreadProps(__spreadValues({}, component), {
@@ -681,6 +1196,7 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
681
1196
  },
682
1197
  resolveFields(data, params) {
683
1198
  return __async(this, null, function* () {
1199
+ var _a2;
684
1200
  let fields = {};
685
1201
  if (!fields._slot) {
686
1202
  const slotFields = Object.entries(params.fields).filter(
@@ -701,8 +1217,8 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
701
1217
  { label: "Select a slot", value: "" },
702
1218
  ...slotFields.filter(
703
1219
  ([fieldName, field]) => {
704
- var _a2;
705
- return field.type === "slot" && !(((_a2 = data.props) == null ? void 0 : _a2._slot) || []).some(
1220
+ var _a3;
1221
+ return field.type === "slot" && !(((_a3 = data.props) == null ? void 0 : _a3._slot) || []).some(
706
1222
  (s) => s.slot === fieldName
707
1223
  );
708
1224
  }
@@ -721,17 +1237,21 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
721
1237
  };
722
1238
  }
723
1239
  const defaultFields = component.resolveFields ? yield component.resolveFields(data, params) : component.fields || {};
724
- if (!fields._map) {
1240
+ if (!fields._map || params.changed._map) {
725
1241
  const rootProps = getRootProps(params.appState);
726
1242
  const fromOptions = generateDynamicFieldOptions(
727
1243
  (rootProps == null ? void 0 : rootProps._fields) || [],
728
- (rootProps == null ? void 0 : rootProps._fieldSettings) || {}
1244
+ (rootProps == null ? void 0 : rootProps._fieldSettings) || {},
1245
+ customFields
729
1246
  );
730
- const toOptions = generateFieldOptions(defaultFields, []);
1247
+ const toOptionsFields = component.resolveFields && ((_a2 = data.props) == null ? void 0 : _a2._map) ? yield component.resolveFields(
1248
+ __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { _map: void 0 }) }),
1249
+ params
1250
+ ) : defaultFields;
1251
+ const toOptions = generateFieldOptions(toOptionsFields);
731
1252
  fields._map = overrides.map ? {
732
1253
  type: "custom",
733
1254
  render: ({ value, onChange, id }) => {
734
- const toOptions2 = generateFieldOptions(defaultFields, []);
735
1255
  const rootProps2 = getRootProps(params.appState);
736
1256
  return overrides.map({
737
1257
  rootProps: rootProps2,
@@ -740,13 +1260,39 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
740
1260
  id,
741
1261
  props: data.props || {},
742
1262
  fromOptions,
743
- toOptions: toOptions2
1263
+ toOptions
1264
+ });
1265
+ }
1266
+ } : (() => {
1267
+ var _a3;
1268
+ const mapEntries = ((_a3 = data.props) == null ? void 0 : _a3._map) || [];
1269
+ const toPaths = mapEntries.flatMap(
1270
+ (entry) => Array.isArray(entry.to) ? entry.to : entry.to ? [entry.to] : []
1271
+ );
1272
+ const toPath = toPaths.find(
1273
+ (path) => typeof path === "string" && isArrayMappingPath(path)
1274
+ );
1275
+ const arrayBaseName = toPath ? getArrayBasePath(toPath) : null;
1276
+ const targetArrayField = arrayBaseName ? defaultFields[arrayBaseName] : null;
1277
+ const mappedSubProps = /* @__PURE__ */ new Set();
1278
+ if (arrayBaseName) {
1279
+ toPaths.forEach((path) => {
1280
+ if (typeof path !== "string") return;
1281
+ if (getArrayBasePath(path) !== arrayBaseName) return;
1282
+ const subProp = getArrayItemSubPath(path);
1283
+ if (subProp) mappedSubProps.add(subProp);
744
1284
  });
745
1285
  }
746
- } : {
747
- type: "array",
748
- label: "Dynamic Field Map",
749
- arrayFields: {
1286
+ const defaultValueFields = {};
1287
+ if (targetArrayField && targetArrayField.type === "array" && targetArrayField.arrayFields) {
1288
+ const arrayFields = targetArrayField.arrayFields;
1289
+ Object.entries(arrayFields).forEach(([key, fld]) => {
1290
+ if (mappedSubProps.has(key)) return;
1291
+ if (fld.type === "array" || fld.type === "object" || fld.type === "slot") return;
1292
+ defaultValueFields[key] = __spreadProps(__spreadValues({}, fld), { label: fld.label || key });
1293
+ });
1294
+ }
1295
+ const baseArrayFields = {
750
1296
  from: {
751
1297
  type: "select",
752
1298
  label: "From",
@@ -769,47 +1315,57 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
769
1315
  }))
770
1316
  ]
771
1317
  }
1318
+ };
1319
+ if (arrayBaseName && Object.keys(defaultValueFields).length > 0) {
1320
+ baseArrayFields.unmappedArrayItemDefaultValues = {
1321
+ type: "object",
1322
+ label: "Default Item Values",
1323
+ objectFields: defaultValueFields
1324
+ };
772
1325
  }
773
- };
1326
+ return {
1327
+ type: "array",
1328
+ label: "Dynamic Field Map",
1329
+ arrayFields: baseArrayFields
1330
+ };
1331
+ })();
774
1332
  }
775
1333
  fields = __spreadValues(__spreadValues({}, fields), defaultFields);
776
1334
  return fields;
777
1335
  });
778
1336
  },
779
1337
  resolveData: ({ props }, { lastData }) => {
780
- var _a2;
781
- const _map = props._map || [];
1338
+ const _map = (props._map || []).map((item) => {
1339
+ const newItem = __spreadValues({}, item);
1340
+ if (typeof newItem.unmappedArrayItemDefaultValues === "string") {
1341
+ try {
1342
+ newItem.unmappedArrayItemDefaultValues = JSON.parse(
1343
+ newItem.unmappedArrayItemDefaultValues
1344
+ );
1345
+ } catch (e) {
1346
+ newItem.unmappedArrayItemDefaultValues = {};
1347
+ }
1348
+ } else if (!newItem.unmappedArrayItemDefaultValues) {
1349
+ newItem.unmappedArrayItemDefaultValues = {};
1350
+ }
1351
+ return newItem;
1352
+ });
782
1353
  const readOnlyFields = _map.flatMap((item) => item.to);
1354
+ const readOnlyArrayBases = readOnlyFields.filter((field) => typeof field === "string").map(getArrayBasePath).filter((base) => base !== null);
783
1355
  if (_map.length) {
784
1356
  return {
785
- props,
786
- readOnly: readOnlyFields.reduce(
1357
+ props: __spreadProps(__spreadValues({}, props), { _map }),
1358
+ readOnly: [
1359
+ ...readOnlyFields.map((f) => String(f)),
1360
+ ...readOnlyArrayBases
1361
+ ].reduce(
787
1362
  (acc2, field) => __spreadProps(__spreadValues({}, acc2), { [field]: true }),
788
1363
  {}
789
1364
  )
790
1365
  };
791
1366
  }
792
- const prevMap = (_a2 = lastData == null ? void 0 : lastData.props) == null ? void 0 : _a2._map;
793
- if (prevMap && prevMap.length === 1) {
794
- const lastField = prevMap[0].to;
795
- if (typeof lastField === "string") {
796
- return {
797
- props,
798
- readOnly: { [lastField]: false }
799
- };
800
- }
801
- if (Array.isArray(lastField)) {
802
- return {
803
- props,
804
- readOnly: lastField.reduce(
805
- (acc2, field) => __spreadProps(__spreadValues({}, acc2), { [String(field)]: false }),
806
- {}
807
- )
808
- };
809
- }
810
- }
811
1367
  return {
812
- props,
1368
+ props: __spreadProps(__spreadValues({}, props), { _map }),
813
1369
  readOnly: {}
814
1370
  };
815
1371
  },
@@ -825,6 +1381,9 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
825
1381
  categories: config.categories || {}
826
1382
  });
827
1383
 
1384
+ // src/puck/lib/soft-component-constants.ts
1385
+ var TECHNICAL_KEYS = /* @__PURE__ */ new Set(["_map", "_slot", "id", "_version"]);
1386
+
828
1387
  // src/puck/lib/strip-id.ts
829
1388
  var stripIdFromProps = (components, allowedTypes) => {
830
1389
  return components.map((component) => sanitizeComponent(component, allowedTypes));
@@ -848,7 +1407,7 @@ var sanitizeComponent = (component, allowedTypes) => {
848
1407
  var getSubComponents = (content, componentConfigs, fieldSettings, slots) => {
849
1408
  if (!content || !Array.isArray(content)) return [];
850
1409
  return content.map((componentProps) => {
851
- var _a, _b, _c;
1410
+ var _a, _b, _c, _d;
852
1411
  const componentConfig = componentConfigs[componentProps.type];
853
1412
  const enabledSlotNames = new Set(
854
1413
  (((_a = componentProps.props) == null ? void 0 : _a._slot) || []).map((s) => s.slot)
@@ -869,7 +1428,27 @@ var getSubComponents = (content, componentConfigs, fieldSettings, slots) => {
869
1428
  },
870
1429
  {}
871
1430
  ) || {};
872
- const fixedProps = __spreadValues(__spreadValues({}, componentConfig == null ? void 0 : componentConfig.defaultProps), componentProps.props);
1431
+ const map = ((_b = componentProps.props) == null ? void 0 : _b._map) || [];
1432
+ const mappedPaths = /* @__PURE__ */ new Set();
1433
+ map.forEach((item) => {
1434
+ const to = Array.isArray(item.to) ? item.to : [item.to];
1435
+ to.forEach((path) => {
1436
+ if (path) {
1437
+ if (isArrayMappingPath(path)) {
1438
+ const basePath = getArrayBasePath(path);
1439
+ if (basePath) mappedPaths.add(basePath);
1440
+ } else {
1441
+ mappedPaths.add(path);
1442
+ }
1443
+ }
1444
+ });
1445
+ });
1446
+ const fixedProps = Object.entries(__spreadValues(__spreadValues({}, componentConfig == null ? void 0 : componentConfig.defaultProps), componentProps.props)).reduce((acc, [key, value]) => {
1447
+ if (!TECHNICAL_KEYS.has(key) && !mappedPaths.has(key)) {
1448
+ acc[key] = value;
1449
+ }
1450
+ return acc;
1451
+ }, {});
873
1452
  (componentProps.props._slot || []).forEach(
874
1453
  (s) => {
875
1454
  var _a2;
@@ -883,19 +1462,34 @@ var getSubComponents = (content, componentConfigs, fieldSettings, slots) => {
883
1462
  }
884
1463
  );
885
1464
  const subComponent = {
886
- map: ((_b = componentProps.props) == null ? void 0 : _b._map) || [],
1465
+ map: ((_c = componentProps.props) == null ? void 0 : _c._map) || [],
887
1466
  fixedProps,
888
1467
  type: componentProps.type,
889
1468
  components,
890
- enabledSlots: ((_c = componentProps.props) == null ? void 0 : _c._slot) || []
1469
+ enabledSlots: ((_d = componentProps.props) == null ? void 0 : _d._slot) || []
891
1470
  };
892
1471
  return subComponent;
893
1472
  });
894
1473
  };
895
- var softFieldsToPuckFields = (fields, fieldSettings) => {
1474
+ var softFieldsToPuckFields = (fields, fieldSettings, customFields) => {
896
1475
  return (fields == null ? void 0 : fields.reduce(
897
1476
  (acc, field) => {
898
- var _a, _b, _c, _d, _e, _f, _g, _h;
1477
+ var _a, _b, _c, _d, _e, _f;
1478
+ const customFieldDefinition = resolveCustomFieldDefinition(
1479
+ field.type,
1480
+ customFields
1481
+ );
1482
+ const customReturnType = resolveCustomFieldReturnType(
1483
+ field.type,
1484
+ customFields
1485
+ );
1486
+ if (customFieldDefinition && customReturnType) {
1487
+ acc[field.name] = __spreadProps(__spreadValues({}, customFieldDefinition.field), {
1488
+ type: "custom",
1489
+ label: customFieldDefinition.field.label || field.name
1490
+ });
1491
+ return acc;
1492
+ }
899
1493
  switch (field.type) {
900
1494
  case "text":
901
1495
  case "textarea":
@@ -920,13 +1514,24 @@ var softFieldsToPuckFields = (fields, fieldSettings) => {
920
1514
  break;
921
1515
  // TODO: Default item props
922
1516
  case "array":
1517
+ const currentArraySettings = (fieldSettings == null ? void 0 : fieldSettings[field.name]) || {};
923
1518
  acc[field.name] = {
924
1519
  type: field.type,
925
1520
  label: field.name,
1521
+ min: currentArraySettings.min,
1522
+ max: currentArraySettings.max,
926
1523
  arrayFields: softFieldsToPuckFields(
927
- ((_e = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _e.subFields) || [],
928
- ((_f = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _f.subFieldSettings) || {}
929
- )
1524
+ currentArraySettings.subFields || [],
1525
+ currentArraySettings.subFieldSettings || {},
1526
+ customFields
1527
+ ),
1528
+ defaultItemProps: buildArrayDefaultItemProps(
1529
+ currentArraySettings.subFields,
1530
+ currentArraySettings.subFieldSettings
1531
+ ),
1532
+ getItemSummary(item, index) {
1533
+ return getArrayItemSummary(item, index, currentArraySettings);
1534
+ }
930
1535
  };
931
1536
  break;
932
1537
  // TODO: Needs testing to see if it works
@@ -935,8 +1540,9 @@ var softFieldsToPuckFields = (fields, fieldSettings) => {
935
1540
  type: field.type,
936
1541
  label: field.name,
937
1542
  objectFields: softFieldsToPuckFields(
938
- ((_g = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _g.subFields) || [],
939
- ((_h = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _h.subFieldSettings) || {}
1543
+ ((_e = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _e.subFields) || [],
1544
+ ((_f = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _f.subFieldSettings) || {},
1545
+ customFields
940
1546
  )
941
1547
  };
942
1548
  break;
@@ -948,11 +1554,34 @@ var softFieldsToPuckFields = (fields, fieldSettings) => {
948
1554
  {}
949
1555
  )) || {};
950
1556
  };
951
- var softComponentFromAppState = (appState, configComponents, editedItem, metadata) => {
1557
+ var softComponentFromAppState = (appState, configComponents, editedItem, metadata, customFields) => {
952
1558
  var _a;
953
1559
  const rootProps = ((_a = appState.data.root) == null ? void 0 : _a.props) || {};
954
1560
  const fields = rootProps._fields || [];
955
1561
  const field_settings = rootProps._fieldSettings || {};
1562
+ const normalizedFieldSettings = __spreadValues({}, field_settings);
1563
+ (fields || []).forEach((field) => {
1564
+ const customFieldDefinition = resolveCustomFieldDefinition(
1565
+ field.type,
1566
+ customFields
1567
+ );
1568
+ const customReturnType = resolveCustomFieldReturnType(
1569
+ field.type,
1570
+ customFields
1571
+ );
1572
+ if (!customFieldDefinition || !customReturnType) {
1573
+ return;
1574
+ }
1575
+ const schema = resolveCustomFieldSchema(field.type, customFields);
1576
+ const existingSettings = normalizedFieldSettings[field.name] || {};
1577
+ normalizedFieldSettings[field.name] = __spreadValues(__spreadProps(__spreadValues({}, existingSettings), {
1578
+ customFieldType: field.type,
1579
+ customFieldReturnType: customReturnType
1580
+ }), schema ? {
1581
+ subFields: schema.subFields,
1582
+ subFieldSettings: schema.subFieldSettings
1583
+ } : {});
1584
+ });
956
1585
  const builtInRootProps = /* @__PURE__ */ new Set([
957
1586
  "_name",
958
1587
  "_category",
@@ -972,12 +1601,22 @@ var softComponentFromAppState = (appState, configComponents, editedItem, metadat
972
1601
  const components = getSubComponents(
973
1602
  [editedItem],
974
1603
  configComponents,
975
- field_settings,
1604
+ normalizedFieldSettings,
976
1605
  slots
977
1606
  );
978
- const defaultProps = __spreadValues(__spreadValues({}, Object.keys(field_settings).reduce(
1607
+ const defaultProps = __spreadValues(__spreadValues({}, Object.keys(normalizedFieldSettings).reduce(
979
1608
  (acc, field) => {
980
- acc[field] = field_settings[field].defaultValue;
1609
+ var _a2;
1610
+ const fieldDefinition = (fields || []).find((item) => item.name === field);
1611
+ const customFieldReturnType = (_a2 = normalizedFieldSettings[field]) == null ? void 0 : _a2.customFieldReturnType;
1612
+ if ((fieldDefinition == null ? void 0 : fieldDefinition.type) === "array" || customFieldReturnType === "array") {
1613
+ acc[field] = normalizedFieldSettings[field].defaultValue !== void 0 ? normalizedFieldSettings[field].defaultValue : buildArrayDefaultValue(
1614
+ normalizedFieldSettings[field].subFields,
1615
+ normalizedFieldSettings[field].subFieldSettings
1616
+ );
1617
+ return acc;
1618
+ }
1619
+ acc[field] = normalizedFieldSettings[field].defaultValue;
981
1620
  return acc;
982
1621
  },
983
1622
  {}
@@ -986,11 +1625,11 @@ var softComponentFromAppState = (appState, configComponents, editedItem, metadat
986
1625
  {
987
1626
  name: metadata.name,
988
1627
  category: metadata.category,
989
- fields: __spreadValues(__spreadValues({}, softFieldsToPuckFields(fields, field_settings)), Object.keys(slots).reduce((acc, slot) => {
1628
+ fields: __spreadValues(__spreadValues({}, softFieldsToPuckFields(fields, normalizedFieldSettings, customFields)), Object.keys(slots).reduce((acc, slot) => {
990
1629
  acc[slot] = { type: "slot", label: slot };
991
1630
  return acc;
992
1631
  }, {})),
993
- fieldSettings: field_settings,
1632
+ fieldSettings: normalizedFieldSettings,
994
1633
  defaultProps,
995
1634
  rootProps: customRootProps,
996
1635
  components,
@@ -1016,23 +1655,55 @@ var createComponentKeyFromName = (displayName, overrides, context) => {
1016
1655
  return key.trim();
1017
1656
  };
1018
1657
  var getComponentNameFromKey = (key, overrides) => {
1019
- if (overrides.componentKeyToName) {
1658
+ if (overrides == null ? void 0 : overrides.componentKeyToName) {
1020
1659
  return overrides.componentKeyToName(key);
1021
1660
  }
1022
1661
  return key;
1023
1662
  };
1024
1663
 
1025
1664
  // src/puck/lib/soft-component-to-appstate.ts
1026
- var puckFieldsToSoftFields = (fields, slots) => {
1665
+ var mergeFieldSettings = (generated = {}, persisted = {}) => {
1666
+ return Object.entries(persisted).reduce((acc, [fieldName, value]) => {
1667
+ const current = acc[fieldName] || {};
1668
+ acc[fieldName] = __spreadProps(__spreadValues(__spreadValues({}, current), value), {
1669
+ subFieldSettings: current.subFieldSettings || (value == null ? void 0 : value.subFieldSettings) ? mergeFieldSettings(
1670
+ current.subFieldSettings || {},
1671
+ (value == null ? void 0 : value.subFieldSettings) || {}
1672
+ ) : void 0
1673
+ });
1674
+ return acc;
1675
+ }, __spreadValues({}, generated));
1676
+ };
1677
+ var puckFieldsToSoftFields = (fields, slots, persistedFieldSettings = {}, customFields) => {
1027
1678
  const softFields = [];
1028
1679
  const fieldSettings = {};
1029
1680
  Object.entries(fields).forEach(([fieldName, field]) => {
1681
+ var _a;
1682
+ const persistedSettings = persistedFieldSettings == null ? void 0 : persistedFieldSettings[fieldName];
1683
+ const fieldWithMeta = field;
1684
+ const customFieldType = fieldWithMeta.customFieldType || (persistedSettings == null ? void 0 : persistedSettings.customFieldType);
1685
+ const customFieldReturnType = fieldWithMeta.customFieldReturnType || (persistedSettings == null ? void 0 : persistedSettings.customFieldReturnType) || (customFieldType ? (_a = customFields == null ? void 0 : customFields[customFieldType]) == null ? void 0 : _a.returnType : void 0);
1030
1686
  if (slots.has(fieldName)) {
1031
1687
  return;
1032
1688
  }
1033
1689
  if (fieldName === "_version") {
1034
1690
  return;
1035
1691
  }
1692
+ if (field.type === "custom" && customFieldType) {
1693
+ softFields.push({ name: fieldName, type: customFieldType });
1694
+ const customSchema = resolveCustomFieldSchema(customFieldType, customFields);
1695
+ fieldSettings[fieldName] = __spreadValues(__spreadProps(__spreadValues({}, persistedSettings || {}), {
1696
+ customFieldType,
1697
+ customFieldReturnType
1698
+ }), customSchema ? {
1699
+ subFields: customSchema.subFields,
1700
+ subFieldSettings: customSchema.subFieldSettings
1701
+ } : {});
1702
+ if (!Object.prototype.hasOwnProperty.call(fieldSettings[fieldName], "defaultValue")) {
1703
+ fieldSettings[fieldName].defaultValue = void 0;
1704
+ }
1705
+ return;
1706
+ }
1036
1707
  switch (field.type) {
1037
1708
  case "text":
1038
1709
  case "textarea":
@@ -1050,67 +1721,81 @@ var puckFieldsToSoftFields = (fields, slots) => {
1050
1721
  case "radio":
1051
1722
  softFields.push({ name: fieldName, type: field.type });
1052
1723
  fieldSettings[fieldName] = {
1053
- options: field.options || []
1724
+ options: field.options ? [...field.options] : []
1054
1725
  };
1055
1726
  break;
1056
1727
  case "array":
1057
1728
  softFields.push({ name: fieldName, type: "array" });
1058
1729
  const arrayFieldsResult = puckFieldsToSoftFields(
1059
1730
  field.arrayFields || {},
1060
- /* @__PURE__ */ new Set()
1731
+ /* @__PURE__ */ new Set(),
1732
+ persistedSettings == null ? void 0 : persistedSettings.subFieldSettings,
1733
+ customFields
1061
1734
  );
1062
- fieldSettings[fieldName] = {
1735
+ fieldSettings[fieldName] = __spreadProps(__spreadValues({}, persistedSettings || {}), {
1063
1736
  subFields: arrayFieldsResult.fields,
1064
1737
  subFieldSettings: arrayFieldsResult.fieldSettings
1065
- };
1738
+ });
1066
1739
  break;
1067
1740
  case "object":
1068
1741
  softFields.push({ name: fieldName, type: "object" });
1069
1742
  const objectFieldsResult = puckFieldsToSoftFields(
1070
1743
  field.objectFields || {},
1071
- /* @__PURE__ */ new Set()
1744
+ /* @__PURE__ */ new Set(),
1745
+ persistedSettings == null ? void 0 : persistedSettings.subFieldSettings,
1746
+ customFields
1072
1747
  );
1073
- fieldSettings[fieldName] = {
1748
+ fieldSettings[fieldName] = __spreadProps(__spreadValues({}, persistedSettings || {}), {
1074
1749
  subFields: objectFieldsResult.fields,
1075
1750
  subFieldSettings: objectFieldsResult.fieldSettings
1076
- };
1751
+ });
1077
1752
  break;
1078
1753
  default:
1079
1754
  softFields.push({ name: fieldName, type: "text" });
1080
1755
  }
1081
- if (fieldSettings[fieldName]) {
1082
- fieldSettings[fieldName].defaultValue = void 0;
1083
- } else {
1084
- fieldSettings[fieldName] = { defaultValue: void 0 };
1085
- }
1756
+ fieldSettings[fieldName] = __spreadProps(__spreadValues({}, fieldSettings[fieldName] || persistedSettings || {}), {
1757
+ defaultValue: Object.prototype.hasOwnProperty.call(
1758
+ fieldSettings[fieldName] || persistedSettings || {},
1759
+ "defaultValue"
1760
+ ) ? (fieldSettings[fieldName] || persistedSettings || {}).defaultValue : void 0
1761
+ });
1086
1762
  });
1087
1763
  return { fields: softFields, fieldSettings };
1088
1764
  };
1089
1765
  var reconstructComponents = (subComponents, componentConfigs, softComponentProps) => {
1090
1766
  return subComponents.map((subComponent) => {
1091
- var _a;
1092
- const props = __spreadValues({}, subComponent.fixedProps);
1093
- (_a = subComponent.map) == null ? void 0 : _a.forEach((mapItem, i) => {
1094
- var _a2;
1095
- const { from, to, transform } = mapItem || {};
1096
- const fromPaths = Array.isArray(from) ? from : from ? [from] : [];
1097
- const toPaths = Array.isArray(to) ? to : to ? [to] : [];
1098
- const inputs = fromPaths.map(
1099
- (path) => getFieldSettingsByPath(softComponentProps || {}, path)
1100
- );
1101
- const runner = transform;
1102
- const result = runner ? runner(inputs, softComponentProps) : inputs[0];
1103
- if (Array.isArray(result)) {
1104
- result.forEach((val, idx) => {
1105
- if (toPaths[idx]) setPropertyByPath(props, toPaths[idx], val);
1767
+ const componentConfig = componentConfigs[subComponent.type];
1768
+ const props = __spreadProps(__spreadValues({}, subComponent.fixedProps), {
1769
+ _map: subComponent.map
1770
+ });
1771
+ const arrayDefaults = (subComponent.map || []).reduce(
1772
+ (acc, mapEntry) => {
1773
+ const toPaths = Array.isArray(mapEntry.to) ? mapEntry.to : [mapEntry.to];
1774
+ toPaths.forEach((path) => {
1775
+ var _a;
1776
+ if (typeof path !== "string" || !isArrayMappingPath(path)) return;
1777
+ const arrayBase = getArrayBasePath(path);
1778
+ if (!arrayBase || acc[arrayBase]) return;
1779
+ const defaultValue = (_a = componentConfig == null ? void 0 : componentConfig.defaultProps) == null ? void 0 : _a[arrayBase];
1780
+ if (Array.isArray(defaultValue)) acc[arrayBase] = defaultValue;
1106
1781
  });
1107
- } else {
1108
- toPaths.forEach((toPath) => setPropertyByPath(props, toPath, result));
1109
- }
1110
- if (transform && ((_a2 = props._map) == null ? void 0 : _a2[i])) {
1111
- props._map[i].transform = transform;
1782
+ return acc;
1783
+ },
1784
+ {}
1785
+ );
1786
+ const sourceProps = __spreadValues(__spreadValues(__spreadValues({}, (componentConfig == null ? void 0 : componentConfig.defaultProps) || {}), softComponentProps), props);
1787
+ const { newProps } = applyMapping(
1788
+ props,
1789
+ {},
1790
+ // fieldSettings not needed for "propsFirst" mode as it resolves from propsFirst
1791
+ subComponent.map || [],
1792
+ "propsFirst",
1793
+ {
1794
+ sourceProps,
1795
+ arrayDefaults
1112
1796
  }
1113
- });
1797
+ );
1798
+ Object.assign(props, newProps);
1114
1799
  if (subComponent.enabledSlots.length > 0) {
1115
1800
  props._slot = subComponent.enabledSlots;
1116
1801
  subComponent.enabledSlots.forEach(({ slot, name }) => {
@@ -1140,16 +1825,33 @@ var reconstructComponents = (subComponents, componentConfigs, softComponentProps
1140
1825
  return componentData;
1141
1826
  });
1142
1827
  };
1143
- var softComponentToAppState = (softComponent, componentName, version, versions, componentProps, componentConfigs, overrides, displayName, category) => {
1828
+ var softComponentToAppState = (softComponent, componentName, version, versions, componentProps, componentConfigs, overrides, displayName, category, customFields) => {
1144
1829
  const slots = new Set(Object.keys(softComponent.slots));
1145
1830
  const { fields, fieldSettings } = puckFieldsToSoftFields(
1146
1831
  softComponent.fields,
1147
- slots
1832
+ slots,
1833
+ softComponent.fieldSettings,
1834
+ customFields
1148
1835
  );
1836
+ const mergedFieldSettings = mergeFieldSettings(
1837
+ fieldSettings,
1838
+ softComponent.fieldSettings || {}
1839
+ ) || {};
1149
1840
  Object.entries(softComponent.defaultProps).forEach(([key, value]) => {
1150
- if (fieldSettings && fieldSettings[key] && !slots.has(key)) {
1151
- fieldSettings[key].defaultValue = value;
1841
+ if (mergedFieldSettings && mergedFieldSettings[key] && !slots.has(key)) {
1842
+ mergedFieldSettings[key].defaultValue = value;
1843
+ }
1844
+ });
1845
+ (fields || []).forEach((field) => {
1846
+ if (field.type !== "array" || slots.has(field.name)) return;
1847
+ const settings = mergedFieldSettings[field.name] || {};
1848
+ if (settings.defaultValue === void 0) {
1849
+ settings.defaultValue = buildArrayDefaultValue(
1850
+ settings.subFields,
1851
+ settings.subFieldSettings
1852
+ );
1152
1853
  }
1854
+ mergedFieldSettings[field.name] = settings;
1153
1855
  });
1154
1856
  let rootProps = __spreadValues({
1155
1857
  _name: displayName || getComponentNameFromKey(componentName, overrides),
@@ -1157,7 +1859,7 @@ var softComponentToAppState = (softComponent, componentName, version, versions,
1157
1859
  _version: version,
1158
1860
  _versions: versions,
1159
1861
  _fields: fields,
1160
- _fieldSettings: fieldSettings
1862
+ _fieldSettings: mergedFieldSettings
1161
1863
  }, softComponent.rootProps || {});
1162
1864
  if (overrides.onRemodel) {
1163
1865
  rootProps = __spreadValues(__spreadValues({}, rootProps), overrides.onRemodel(componentName));
@@ -1184,7 +1886,7 @@ var rootDroppableId = `${rootAreaId}:${rootZone}`;
1184
1886
 
1185
1887
  // src/puck/components/soft-render/index.tsx
1186
1888
  var import_react4 = __toESM(require("react"));
1187
- var import_react_fast_compare = __toESM(require("react-fast-compare"));
1889
+ var import_react_fast_compare3 = __toESM(require("react-fast-compare"));
1188
1890
  var import_jsx_runtime5 = require("react/jsx-runtime");
1189
1891
  function isPlainObject(val) {
1190
1892
  if (typeof val !== "object" || val === null) return false;
@@ -1223,28 +1925,19 @@ var SubComponentRenderer = (0, import_react4.memo)(
1223
1925
  if (!componentConfig) return {};
1224
1926
  const clonedProps = cloneData(subComponent.fixedProps || {});
1225
1927
  if ((_a = subComponent.map) == null ? void 0 : _a.length) {
1226
- subComponent.map.forEach((mapItem) => {
1227
- const { from, to, transform } = mapItem || {};
1228
- const fromPaths = Array.isArray(from) ? from : from ? [from] : [];
1229
- const toPaths = Array.isArray(to) ? to : to ? [to] : [];
1230
- const inputValues = fromPaths.map((f) => {
1231
- const propValue = getFieldSettingsByPath(props, f);
1232
- if (propValue !== void 0) return propValue;
1233
- const setting = getFieldSettingsByPath(softComponentFieldSettings || {}, f);
1234
- if (setting && Object.prototype.hasOwnProperty.call(setting, "defaultValue")) {
1235
- return setting.defaultValue;
1236
- }
1237
- return propValue;
1238
- });
1239
- const result = transform ? transform(inputValues, props) : inputValues[0];
1240
- if (Array.isArray(result)) {
1241
- result.forEach(
1242
- (val, i) => toPaths[i] && setPropertyByPath(clonedProps, toPaths[i], val)
1243
- );
1244
- } else if (toPaths[0]) {
1245
- setPropertyByPath(clonedProps, toPaths[0], result);
1928
+ const mergedInput = __spreadValues(__spreadValues({}, clonedProps), props);
1929
+ const { newProps } = applyMapping(
1930
+ mergedInput,
1931
+ softComponentFieldSettings || {},
1932
+ subComponent.map,
1933
+ "propsFirst"
1934
+ );
1935
+ const parentKeys = new Set(Object.keys(props));
1936
+ for (const [key, value] of Object.entries(newProps)) {
1937
+ if (!parentKeys.has(key) || key in clonedProps) {
1938
+ clonedProps[key] = value;
1246
1939
  }
1247
- });
1940
+ }
1248
1941
  }
1249
1942
  Object.entries(componentConfig.fields || {}).forEach(
1250
1943
  ([slotKey, field]) => {
@@ -1305,7 +1998,7 @@ var SubComponentRenderer = (0, import_react4.memo)(
1305
1998
  // and on props (the primary driver of field-mapping changes).
1306
1999
  // configComponents and softComponentFields are treated as stable config
1307
2000
  // references — reference equality is intentional and fast here.
1308
- (prev, next) => prev.depth === next.depth && prev.index === next.index && prev.configComponents === next.configComponents && prev.softComponentFields === next.softComponentFields && (0, import_react_fast_compare.default)(prev.props, next.props) && (0, import_react_fast_compare.default)(prev.subComponent, next.subComponent) && (0, import_react_fast_compare.default)(prev.softComponentFieldSettings, next.softComponentFieldSettings)
2001
+ (prev, next) => prev.depth === next.depth && prev.index === next.index && prev.configComponents === next.configComponents && prev.softComponentFields === next.softComponentFields && (0, import_react_fast_compare3.default)(prev.props, next.props) && (0, import_react_fast_compare3.default)(prev.subComponent, next.subComponent) && (0, import_react_fast_compare3.default)(prev.softComponentFieldSettings, next.softComponentFieldSettings)
1309
2002
  );
1310
2003
  SubComponentRenderer.displayName = "SubComponentRenderer";
1311
2004
  var SoftRender = (0, import_react4.memo)(
@@ -1339,13 +2032,32 @@ var SoftRender = (0, import_react4.memo)(
1339
2032
  // configComponents / softComponentFields: reference equality (stable config).
1340
2033
  // softComponentFieldSettings: deep equality (may carry dynamic defaults).
1341
2034
  // props / softSubComponent: deep equality (primary render drivers).
1342
- (prev, next) => prev.configComponents === next.configComponents && prev.softComponentFields === next.softComponentFields && (0, import_react_fast_compare.default)(prev.props, next.props) && (0, import_react_fast_compare.default)(prev.softSubComponent, next.softSubComponent) && (0, import_react_fast_compare.default)(prev.softComponentFieldSettings, next.softComponentFieldSettings)
2035
+ (prev, next) => prev.configComponents === next.configComponents && prev.softComponentFields === next.softComponentFields && (0, import_react_fast_compare3.default)(prev.props, next.props) && (0, import_react_fast_compare3.default)(prev.softSubComponent, next.softSubComponent) && (0, import_react_fast_compare3.default)(prev.softComponentFieldSettings, next.softComponentFieldSettings)
1343
2036
  );
1344
2037
  SoftRender.displayName = "SoftRender";
1345
2038
 
1346
2039
  // src/puck/lib/create-versioned-component-config.tsx
1347
2040
  var import_jsx_runtime6 = require("react/jsx-runtime");
1348
- var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true) => {
2041
+ var hydrateCustomField = (fieldName, field, fieldSettings, customFields) => {
2042
+ var _a;
2043
+ if (field.type !== "custom") {
2044
+ return field;
2045
+ }
2046
+ const fieldWithMeta = field;
2047
+ const customFieldType = fieldWithMeta.customFieldType || ((_a = fieldSettings == null ? void 0 : fieldSettings[fieldName]) == null ? void 0 : _a.customFieldType);
2048
+ if (!customFieldType) {
2049
+ return field;
2050
+ }
2051
+ const customField = customFields == null ? void 0 : customFields[customFieldType];
2052
+ if (!customField) {
2053
+ return field;
2054
+ }
2055
+ return __spreadProps(__spreadValues(__spreadValues({}, field), customField.field), {
2056
+ type: "custom",
2057
+ label: field.label || customField.field.label || fieldName
2058
+ });
2059
+ };
2060
+ var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true, customFields) => {
1349
2061
  var _a, _b;
1350
2062
  const softConfig = config;
1351
2063
  return {
@@ -1373,7 +2085,12 @@ var createVersionedComponentConfig = (componentName, displayName, version, allVe
1373
2085
  };
1374
2086
  }
1375
2087
  Object.entries((versionedComponent == null ? void 0 : versionedComponent.fields) || {}).filter(([, field]) => field.type !== "slot").forEach(([key, field]) => {
1376
- fields[key] = field;
2088
+ fields[key] = hydrateCustomField(
2089
+ key,
2090
+ field,
2091
+ versionedComponent == null ? void 0 : versionedComponent.fieldSettings,
2092
+ customFields
2093
+ );
1377
2094
  });
1378
2095
  return fields;
1379
2096
  },
@@ -1400,21 +2117,16 @@ var subComponentDecomposer = (componentRootData, softSubComponent) => {
1400
2117
  var _a;
1401
2118
  const resolvedProps = __spreadValues({}, softSubComponent.fixedProps);
1402
2119
  (_a = softSubComponent.map) == null ? void 0 : _a.forEach((mapItem) => {
1403
- const { from, to, transform } = mapItem || {};
1404
- const fromPaths = Array.isArray(from) ? from : from ? [from] : [];
1405
- const toPaths = Array.isArray(to) ? to : to ? [to] : [];
1406
- const inputs = fromPaths.map(
1407
- (path) => getFieldSettingsByPath(componentRootData.props || {}, path)
2120
+ const { newProps } = applyMapping(
2121
+ resolvedProps,
2122
+ {},
2123
+ [mapItem],
2124
+ "propsFirst",
2125
+ {
2126
+ sourceProps: componentRootData.props || {}
2127
+ }
1408
2128
  );
1409
- const runner = transform;
1410
- const result = runner ? runner(inputs, componentRootData.props) : inputs[0];
1411
- if (Array.isArray(result)) {
1412
- result.forEach((val, idx) => {
1413
- if (toPaths[idx]) setPropertyByPath(resolvedProps, toPaths[idx], val);
1414
- });
1415
- } else if (toPaths[0]) {
1416
- setPropertyByPath(resolvedProps, toPaths[0], result);
1417
- }
2129
+ Object.assign(resolvedProps, newProps);
1418
2130
  });
1419
2131
  softSubComponent.enabledSlots.forEach(({ slot, name }) => {
1420
2132
  var _a2, _b;
@@ -1437,9 +2149,22 @@ var subComponentDecomposer = (componentRootData, softSubComponent) => {
1437
2149
  return accItem;
1438
2150
  };
1439
2151
 
2152
+ // src/puck/lib/builder/resolve-soft-component-data.ts
2153
+ var resolveSoftComponentData = (props, _fieldSettings = {}) => {
2154
+ const map = props._map;
2155
+ if (!(map == null ? void 0 : map.length)) return __spreadValues({}, props);
2156
+ const { newProps } = applyMapping(
2157
+ props,
2158
+ _fieldSettings,
2159
+ map,
2160
+ "propsFirst"
2161
+ );
2162
+ return newProps;
2163
+ };
2164
+
1440
2165
  // src/puck/lib/decompose-soft-component.ts
1441
- function decomposeSoftComponent(componentData, softComponents) {
1442
- var _a, _b;
2166
+ function decomposeSoftComponent(componentData, softComponents, fieldSettings) {
2167
+ var _a, _b, _c, _d;
1443
2168
  if (!(componentData == null ? void 0 : componentData.type) || !(componentData == null ? void 0 : componentData.props.id)) {
1444
2169
  throw new Error("Component data must have type and id to decompose.");
1445
2170
  }
@@ -1450,9 +2175,19 @@ function decomposeSoftComponent(componentData, softComponents) {
1450
2175
  `Soft component "${componentData.type}" version "${version}" not found.`
1451
2176
  );
1452
2177
  }
2178
+ let resolvedComponentData = componentData;
2179
+ if (fieldSettings && ((_d = (_c = componentData.props) == null ? void 0 : _c._map) == null ? void 0 : _d.length)) {
2180
+ const resolvedProps = resolveSoftComponentData(
2181
+ componentData.props,
2182
+ fieldSettings
2183
+ );
2184
+ resolvedComponentData = __spreadProps(__spreadValues({}, componentData), {
2185
+ props: resolvedProps
2186
+ });
2187
+ }
1453
2188
  const decomposedComponentData = softComponent.components.map(
1454
2189
  (softSubComponent) => {
1455
- return subComponentDecomposer(componentData, softSubComponent);
2190
+ return subComponentDecomposer(resolvedComponentData, softSubComponent);
1456
2191
  }
1457
2192
  );
1458
2193
  return decomposedComponentData;
@@ -1522,7 +2257,14 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1522
2257
  });
1523
2258
  const config = __spreadValues({}, get().softConfig);
1524
2259
  const overrides = get().overrides;
1525
- const buildConfig = builderConfig(config, overrides, void 0, get().showVersionFields);
2260
+ const buildConfig = builderConfig(
2261
+ config,
2262
+ overrides,
2263
+ void 0,
2264
+ get().showVersionFields,
2265
+ void 0,
2266
+ get().customFields
2267
+ );
1526
2268
  const editableIds = /* @__PURE__ */ new Set([selectedItem.props.id]);
1527
2269
  const initialContent = [__spreadValues({}, selectedItem)];
1528
2270
  (0, import_puck4.walkTree)(
@@ -1596,12 +2338,20 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1596
2338
  get().softConfig.components,
1597
2339
  get().overrides,
1598
2340
  (softComponentMeta == null ? void 0 : softComponentMeta.name) || softComponentName,
1599
- softComponentMeta == null ? void 0 : softComponentMeta.category
2341
+ softComponentMeta == null ? void 0 : softComponentMeta.category,
2342
+ get().customFields
1600
2343
  );
1601
2344
  const config = __spreadValues({}, get().softConfig);
1602
2345
  const overrides = get().overrides;
1603
2346
  const dependents = get().dependencyGraph.get(softComponentName) || /* @__PURE__ */ new Set();
1604
- const buildConfig = builderConfig(config, overrides, softComponentName, get().showVersionFields, dependents);
2347
+ const buildConfig = builderConfig(
2348
+ config,
2349
+ overrides,
2350
+ softComponentName,
2351
+ get().showVersionFields,
2352
+ dependents,
2353
+ get().customFields
2354
+ );
1605
2355
  const editableIds = /* @__PURE__ */ new Set([]);
1606
2356
  const decomposedComponents = get().builder.decompose(selectedItem);
1607
2357
  (0, import_puck4.walkTree)(
@@ -1828,7 +2578,8 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1828
2578
  {
1829
2579
  name: displayName,
1830
2580
  category
1831
- }
2581
+ },
2582
+ get().customFields
1832
2583
  );
1833
2584
  const existingComponent = get().softComponents[componentName];
1834
2585
  const allVersions = Object.keys((existingComponent == null ? void 0 : existingComponent.versions) || {});
@@ -1847,7 +2598,8 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1847
2598
  })
1848
2599
  }),
1849
2600
  softComponent.defaultProps,
1850
- get().showVersionFields
2601
+ get().showVersionFields,
2602
+ get().customFields
1851
2603
  );
1852
2604
  get().setSoftComponent(componentName, version, softComponent);
1853
2605
  return [newSoftComponentConfig, version];
@@ -1901,7 +2653,8 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1901
2653
  get().softConfig.components,
1902
2654
  get().overrides,
1903
2655
  (softComponentMeta == null ? void 0 : softComponentMeta.name) || componentName,
1904
- softComponentMeta == null ? void 0 : softComponentMeta.category
2656
+ softComponentMeta == null ? void 0 : softComponentMeta.category,
2657
+ get().customFields
1905
2658
  );
1906
2659
  puckDispatch({
1907
2660
  type: "setData",
@@ -2048,7 +2801,7 @@ function topologicalSort(softComponents, hardComponentNames) {
2048
2801
  }
2049
2802
  return sorted;
2050
2803
  }
2051
- function buildInitialSoftComponents(hardConfig, softComponents, overrides, showVersioning = false) {
2804
+ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showVersioning = false, customFields) {
2052
2805
  var _a, _b;
2053
2806
  if (!softComponents || Object.keys(softComponents).length === 0) {
2054
2807
  return {};
@@ -2084,7 +2837,8 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
2084
2837
  // Pass the accumulating config
2085
2838
  hydratedSoftComponents,
2086
2839
  versionedComponent.defaultProps,
2087
- showVersioning
2840
+ showVersioning,
2841
+ customFields
2088
2842
  );
2089
2843
  componentConfigs[name] = newSoftComponentConfig;
2090
2844
  buildingConfig.components[name] = newSoftComponentConfig;
@@ -2112,7 +2866,8 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
2112
2866
  hardConfig,
2113
2867
  hydratedSoftComponents,
2114
2868
  versionedComponent.defaultProps,
2115
- showVersioning
2869
+ showVersioning,
2870
+ customFields
2116
2871
  );
2117
2872
  componentConfigs[name] = newSoftComponentConfig;
2118
2873
  }
@@ -2178,9 +2933,9 @@ var clearEditVisibility = (doc) => {
2178
2933
  // src/puck/store/index.tsx
2179
2934
  var createSoftConfigStore = (hardConfig = {
2180
2935
  components: {}
2181
- }, softComponents = {}, overrides = {}, onActions, showVersionFields = true) => {
2936
+ }, softComponents = {}, overrides = {}, onActions, showVersionFields = true, customFields = {}) => {
2182
2937
  const normalizedSoftComponents = Object.fromEntries(
2183
- Object.entries(softComponents || {}).map(([key, value]) => [
2938
+ Object.entries(softComponents || {}).filter(([key]) => !hardConfig.components || !hardConfig.components[key]).map(([key, value]) => [
2184
2939
  key,
2185
2940
  __spreadProps(__spreadValues({}, value), {
2186
2941
  name: value.name || key
@@ -2201,6 +2956,7 @@ var createSoftConfigStore = (hardConfig = {
2201
2956
  state: "ready",
2202
2957
  originalHistory: [],
2203
2958
  overrides,
2959
+ customFields,
2204
2960
  onActions,
2205
2961
  iframeDocRef,
2206
2962
  showVersionFields,
@@ -2242,11 +2998,17 @@ var createSoftConfigStore = (hardConfig = {
2242
2998
  components: __spreadValues(__spreadValues({}, hardConfig.components), buildInitialSoftComponents(
2243
2999
  hardConfig,
2244
3000
  hydratedSoftComponents,
2245
- overrides
3001
+ overrides,
3002
+ showVersionFields,
3003
+ customFields
2246
3004
  )),
2247
3005
  categories: __spreadValues({}, hardConfig.categories || {})
2248
3006
  }),
2249
3007
  setSoftComponent: (name, version, component) => {
3008
+ if (hardConfig.components && hardConfig.components[name]) {
3009
+ console.warn(`Cannot set soft component "${name}" because it conflicts with a base hardConfig component.`);
3010
+ return;
3011
+ }
2250
3012
  const existing = get().softComponents[name];
2251
3013
  set((state) => {
2252
3014
  var _a, _b;
@@ -2269,6 +3031,9 @@ var createSoftConfigStore = (hardConfig = {
2269
3031
  const nextSoftComponents = __spreadValues({}, state.softComponents);
2270
3032
  const nextConfigComponents = __spreadValues({}, state.softConfig.components);
2271
3033
  Object.entries(incomingComponents).forEach(([name, data]) => {
3034
+ if (hardConfig.components && hardConfig.components[name]) {
3035
+ return;
3036
+ }
2272
3037
  const existing = nextSoftComponents[name];
2273
3038
  const finalComponentData = existing ? __spreadProps(__spreadValues(__spreadValues({}, existing), data), {
2274
3039
  name: data.name || existing.name || name,
@@ -2287,7 +3052,8 @@ var createSoftConfigStore = (hardConfig = {
2287
3052
  state.softConfig,
2288
3053
  nextSoftComponents,
2289
3054
  activeVersionData.defaultProps,
2290
- state.showVersionFields
3055
+ state.showVersionFields,
3056
+ state.customFields
2291
3057
  );
2292
3058
  }
2293
3059
  });
@@ -2318,7 +3084,8 @@ var createSoftConfigStore = (hardConfig = {
2318
3084
  softConfig,
2319
3085
  hydratedComponents,
2320
3086
  activeVersionData.defaultProps,
2321
- get().showVersionFields
3087
+ get().showVersionFields,
3088
+ get().customFields
2322
3089
  );
2323
3090
  }
2324
3091
  });
@@ -2349,7 +3116,8 @@ var createSoftConfigStore = (hardConfig = {
2349
3116
  get().softConfig,
2350
3117
  get().softComponents,
2351
3118
  softComponent.defaultProps,
2352
- get().showVersionFields
3119
+ get().showVersionFields,
3120
+ get().customFields
2353
3121
  );
2354
3122
  set((state) => ({
2355
3123
  softConfig: __spreadProps(__spreadValues({}, state.softConfig), {
@@ -2486,7 +3254,8 @@ var createSoftConfigStore = (hardConfig = {
2486
3254
  config,
2487
3255
  softComponents2,
2488
3256
  versionedComponent.defaultProps,
2489
- state.showVersionFields
3257
+ state.showVersionFields,
3258
+ state.customFields
2490
3259
  );
2491
3260
  config.components[dependentName] = newConfig;
2492
3261
  }
@@ -2504,14 +3273,29 @@ var SoftConfigProvider = ({
2504
3273
  children,
2505
3274
  hardConfig,
2506
3275
  softComponents,
3276
+ customFields,
2507
3277
  overrides,
2508
3278
  value,
2509
3279
  onActions,
2510
3280
  useVersioning = false
2511
3281
  }) => {
2512
3282
  const store = value != null ? value : (0, import_react5.useMemo)(
2513
- () => createSoftConfigStore(hardConfig, softComponents, overrides, onActions, useVersioning),
2514
- [hardConfig, softComponents, overrides, onActions, useVersioning]
3283
+ () => createSoftConfigStore(
3284
+ hardConfig,
3285
+ softComponents,
3286
+ overrides,
3287
+ onActions,
3288
+ useVersioning,
3289
+ customFields
3290
+ ),
3291
+ [
3292
+ hardConfig,
3293
+ softComponents,
3294
+ overrides,
3295
+ onActions,
3296
+ useVersioning,
3297
+ customFields
3298
+ ]
2515
3299
  );
2516
3300
  const [softConfig, setSoftConfig] = (0, import_react5.useState)(
2517
3301
  () => store.getState().softConfig
@@ -3107,7 +3891,7 @@ var getClassName3 = get_class_name_factory_default("ActionBar", ActionBar_module
3107
3891
  var usePuck2 = (0, import_puck14.createUsePuck)();
3108
3892
  var ActionBarOverride = (props) => {
3109
3893
  var _a, _b;
3110
- const { handleBuild } = useBuild("Custom Name");
3894
+ const { handleBuild } = useBuild(props.label ? props.label + " Soft Component" : "New Soft Component");
3111
3895
  const { handleRemodel } = useRemodel();
3112
3896
  const { handleDecompose } = useDecompose();
3113
3897
  const overrides = useSoftConfig((s) => s.overrides);
@@ -3139,10 +3923,17 @@ var ActionBarOverride = (props) => {
3139
3923
  const selectedId = (_a = selectedItem == null ? void 0 : selectedItem.props) == null ? void 0 : _a.id;
3140
3924
  const parentId = (_b = itemSelector == null ? void 0 : itemSelector.zone) == null ? void 0 : _b.split(":")[0];
3141
3925
  const isEditable = Boolean(selectedId && (editableIds.has(selectedId) || parentId && editableIds.has(parentId)));
3926
+ const displayName = (0, import_react9.useMemo)(() => {
3927
+ var _a2;
3928
+ if (isSoftComponent2) {
3929
+ return ((_a2 = softComponents[key]) == null ? void 0 : _a2.name) || getComponentNameFromKey(key, overrides);
3930
+ }
3931
+ return props.label || "";
3932
+ }, [isSoftComponent2, key, props.label, overrides, softComponents]);
3142
3933
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: getClassName3(), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_puck14.ActionBar, { children: [
3143
3934
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_puck14.ActionBar.Group, { children: [
3144
3935
  props.parentAction,
3145
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_puck14.ActionBar.Label, { label: props.label })
3936
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_puck14.ActionBar.Label, { label: displayName })
3146
3937
  ] }),
3147
3938
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_puck14.ActionBar.Group, { children: [
3148
3939
  status === "ready" ? isSoftComponent2 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
@@ -3267,7 +4058,7 @@ var getClassName5 = get_class_name_factory_default("DrawerItem", DrawerItem_modu
3267
4058
  var usePuck3 = (0, import_puck15.createUsePuck)();
3268
4059
  var DrawerItem = (props) => {
3269
4060
  const componentMeta = useSoftConfig((s) => s.softComponents[props.name]);
3270
- const displayName = (componentMeta == null ? void 0 : componentMeta.name) || props.name;
4061
+ const displayName = props.label || (componentMeta == null ? void 0 : componentMeta.name) || props.name;
3271
4062
  const softComponents = new Set(
3272
4063
  Object.keys(useSoftConfig((s) => s.softComponents, import_shallow2.shallow))
3273
4064
  );
@@ -3363,6 +4154,7 @@ var DrawerItem = (props) => {
3363
4154
  onMouseEnter: () => setIsHovering(true),
3364
4155
  onMouseLeave: () => setIsHovering(false),
3365
4156
  children: [
4157
+ props.label,
3366
4158
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: getClassName5("content"), children: [
3367
4159
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: getClassName5("name"), children: displayName }),
3368
4160
  useVersioning && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: getClassName5("version"), children: [
@@ -3539,6 +4331,10 @@ var Drawer = (_props) => {
3539
4331
  })
3540
4332
  );
3541
4333
  const allKeys = Object.keys(config.components);
4334
+ const labels = Object.entries(config.components).reduce((acc, [key, comp]) => {
4335
+ acc[key] = comp.label || key;
4336
+ return acc;
4337
+ }, {});
3542
4338
  const otherKeys = allKeys.filter((k) => !categorised.has(k));
3543
4339
  const categoryEntries = Object.entries(categories).filter(
3544
4340
  ([, cat]) => cat.visible !== false
@@ -3557,6 +4353,7 @@ var Drawer = (_props) => {
3557
4353
  import_puck16.Drawer.Item,
3558
4354
  {
3559
4355
  name: key,
4356
+ label: labels[key],
3560
4357
  isDragDisabled: !getPermissions({ type: key }).insert,
3561
4358
  children: DrawerItem
3562
4359
  },
@@ -3641,9 +4438,6 @@ function extractDependencies2(softComponents, componentName, version) {
3641
4438
  return dependencies;
3642
4439
  }
3643
4440
  function reverseTopologicalSort(softComponents, hardComponentNames) {
3644
- const sorted = [];
3645
- const visiting = /* @__PURE__ */ new Set();
3646
- const visited = /* @__PURE__ */ new Set();
3647
4441
  const dependencyGraph = /* @__PURE__ */ new Map();
3648
4442
  const dependents = /* @__PURE__ */ new Map();
3649
4443
  for (const [componentName, component] of Object.entries(softComponents)) {
@@ -3691,7 +4485,7 @@ function reverseTopologicalSort(softComponents, hardComponentNames) {
3691
4485
  const sortedByDepth = [...depths.entries()].sort(([, depthA], [, depthB]) => depthB - depthA).map(([name]) => name);
3692
4486
  return sortedByDepth;
3693
4487
  }
3694
- function dissolveComponentRecursively(componentData, softComponents, hardComponentNames, depth = 0) {
4488
+ function dissolveComponentRecursively(componentData, softComponents, hardComponentNames, depth = 0, fieldSettings) {
3695
4489
  const MAX_DEPTH = 50;
3696
4490
  if (depth > MAX_DEPTH) {
3697
4491
  console.error(
@@ -3701,11 +4495,11 @@ function dissolveComponentRecursively(componentData, softComponents, hardCompone
3701
4495
  }
3702
4496
  const componentType = componentData.type;
3703
4497
  if (!isSoftComponent(componentType, softComponents)) {
3704
- return [dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth)];
4498
+ return [dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth, fieldSettings)];
3705
4499
  }
3706
4500
  let decomposed;
3707
4501
  try {
3708
- decomposed = decomposeSoftComponent(componentData, softComponents);
4502
+ decomposed = decomposeSoftComponent(componentData, softComponents, fieldSettings);
3709
4503
  } catch (error) {
3710
4504
  console.warn(
3711
4505
  `Failed to decompose soft component "${componentType}":`,
@@ -3719,13 +4513,14 @@ function dissolveComponentRecursively(componentData, softComponents, hardCompone
3719
4513
  component,
3720
4514
  softComponents,
3721
4515
  hardComponentNames,
3722
- depth + 1
4516
+ depth + 1,
4517
+ fieldSettings
3723
4518
  );
3724
4519
  fullyDissolved.push(...dissolved);
3725
4520
  }
3726
4521
  return fullyDissolved;
3727
4522
  }
3728
- function dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth) {
4523
+ function dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth, fieldSettings) {
3729
4524
  const newProps = __spreadValues({}, componentData.props);
3730
4525
  Object.entries(newProps).forEach(([key, value]) => {
3731
4526
  var _a;
@@ -3735,7 +4530,8 @@ function dissolveComponentSlots(componentData, softComponents, hardComponentName
3735
4530
  slotComponent,
3736
4531
  softComponents,
3737
4532
  hardComponentNames,
3738
- depth
4533
+ depth,
4534
+ fieldSettings
3739
4535
  )
3740
4536
  );
3741
4537
  }
@@ -3745,22 +4541,23 @@ function dissolveComponentSlots(componentData, softComponents, hardComponentName
3745
4541
  });
3746
4542
  }
3747
4543
  function dissolveAllSoftComponents(data, softComponents, config) {
4544
+ var _a;
3748
4545
  const hardComponentNames = new Set(
3749
4546
  Object.keys(config.components || {}).filter(
3750
4547
  (name) => !isSoftComponent(name, softComponents)
3751
4548
  )
3752
4549
  );
3753
- const dissolutionOrder = reverseTopologicalSort(
3754
- softComponents,
3755
- hardComponentNames
3756
- );
4550
+ reverseTopologicalSort(softComponents, hardComponentNames);
4551
+ const rootParams = ((_a = data.root) == null ? void 0 : _a.props) || {};
4552
+ const fieldSettings = __spreadValues(__spreadValues({}, rootParams._fieldSettings || {}), rootParams);
3757
4553
  const dissolveComponents = (components) => {
3758
4554
  return components.flatMap((componentData) => {
3759
4555
  return dissolveComponentRecursively(
3760
4556
  componentData,
3761
4557
  softComponents,
3762
4558
  hardComponentNames,
3763
- 0
4559
+ 0,
4560
+ fieldSettings
3764
4561
  );
3765
4562
  });
3766
4563
  };
@@ -3827,12 +4624,18 @@ var resolveSoftConfig = (data, softComponents, config) => {
3827
4624
  Header,
3828
4625
  Modal,
3829
4626
  SoftConfigProvider,
4627
+ applyMapping,
3830
4628
  confirm,
3831
4629
  createActionCallback,
3832
4630
  createSoftConfigStore,
3833
4631
  createUseSoftConfig,
4632
+ filterToOptionsForFrom,
4633
+ getArrayBasePath,
4634
+ getArrayItemSubPath,
4635
+ isArrayMappingPath,
3834
4636
  notify,
3835
4637
  resolveSoftConfig,
4638
+ resolveValueByPath,
3836
4639
  setConfirmHandler,
3837
4640
  setNotificationHandler,
3838
4641
  useBuild,