@netlisian/softconfig 0.1.4 → 0.1.6

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];
347
684
  }
348
- return `${major}.${minor}.${patch}`;
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);
349
707
  };
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
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;
723
+ }
724
+ return currentEntry;
725
+ };
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 = {};
784
+ }
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);
398
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;
399
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
744
1264
  });
745
1265
  }
746
- } : {
747
- type: "array",
748
- label: "Dynamic Field Map",
749
- arrayFields: {
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);
1284
+ });
1285
+ }
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,
@@ -1005,34 +1644,74 @@ var import_uuid = require("uuid");
1005
1644
  var generateId = (type) => type ? `${type}-${(0, import_uuid.v4)()}` : (0, import_uuid.v4)();
1006
1645
 
1007
1646
  // src/puck/lib/component-key.ts
1008
- var defaultToCamelCase = (value) => {
1009
- const tokens = value.trim().replace(/[^a-zA-Z0-9\s_-]/g, " ").split(/[\s_-]+/).filter(Boolean);
1010
- if (tokens.length === 0) return "";
1011
- const [first, ...rest] = tokens;
1012
- return `${first.toLowerCase()}${rest.map((token) => token.charAt(0).toUpperCase() + token.slice(1).toLowerCase()).join("")}`;
1647
+ var toSlug = (value) => {
1648
+ return value.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
1649
+ };
1650
+ var defaultComponentNameToKey = (displayName, context) => {
1651
+ var _a, _b;
1652
+ const registry = (_b = (_a = context.registryName) != null ? _a : context.registry) != null ? _b : "default";
1653
+ return `${toSlug(registry)}/${toSlug(displayName)}`;
1654
+ };
1655
+ var defaultComponentKeyToName = (key) => {
1656
+ const slashIndex = key.indexOf("/");
1657
+ const componentPart = slashIndex === -1 ? key : key.slice(slashIndex + 1);
1658
+ if (!componentPart) return "";
1659
+ return componentPart.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
1013
1660
  };
1014
1661
  var createComponentKeyFromName = (displayName, overrides, context) => {
1015
- const key = overrides.componentNameToKey ? overrides.componentNameToKey(displayName, context) : defaultToCamelCase(displayName);
1662
+ const key = overrides.componentNameToKey ? overrides.componentNameToKey(displayName, context) : defaultComponentNameToKey(displayName, context);
1016
1663
  return key.trim();
1017
1664
  };
1018
1665
  var getComponentNameFromKey = (key, overrides) => {
1019
- if (overrides.componentKeyToName) {
1666
+ if (overrides == null ? void 0 : overrides.componentKeyToName) {
1020
1667
  return overrides.componentKeyToName(key);
1021
1668
  }
1022
- return key;
1669
+ return defaultComponentKeyToName(key);
1023
1670
  };
1024
1671
 
1025
1672
  // src/puck/lib/soft-component-to-appstate.ts
1026
- var puckFieldsToSoftFields = (fields, slots) => {
1673
+ var mergeFieldSettings = (generated = {}, persisted = {}) => {
1674
+ return Object.entries(persisted).reduce((acc, [fieldName, value]) => {
1675
+ const current = acc[fieldName] || {};
1676
+ acc[fieldName] = __spreadProps(__spreadValues(__spreadValues({}, current), value), {
1677
+ subFieldSettings: current.subFieldSettings || (value == null ? void 0 : value.subFieldSettings) ? mergeFieldSettings(
1678
+ current.subFieldSettings || {},
1679
+ (value == null ? void 0 : value.subFieldSettings) || {}
1680
+ ) : void 0
1681
+ });
1682
+ return acc;
1683
+ }, __spreadValues({}, generated));
1684
+ };
1685
+ var puckFieldsToSoftFields = (fields, slots, persistedFieldSettings = {}, customFields) => {
1027
1686
  const softFields = [];
1028
1687
  const fieldSettings = {};
1029
1688
  Object.entries(fields).forEach(([fieldName, field]) => {
1689
+ var _a;
1690
+ const persistedSettings = persistedFieldSettings == null ? void 0 : persistedFieldSettings[fieldName];
1691
+ const fieldWithMeta = field;
1692
+ const customFieldType = fieldWithMeta.customFieldType || (persistedSettings == null ? void 0 : persistedSettings.customFieldType);
1693
+ 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
1694
  if (slots.has(fieldName)) {
1031
1695
  return;
1032
1696
  }
1033
1697
  if (fieldName === "_version") {
1034
1698
  return;
1035
1699
  }
1700
+ if (field.type === "custom" && customFieldType) {
1701
+ softFields.push({ name: fieldName, type: customFieldType });
1702
+ const customSchema = resolveCustomFieldSchema(customFieldType, customFields);
1703
+ fieldSettings[fieldName] = __spreadValues(__spreadProps(__spreadValues({}, persistedSettings || {}), {
1704
+ customFieldType,
1705
+ customFieldReturnType
1706
+ }), customSchema ? {
1707
+ subFields: customSchema.subFields,
1708
+ subFieldSettings: customSchema.subFieldSettings
1709
+ } : {});
1710
+ if (!Object.prototype.hasOwnProperty.call(fieldSettings[fieldName], "defaultValue")) {
1711
+ fieldSettings[fieldName].defaultValue = void 0;
1712
+ }
1713
+ return;
1714
+ }
1036
1715
  switch (field.type) {
1037
1716
  case "text":
1038
1717
  case "textarea":
@@ -1050,67 +1729,81 @@ var puckFieldsToSoftFields = (fields, slots) => {
1050
1729
  case "radio":
1051
1730
  softFields.push({ name: fieldName, type: field.type });
1052
1731
  fieldSettings[fieldName] = {
1053
- options: field.options || []
1732
+ options: field.options ? [...field.options] : []
1054
1733
  };
1055
1734
  break;
1056
1735
  case "array":
1057
1736
  softFields.push({ name: fieldName, type: "array" });
1058
1737
  const arrayFieldsResult = puckFieldsToSoftFields(
1059
1738
  field.arrayFields || {},
1060
- /* @__PURE__ */ new Set()
1739
+ /* @__PURE__ */ new Set(),
1740
+ persistedSettings == null ? void 0 : persistedSettings.subFieldSettings,
1741
+ customFields
1061
1742
  );
1062
- fieldSettings[fieldName] = {
1743
+ fieldSettings[fieldName] = __spreadProps(__spreadValues({}, persistedSettings || {}), {
1063
1744
  subFields: arrayFieldsResult.fields,
1064
1745
  subFieldSettings: arrayFieldsResult.fieldSettings
1065
- };
1746
+ });
1066
1747
  break;
1067
1748
  case "object":
1068
1749
  softFields.push({ name: fieldName, type: "object" });
1069
1750
  const objectFieldsResult = puckFieldsToSoftFields(
1070
1751
  field.objectFields || {},
1071
- /* @__PURE__ */ new Set()
1752
+ /* @__PURE__ */ new Set(),
1753
+ persistedSettings == null ? void 0 : persistedSettings.subFieldSettings,
1754
+ customFields
1072
1755
  );
1073
- fieldSettings[fieldName] = {
1756
+ fieldSettings[fieldName] = __spreadProps(__spreadValues({}, persistedSettings || {}), {
1074
1757
  subFields: objectFieldsResult.fields,
1075
1758
  subFieldSettings: objectFieldsResult.fieldSettings
1076
- };
1759
+ });
1077
1760
  break;
1078
1761
  default:
1079
1762
  softFields.push({ name: fieldName, type: "text" });
1080
1763
  }
1081
- if (fieldSettings[fieldName]) {
1082
- fieldSettings[fieldName].defaultValue = void 0;
1083
- } else {
1084
- fieldSettings[fieldName] = { defaultValue: void 0 };
1085
- }
1764
+ fieldSettings[fieldName] = __spreadProps(__spreadValues({}, fieldSettings[fieldName] || persistedSettings || {}), {
1765
+ defaultValue: Object.prototype.hasOwnProperty.call(
1766
+ fieldSettings[fieldName] || persistedSettings || {},
1767
+ "defaultValue"
1768
+ ) ? (fieldSettings[fieldName] || persistedSettings || {}).defaultValue : void 0
1769
+ });
1086
1770
  });
1087
1771
  return { fields: softFields, fieldSettings };
1088
1772
  };
1089
1773
  var reconstructComponents = (subComponents, componentConfigs, softComponentProps) => {
1090
1774
  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);
1775
+ const componentConfig = componentConfigs[subComponent.type];
1776
+ const props = __spreadProps(__spreadValues({}, subComponent.fixedProps), {
1777
+ _map: subComponent.map
1778
+ });
1779
+ const arrayDefaults = (subComponent.map || []).reduce(
1780
+ (acc, mapEntry) => {
1781
+ const toPaths = Array.isArray(mapEntry.to) ? mapEntry.to : [mapEntry.to];
1782
+ toPaths.forEach((path) => {
1783
+ var _a;
1784
+ if (typeof path !== "string" || !isArrayMappingPath(path)) return;
1785
+ const arrayBase = getArrayBasePath(path);
1786
+ if (!arrayBase || acc[arrayBase]) return;
1787
+ const defaultValue = (_a = componentConfig == null ? void 0 : componentConfig.defaultProps) == null ? void 0 : _a[arrayBase];
1788
+ if (Array.isArray(defaultValue)) acc[arrayBase] = defaultValue;
1106
1789
  });
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;
1790
+ return acc;
1791
+ },
1792
+ {}
1793
+ );
1794
+ const sourceProps = __spreadValues(__spreadValues(__spreadValues({}, (componentConfig == null ? void 0 : componentConfig.defaultProps) || {}), softComponentProps), props);
1795
+ const { newProps } = applyMapping(
1796
+ props,
1797
+ {},
1798
+ // fieldSettings not needed for "propsFirst" mode as it resolves from propsFirst
1799
+ subComponent.map || [],
1800
+ "propsFirst",
1801
+ {
1802
+ sourceProps,
1803
+ arrayDefaults
1112
1804
  }
1113
- });
1805
+ );
1806
+ Object.assign(props, newProps);
1114
1807
  if (subComponent.enabledSlots.length > 0) {
1115
1808
  props._slot = subComponent.enabledSlots;
1116
1809
  subComponent.enabledSlots.forEach(({ slot, name }) => {
@@ -1140,24 +1833,41 @@ var reconstructComponents = (subComponents, componentConfigs, softComponentProps
1140
1833
  return componentData;
1141
1834
  });
1142
1835
  };
1143
- var softComponentToAppState = (softComponent, componentName, version, versions, componentProps, componentConfigs, overrides, displayName, category) => {
1836
+ var softComponentToAppState = (softComponent, componentName, version, versions, componentProps, componentConfigs, overrides, displayName, category, customFields) => {
1144
1837
  const slots = new Set(Object.keys(softComponent.slots));
1145
1838
  const { fields, fieldSettings } = puckFieldsToSoftFields(
1146
1839
  softComponent.fields,
1147
- slots
1840
+ slots,
1841
+ softComponent.fieldSettings,
1842
+ customFields
1148
1843
  );
1844
+ const mergedFieldSettings = mergeFieldSettings(
1845
+ fieldSettings,
1846
+ softComponent.fieldSettings || {}
1847
+ ) || {};
1149
1848
  Object.entries(softComponent.defaultProps).forEach(([key, value]) => {
1150
- if (fieldSettings && fieldSettings[key] && !slots.has(key)) {
1151
- fieldSettings[key].defaultValue = value;
1849
+ if (mergedFieldSettings && mergedFieldSettings[key] && !slots.has(key)) {
1850
+ mergedFieldSettings[key].defaultValue = value;
1152
1851
  }
1153
1852
  });
1853
+ (fields || []).forEach((field) => {
1854
+ if (field.type !== "array" || slots.has(field.name)) return;
1855
+ const settings = mergedFieldSettings[field.name] || {};
1856
+ if (settings.defaultValue === void 0) {
1857
+ settings.defaultValue = buildArrayDefaultValue(
1858
+ settings.subFields,
1859
+ settings.subFieldSettings
1860
+ );
1861
+ }
1862
+ mergedFieldSettings[field.name] = settings;
1863
+ });
1154
1864
  let rootProps = __spreadValues({
1155
1865
  _name: displayName || getComponentNameFromKey(componentName, overrides),
1156
1866
  _category: category,
1157
1867
  _version: version,
1158
1868
  _versions: versions,
1159
1869
  _fields: fields,
1160
- _fieldSettings: fieldSettings
1870
+ _fieldSettings: mergedFieldSettings
1161
1871
  }, softComponent.rootProps || {});
1162
1872
  if (overrides.onRemodel) {
1163
1873
  rootProps = __spreadValues(__spreadValues({}, rootProps), overrides.onRemodel(componentName));
@@ -1184,7 +1894,7 @@ var rootDroppableId = `${rootAreaId}:${rootZone}`;
1184
1894
 
1185
1895
  // src/puck/components/soft-render/index.tsx
1186
1896
  var import_react4 = __toESM(require("react"));
1187
- var import_react_fast_compare = __toESM(require("react-fast-compare"));
1897
+ var import_react_fast_compare3 = __toESM(require("react-fast-compare"));
1188
1898
  var import_jsx_runtime5 = require("react/jsx-runtime");
1189
1899
  function isPlainObject(val) {
1190
1900
  if (typeof val !== "object" || val === null) return false;
@@ -1223,28 +1933,19 @@ var SubComponentRenderer = (0, import_react4.memo)(
1223
1933
  if (!componentConfig) return {};
1224
1934
  const clonedProps = cloneData(subComponent.fixedProps || {});
1225
1935
  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);
1936
+ const mergedInput = __spreadValues(__spreadValues({}, clonedProps), props);
1937
+ const { newProps } = applyMapping(
1938
+ mergedInput,
1939
+ softComponentFieldSettings || {},
1940
+ subComponent.map,
1941
+ "propsFirst"
1942
+ );
1943
+ const parentKeys = new Set(Object.keys(props));
1944
+ for (const [key, value] of Object.entries(newProps)) {
1945
+ if (!parentKeys.has(key) || key in clonedProps) {
1946
+ clonedProps[key] = value;
1246
1947
  }
1247
- });
1948
+ }
1248
1949
  }
1249
1950
  Object.entries(componentConfig.fields || {}).forEach(
1250
1951
  ([slotKey, field]) => {
@@ -1305,7 +2006,7 @@ var SubComponentRenderer = (0, import_react4.memo)(
1305
2006
  // and on props (the primary driver of field-mapping changes).
1306
2007
  // configComponents and softComponentFields are treated as stable config
1307
2008
  // 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)
2009
+ (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
2010
  );
1310
2011
  SubComponentRenderer.displayName = "SubComponentRenderer";
1311
2012
  var SoftRender = (0, import_react4.memo)(
@@ -1339,16 +2040,34 @@ var SoftRender = (0, import_react4.memo)(
1339
2040
  // configComponents / softComponentFields: reference equality (stable config).
1340
2041
  // softComponentFieldSettings: deep equality (may carry dynamic defaults).
1341
2042
  // 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)
2043
+ (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
2044
  );
1344
2045
  SoftRender.displayName = "SoftRender";
1345
2046
 
1346
2047
  // src/puck/lib/create-versioned-component-config.tsx
1347
2048
  var import_jsx_runtime6 = require("react/jsx-runtime");
1348
- var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true) => {
2049
+ var hydrateCustomField = (fieldName, field, fieldSettings, customFields) => {
2050
+ var _a;
2051
+ if (field.type !== "custom") {
2052
+ return field;
2053
+ }
2054
+ const fieldWithMeta = field;
2055
+ const customFieldType = fieldWithMeta.customFieldType || ((_a = fieldSettings == null ? void 0 : fieldSettings[fieldName]) == null ? void 0 : _a.customFieldType);
2056
+ if (!customFieldType) {
2057
+ return field;
2058
+ }
2059
+ const customField = customFields == null ? void 0 : customFields[customFieldType];
2060
+ if (!customField) {
2061
+ return field;
2062
+ }
2063
+ return __spreadProps(__spreadValues(__spreadValues({}, field), customField.field), {
2064
+ type: "custom",
2065
+ label: field.label || customField.field.label || fieldName
2066
+ });
2067
+ };
2068
+ var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true, customFields, overrides) => {
1349
2069
  var _a, _b;
1350
- const softConfig = config;
1351
- return {
2070
+ const baseConfig = {
1352
2071
  label: displayName,
1353
2072
  fields: Object.fromEntries(
1354
2073
  (Object.entries(
@@ -1373,7 +2092,12 @@ var createVersionedComponentConfig = (componentName, displayName, version, allVe
1373
2092
  };
1374
2093
  }
1375
2094
  Object.entries((versionedComponent == null ? void 0 : versionedComponent.fields) || {}).filter(([, field]) => field.type !== "slot").forEach(([key, field]) => {
1376
- fields[key] = field;
2095
+ fields[key] = hydrateCustomField(
2096
+ key,
2097
+ field,
2098
+ versionedComponent == null ? void 0 : versionedComponent.fieldSettings,
2099
+ customFields
2100
+ );
1377
2101
  });
1378
2102
  return fields;
1379
2103
  },
@@ -1387,12 +2111,16 @@ var createVersionedComponentConfig = (componentName, displayName, version, allVe
1387
2111
  softComponentFields: versionedComponent.fields,
1388
2112
  softComponentFieldSettings: versionedComponent.fieldSettings,
1389
2113
  softSubComponent: versionedComponent.components,
1390
- configComponents: softConfig.components,
2114
+ configComponents: config.components,
1391
2115
  props
1392
2116
  }
1393
2117
  );
1394
2118
  }
1395
2119
  };
2120
+ if (overrides == null ? void 0 : overrides.mapComponentConfig) {
2121
+ return __spreadValues(__spreadValues({}, baseConfig), overrides.mapComponentConfig(componentName, baseConfig));
2122
+ }
2123
+ return baseConfig;
1396
2124
  };
1397
2125
 
1398
2126
  // src/puck/lib/builder/sub-component-decomposer.tsx
@@ -1400,21 +2128,16 @@ var subComponentDecomposer = (componentRootData, softSubComponent) => {
1400
2128
  var _a;
1401
2129
  const resolvedProps = __spreadValues({}, softSubComponent.fixedProps);
1402
2130
  (_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)
2131
+ const { newProps } = applyMapping(
2132
+ resolvedProps,
2133
+ {},
2134
+ [mapItem],
2135
+ "propsFirst",
2136
+ {
2137
+ sourceProps: componentRootData.props || {}
2138
+ }
1408
2139
  );
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
- }
2140
+ Object.assign(resolvedProps, newProps);
1418
2141
  });
1419
2142
  softSubComponent.enabledSlots.forEach(({ slot, name }) => {
1420
2143
  var _a2, _b;
@@ -1437,9 +2160,22 @@ var subComponentDecomposer = (componentRootData, softSubComponent) => {
1437
2160
  return accItem;
1438
2161
  };
1439
2162
 
2163
+ // src/puck/lib/builder/resolve-soft-component-data.ts
2164
+ var resolveSoftComponentData = (props, _fieldSettings = {}) => {
2165
+ const map = props._map;
2166
+ if (!(map == null ? void 0 : map.length)) return __spreadValues({}, props);
2167
+ const { newProps } = applyMapping(
2168
+ props,
2169
+ _fieldSettings,
2170
+ map,
2171
+ "propsFirst"
2172
+ );
2173
+ return newProps;
2174
+ };
2175
+
1440
2176
  // src/puck/lib/decompose-soft-component.ts
1441
- function decomposeSoftComponent(componentData, softComponents) {
1442
- var _a, _b;
2177
+ function decomposeSoftComponent(componentData, softComponents, fieldSettings) {
2178
+ var _a, _b, _c, _d;
1443
2179
  if (!(componentData == null ? void 0 : componentData.type) || !(componentData == null ? void 0 : componentData.props.id)) {
1444
2180
  throw new Error("Component data must have type and id to decompose.");
1445
2181
  }
@@ -1450,9 +2186,19 @@ function decomposeSoftComponent(componentData, softComponents) {
1450
2186
  `Soft component "${componentData.type}" version "${version}" not found.`
1451
2187
  );
1452
2188
  }
2189
+ let resolvedComponentData = componentData;
2190
+ if (fieldSettings && ((_d = (_c = componentData.props) == null ? void 0 : _c._map) == null ? void 0 : _d.length)) {
2191
+ const resolvedProps = resolveSoftComponentData(
2192
+ componentData.props,
2193
+ fieldSettings
2194
+ );
2195
+ resolvedComponentData = __spreadProps(__spreadValues({}, componentData), {
2196
+ props: resolvedProps
2197
+ });
2198
+ }
1453
2199
  const decomposedComponentData = softComponent.components.map(
1454
2200
  (softSubComponent) => {
1455
- return subComponentDecomposer(componentData, softSubComponent);
2201
+ return subComponentDecomposer(resolvedComponentData, softSubComponent);
1456
2202
  }
1457
2203
  );
1458
2204
  return decomposedComponentData;
@@ -1522,7 +2268,14 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1522
2268
  });
1523
2269
  const config = __spreadValues({}, get().softConfig);
1524
2270
  const overrides = get().overrides;
1525
- const buildConfig = builderConfig(config, overrides, void 0, get().showVersionFields);
2271
+ const buildConfig = builderConfig(
2272
+ config,
2273
+ overrides,
2274
+ void 0,
2275
+ get().showVersionFields,
2276
+ void 0,
2277
+ get().customFields
2278
+ );
1526
2279
  const editableIds = /* @__PURE__ */ new Set([selectedItem.props.id]);
1527
2280
  const initialContent = [__spreadValues({}, selectedItem)];
1528
2281
  (0, import_puck4.walkTree)(
@@ -1596,12 +2349,20 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1596
2349
  get().softConfig.components,
1597
2350
  get().overrides,
1598
2351
  (softComponentMeta == null ? void 0 : softComponentMeta.name) || softComponentName,
1599
- softComponentMeta == null ? void 0 : softComponentMeta.category
2352
+ softComponentMeta == null ? void 0 : softComponentMeta.category,
2353
+ get().customFields
1600
2354
  );
1601
2355
  const config = __spreadValues({}, get().softConfig);
1602
2356
  const overrides = get().overrides;
1603
2357
  const dependents = get().dependencyGraph.get(softComponentName) || /* @__PURE__ */ new Set();
1604
- const buildConfig = builderConfig(config, overrides, softComponentName, get().showVersionFields, dependents);
2358
+ const buildConfig = builderConfig(
2359
+ config,
2360
+ overrides,
2361
+ softComponentName,
2362
+ get().showVersionFields,
2363
+ dependents,
2364
+ get().customFields
2365
+ );
1605
2366
  const editableIds = /* @__PURE__ */ new Set([]);
1606
2367
  const decomposedComponents = get().builder.decompose(selectedItem);
1607
2368
  (0, import_puck4.walkTree)(
@@ -1828,7 +2589,8 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1828
2589
  {
1829
2590
  name: displayName,
1830
2591
  category
1831
- }
2592
+ },
2593
+ get().customFields
1832
2594
  );
1833
2595
  const existingComponent = get().softComponents[componentName];
1834
2596
  const allVersions = Object.keys((existingComponent == null ? void 0 : existingComponent.versions) || {});
@@ -1847,7 +2609,8 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1847
2609
  })
1848
2610
  }),
1849
2611
  softComponent.defaultProps,
1850
- get().showVersionFields
2612
+ get().showVersionFields,
2613
+ get().customFields
1851
2614
  );
1852
2615
  get().setSoftComponent(componentName, version, softComponent);
1853
2616
  return [newSoftComponentConfig, version];
@@ -1901,7 +2664,8 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1901
2664
  get().softConfig.components,
1902
2665
  get().overrides,
1903
2666
  (softComponentMeta == null ? void 0 : softComponentMeta.name) || componentName,
1904
- softComponentMeta == null ? void 0 : softComponentMeta.category
2667
+ softComponentMeta == null ? void 0 : softComponentMeta.category,
2668
+ get().customFields
1905
2669
  );
1906
2670
  puckDispatch({
1907
2671
  type: "setData",
@@ -2048,7 +2812,7 @@ function topologicalSort(softComponents, hardComponentNames) {
2048
2812
  }
2049
2813
  return sorted;
2050
2814
  }
2051
- function buildInitialSoftComponents(hardConfig, softComponents, overrides, showVersioning = false) {
2815
+ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showVersioning = false, customFields) {
2052
2816
  var _a, _b;
2053
2817
  if (!softComponents || Object.keys(softComponents).length === 0) {
2054
2818
  return {};
@@ -2084,7 +2848,9 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
2084
2848
  // Pass the accumulating config
2085
2849
  hydratedSoftComponents,
2086
2850
  versionedComponent.defaultProps,
2087
- showVersioning
2851
+ showVersioning,
2852
+ customFields,
2853
+ overrides
2088
2854
  );
2089
2855
  componentConfigs[name] = newSoftComponentConfig;
2090
2856
  buildingConfig.components[name] = newSoftComponentConfig;
@@ -2112,7 +2878,9 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
2112
2878
  hardConfig,
2113
2879
  hydratedSoftComponents,
2114
2880
  versionedComponent.defaultProps,
2115
- showVersioning
2881
+ showVersioning,
2882
+ customFields,
2883
+ overrides
2116
2884
  );
2117
2885
  componentConfigs[name] = newSoftComponentConfig;
2118
2886
  }
@@ -2178,9 +2946,9 @@ var clearEditVisibility = (doc) => {
2178
2946
  // src/puck/store/index.tsx
2179
2947
  var createSoftConfigStore = (hardConfig = {
2180
2948
  components: {}
2181
- }, softComponents = {}, overrides = {}, onActions, showVersionFields = true) => {
2949
+ }, softComponents = {}, overrides = {}, onActions, showVersionFields = true, customFields = {}) => {
2182
2950
  const normalizedSoftComponents = Object.fromEntries(
2183
- Object.entries(softComponents || {}).map(([key, value]) => [
2951
+ Object.entries(softComponents || {}).filter(([key]) => !hardConfig.components || !hardConfig.components[key]).map(([key, value]) => [
2184
2952
  key,
2185
2953
  __spreadProps(__spreadValues({}, value), {
2186
2954
  name: value.name || key
@@ -2201,6 +2969,7 @@ var createSoftConfigStore = (hardConfig = {
2201
2969
  state: "ready",
2202
2970
  originalHistory: [],
2203
2971
  overrides,
2972
+ customFields,
2204
2973
  onActions,
2205
2974
  iframeDocRef,
2206
2975
  showVersionFields,
@@ -2242,11 +3011,17 @@ var createSoftConfigStore = (hardConfig = {
2242
3011
  components: __spreadValues(__spreadValues({}, hardConfig.components), buildInitialSoftComponents(
2243
3012
  hardConfig,
2244
3013
  hydratedSoftComponents,
2245
- overrides
3014
+ overrides,
3015
+ showVersionFields,
3016
+ customFields
2246
3017
  )),
2247
3018
  categories: __spreadValues({}, hardConfig.categories || {})
2248
3019
  }),
2249
3020
  setSoftComponent: (name, version, component) => {
3021
+ if (hardConfig.components && hardConfig.components[name]) {
3022
+ console.warn(`Cannot set soft component "${name}" because it conflicts with a base hardConfig component.`);
3023
+ return;
3024
+ }
2250
3025
  const existing = get().softComponents[name];
2251
3026
  set((state) => {
2252
3027
  var _a, _b;
@@ -2269,6 +3044,9 @@ var createSoftConfigStore = (hardConfig = {
2269
3044
  const nextSoftComponents = __spreadValues({}, state.softComponents);
2270
3045
  const nextConfigComponents = __spreadValues({}, state.softConfig.components);
2271
3046
  Object.entries(incomingComponents).forEach(([name, data]) => {
3047
+ if (hardConfig.components && hardConfig.components[name]) {
3048
+ return;
3049
+ }
2272
3050
  const existing = nextSoftComponents[name];
2273
3051
  const finalComponentData = existing ? __spreadProps(__spreadValues(__spreadValues({}, existing), data), {
2274
3052
  name: data.name || existing.name || name,
@@ -2287,7 +3065,8 @@ var createSoftConfigStore = (hardConfig = {
2287
3065
  state.softConfig,
2288
3066
  nextSoftComponents,
2289
3067
  activeVersionData.defaultProps,
2290
- state.showVersionFields
3068
+ state.showVersionFields,
3069
+ state.customFields
2291
3070
  );
2292
3071
  }
2293
3072
  });
@@ -2318,7 +3097,8 @@ var createSoftConfigStore = (hardConfig = {
2318
3097
  softConfig,
2319
3098
  hydratedComponents,
2320
3099
  activeVersionData.defaultProps,
2321
- get().showVersionFields
3100
+ get().showVersionFields,
3101
+ get().customFields
2322
3102
  );
2323
3103
  }
2324
3104
  });
@@ -2349,7 +3129,8 @@ var createSoftConfigStore = (hardConfig = {
2349
3129
  get().softConfig,
2350
3130
  get().softComponents,
2351
3131
  softComponent.defaultProps,
2352
- get().showVersionFields
3132
+ get().showVersionFields,
3133
+ get().customFields
2353
3134
  );
2354
3135
  set((state) => ({
2355
3136
  softConfig: __spreadProps(__spreadValues({}, state.softConfig), {
@@ -2486,7 +3267,8 @@ var createSoftConfigStore = (hardConfig = {
2486
3267
  config,
2487
3268
  softComponents2,
2488
3269
  versionedComponent.defaultProps,
2489
- state.showVersionFields
3270
+ state.showVersionFields,
3271
+ state.customFields
2490
3272
  );
2491
3273
  config.components[dependentName] = newConfig;
2492
3274
  }
@@ -2504,14 +3286,29 @@ var SoftConfigProvider = ({
2504
3286
  children,
2505
3287
  hardConfig,
2506
3288
  softComponents,
3289
+ customFields,
2507
3290
  overrides,
2508
3291
  value,
2509
3292
  onActions,
2510
3293
  useVersioning = false
2511
3294
  }) => {
2512
3295
  const store = value != null ? value : (0, import_react5.useMemo)(
2513
- () => createSoftConfigStore(hardConfig, softComponents, overrides, onActions, useVersioning),
2514
- [hardConfig, softComponents, overrides, onActions, useVersioning]
3296
+ () => createSoftConfigStore(
3297
+ hardConfig,
3298
+ softComponents,
3299
+ overrides,
3300
+ onActions,
3301
+ useVersioning,
3302
+ customFields
3303
+ ),
3304
+ [
3305
+ hardConfig,
3306
+ softComponents,
3307
+ overrides,
3308
+ onActions,
3309
+ useVersioning,
3310
+ customFields
3311
+ ]
2515
3312
  );
2516
3313
  const [softConfig, setSoftConfig] = (0, import_react5.useState)(
2517
3314
  () => store.getState().softConfig
@@ -3107,7 +3904,7 @@ var getClassName3 = get_class_name_factory_default("ActionBar", ActionBar_module
3107
3904
  var usePuck2 = (0, import_puck14.createUsePuck)();
3108
3905
  var ActionBarOverride = (props) => {
3109
3906
  var _a, _b;
3110
- const { handleBuild } = useBuild("Custom Name");
3907
+ const { handleBuild } = useBuild(props.label ? props.label + " Soft Component" : "New Soft Component");
3111
3908
  const { handleRemodel } = useRemodel();
3112
3909
  const { handleDecompose } = useDecompose();
3113
3910
  const overrides = useSoftConfig((s) => s.overrides);
@@ -3139,10 +3936,17 @@ var ActionBarOverride = (props) => {
3139
3936
  const selectedId = (_a = selectedItem == null ? void 0 : selectedItem.props) == null ? void 0 : _a.id;
3140
3937
  const parentId = (_b = itemSelector == null ? void 0 : itemSelector.zone) == null ? void 0 : _b.split(":")[0];
3141
3938
  const isEditable = Boolean(selectedId && (editableIds.has(selectedId) || parentId && editableIds.has(parentId)));
3939
+ const displayName = (0, import_react9.useMemo)(() => {
3940
+ var _a2;
3941
+ if (isSoftComponent2) {
3942
+ return ((_a2 = softComponents[key]) == null ? void 0 : _a2.name) || getComponentNameFromKey(key, overrides);
3943
+ }
3944
+ return props.label || "";
3945
+ }, [isSoftComponent2, key, props.label, overrides, softComponents]);
3142
3946
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: getClassName3(), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_puck14.ActionBar, { children: [
3143
3947
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_puck14.ActionBar.Group, { children: [
3144
3948
  props.parentAction,
3145
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_puck14.ActionBar.Label, { label: props.label })
3949
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_puck14.ActionBar.Label, { label: displayName })
3146
3950
  ] }),
3147
3951
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_puck14.ActionBar.Group, { children: [
3148
3952
  status === "ready" ? isSoftComponent2 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
@@ -3267,7 +4071,7 @@ var getClassName5 = get_class_name_factory_default("DrawerItem", DrawerItem_modu
3267
4071
  var usePuck3 = (0, import_puck15.createUsePuck)();
3268
4072
  var DrawerItem = (props) => {
3269
4073
  const componentMeta = useSoftConfig((s) => s.softComponents[props.name]);
3270
- const displayName = (componentMeta == null ? void 0 : componentMeta.name) || props.name;
4074
+ const displayName = props.label || (componentMeta == null ? void 0 : componentMeta.name) || props.name;
3271
4075
  const softComponents = new Set(
3272
4076
  Object.keys(useSoftConfig((s) => s.softComponents, import_shallow2.shallow))
3273
4077
  );
@@ -3363,6 +4167,7 @@ var DrawerItem = (props) => {
3363
4167
  onMouseEnter: () => setIsHovering(true),
3364
4168
  onMouseLeave: () => setIsHovering(false),
3365
4169
  children: [
4170
+ props.label,
3366
4171
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: getClassName5("content"), children: [
3367
4172
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: getClassName5("name"), children: displayName }),
3368
4173
  useVersioning && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: getClassName5("version"), children: [
@@ -3539,6 +4344,10 @@ var Drawer = (_props) => {
3539
4344
  })
3540
4345
  );
3541
4346
  const allKeys = Object.keys(config.components);
4347
+ const labels = Object.entries(config.components).reduce((acc, [key, comp]) => {
4348
+ acc[key] = comp.label || key;
4349
+ return acc;
4350
+ }, {});
3542
4351
  const otherKeys = allKeys.filter((k) => !categorised.has(k));
3543
4352
  const categoryEntries = Object.entries(categories).filter(
3544
4353
  ([, cat]) => cat.visible !== false
@@ -3557,6 +4366,7 @@ var Drawer = (_props) => {
3557
4366
  import_puck16.Drawer.Item,
3558
4367
  {
3559
4368
  name: key,
4369
+ label: labels[key],
3560
4370
  isDragDisabled: !getPermissions({ type: key }).insert,
3561
4371
  children: DrawerItem
3562
4372
  },
@@ -3641,9 +4451,6 @@ function extractDependencies2(softComponents, componentName, version) {
3641
4451
  return dependencies;
3642
4452
  }
3643
4453
  function reverseTopologicalSort(softComponents, hardComponentNames) {
3644
- const sorted = [];
3645
- const visiting = /* @__PURE__ */ new Set();
3646
- const visited = /* @__PURE__ */ new Set();
3647
4454
  const dependencyGraph = /* @__PURE__ */ new Map();
3648
4455
  const dependents = /* @__PURE__ */ new Map();
3649
4456
  for (const [componentName, component] of Object.entries(softComponents)) {
@@ -3691,7 +4498,7 @@ function reverseTopologicalSort(softComponents, hardComponentNames) {
3691
4498
  const sortedByDepth = [...depths.entries()].sort(([, depthA], [, depthB]) => depthB - depthA).map(([name]) => name);
3692
4499
  return sortedByDepth;
3693
4500
  }
3694
- function dissolveComponentRecursively(componentData, softComponents, hardComponentNames, depth = 0) {
4501
+ function dissolveComponentRecursively(componentData, softComponents, hardComponentNames, depth = 0, fieldSettings) {
3695
4502
  const MAX_DEPTH = 50;
3696
4503
  if (depth > MAX_DEPTH) {
3697
4504
  console.error(
@@ -3701,11 +4508,11 @@ function dissolveComponentRecursively(componentData, softComponents, hardCompone
3701
4508
  }
3702
4509
  const componentType = componentData.type;
3703
4510
  if (!isSoftComponent(componentType, softComponents)) {
3704
- return [dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth)];
4511
+ return [dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth, fieldSettings)];
3705
4512
  }
3706
4513
  let decomposed;
3707
4514
  try {
3708
- decomposed = decomposeSoftComponent(componentData, softComponents);
4515
+ decomposed = decomposeSoftComponent(componentData, softComponents, fieldSettings);
3709
4516
  } catch (error) {
3710
4517
  console.warn(
3711
4518
  `Failed to decompose soft component "${componentType}":`,
@@ -3719,13 +4526,14 @@ function dissolveComponentRecursively(componentData, softComponents, hardCompone
3719
4526
  component,
3720
4527
  softComponents,
3721
4528
  hardComponentNames,
3722
- depth + 1
4529
+ depth + 1,
4530
+ fieldSettings
3723
4531
  );
3724
4532
  fullyDissolved.push(...dissolved);
3725
4533
  }
3726
4534
  return fullyDissolved;
3727
4535
  }
3728
- function dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth) {
4536
+ function dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth, fieldSettings) {
3729
4537
  const newProps = __spreadValues({}, componentData.props);
3730
4538
  Object.entries(newProps).forEach(([key, value]) => {
3731
4539
  var _a;
@@ -3735,7 +4543,8 @@ function dissolveComponentSlots(componentData, softComponents, hardComponentName
3735
4543
  slotComponent,
3736
4544
  softComponents,
3737
4545
  hardComponentNames,
3738
- depth
4546
+ depth,
4547
+ fieldSettings
3739
4548
  )
3740
4549
  );
3741
4550
  }
@@ -3745,22 +4554,23 @@ function dissolveComponentSlots(componentData, softComponents, hardComponentName
3745
4554
  });
3746
4555
  }
3747
4556
  function dissolveAllSoftComponents(data, softComponents, config) {
4557
+ var _a;
3748
4558
  const hardComponentNames = new Set(
3749
4559
  Object.keys(config.components || {}).filter(
3750
4560
  (name) => !isSoftComponent(name, softComponents)
3751
4561
  )
3752
4562
  );
3753
- const dissolutionOrder = reverseTopologicalSort(
3754
- softComponents,
3755
- hardComponentNames
3756
- );
4563
+ reverseTopologicalSort(softComponents, hardComponentNames);
4564
+ const rootParams = ((_a = data.root) == null ? void 0 : _a.props) || {};
4565
+ const fieldSettings = __spreadValues(__spreadValues({}, rootParams._fieldSettings || {}), rootParams);
3757
4566
  const dissolveComponents = (components) => {
3758
4567
  return components.flatMap((componentData) => {
3759
4568
  return dissolveComponentRecursively(
3760
4569
  componentData,
3761
4570
  softComponents,
3762
4571
  hardComponentNames,
3763
- 0
4572
+ 0,
4573
+ fieldSettings
3764
4574
  );
3765
4575
  });
3766
4576
  };
@@ -3827,12 +4637,18 @@ var resolveSoftConfig = (data, softComponents, config) => {
3827
4637
  Header,
3828
4638
  Modal,
3829
4639
  SoftConfigProvider,
4640
+ applyMapping,
3830
4641
  confirm,
3831
4642
  createActionCallback,
3832
4643
  createSoftConfigStore,
3833
4644
  createUseSoftConfig,
4645
+ filterToOptionsForFrom,
4646
+ getArrayBasePath,
4647
+ getArrayItemSubPath,
4648
+ isArrayMappingPath,
3834
4649
  notify,
3835
4650
  resolveSoftConfig,
4651
+ resolveValueByPath,
3836
4652
  setConfirmHandler,
3837
4653
  setNotificationHandler,
3838
4654
  useBuild,