@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.
@@ -52,6 +52,8 @@ import {
52
52
  var getRootProps = (appState) => appState.data.root.props;
53
53
 
54
54
  // src/puck/lib/builder/root-config.tsx
55
+ import { useEffect } from "react";
56
+ import equal2 from "react-fast-compare";
55
57
  import {
56
58
  createUsePuck,
57
59
  walkTree
@@ -59,59 +61,352 @@ import {
59
61
 
60
62
  // src/puck/lib/get-field-settings.tsx
61
63
  import { AutoField } from "@measured/puck";
64
+
65
+ // src/puck/lib/get-settings-by-path.ts
66
+ function getFieldSettingsByPath(fieldSettings, path) {
67
+ return path.split(".").reduce((o, key) => o ? o[key] : void 0, fieldSettings);
68
+ }
69
+
70
+ // src/puck/lib/array-field-utils.ts
71
+ var primitiveFieldTypes = /* @__PURE__ */ new Set([
72
+ "text",
73
+ "textarea",
74
+ "number",
75
+ "select",
76
+ "radio",
77
+ "reference"
78
+ ]);
79
+ var isPrimitiveValue = (value) => ["string", "number", "boolean"].includes(typeof value);
80
+ var getFallbackValueForField = (type) => {
81
+ switch (type) {
82
+ case "number":
83
+ return 0;
84
+ case "array":
85
+ return [];
86
+ case "object":
87
+ return {};
88
+ default:
89
+ return "";
90
+ }
91
+ };
92
+ var resolveExpressionSummary = (item, index, expression) => {
93
+ if (!expression) return "";
94
+ let isValid = true;
95
+ const result = expression.replace(/\{([^}]+)\}/g, (_match, token) => {
96
+ if (token === "index") {
97
+ return String(index);
98
+ }
99
+ if (token.startsWith("item.")) {
100
+ const value = getFieldSettingsByPath(item, token.slice(5));
101
+ if (isPrimitiveValue(value)) {
102
+ return String(value);
103
+ }
104
+ }
105
+ isValid = false;
106
+ return "";
107
+ });
108
+ return isValid ? result : "";
109
+ };
110
+ var isPrimitiveFieldType = (type) => primitiveFieldTypes.has(type);
111
+ var buildArrayDefaultItemProps = (subFields = [], subFieldSettings = {}) => {
112
+ if (!subFields.length) return void 0;
113
+ const item = {};
114
+ let hasValue = false;
115
+ subFields.forEach((subField) => {
116
+ const settings = subFieldSettings[subField.name];
117
+ if (settings && Object.prototype.hasOwnProperty.call(settings, "defaultValue") && settings.defaultValue !== void 0) {
118
+ item[subField.name] = settings.defaultValue;
119
+ hasValue = true;
120
+ return;
121
+ }
122
+ item[subField.name] = getFallbackValueForField(subField.type);
123
+ hasValue = true;
124
+ });
125
+ return hasValue ? item : void 0;
126
+ };
127
+ var buildArrayDefaultValue = (subFields = [], subFieldSettings = {}) => {
128
+ const item = buildArrayDefaultItemProps(subFields, subFieldSettings);
129
+ return item ? [item] : [];
130
+ };
131
+ var getArrayItemSummary = (item, index = 0, settings) => {
132
+ if ((settings == null ? void 0 : settings.summary) === "field" && settings.summaryField) {
133
+ const value = getFieldSettingsByPath(item, settings.summaryField);
134
+ if (isPrimitiveValue(value) && String(value).length > 0) {
135
+ return String(value);
136
+ }
137
+ return `Item ${(index || 0) + 1}`;
138
+ }
139
+ if ((settings == null ? void 0 : settings.summary) === "expression") {
140
+ const summary = resolveExpressionSummary(
141
+ item,
142
+ index,
143
+ settings.summaryExpression
144
+ );
145
+ return summary || `Item ${(index || 0) + 1}`;
146
+ }
147
+ return `Item ${(index || 0) + 1}`;
148
+ };
149
+ var isArrayMappingPath = (path) => {
150
+ return typeof path === "string" && /^[^.]+\[\]\.[^.]+$/.test(path);
151
+ };
152
+ var getArrayBasePath = (arrayPath) => {
153
+ if (!isArrayMappingPath(arrayPath)) return null;
154
+ const match = arrayPath.match(/^([^.]+)\[\]\./);
155
+ return match ? match[1] : null;
156
+ };
157
+ var getArrayItemSubPath = (arrayPath) => {
158
+ if (!isArrayMappingPath(arrayPath)) return null;
159
+ const match = arrayPath.match(/\[\]\.(.+)$/);
160
+ return match ? match[1] : null;
161
+ };
162
+
163
+ // src/puck/lib/custom-fields.ts
164
+ var builtInSoftFieldTypes = /* @__PURE__ */ new Set([
165
+ "text",
166
+ "textarea",
167
+ "number",
168
+ "select",
169
+ "radio",
170
+ "array",
171
+ "object",
172
+ "reference"
173
+ ]);
174
+ var warnedMessages = /* @__PURE__ */ new Set();
175
+ var warnOnce = (message) => {
176
+ if (warnedMessages.has(message)) {
177
+ return;
178
+ }
179
+ warnedMessages.add(message);
180
+ console.warn(message);
181
+ };
182
+ var isBuiltInSoftFieldType = (fieldType) => {
183
+ return builtInSoftFieldTypes.has(fieldType);
184
+ };
185
+ var resolveCustomFieldDefinition = (fieldType, customFields) => {
186
+ if (isBuiltInSoftFieldType(fieldType)) {
187
+ return void 0;
188
+ }
189
+ return customFields == null ? void 0 : customFields[fieldType];
190
+ };
191
+ var resolveCustomFieldReturnType = (fieldType, customFields) => {
192
+ const customField = resolveCustomFieldDefinition(fieldType, customFields);
193
+ if (!customField) {
194
+ return null;
195
+ }
196
+ if (!customField.returnType) {
197
+ warnOnce(
198
+ `[soft-config] Custom field "${fieldType}" is missing a required returnType and will be skipped from mapping options.`
199
+ );
200
+ return null;
201
+ }
202
+ return customField.returnType;
203
+ };
204
+ var resolveCustomFieldSchema = (fieldType, customFields) => {
205
+ const customField = resolveCustomFieldDefinition(fieldType, customFields);
206
+ if (!customField) {
207
+ return null;
208
+ }
209
+ const returnType = resolveCustomFieldReturnType(fieldType, customFields);
210
+ if (!returnType) {
211
+ return null;
212
+ }
213
+ if (returnType !== "array" && returnType !== "object") {
214
+ return null;
215
+ }
216
+ const subFields = customField.subFields || [];
217
+ if (!subFields.length) {
218
+ warnOnce(
219
+ `[soft-config] Custom field "${fieldType}" returns ${returnType} but does not define subFields. It will be skipped from mapping options.`
220
+ );
221
+ return null;
222
+ }
223
+ return {
224
+ subFields,
225
+ subFieldSettings: customField.subFieldSettings || {}
226
+ };
227
+ };
228
+ var getCustomFieldTypeOptions = (customFields) => {
229
+ if (!customFields) {
230
+ return [];
231
+ }
232
+ return Object.entries(customFields).filter(([fieldType]) => !isBuiltInSoftFieldType(fieldType)).map(([fieldType, definition]) => ({
233
+ label: typeof definition.field.label === "string" && definition.field.label ? definition.field.label : fieldType,
234
+ value: fieldType
235
+ }));
236
+ };
237
+ var mapCustomReturnTypeToMappingType = (returnType) => {
238
+ switch (returnType) {
239
+ case "string":
240
+ return "textarea";
241
+ case "number":
242
+ return "number";
243
+ case "boolean":
244
+ return "select";
245
+ case "array":
246
+ return "array";
247
+ case "object":
248
+ return "object";
249
+ default:
250
+ return "textarea";
251
+ }
252
+ };
253
+
254
+ // src/puck/lib/get-field-settings.tsx
62
255
  import { jsx } from "react/jsx-runtime";
63
- var getFieldSettings = (_fields, _fieldSettings, deep) => {
256
+ var buildPuckField = (field, fieldSettings, customFields) => {
257
+ const customFieldDefinition = resolveCustomFieldDefinition(
258
+ field.type,
259
+ customFields
260
+ );
261
+ const customReturnType = resolveCustomFieldReturnType(field.type, customFields);
262
+ if (customFieldDefinition && customReturnType) {
263
+ return __spreadProps(__spreadValues({}, customFieldDefinition.field), {
264
+ type: "custom",
265
+ label: customFieldDefinition.field.label || field.name
266
+ });
267
+ }
268
+ const resolvedType = field.type;
269
+ switch (resolvedType) {
270
+ case "text":
271
+ case "textarea":
272
+ return { type: resolvedType, label: field.name };
273
+ case "number":
274
+ return {
275
+ type: resolvedType,
276
+ label: field.name,
277
+ min: fieldSettings == null ? void 0 : fieldSettings.min,
278
+ max: fieldSettings == null ? void 0 : fieldSettings.max,
279
+ step: fieldSettings == null ? void 0 : fieldSettings.step
280
+ };
281
+ case "select":
282
+ case "radio":
283
+ return {
284
+ type: resolvedType,
285
+ label: field.name,
286
+ options: (fieldSettings == null ? void 0 : fieldSettings.options) || []
287
+ };
288
+ case "array": {
289
+ const subFields = (fieldSettings == null ? void 0 : fieldSettings.subFields) || [];
290
+ const subFieldSettings = (fieldSettings == null ? void 0 : fieldSettings.subFieldSettings) || {};
291
+ return {
292
+ type: "array",
293
+ label: field.name,
294
+ min: fieldSettings == null ? void 0 : fieldSettings.min,
295
+ max: fieldSettings == null ? void 0 : fieldSettings.max,
296
+ arrayFields: buildDefaultEditorFields(
297
+ subFields,
298
+ subFieldSettings,
299
+ customFields
300
+ ),
301
+ defaultItemProps: buildArrayDefaultItemProps(subFields, subFieldSettings),
302
+ getItemSummary(item, index) {
303
+ return getArrayItemSummary(item, index, fieldSettings);
304
+ }
305
+ };
306
+ }
307
+ case "object":
308
+ return {
309
+ type: "object",
310
+ label: field.name,
311
+ objectFields: buildDefaultEditorFields(
312
+ (fieldSettings == null ? void 0 : fieldSettings.subFields) || [],
313
+ (fieldSettings == null ? void 0 : fieldSettings.subFieldSettings) || {},
314
+ customFields
315
+ )
316
+ };
317
+ default:
318
+ return { type: "text", label: field.name };
319
+ }
320
+ };
321
+ var buildDefaultEditorFields = (fields = [], fieldSettings = {}, customFields) => {
322
+ return fields.reduce((acc, field) => {
323
+ acc[field.name] = buildPuckField(
324
+ field,
325
+ fieldSettings[field.name],
326
+ customFields
327
+ );
328
+ return acc;
329
+ }, {});
330
+ };
331
+ var getFieldSettings = (_fields, _fieldSettings, customFields, deep) => {
332
+ const customTypeOptions = getCustomFieldTypeOptions(customFields);
64
333
  return (_fields || []).reduce((fields, field) => {
65
334
  const fieldSettings = {
66
335
  // placeholder: { type: "text", label: "Placeholder" },
67
336
  };
68
337
  const currentFieldSettings = _fieldSettings == null ? void 0 : _fieldSettings[field.name];
69
- switch (field.type) {
338
+ const customFieldDefinition = resolveCustomFieldDefinition(
339
+ field.type,
340
+ customFields
341
+ );
342
+ const customReturnType = resolveCustomFieldReturnType(
343
+ field.type,
344
+ customFields
345
+ );
346
+ const resolvedType = field.type;
347
+ const customSchema = resolveCustomFieldSchema(field.type, customFields);
348
+ const resolvedSubFields = (customSchema == null ? void 0 : customSchema.subFields) || (currentFieldSettings == null ? void 0 : currentFieldSettings.subFields) || [];
349
+ const resolvedSubFieldSettings = (customSchema == null ? void 0 : customSchema.subFieldSettings) || (currentFieldSettings == null ? void 0 : currentFieldSettings.subFieldSettings) || {};
350
+ const customDefaultValueField = customFieldDefinition && customReturnType ? __spreadProps(__spreadValues({}, customFieldDefinition.field), {
351
+ type: "custom",
352
+ label: customFieldDefinition.field.label || "Default Value"
353
+ }) : null;
354
+ if (customDefaultValueField) {
355
+ fieldSettings.defaultValue = customDefaultValueField;
356
+ }
357
+ switch (resolvedType) {
70
358
  case "text":
71
359
  case "textarea":
72
- fieldSettings.defaultValue = {
73
- type: field.type,
74
- label: "Default Value"
75
- };
360
+ if (!customDefaultValueField) {
361
+ fieldSettings.defaultValue = {
362
+ type: resolvedType,
363
+ label: "Default Value"
364
+ };
365
+ }
76
366
  break;
77
367
  case "number":
78
- fieldSettings.defaultValue = {
79
- type: field.type,
80
- label: "Default Value"
81
- };
368
+ if (!customDefaultValueField) {
369
+ fieldSettings.defaultValue = {
370
+ type: resolvedType,
371
+ label: "Default Value"
372
+ };
373
+ }
82
374
  fieldSettings.min = {
83
- type: field.type,
375
+ type: resolvedType,
84
376
  label: "Minimum Value"
85
377
  };
86
378
  fieldSettings.max = {
87
- type: field.type,
379
+ type: resolvedType,
88
380
  label: "Maximum Value"
89
381
  };
90
382
  fieldSettings.step = {
91
- type: field.type,
383
+ type: resolvedType,
92
384
  label: "Step Size"
93
385
  };
94
386
  break;
95
387
  case "radio":
96
- case "select":
97
- fieldSettings.defaultValue = {
98
- type: "custom",
99
- label: "Default Value",
100
- render: ({ value, onChange, id }) => /* @__PURE__ */ jsx(
101
- AutoField,
102
- {
103
- field: {
104
- type: field.type,
105
- label: "Default Value",
106
- options: (currentFieldSettings == null ? void 0 : currentFieldSettings.options) || []
107
- },
108
- value,
109
- onChange,
110
- readOnly: false,
111
- id
112
- }
113
- )
114
- };
388
+ case "select": {
389
+ const selectOptions = (currentFieldSettings == null ? void 0 : currentFieldSettings.options) || [];
390
+ if (!customDefaultValueField) {
391
+ fieldSettings.defaultValue = {
392
+ type: "custom",
393
+ label: "Default Value",
394
+ render: ({ value, onChange, id }) => /* @__PURE__ */ jsx(
395
+ AutoField,
396
+ {
397
+ field: {
398
+ type: resolvedType,
399
+ label: "Default Value",
400
+ options: selectOptions
401
+ },
402
+ value,
403
+ onChange,
404
+ readOnly: false,
405
+ id
406
+ }
407
+ )
408
+ };
409
+ }
115
410
  fieldSettings.options = {
116
411
  type: "array",
117
412
  label: "Options",
@@ -131,21 +426,8 @@ var getFieldSettings = (_fields, _fieldSettings, deep) => {
131
426
  }
132
427
  };
133
428
  break;
429
+ }
134
430
  case "array":
135
- fieldSettings.summary = {
136
- type: "select",
137
- label: "Summary Field",
138
- options: [
139
- {
140
- label: "Default Numbering",
141
- value: ""
142
- },
143
- ...((currentFieldSettings == null ? void 0 : currentFieldSettings.subFields) || []).map((f) => ({
144
- label: f.name,
145
- value: f.name
146
- }))
147
- ]
148
- };
149
431
  case "object":
150
432
  fieldSettings.subFields = {
151
433
  type: "array",
@@ -174,7 +456,8 @@ var getFieldSettings = (_fields, _fieldSettings, deep) => {
174
456
  {
175
457
  label: "Radio",
176
458
  value: "radio"
177
- }
459
+ },
460
+ ...customTypeOptions
178
461
  ] : [
179
462
  {
180
463
  label: "Text",
@@ -203,7 +486,8 @@ var getFieldSettings = (_fields, _fieldSettings, deep) => {
203
486
  {
204
487
  label: "Reference",
205
488
  value: "reference"
206
- }
489
+ },
490
+ ...customTypeOptions
207
491
  ]
208
492
  }
209
493
  },
@@ -215,44 +499,99 @@ var getFieldSettings = (_fields, _fieldSettings, deep) => {
215
499
  fieldSettings.subFieldSettings = {
216
500
  type: "object",
217
501
  label: "Sub Field Settings",
218
- objectFields: (currentFieldSettings == null ? void 0 : currentFieldSettings.subFields) ? getFieldSettings(
219
- currentFieldSettings.subFields,
220
- currentFieldSettings.subFieldSettings,
502
+ objectFields: resolvedSubFields ? getFieldSettings(
503
+ resolvedSubFields,
504
+ resolvedSubFieldSettings,
505
+ customFields,
221
506
  true
222
507
  ) : {}
223
508
  };
509
+ if (resolvedType === "array") {
510
+ if (!customDefaultValueField) {
511
+ fieldSettings.defaultValue = {
512
+ type: "array",
513
+ label: "Default Items",
514
+ arrayFields: buildDefaultEditorFields(
515
+ resolvedSubFields,
516
+ resolvedSubFieldSettings,
517
+ customFields
518
+ ),
519
+ defaultItemProps: buildArrayDefaultItemProps(
520
+ resolvedSubFields,
521
+ resolvedSubFieldSettings
522
+ ),
523
+ getItemSummary(item, index) {
524
+ return getArrayItemSummary(item, index, currentFieldSettings);
525
+ }
526
+ };
527
+ }
528
+ fieldSettings.min = {
529
+ type: "number",
530
+ label: "Minimum Items"
531
+ };
532
+ fieldSettings.max = {
533
+ type: "number",
534
+ label: "Maximum Items"
535
+ };
536
+ fieldSettings.summary = {
537
+ type: "select",
538
+ label: "Summary",
539
+ options: [
540
+ {
541
+ label: "Default Numbering / Count",
542
+ value: "count"
543
+ },
544
+ {
545
+ label: "Field",
546
+ value: "field"
547
+ },
548
+ {
549
+ label: "Expression",
550
+ value: "expression"
551
+ }
552
+ ]
553
+ };
554
+ if ((currentFieldSettings == null ? void 0 : currentFieldSettings.summary) === "field") {
555
+ fieldSettings.summaryField = {
556
+ type: "select",
557
+ label: "Summary Field",
558
+ options: [
559
+ {
560
+ label: "Select a field",
561
+ value: ""
562
+ },
563
+ ...resolvedSubFields.filter((subField) => isPrimitiveFieldType(subField.type)).map((subField) => ({
564
+ label: subField.name,
565
+ value: subField.name
566
+ }))
567
+ ]
568
+ };
569
+ }
570
+ if ((currentFieldSettings == null ? void 0 : currentFieldSettings.summary) === "expression") {
571
+ fieldSettings.summaryExpression = {
572
+ type: "text",
573
+ label: "Summary Expression"
574
+ };
575
+ }
576
+ }
224
577
  break;
225
578
  }
579
+ const overriddenFieldSettings = (customFieldDefinition == null ? void 0 : customFieldDefinition.fieldSettingsOverride) ? customFieldDefinition.fieldSettingsOverride({
580
+ fieldName: field.name,
581
+ fieldType: field.type,
582
+ fieldSettings: currentFieldSettings,
583
+ originalFieldSettings: fieldSettings
584
+ }) : fieldSettings;
226
585
  fields[field.name] = {
227
586
  type: "object",
228
587
  label: field.name,
229
- objectFields: fieldSettings
588
+ objectFields: overriddenFieldSettings
230
589
  };
231
590
  return fields;
232
591
  }, {});
233
592
  };
234
593
  var get_field_settings_default = getFieldSettings;
235
594
 
236
- // src/puck/lib/get-settings-by-path.ts
237
- function getFieldSettingsByPath(fieldSettings, path) {
238
- return path.split(".").reduce((o, key) => o ? o[key] : void 0, fieldSettings);
239
- }
240
-
241
- // src/puck/lib/set-prop-by-path.ts
242
- function setPropertyByPath(props, path, value) {
243
- const parts = path.split(".");
244
- const last = parts.pop();
245
- let cur = props;
246
- for (const p of parts) {
247
- if (typeof cur[p] !== "object" || cur[p] === null) cur[p] = {};
248
- cur = cur[p];
249
- }
250
- cur[last] = value;
251
- }
252
-
253
- // src/puck/lib/builder/root-config.tsx
254
- import { useEffect } from "react";
255
-
256
595
  // src/puck/context/useStore.ts
257
596
  import { createContext, useContext } from "react";
258
597
  import { useStore } from "zustand";
@@ -273,224 +612,356 @@ var createUseSoftConfig = () => {
273
612
  };
274
613
  var useSoftConfig = createUseSoftConfig();
275
614
 
276
- // src/puck/lib/builder/root-config.tsx
277
- import { useDebounce } from "use-debounce";
278
- import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
279
- var useCustomPuck = createUsePuck();
280
- var breakVersion = (version) => {
281
- const [major, minor, patch] = version.split(".").map((v) => parseInt(v));
282
- return [major, minor, patch];
283
- };
284
- var updateVersion = (version, increment) => {
285
- let [major, minor, patch] = breakVersion(version);
286
- if (increment === "major") {
287
- major += 1;
288
- minor = 0;
289
- patch = 0;
290
- } else if (increment === "minor") {
291
- minor += 1;
292
- patch = 0;
293
- } else {
294
- patch += 1;
615
+ // src/puck/lib/apply-mapping.ts
616
+ import equal from "react-fast-compare";
617
+
618
+ // src/puck/lib/set-prop-by-path.ts
619
+ function setPropertyByPath(props, path, value) {
620
+ const parts = path.split(".");
621
+ const last = parts.pop();
622
+ let cur = props;
623
+ for (const p of parts) {
624
+ if (typeof cur[p] !== "object" || cur[p] === null) cur[p] = {};
625
+ cur = cur[p];
295
626
  }
296
- return `${major}.${minor}.${patch}`;
627
+ cur[last] = value;
628
+ }
629
+
630
+ // src/puck/lib/apply-mapping.ts
631
+ var resolveValueByPath = (source, path) => {
632
+ if (!path) return source;
633
+ const segments = path.split(".");
634
+ const resolveSegments = (current, index) => {
635
+ if (current === null || current === void 0) return void 0;
636
+ if (index >= segments.length) return current;
637
+ const segment = segments[index];
638
+ if (segment.endsWith("[]")) {
639
+ const arrayKey = segment.slice(0, -2);
640
+ const arraySource = arrayKey ? current == null ? void 0 : current[arrayKey] : current;
641
+ const resolvedArray = Array.isArray(arraySource) ? arraySource : Array.isArray(arraySource == null ? void 0 : arraySource.defaultValue) ? arraySource.defaultValue : void 0;
642
+ if (!resolvedArray) return void 0;
643
+ if (index === segments.length - 1) return resolvedArray;
644
+ return resolvedArray.map((item) => resolveSegments(item, index + 1));
645
+ }
646
+ return resolveSegments(current[segment], index + 1);
647
+ };
648
+ return resolveSegments(source, 0);
297
649
  };
298
- var builderRootConfig = (config, overrides, editingComponent, showVersionFields = true) => ({
299
- fields: __spreadValues({
300
- _name: overrides.name || {
301
- type: "text",
302
- label: "Soft Component Name"
303
- },
304
- _category: overrides.categories || {
305
- type: "select",
306
- label: "Category",
307
- options: [
308
- ...Object.keys(config.categories || {}).map((cat) => {
309
- var _a;
310
- return {
311
- label: ((_a = config.categories) == null ? void 0 : _a[cat].title) || cat,
312
- value: cat
313
- };
314
- }) || [],
315
- {
316
- label: Object.keys(config.categories || {}).length ? "Other" : "Uncategorized",
317
- value: void 0
650
+ var resolveFieldSettingEntryByPath = (settings, path) => {
651
+ if (!path) return void 0;
652
+ const segments = path.split(".");
653
+ let currentSettings = settings;
654
+ let currentEntry;
655
+ for (const segmentWithArraySuffix of segments) {
656
+ const segment = segmentWithArraySuffix.endsWith("[]") ? segmentWithArraySuffix.slice(0, -2) : segmentWithArraySuffix;
657
+ if (!currentSettings || typeof currentSettings !== "object") {
658
+ return void 0;
659
+ }
660
+ currentEntry = currentSettings[segment];
661
+ if (currentEntry === void 0) {
662
+ return void 0;
663
+ }
664
+ currentSettings = currentEntry == null ? void 0 : currentEntry.subFieldSettings;
665
+ }
666
+ return currentEntry;
667
+ };
668
+ function applyMapping(props, fieldSettings, map, resolveInput = "fieldSettings", options) {
669
+ var _a, _b, _c;
670
+ const newProps = __spreadValues({}, props);
671
+ const sourceProps = (_a = options == null ? void 0 : options.sourceProps) != null ? _a : props;
672
+ const mappedArrayPaths = /* @__PURE__ */ new Set();
673
+ let changed = false;
674
+ const changedArrayBases = /* @__PURE__ */ new Set();
675
+ for (const entry of map) {
676
+ const { from, to, transform } = entry;
677
+ if (!from || !to) continue;
678
+ const fromPaths = Array.isArray(from) ? from : [from];
679
+ const toPaths = Array.isArray(to) ? to : [to];
680
+ const hasInvalidPair = fromPaths.some((fp, idx) => {
681
+ const tp = toPaths[idx] || toPaths[0];
682
+ if (typeof fp !== "string" || typeof tp !== "string") return false;
683
+ return isArrayMappingPath(fp) && !isArrayMappingPath(tp);
684
+ });
685
+ if (hasInvalidPair) continue;
686
+ const inputValues = fromPaths.map((f) => {
687
+ if (resolveInput === "propsFirst") {
688
+ const propVal = resolveValueByPath(sourceProps, f);
689
+ if (propVal !== void 0) return propVal;
690
+ const setting = resolveValueByPath(fieldSettings, f);
691
+ if (setting && Object.prototype.hasOwnProperty.call(setting, "defaultValue")) {
692
+ return setting.defaultValue;
318
693
  }
319
- ]
320
- },
321
- _fields: {
322
- type: "array",
323
- label: "Fields",
324
- defaultItemProps: {
325
- name: "New Field",
326
- type: "text"
327
- },
328
- getItemSummary(item, index) {
329
- return item.name || `Field ${(index || 0) + 1}`;
330
- },
331
- arrayFields: {
332
- name: { type: "text", label: "Name" },
333
- type: {
334
- type: "select",
335
- label: "Type",
336
- options: [
337
- { label: "Text", value: "text" },
338
- { label: "Textarea", value: "textarea" },
339
- { label: "Number", value: "number" },
340
- { label: "Select", value: "select" },
341
- { label: "Radio", value: "radio" },
342
- { label: "Array", value: "array" },
343
- { label: "Object", value: "object" }
344
- // { label: "Reference", value: "reference" },
345
- ]
694
+ return propVal;
695
+ }
696
+ const directValue = resolveValueByPath(fieldSettings, f);
697
+ if (directValue !== void 0) {
698
+ return directValue;
699
+ }
700
+ return resolveFieldSettingEntryByPath(fieldSettings, f);
701
+ });
702
+ const resolvedInputs = inputValues.map(
703
+ (v) => resolveInput === "fieldSettings" ? v == null ? void 0 : v.defaultValue : v
704
+ );
705
+ let result = transform ? transform(resolvedInputs, newProps) : inputValues[0];
706
+ if (resolveInput === "fieldSettings" && !transform && result !== void 0 && typeof result === "object" && result !== null && "defaultValue" in result) {
707
+ result = result.defaultValue;
708
+ }
709
+ const isSingleArrayTarget = toPaths.length === 1 && typeof toPaths[0] === "string" && isArrayMappingPath(toPaths[0]);
710
+ if (isSingleArrayTarget) {
711
+ const toPath = toPaths[0];
712
+ const arrayBase = getArrayBasePath(toPath);
713
+ const subProp = getArrayItemSubPath(toPath) || "";
714
+ if (!arrayBase) continue;
715
+ 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] : [];
716
+ const currentArrayAtPath = resolveValueByPath(newProps, arrayBase);
717
+ const currentArray = Array.isArray(currentArrayAtPath) ? currentArrayAtPath : [];
718
+ const isFromArrayPath = typeof fromPaths[0] === "string" && isArrayMappingPath(fromPaths[0]);
719
+ const sourceArray = isFromArrayPath ? Array.isArray(result) ? result : result !== void 0 ? [result] : [] : Array.isArray(result) ? result : defaultArray.map(() => result);
720
+ let defaults = entry.unmappedArrayItemDefaultValues || entry.defaultOverrides || {};
721
+ if (typeof defaults === "string") {
722
+ try {
723
+ defaults = JSON.parse(defaults);
724
+ } catch (e) {
725
+ defaults = {};
726
+ }
727
+ }
728
+ const targetLength = sourceArray.length;
729
+ const constructed = Array.from({ length: targetLength }).map((_, idx) => {
730
+ const mappedValue = sourceArray[idx];
731
+ const defaultItem = defaultArray[idx] && typeof defaultArray[idx] === "object" ? defaultArray[idx] : {};
732
+ const currentItem = currentArray[idx] && typeof currentArray[idx] === "object" ? currentArray[idx] : {};
733
+ const item = __spreadValues(__spreadValues(__spreadValues({}, defaultItem), defaults), currentItem);
734
+ if (subProp && mappedValue !== void 0) {
735
+ setPropertyByPath(item, subProp, mappedValue);
346
736
  }
737
+ return item;
738
+ });
739
+ const originalArray = resolveValueByPath(newProps, arrayBase);
740
+ if (!equal(originalArray, constructed)) {
741
+ setPropertyByPath(newProps, arrayBase, constructed);
742
+ changedArrayBases.add(arrayBase);
743
+ }
744
+ mappedArrayPaths.add(arrayBase);
745
+ } else if (toPaths.length === 1 && Array.isArray(result) && toPaths[0].includes("array")) {
746
+ const toPath = toPaths[0];
747
+ const original = resolveValueByPath(newProps, toPath);
748
+ if (!equal(original, result)) {
749
+ setPropertyByPath(newProps, toPath, result);
750
+ changed = true;
751
+ }
752
+ } else if (Array.isArray(result) && toPaths.length > 1) {
753
+ result.forEach((val, idx) => {
754
+ if (toPaths[idx]) {
755
+ const orig = resolveValueByPath(newProps, toPaths[idx]);
756
+ if (!equal(orig, val)) {
757
+ setPropertyByPath(newProps, toPaths[idx], val);
758
+ changed = true;
759
+ }
760
+ }
761
+ });
762
+ } else if (toPaths[0]) {
763
+ const finalValue = result;
764
+ const originalValue = resolveValueByPath(newProps, toPaths[0]);
765
+ if (!equal(originalValue, finalValue)) {
766
+ setPropertyByPath(newProps, toPaths[0], finalValue);
767
+ changed = true;
347
768
  }
348
769
  }
349
- }, overrides.additionalRootFields || {}),
350
- resolveFields({ props: data }, { fields, changed }) {
351
- var _a, _b;
352
- if (!(data == null ? void 0 : data._fields) || changed._fields || changed._fieldSettings)
353
- if ((_a = data == null ? void 0 : data._fields) == null ? void 0 : _a.length)
354
- fields._fieldSettings = {
355
- type: "object",
356
- label: "Field Settings",
357
- objectFields: get_field_settings_default(
358
- data._fields || [],
359
- data._fieldSettings || {}
360
- )
361
- };
362
- else delete fields._fieldSettings;
363
- if (showVersionFields && ((_b = data == null ? void 0 : data._versions) == null ? void 0 : _b.length)) {
364
- const latestVersion = data._versions[data._versions.length - 1] || "1.0.0";
365
- delete fields._version;
366
- fields._version = {
770
+ }
771
+ const hasNetArrayChanges = Array.from(changedArrayBases).some(
772
+ (arrayBase) => !equal(resolveValueByPath(props, arrayBase), resolveValueByPath(newProps, arrayBase))
773
+ );
774
+ return { newProps, mappedArrayPaths, changed: changed || hasNetArrayChanges };
775
+ }
776
+
777
+ // src/puck/lib/builder/root-config.tsx
778
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
779
+ var useCustomPuck = createUsePuck();
780
+ var getSerializableProps = (props) => {
781
+ const cleanProps = {
782
+ id: props.id
783
+ };
784
+ for (const key in props) {
785
+ const value = props[key];
786
+ if (["children", "puck", "editMode"].includes(key)) continue;
787
+ if (value && typeof value === "object" && value.$$typeof) continue;
788
+ if (typeof value === "function") continue;
789
+ cleanProps[key] = value;
790
+ }
791
+ return cleanProps;
792
+ };
793
+ var builderRootConfig = (config, overrides, editingComponent, showVersionFields = true, customFields) => {
794
+ const customTypeOptions = getCustomFieldTypeOptions(customFields);
795
+ return {
796
+ fields: __spreadValues({
797
+ _name: overrides.name || {
798
+ type: "text",
799
+ label: "Soft Component Name"
800
+ },
801
+ _category: overrides.categories || {
367
802
  type: "select",
368
- label: "Version",
803
+ label: "Category",
369
804
  options: [
370
- ...data._versions.map((v) => ({ label: v, value: v })),
371
- {
372
- label: `${updateVersion(latestVersion, "patch")} (Patch)`,
373
- value: updateVersion(latestVersion, "patch")
374
- },
375
- {
376
- label: `${updateVersion(latestVersion, "minor")} (Minor)`,
377
- value: updateVersion(latestVersion, "minor")
378
- },
805
+ ...Object.keys(config.categories || {}).map((cat) => {
806
+ var _a;
807
+ return {
808
+ label: ((_a = config.categories) == null ? void 0 : _a[cat].title) || cat,
809
+ value: cat
810
+ };
811
+ }) || [],
379
812
  {
380
- label: `${updateVersion(latestVersion, "major")} (Major)`,
381
- value: updateVersion(latestVersion, "major")
813
+ label: Object.keys(config.categories || {}).length ? "Other" : "Uncategorized",
814
+ value: void 0
382
815
  }
383
816
  ]
384
- };
385
- } else {
386
- delete fields._version;
387
- }
388
- return fields;
389
- },
390
- resolveData: (props, params) => {
391
- if (overrides.resolveRootData) {
392
- return overrides.resolveRootData(props, params, { editingComponent });
393
- }
394
- let result = {
395
- props,
396
- readOnly: void 0
397
- };
398
- return result;
399
- },
400
- render: (props) => {
401
- const fieldSettings = props == null ? void 0 : props._fieldSettings;
402
- const data = useCustomPuck((s) => s.appState.data);
403
- const dispatch = useCustomPuck((s) => s.dispatch);
404
- const getSelectorForId = useCustomPuck((s) => s.getSelectorForId);
405
- const setVersion = useSoftConfig((s) => s.builder.setVersion);
406
- const state = useSoftConfig((s) => s.state);
407
- const [debouncedFieldSettings] = useDebounce(fieldSettings, 500);
408
- useEffect(() => {
409
- if (!debouncedFieldSettings || Object.keys(debouncedFieldSettings).length === 0) return;
410
- walkTree(
411
- data,
412
- {
413
- components: config.components
817
+ },
818
+ _fields: {
819
+ type: "array",
820
+ label: "Fields",
821
+ defaultItemProps: {
822
+ name: "New Field",
823
+ type: "text"
414
824
  },
415
- (content) => content.map((child) => {
416
- var _a;
417
- const map = ((_a = child.props) == null ? void 0 : _a._map) || [];
418
- if (map.length) {
419
- map.forEach(({ from, to, transform }) => {
420
- if (!from || !to) return;
421
- const fromPaths = Array.isArray(from) ? from : [from];
422
- const toPaths = Array.isArray(to) ? to : [to];
423
- const inputValues = fromPaths.map(
424
- (f) => getFieldSettingsByPath(props._fieldSettings || {}, f)
425
- );
426
- let value = transform ? transform(
427
- inputValues.map((v) => v == null ? void 0 : v.defaultValue),
428
- child.props
429
- ) : inputValues[0];
430
- if (Array.isArray(value)) {
431
- value.forEach((val, i) => {
432
- if (toPaths[i]) {
433
- const originalValue = getFieldSettingsByPath(
434
- child.props,
435
- toPaths[i]
436
- );
437
- if (originalValue !== val) {
438
- const itemSelector = getSelectorForId(child.props.id);
439
- if (!itemSelector) return;
440
- setPropertyByPath(child.props, toPaths[i], val);
441
- dispatch({
442
- type: "replace",
443
- data: child,
444
- destinationIndex: itemSelector == null ? void 0 : itemSelector.index,
445
- destinationZone: itemSelector == null ? void 0 : itemSelector.zone
446
- });
447
- }
448
- }
449
- });
450
- } else if (toPaths[0]) {
451
- const setting = getFieldSettingsByPath(
452
- debouncedFieldSettings,
453
- fromPaths.length === 1 ? fromPaths[0] : fromPaths.join(".")
454
- );
455
- const defaultValue = setting == null ? void 0 : setting.defaultValue;
456
- const originalValue = getFieldSettingsByPath(
457
- child.props,
458
- toPaths[0]
459
- );
460
- const finalValue = transform !== void 0 && value !== void 0 ? value : defaultValue !== void 0 ? defaultValue : value;
461
- if (originalValue !== finalValue) {
462
- const itemSelector = getSelectorForId(child.props.id);
463
- if (!itemSelector) return;
464
- setPropertyByPath(child.props, toPaths[0], finalValue);
465
- dispatch({
466
- type: "replace",
467
- data: child,
468
- destinationIndex: itemSelector == null ? void 0 : itemSelector.index,
469
- destinationZone: itemSelector == null ? void 0 : itemSelector.zone
470
- });
471
- }
472
- }
473
- });
825
+ getItemSummary(item, index) {
826
+ return item.name || `Field ${(index || 0) + 1}`;
827
+ },
828
+ arrayFields: {
829
+ name: { type: "text", label: "Name" },
830
+ type: {
831
+ type: "select",
832
+ label: "Type",
833
+ options: [
834
+ { label: "Text", value: "text" },
835
+ { label: "Textarea", value: "textarea" },
836
+ { label: "Number", value: "number" },
837
+ { label: "Select", value: "select" },
838
+ { label: "Radio", value: "radio" },
839
+ { label: "Array", value: "array" },
840
+ { label: "Object", value: "object" },
841
+ // { label: "Reference", value: "reference" },
842
+ ...customTypeOptions
843
+ ]
474
844
  }
475
- return child;
476
- })
477
- );
478
- }, [debouncedFieldSettings, data, dispatch, getSelectorForId, props._fieldSettings]);
479
- useEffect(() => {
480
- var _a;
481
- if (state !== "remodeling") return;
482
- if (!(props == null ? void 0 : props._version) || !(props == null ? void 0 : props._name)) return;
483
- const currentVersion = props == null ? void 0 : props._version;
484
- if (((_a = props._versions) == null ? void 0 : _a.includes(currentVersion)) && props._versions.length > 1) {
485
- setVersion(props._name, currentVersion, props, dispatch);
845
+ }
486
846
  }
487
- }, [props == null ? void 0 : props._version]);
488
- return /* @__PURE__ */ jsx2(Fragment, { children: props.children });
489
- }
490
- });
847
+ }, overrides.additionalRootFields || {}),
848
+ resolveFields({ props: data }, { fields, changed }) {
849
+ const newFields = __spreadValues({}, fields);
850
+ const rootFields = Array.isArray(
851
+ data == null ? void 0 : data._fields
852
+ ) ? (data == null ? void 0 : data._fields) || [] : [];
853
+ const rootFieldSettings = (data == null ? void 0 : data._fieldSettings) || {};
854
+ if (changed._fields || changed._fieldSettings) {
855
+ if (rootFields.length) {
856
+ newFields._fieldSettings = {
857
+ type: "object",
858
+ label: "Field Settings",
859
+ objectFields: get_field_settings_default(
860
+ rootFields,
861
+ rootFieldSettings,
862
+ customFields
863
+ )
864
+ };
865
+ } else {
866
+ delete newFields._fieldSettings;
867
+ }
868
+ }
869
+ return newFields;
870
+ },
871
+ // resolveData: (props, params) => {
872
+ // if (overrides.resolveRootData) {
873
+ // return overrides.resolveRootData(props, params, { editingComponent });
874
+ // }
875
+ // const result: {
876
+ // props: RootData<AsFieldProps<WithChildren<BuilderRootConfig>>>;
877
+ // readOnly: Readonly<Record<string, boolean>> | undefined;
878
+ // } = {
879
+ // props,
880
+ // readOnly: undefined,
881
+ // };
882
+ // return result;
883
+ // },
884
+ render: (props) => {
885
+ const fieldSettings = props == null ? void 0 : props._fieldSettings;
886
+ const data = useCustomPuck((s) => s.appState.data);
887
+ const dispatch = useCustomPuck((s) => s.dispatch);
888
+ const getSelectorForId = useCustomPuck((s) => s.getSelectorForId);
889
+ const setVersion = useSoftConfig((s) => s.builder.setVersion);
890
+ const state = useSoftConfig((s) => s.state);
891
+ useEffect(() => {
892
+ if (!fieldSettings || Object.keys(fieldSettings).length === 0) return;
893
+ const replacements = [];
894
+ walkTree(
895
+ {
896
+ content: (data == null ? void 0 : data.content) || [],
897
+ root: (data == null ? void 0 : data.root) || {}
898
+ },
899
+ {
900
+ components: config.components
901
+ },
902
+ (content) => content.map((child) => {
903
+ var _a;
904
+ const map = ((_a = child.props) == null ? void 0 : _a._map) || [];
905
+ if (!map.length) return child;
906
+ const cleanProps = getSerializableProps(child.props);
907
+ const { newProps, changed } = applyMapping(
908
+ cleanProps,
909
+ fieldSettings,
910
+ map,
911
+ "fieldSettings"
912
+ );
913
+ if (!changed || equal2(cleanProps, newProps)) return child;
914
+ replacements.push({
915
+ id: child.props.id,
916
+ data: __spreadProps(__spreadValues({}, child), { props: newProps })
917
+ });
918
+ return child;
919
+ })
920
+ );
921
+ if (!replacements.length) return;
922
+ replacements.forEach((replacement) => {
923
+ const itemSelector = getSelectorForId(replacement.id);
924
+ if (!itemSelector) return;
925
+ dispatch({
926
+ type: "replace",
927
+ data: replacement.data,
928
+ destinationIndex: itemSelector.index,
929
+ destinationZone: itemSelector.zone
930
+ });
931
+ });
932
+ }, [fieldSettings, data, dispatch, getSelectorForId]);
933
+ useEffect(() => {
934
+ var _a;
935
+ if (state !== "remodeling" || !(props == null ? void 0 : props._version) || !(props == null ? void 0 : props._name)) return;
936
+ const currentVersion = props._version;
937
+ if (((_a = props._versions) == null ? void 0 : _a.includes(currentVersion)) && props._versions.length > 1) {
938
+ setVersion(props._name, currentVersion, props, dispatch);
939
+ }
940
+ }, [props == null ? void 0 : props._version]);
941
+ return /* @__PURE__ */ jsx2(Fragment, { children: props.children });
942
+ }
943
+ };
944
+ };
491
945
 
492
946
  // src/puck/lib/builder/generate-field-options.ts
493
- function generateFieldOptions(fields, selectedFields, prefix = "") {
947
+ var hasArrayMappingPath = (value) => value.includes("[]");
948
+ var isBareArrayPath = (value) => !hasArrayMappingPath(value) && !value.includes(".");
949
+ function filterToOptionsForFrom(fromPath, toOptions) {
950
+ if (!fromPath) return toOptions;
951
+ const fromHasArrayMapping = hasArrayMappingPath(fromPath);
952
+ const fromIsBareArray = isBareArrayPath(fromPath);
953
+ return toOptions.filter((option) => {
954
+ const optionHasArrayMapping = hasArrayMappingPath(option.value);
955
+ if (fromHasArrayMapping) {
956
+ return optionHasArrayMapping;
957
+ }
958
+ if (fromIsBareArray) {
959
+ return isBareArrayPath(option.value);
960
+ }
961
+ return !optionHasArrayMapping;
962
+ });
963
+ }
964
+ function generateFieldOptions(fields, prefix = "") {
494
965
  const opts = [];
495
966
  function recurse(current, prefix2) {
496
967
  Object.entries(current).forEach(([key, fld]) => {
@@ -498,36 +969,68 @@ function generateFieldOptions(fields, selectedFields, prefix = "") {
498
969
  if (key === "_map") return;
499
970
  if (key === "_slotEnabled") return;
500
971
  const path = prefix2 ? `${prefix2}.${key}` : key;
501
- if (selectedFields.includes(path)) {
502
- return;
503
- }
504
- opts.push({ label: path, value: path, type: fld.type });
505
972
  if (fld.type === "object" && fld.objectFields) {
506
973
  recurse(fld.objectFields, path);
507
- }
508
- if (fld.type === "array" && fld.arrayFields) {
509
- recurse(fld.arrayFields, path);
974
+ } else if (fld.type === "array" && fld.arrayFields) {
975
+ recurse(
976
+ fld.arrayFields,
977
+ path + "[]"
978
+ );
979
+ } else {
980
+ opts.push({ label: path, value: path, type: fld.type });
510
981
  }
511
982
  });
512
983
  }
513
984
  recurse(fields, prefix);
514
985
  return opts;
515
986
  }
516
- function generateDynamicFieldOptions(_fields, _fieldSettings, prefix = "") {
987
+ function generateDynamicFieldOptions(_fields, _fieldSettings, customFields, prefix = "") {
517
988
  const opts = [];
518
- if (!_fields || !_fieldSettings) return opts;
989
+ if (!_fields) return opts;
519
990
  function recurse(fields, fieldSettings, currentPrefix) {
520
991
  fields.forEach((field) => {
521
992
  var _a;
522
993
  const settings = fieldSettings[field.name];
994
+ const customReturnType = resolveCustomFieldReturnType(
995
+ field.type,
996
+ customFields
997
+ );
523
998
  const path = currentPrefix ? `${currentPrefix}.${field.name}` : field.name;
524
- opts.push({ label: path, value: path, type: field.type });
999
+ if (customReturnType) {
1000
+ if (customReturnType === "array" || customReturnType === "object") {
1001
+ const customSchema = resolveCustomFieldSchema(field.type, customFields);
1002
+ if (!customSchema) {
1003
+ return;
1004
+ }
1005
+ recurse(
1006
+ customSchema.subFields,
1007
+ customSchema.subFieldSettings,
1008
+ path + (customReturnType === "array" ? "[]" : "")
1009
+ );
1010
+ return;
1011
+ }
1012
+ opts.push({
1013
+ label: path,
1014
+ value: path,
1015
+ type: mapCustomReturnTypeToMappingType(customReturnType)
1016
+ });
1017
+ return;
1018
+ }
1019
+ if (!isBuiltInSoftFieldType(field.type)) {
1020
+ return;
1021
+ }
525
1022
  if ((_a = settings == null ? void 0 : settings.subFields) == null ? void 0 : _a.length) {
526
- recurse(settings.subFields, settings.subFieldSettings || {}, path);
1023
+ recurse(
1024
+ settings.subFields,
1025
+ settings.subFieldSettings || {},
1026
+ path + (field.type === "array" ? "[]" : "")
1027
+ );
1028
+ } else if (field.type !== "array" && field.type !== "object") {
1029
+ opts.push({ label: path, value: path, type: field.type });
527
1030
  }
528
1031
  });
529
1032
  }
530
- recurse(_fields, _fieldSettings, prefix);
1033
+ recurse(_fields, _fieldSettings || {}, prefix);
531
1034
  return opts;
532
1035
  }
533
1036
 
@@ -619,8 +1122,14 @@ var ErrorBoundary = class extends Component {
619
1122
 
620
1123
  // src/puck/lib/builder/builder-config.tsx
621
1124
  import { jsx as jsx4 } from "react/jsx-runtime";
622
- var builderConfig = (config, overrides, editingComponent, showVersionFields = true, dependents) => ({
623
- root: builderRootConfig(config, overrides, editingComponent, showVersionFields),
1125
+ var builderConfig = (config, overrides, editingComponent, showVersionFields = true, dependents, customFields) => ({
1126
+ root: builderRootConfig(
1127
+ config,
1128
+ overrides,
1129
+ editingComponent,
1130
+ showVersionFields,
1131
+ customFields
1132
+ ),
624
1133
  components: Object.entries(__spreadValues({}, config.components)).reduce(
625
1134
  (acc, [name, component]) => {
626
1135
  const tempComponent = __spreadProps(__spreadValues({}, component), {
@@ -629,6 +1138,7 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
629
1138
  },
630
1139
  resolveFields(data, params) {
631
1140
  return __async(this, null, function* () {
1141
+ var _a2;
632
1142
  let fields = {};
633
1143
  if (!fields._slot) {
634
1144
  const slotFields = Object.entries(params.fields).filter(
@@ -649,8 +1159,8 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
649
1159
  { label: "Select a slot", value: "" },
650
1160
  ...slotFields.filter(
651
1161
  ([fieldName, field]) => {
652
- var _a2;
653
- return field.type === "slot" && !(((_a2 = data.props) == null ? void 0 : _a2._slot) || []).some(
1162
+ var _a3;
1163
+ return field.type === "slot" && !(((_a3 = data.props) == null ? void 0 : _a3._slot) || []).some(
654
1164
  (s) => s.slot === fieldName
655
1165
  );
656
1166
  }
@@ -669,17 +1179,21 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
669
1179
  };
670
1180
  }
671
1181
  const defaultFields = component.resolveFields ? yield component.resolveFields(data, params) : component.fields || {};
672
- if (!fields._map) {
1182
+ if (!fields._map || params.changed._map) {
673
1183
  const rootProps = getRootProps(params.appState);
674
1184
  const fromOptions = generateDynamicFieldOptions(
675
1185
  (rootProps == null ? void 0 : rootProps._fields) || [],
676
- (rootProps == null ? void 0 : rootProps._fieldSettings) || {}
1186
+ (rootProps == null ? void 0 : rootProps._fieldSettings) || {},
1187
+ customFields
677
1188
  );
678
- const toOptions = generateFieldOptions(defaultFields, []);
1189
+ const toOptionsFields = component.resolveFields && ((_a2 = data.props) == null ? void 0 : _a2._map) ? yield component.resolveFields(
1190
+ __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { _map: void 0 }) }),
1191
+ params
1192
+ ) : defaultFields;
1193
+ const toOptions = generateFieldOptions(toOptionsFields);
679
1194
  fields._map = overrides.map ? {
680
1195
  type: "custom",
681
1196
  render: ({ value, onChange, id }) => {
682
- const toOptions2 = generateFieldOptions(defaultFields, []);
683
1197
  const rootProps2 = getRootProps(params.appState);
684
1198
  return overrides.map({
685
1199
  rootProps: rootProps2,
@@ -688,13 +1202,39 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
688
1202
  id,
689
1203
  props: data.props || {},
690
1204
  fromOptions,
691
- toOptions: toOptions2
1205
+ toOptions
692
1206
  });
693
1207
  }
694
- } : {
695
- type: "array",
696
- label: "Dynamic Field Map",
697
- arrayFields: {
1208
+ } : (() => {
1209
+ var _a3;
1210
+ const mapEntries = ((_a3 = data.props) == null ? void 0 : _a3._map) || [];
1211
+ const toPaths = mapEntries.flatMap(
1212
+ (entry) => Array.isArray(entry.to) ? entry.to : entry.to ? [entry.to] : []
1213
+ );
1214
+ const toPath = toPaths.find(
1215
+ (path) => typeof path === "string" && isArrayMappingPath(path)
1216
+ );
1217
+ const arrayBaseName = toPath ? getArrayBasePath(toPath) : null;
1218
+ const targetArrayField = arrayBaseName ? defaultFields[arrayBaseName] : null;
1219
+ const mappedSubProps = /* @__PURE__ */ new Set();
1220
+ if (arrayBaseName) {
1221
+ toPaths.forEach((path) => {
1222
+ if (typeof path !== "string") return;
1223
+ if (getArrayBasePath(path) !== arrayBaseName) return;
1224
+ const subProp = getArrayItemSubPath(path);
1225
+ if (subProp) mappedSubProps.add(subProp);
1226
+ });
1227
+ }
1228
+ const defaultValueFields = {};
1229
+ if (targetArrayField && targetArrayField.type === "array" && targetArrayField.arrayFields) {
1230
+ const arrayFields = targetArrayField.arrayFields;
1231
+ Object.entries(arrayFields).forEach(([key, fld]) => {
1232
+ if (mappedSubProps.has(key)) return;
1233
+ if (fld.type === "array" || fld.type === "object" || fld.type === "slot") return;
1234
+ defaultValueFields[key] = __spreadProps(__spreadValues({}, fld), { label: fld.label || key });
1235
+ });
1236
+ }
1237
+ const baseArrayFields = {
698
1238
  from: {
699
1239
  type: "select",
700
1240
  label: "From",
@@ -717,47 +1257,57 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
717
1257
  }))
718
1258
  ]
719
1259
  }
1260
+ };
1261
+ if (arrayBaseName && Object.keys(defaultValueFields).length > 0) {
1262
+ baseArrayFields.unmappedArrayItemDefaultValues = {
1263
+ type: "object",
1264
+ label: "Default Item Values",
1265
+ objectFields: defaultValueFields
1266
+ };
720
1267
  }
721
- };
1268
+ return {
1269
+ type: "array",
1270
+ label: "Dynamic Field Map",
1271
+ arrayFields: baseArrayFields
1272
+ };
1273
+ })();
722
1274
  }
723
1275
  fields = __spreadValues(__spreadValues({}, fields), defaultFields);
724
1276
  return fields;
725
1277
  });
726
1278
  },
727
1279
  resolveData: ({ props }, { lastData }) => {
728
- var _a2;
729
- const _map = props._map || [];
1280
+ const _map = (props._map || []).map((item) => {
1281
+ const newItem = __spreadValues({}, item);
1282
+ if (typeof newItem.unmappedArrayItemDefaultValues === "string") {
1283
+ try {
1284
+ newItem.unmappedArrayItemDefaultValues = JSON.parse(
1285
+ newItem.unmappedArrayItemDefaultValues
1286
+ );
1287
+ } catch (e) {
1288
+ newItem.unmappedArrayItemDefaultValues = {};
1289
+ }
1290
+ } else if (!newItem.unmappedArrayItemDefaultValues) {
1291
+ newItem.unmappedArrayItemDefaultValues = {};
1292
+ }
1293
+ return newItem;
1294
+ });
730
1295
  const readOnlyFields = _map.flatMap((item) => item.to);
1296
+ const readOnlyArrayBases = readOnlyFields.filter((field) => typeof field === "string").map(getArrayBasePath).filter((base) => base !== null);
731
1297
  if (_map.length) {
732
1298
  return {
733
- props,
734
- readOnly: readOnlyFields.reduce(
1299
+ props: __spreadProps(__spreadValues({}, props), { _map }),
1300
+ readOnly: [
1301
+ ...readOnlyFields.map((f) => String(f)),
1302
+ ...readOnlyArrayBases
1303
+ ].reduce(
735
1304
  (acc2, field) => __spreadProps(__spreadValues({}, acc2), { [field]: true }),
736
1305
  {}
737
1306
  )
738
1307
  };
739
1308
  }
740
- const prevMap = (_a2 = lastData == null ? void 0 : lastData.props) == null ? void 0 : _a2._map;
741
- if (prevMap && prevMap.length === 1) {
742
- const lastField = prevMap[0].to;
743
- if (typeof lastField === "string") {
744
- return {
745
- props,
746
- readOnly: { [lastField]: false }
747
- };
748
- }
749
- if (Array.isArray(lastField)) {
750
- return {
751
- props,
752
- readOnly: lastField.reduce(
753
- (acc2, field) => __spreadProps(__spreadValues({}, acc2), { [String(field)]: false }),
754
- {}
755
- )
756
- };
757
- }
758
- }
759
1309
  return {
760
- props,
1310
+ props: __spreadProps(__spreadValues({}, props), { _map }),
761
1311
  readOnly: {}
762
1312
  };
763
1313
  },
@@ -773,6 +1323,9 @@ var builderConfig = (config, overrides, editingComponent, showVersionFields = tr
773
1323
  categories: config.categories || {}
774
1324
  });
775
1325
 
1326
+ // src/puck/lib/soft-component-constants.ts
1327
+ var TECHNICAL_KEYS = /* @__PURE__ */ new Set(["_map", "_slot", "id", "_version"]);
1328
+
776
1329
  // src/puck/lib/strip-id.ts
777
1330
  var stripIdFromProps = (components, allowedTypes) => {
778
1331
  return components.map((component) => sanitizeComponent(component, allowedTypes));
@@ -796,7 +1349,7 @@ var sanitizeComponent = (component, allowedTypes) => {
796
1349
  var getSubComponents = (content, componentConfigs, fieldSettings, slots) => {
797
1350
  if (!content || !Array.isArray(content)) return [];
798
1351
  return content.map((componentProps) => {
799
- var _a, _b, _c;
1352
+ var _a, _b, _c, _d;
800
1353
  const componentConfig = componentConfigs[componentProps.type];
801
1354
  const enabledSlotNames = new Set(
802
1355
  (((_a = componentProps.props) == null ? void 0 : _a._slot) || []).map((s) => s.slot)
@@ -817,7 +1370,27 @@ var getSubComponents = (content, componentConfigs, fieldSettings, slots) => {
817
1370
  },
818
1371
  {}
819
1372
  ) || {};
820
- const fixedProps = __spreadValues(__spreadValues({}, componentConfig == null ? void 0 : componentConfig.defaultProps), componentProps.props);
1373
+ const map = ((_b = componentProps.props) == null ? void 0 : _b._map) || [];
1374
+ const mappedPaths = /* @__PURE__ */ new Set();
1375
+ map.forEach((item) => {
1376
+ const to = Array.isArray(item.to) ? item.to : [item.to];
1377
+ to.forEach((path) => {
1378
+ if (path) {
1379
+ if (isArrayMappingPath(path)) {
1380
+ const basePath = getArrayBasePath(path);
1381
+ if (basePath) mappedPaths.add(basePath);
1382
+ } else {
1383
+ mappedPaths.add(path);
1384
+ }
1385
+ }
1386
+ });
1387
+ });
1388
+ const fixedProps = Object.entries(__spreadValues(__spreadValues({}, componentConfig == null ? void 0 : componentConfig.defaultProps), componentProps.props)).reduce((acc, [key, value]) => {
1389
+ if (!TECHNICAL_KEYS.has(key) && !mappedPaths.has(key)) {
1390
+ acc[key] = value;
1391
+ }
1392
+ return acc;
1393
+ }, {});
821
1394
  (componentProps.props._slot || []).forEach(
822
1395
  (s) => {
823
1396
  var _a2;
@@ -831,19 +1404,34 @@ var getSubComponents = (content, componentConfigs, fieldSettings, slots) => {
831
1404
  }
832
1405
  );
833
1406
  const subComponent = {
834
- map: ((_b = componentProps.props) == null ? void 0 : _b._map) || [],
1407
+ map: ((_c = componentProps.props) == null ? void 0 : _c._map) || [],
835
1408
  fixedProps,
836
1409
  type: componentProps.type,
837
1410
  components,
838
- enabledSlots: ((_c = componentProps.props) == null ? void 0 : _c._slot) || []
1411
+ enabledSlots: ((_d = componentProps.props) == null ? void 0 : _d._slot) || []
839
1412
  };
840
1413
  return subComponent;
841
1414
  });
842
1415
  };
843
- var softFieldsToPuckFields = (fields, fieldSettings) => {
1416
+ var softFieldsToPuckFields = (fields, fieldSettings, customFields) => {
844
1417
  return (fields == null ? void 0 : fields.reduce(
845
1418
  (acc, field) => {
846
- var _a, _b, _c, _d, _e, _f, _g, _h;
1419
+ var _a, _b, _c, _d, _e, _f;
1420
+ const customFieldDefinition = resolveCustomFieldDefinition(
1421
+ field.type,
1422
+ customFields
1423
+ );
1424
+ const customReturnType = resolveCustomFieldReturnType(
1425
+ field.type,
1426
+ customFields
1427
+ );
1428
+ if (customFieldDefinition && customReturnType) {
1429
+ acc[field.name] = __spreadProps(__spreadValues({}, customFieldDefinition.field), {
1430
+ type: "custom",
1431
+ label: customFieldDefinition.field.label || field.name
1432
+ });
1433
+ return acc;
1434
+ }
847
1435
  switch (field.type) {
848
1436
  case "text":
849
1437
  case "textarea":
@@ -868,13 +1456,24 @@ var softFieldsToPuckFields = (fields, fieldSettings) => {
868
1456
  break;
869
1457
  // TODO: Default item props
870
1458
  case "array":
1459
+ const currentArraySettings = (fieldSettings == null ? void 0 : fieldSettings[field.name]) || {};
871
1460
  acc[field.name] = {
872
1461
  type: field.type,
873
1462
  label: field.name,
1463
+ min: currentArraySettings.min,
1464
+ max: currentArraySettings.max,
874
1465
  arrayFields: softFieldsToPuckFields(
875
- ((_e = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _e.subFields) || [],
876
- ((_f = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _f.subFieldSettings) || {}
877
- )
1466
+ currentArraySettings.subFields || [],
1467
+ currentArraySettings.subFieldSettings || {},
1468
+ customFields
1469
+ ),
1470
+ defaultItemProps: buildArrayDefaultItemProps(
1471
+ currentArraySettings.subFields,
1472
+ currentArraySettings.subFieldSettings
1473
+ ),
1474
+ getItemSummary(item, index) {
1475
+ return getArrayItemSummary(item, index, currentArraySettings);
1476
+ }
878
1477
  };
879
1478
  break;
880
1479
  // TODO: Needs testing to see if it works
@@ -883,8 +1482,9 @@ var softFieldsToPuckFields = (fields, fieldSettings) => {
883
1482
  type: field.type,
884
1483
  label: field.name,
885
1484
  objectFields: softFieldsToPuckFields(
886
- ((_g = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _g.subFields) || [],
887
- ((_h = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _h.subFieldSettings) || {}
1485
+ ((_e = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _e.subFields) || [],
1486
+ ((_f = fieldSettings == null ? void 0 : fieldSettings[field.name]) == null ? void 0 : _f.subFieldSettings) || {},
1487
+ customFields
888
1488
  )
889
1489
  };
890
1490
  break;
@@ -896,11 +1496,34 @@ var softFieldsToPuckFields = (fields, fieldSettings) => {
896
1496
  {}
897
1497
  )) || {};
898
1498
  };
899
- var softComponentFromAppState = (appState, configComponents, editedItem, metadata) => {
1499
+ var softComponentFromAppState = (appState, configComponents, editedItem, metadata, customFields) => {
900
1500
  var _a;
901
1501
  const rootProps = ((_a = appState.data.root) == null ? void 0 : _a.props) || {};
902
1502
  const fields = rootProps._fields || [];
903
1503
  const field_settings = rootProps._fieldSettings || {};
1504
+ const normalizedFieldSettings = __spreadValues({}, field_settings);
1505
+ (fields || []).forEach((field) => {
1506
+ const customFieldDefinition = resolveCustomFieldDefinition(
1507
+ field.type,
1508
+ customFields
1509
+ );
1510
+ const customReturnType = resolveCustomFieldReturnType(
1511
+ field.type,
1512
+ customFields
1513
+ );
1514
+ if (!customFieldDefinition || !customReturnType) {
1515
+ return;
1516
+ }
1517
+ const schema = resolveCustomFieldSchema(field.type, customFields);
1518
+ const existingSettings = normalizedFieldSettings[field.name] || {};
1519
+ normalizedFieldSettings[field.name] = __spreadValues(__spreadProps(__spreadValues({}, existingSettings), {
1520
+ customFieldType: field.type,
1521
+ customFieldReturnType: customReturnType
1522
+ }), schema ? {
1523
+ subFields: schema.subFields,
1524
+ subFieldSettings: schema.subFieldSettings
1525
+ } : {});
1526
+ });
904
1527
  const builtInRootProps = /* @__PURE__ */ new Set([
905
1528
  "_name",
906
1529
  "_category",
@@ -920,12 +1543,22 @@ var softComponentFromAppState = (appState, configComponents, editedItem, metadat
920
1543
  const components = getSubComponents(
921
1544
  [editedItem],
922
1545
  configComponents,
923
- field_settings,
1546
+ normalizedFieldSettings,
924
1547
  slots
925
1548
  );
926
- const defaultProps = __spreadValues(__spreadValues({}, Object.keys(field_settings).reduce(
1549
+ const defaultProps = __spreadValues(__spreadValues({}, Object.keys(normalizedFieldSettings).reduce(
927
1550
  (acc, field) => {
928
- acc[field] = field_settings[field].defaultValue;
1551
+ var _a2;
1552
+ const fieldDefinition = (fields || []).find((item) => item.name === field);
1553
+ const customFieldReturnType = (_a2 = normalizedFieldSettings[field]) == null ? void 0 : _a2.customFieldReturnType;
1554
+ if ((fieldDefinition == null ? void 0 : fieldDefinition.type) === "array" || customFieldReturnType === "array") {
1555
+ acc[field] = normalizedFieldSettings[field].defaultValue !== void 0 ? normalizedFieldSettings[field].defaultValue : buildArrayDefaultValue(
1556
+ normalizedFieldSettings[field].subFields,
1557
+ normalizedFieldSettings[field].subFieldSettings
1558
+ );
1559
+ return acc;
1560
+ }
1561
+ acc[field] = normalizedFieldSettings[field].defaultValue;
929
1562
  return acc;
930
1563
  },
931
1564
  {}
@@ -934,11 +1567,11 @@ var softComponentFromAppState = (appState, configComponents, editedItem, metadat
934
1567
  {
935
1568
  name: metadata.name,
936
1569
  category: metadata.category,
937
- fields: __spreadValues(__spreadValues({}, softFieldsToPuckFields(fields, field_settings)), Object.keys(slots).reduce((acc, slot) => {
1570
+ fields: __spreadValues(__spreadValues({}, softFieldsToPuckFields(fields, normalizedFieldSettings, customFields)), Object.keys(slots).reduce((acc, slot) => {
938
1571
  acc[slot] = { type: "slot", label: slot };
939
1572
  return acc;
940
1573
  }, {})),
941
- fieldSettings: field_settings,
1574
+ fieldSettings: normalizedFieldSettings,
942
1575
  defaultProps,
943
1576
  rootProps: customRootProps,
944
1577
  components,
@@ -953,34 +1586,74 @@ import { v4 as uuidv4 } from "uuid";
953
1586
  var generateId = (type) => type ? `${type}-${uuidv4()}` : uuidv4();
954
1587
 
955
1588
  // src/puck/lib/component-key.ts
956
- var defaultToCamelCase = (value) => {
957
- const tokens = value.trim().replace(/[^a-zA-Z0-9\s_-]/g, " ").split(/[\s_-]+/).filter(Boolean);
958
- if (tokens.length === 0) return "";
959
- const [first, ...rest] = tokens;
960
- return `${first.toLowerCase()}${rest.map((token) => token.charAt(0).toUpperCase() + token.slice(1).toLowerCase()).join("")}`;
1589
+ var toSlug = (value) => {
1590
+ 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, "");
1591
+ };
1592
+ var defaultComponentNameToKey = (displayName, context) => {
1593
+ var _a, _b;
1594
+ const registry = (_b = (_a = context.registryName) != null ? _a : context.registry) != null ? _b : "default";
1595
+ return `${toSlug(registry)}/${toSlug(displayName)}`;
1596
+ };
1597
+ var defaultComponentKeyToName = (key) => {
1598
+ const slashIndex = key.indexOf("/");
1599
+ const componentPart = slashIndex === -1 ? key : key.slice(slashIndex + 1);
1600
+ if (!componentPart) return "";
1601
+ return componentPart.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
961
1602
  };
962
1603
  var createComponentKeyFromName = (displayName, overrides, context) => {
963
- const key = overrides.componentNameToKey ? overrides.componentNameToKey(displayName, context) : defaultToCamelCase(displayName);
1604
+ const key = overrides.componentNameToKey ? overrides.componentNameToKey(displayName, context) : defaultComponentNameToKey(displayName, context);
964
1605
  return key.trim();
965
1606
  };
966
1607
  var getComponentNameFromKey = (key, overrides) => {
967
- if (overrides.componentKeyToName) {
1608
+ if (overrides == null ? void 0 : overrides.componentKeyToName) {
968
1609
  return overrides.componentKeyToName(key);
969
1610
  }
970
- return key;
1611
+ return defaultComponentKeyToName(key);
971
1612
  };
972
1613
 
973
1614
  // src/puck/lib/soft-component-to-appstate.ts
974
- var puckFieldsToSoftFields = (fields, slots) => {
1615
+ var mergeFieldSettings = (generated = {}, persisted = {}) => {
1616
+ return Object.entries(persisted).reduce((acc, [fieldName, value]) => {
1617
+ const current = acc[fieldName] || {};
1618
+ acc[fieldName] = __spreadProps(__spreadValues(__spreadValues({}, current), value), {
1619
+ subFieldSettings: current.subFieldSettings || (value == null ? void 0 : value.subFieldSettings) ? mergeFieldSettings(
1620
+ current.subFieldSettings || {},
1621
+ (value == null ? void 0 : value.subFieldSettings) || {}
1622
+ ) : void 0
1623
+ });
1624
+ return acc;
1625
+ }, __spreadValues({}, generated));
1626
+ };
1627
+ var puckFieldsToSoftFields = (fields, slots, persistedFieldSettings = {}, customFields) => {
975
1628
  const softFields = [];
976
1629
  const fieldSettings = {};
977
1630
  Object.entries(fields).forEach(([fieldName, field]) => {
1631
+ var _a;
1632
+ const persistedSettings = persistedFieldSettings == null ? void 0 : persistedFieldSettings[fieldName];
1633
+ const fieldWithMeta = field;
1634
+ const customFieldType = fieldWithMeta.customFieldType || (persistedSettings == null ? void 0 : persistedSettings.customFieldType);
1635
+ 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);
978
1636
  if (slots.has(fieldName)) {
979
1637
  return;
980
1638
  }
981
1639
  if (fieldName === "_version") {
982
1640
  return;
983
1641
  }
1642
+ if (field.type === "custom" && customFieldType) {
1643
+ softFields.push({ name: fieldName, type: customFieldType });
1644
+ const customSchema = resolveCustomFieldSchema(customFieldType, customFields);
1645
+ fieldSettings[fieldName] = __spreadValues(__spreadProps(__spreadValues({}, persistedSettings || {}), {
1646
+ customFieldType,
1647
+ customFieldReturnType
1648
+ }), customSchema ? {
1649
+ subFields: customSchema.subFields,
1650
+ subFieldSettings: customSchema.subFieldSettings
1651
+ } : {});
1652
+ if (!Object.prototype.hasOwnProperty.call(fieldSettings[fieldName], "defaultValue")) {
1653
+ fieldSettings[fieldName].defaultValue = void 0;
1654
+ }
1655
+ return;
1656
+ }
984
1657
  switch (field.type) {
985
1658
  case "text":
986
1659
  case "textarea":
@@ -998,67 +1671,81 @@ var puckFieldsToSoftFields = (fields, slots) => {
998
1671
  case "radio":
999
1672
  softFields.push({ name: fieldName, type: field.type });
1000
1673
  fieldSettings[fieldName] = {
1001
- options: field.options || []
1674
+ options: field.options ? [...field.options] : []
1002
1675
  };
1003
1676
  break;
1004
1677
  case "array":
1005
1678
  softFields.push({ name: fieldName, type: "array" });
1006
1679
  const arrayFieldsResult = puckFieldsToSoftFields(
1007
1680
  field.arrayFields || {},
1008
- /* @__PURE__ */ new Set()
1681
+ /* @__PURE__ */ new Set(),
1682
+ persistedSettings == null ? void 0 : persistedSettings.subFieldSettings,
1683
+ customFields
1009
1684
  );
1010
- fieldSettings[fieldName] = {
1685
+ fieldSettings[fieldName] = __spreadProps(__spreadValues({}, persistedSettings || {}), {
1011
1686
  subFields: arrayFieldsResult.fields,
1012
1687
  subFieldSettings: arrayFieldsResult.fieldSettings
1013
- };
1688
+ });
1014
1689
  break;
1015
1690
  case "object":
1016
1691
  softFields.push({ name: fieldName, type: "object" });
1017
1692
  const objectFieldsResult = puckFieldsToSoftFields(
1018
1693
  field.objectFields || {},
1019
- /* @__PURE__ */ new Set()
1694
+ /* @__PURE__ */ new Set(),
1695
+ persistedSettings == null ? void 0 : persistedSettings.subFieldSettings,
1696
+ customFields
1020
1697
  );
1021
- fieldSettings[fieldName] = {
1698
+ fieldSettings[fieldName] = __spreadProps(__spreadValues({}, persistedSettings || {}), {
1022
1699
  subFields: objectFieldsResult.fields,
1023
1700
  subFieldSettings: objectFieldsResult.fieldSettings
1024
- };
1701
+ });
1025
1702
  break;
1026
1703
  default:
1027
1704
  softFields.push({ name: fieldName, type: "text" });
1028
1705
  }
1029
- if (fieldSettings[fieldName]) {
1030
- fieldSettings[fieldName].defaultValue = void 0;
1031
- } else {
1032
- fieldSettings[fieldName] = { defaultValue: void 0 };
1033
- }
1706
+ fieldSettings[fieldName] = __spreadProps(__spreadValues({}, fieldSettings[fieldName] || persistedSettings || {}), {
1707
+ defaultValue: Object.prototype.hasOwnProperty.call(
1708
+ fieldSettings[fieldName] || persistedSettings || {},
1709
+ "defaultValue"
1710
+ ) ? (fieldSettings[fieldName] || persistedSettings || {}).defaultValue : void 0
1711
+ });
1034
1712
  });
1035
1713
  return { fields: softFields, fieldSettings };
1036
1714
  };
1037
1715
  var reconstructComponents = (subComponents, componentConfigs, softComponentProps) => {
1038
1716
  return subComponents.map((subComponent) => {
1039
- var _a;
1040
- const props = __spreadValues({}, subComponent.fixedProps);
1041
- (_a = subComponent.map) == null ? void 0 : _a.forEach((mapItem, i) => {
1042
- var _a2;
1043
- const { from, to, transform } = mapItem || {};
1044
- const fromPaths = Array.isArray(from) ? from : from ? [from] : [];
1045
- const toPaths = Array.isArray(to) ? to : to ? [to] : [];
1046
- const inputs = fromPaths.map(
1047
- (path) => getFieldSettingsByPath(softComponentProps || {}, path)
1048
- );
1049
- const runner = transform;
1050
- const result = runner ? runner(inputs, softComponentProps) : inputs[0];
1051
- if (Array.isArray(result)) {
1052
- result.forEach((val, idx) => {
1053
- if (toPaths[idx]) setPropertyByPath(props, toPaths[idx], val);
1717
+ const componentConfig = componentConfigs[subComponent.type];
1718
+ const props = __spreadProps(__spreadValues({}, subComponent.fixedProps), {
1719
+ _map: subComponent.map
1720
+ });
1721
+ const arrayDefaults = (subComponent.map || []).reduce(
1722
+ (acc, mapEntry) => {
1723
+ const toPaths = Array.isArray(mapEntry.to) ? mapEntry.to : [mapEntry.to];
1724
+ toPaths.forEach((path) => {
1725
+ var _a;
1726
+ if (typeof path !== "string" || !isArrayMappingPath(path)) return;
1727
+ const arrayBase = getArrayBasePath(path);
1728
+ if (!arrayBase || acc[arrayBase]) return;
1729
+ const defaultValue = (_a = componentConfig == null ? void 0 : componentConfig.defaultProps) == null ? void 0 : _a[arrayBase];
1730
+ if (Array.isArray(defaultValue)) acc[arrayBase] = defaultValue;
1054
1731
  });
1055
- } else {
1056
- toPaths.forEach((toPath) => setPropertyByPath(props, toPath, result));
1057
- }
1058
- if (transform && ((_a2 = props._map) == null ? void 0 : _a2[i])) {
1059
- props._map[i].transform = transform;
1732
+ return acc;
1733
+ },
1734
+ {}
1735
+ );
1736
+ const sourceProps = __spreadValues(__spreadValues(__spreadValues({}, (componentConfig == null ? void 0 : componentConfig.defaultProps) || {}), softComponentProps), props);
1737
+ const { newProps } = applyMapping(
1738
+ props,
1739
+ {},
1740
+ // fieldSettings not needed for "propsFirst" mode as it resolves from propsFirst
1741
+ subComponent.map || [],
1742
+ "propsFirst",
1743
+ {
1744
+ sourceProps,
1745
+ arrayDefaults
1060
1746
  }
1061
- });
1747
+ );
1748
+ Object.assign(props, newProps);
1062
1749
  if (subComponent.enabledSlots.length > 0) {
1063
1750
  props._slot = subComponent.enabledSlots;
1064
1751
  subComponent.enabledSlots.forEach(({ slot, name }) => {
@@ -1088,24 +1775,41 @@ var reconstructComponents = (subComponents, componentConfigs, softComponentProps
1088
1775
  return componentData;
1089
1776
  });
1090
1777
  };
1091
- var softComponentToAppState = (softComponent, componentName, version, versions, componentProps, componentConfigs, overrides, displayName, category) => {
1778
+ var softComponentToAppState = (softComponent, componentName, version, versions, componentProps, componentConfigs, overrides, displayName, category, customFields) => {
1092
1779
  const slots = new Set(Object.keys(softComponent.slots));
1093
1780
  const { fields, fieldSettings } = puckFieldsToSoftFields(
1094
1781
  softComponent.fields,
1095
- slots
1782
+ slots,
1783
+ softComponent.fieldSettings,
1784
+ customFields
1096
1785
  );
1786
+ const mergedFieldSettings = mergeFieldSettings(
1787
+ fieldSettings,
1788
+ softComponent.fieldSettings || {}
1789
+ ) || {};
1097
1790
  Object.entries(softComponent.defaultProps).forEach(([key, value]) => {
1098
- if (fieldSettings && fieldSettings[key] && !slots.has(key)) {
1099
- fieldSettings[key].defaultValue = value;
1791
+ if (mergedFieldSettings && mergedFieldSettings[key] && !slots.has(key)) {
1792
+ mergedFieldSettings[key].defaultValue = value;
1100
1793
  }
1101
1794
  });
1795
+ (fields || []).forEach((field) => {
1796
+ if (field.type !== "array" || slots.has(field.name)) return;
1797
+ const settings = mergedFieldSettings[field.name] || {};
1798
+ if (settings.defaultValue === void 0) {
1799
+ settings.defaultValue = buildArrayDefaultValue(
1800
+ settings.subFields,
1801
+ settings.subFieldSettings
1802
+ );
1803
+ }
1804
+ mergedFieldSettings[field.name] = settings;
1805
+ });
1102
1806
  let rootProps = __spreadValues({
1103
1807
  _name: displayName || getComponentNameFromKey(componentName, overrides),
1104
1808
  _category: category,
1105
1809
  _version: version,
1106
1810
  _versions: versions,
1107
1811
  _fields: fields,
1108
- _fieldSettings: fieldSettings
1812
+ _fieldSettings: mergedFieldSettings
1109
1813
  }, softComponent.rootProps || {});
1110
1814
  if (overrides.onRemodel) {
1111
1815
  rootProps = __spreadValues(__spreadValues({}, rootProps), overrides.onRemodel(componentName));
@@ -1131,12 +1835,12 @@ var rootZone = "default-zone";
1131
1835
  var rootDroppableId = `${rootAreaId}:${rootZone}`;
1132
1836
 
1133
1837
  // src/puck/components/soft-render/index.tsx
1134
- import React2, { useMemo, memo } from "react";
1135
- import equal from "react-fast-compare";
1838
+ import React3, { useMemo, memo } from "react";
1839
+ import equal3 from "react-fast-compare";
1136
1840
  import { Fragment as Fragment2, jsx as jsx5 } from "react/jsx-runtime";
1137
1841
  function isPlainObject(val) {
1138
1842
  if (typeof val !== "object" || val === null) return false;
1139
- if (React2.isValidElement(val)) return false;
1843
+ if (React3.isValidElement(val)) return false;
1140
1844
  if ("$$typeof" in val) return false;
1141
1845
  const proto = Object.getPrototypeOf(val);
1142
1846
  return proto === Object.prototype || proto === null;
@@ -1171,28 +1875,19 @@ var SubComponentRenderer = memo(
1171
1875
  if (!componentConfig) return {};
1172
1876
  const clonedProps = cloneData(subComponent.fixedProps || {});
1173
1877
  if ((_a = subComponent.map) == null ? void 0 : _a.length) {
1174
- subComponent.map.forEach((mapItem) => {
1175
- const { from, to, transform } = mapItem || {};
1176
- const fromPaths = Array.isArray(from) ? from : from ? [from] : [];
1177
- const toPaths = Array.isArray(to) ? to : to ? [to] : [];
1178
- const inputValues = fromPaths.map((f) => {
1179
- const propValue = getFieldSettingsByPath(props, f);
1180
- if (propValue !== void 0) return propValue;
1181
- const setting = getFieldSettingsByPath(softComponentFieldSettings || {}, f);
1182
- if (setting && Object.prototype.hasOwnProperty.call(setting, "defaultValue")) {
1183
- return setting.defaultValue;
1184
- }
1185
- return propValue;
1186
- });
1187
- const result = transform ? transform(inputValues, props) : inputValues[0];
1188
- if (Array.isArray(result)) {
1189
- result.forEach(
1190
- (val, i) => toPaths[i] && setPropertyByPath(clonedProps, toPaths[i], val)
1191
- );
1192
- } else if (toPaths[0]) {
1193
- setPropertyByPath(clonedProps, toPaths[0], result);
1878
+ const mergedInput = __spreadValues(__spreadValues({}, clonedProps), props);
1879
+ const { newProps } = applyMapping(
1880
+ mergedInput,
1881
+ softComponentFieldSettings || {},
1882
+ subComponent.map,
1883
+ "propsFirst"
1884
+ );
1885
+ const parentKeys = new Set(Object.keys(props));
1886
+ for (const [key, value] of Object.entries(newProps)) {
1887
+ if (!parentKeys.has(key) || key in clonedProps) {
1888
+ clonedProps[key] = value;
1194
1889
  }
1195
- });
1890
+ }
1196
1891
  }
1197
1892
  Object.entries(componentConfig.fields || {}).forEach(
1198
1893
  ([slotKey, field]) => {
@@ -1253,7 +1948,7 @@ var SubComponentRenderer = memo(
1253
1948
  // and on props (the primary driver of field-mapping changes).
1254
1949
  // configComponents and softComponentFields are treated as stable config
1255
1950
  // references — reference equality is intentional and fast here.
1256
- (prev, next) => prev.depth === next.depth && prev.index === next.index && prev.configComponents === next.configComponents && prev.softComponentFields === next.softComponentFields && equal(prev.props, next.props) && equal(prev.subComponent, next.subComponent) && equal(prev.softComponentFieldSettings, next.softComponentFieldSettings)
1951
+ (prev, next) => prev.depth === next.depth && prev.index === next.index && prev.configComponents === next.configComponents && prev.softComponentFields === next.softComponentFields && equal3(prev.props, next.props) && equal3(prev.subComponent, next.subComponent) && equal3(prev.softComponentFieldSettings, next.softComponentFieldSettings)
1257
1952
  );
1258
1953
  SubComponentRenderer.displayName = "SubComponentRenderer";
1259
1954
  var SoftRender = memo(
@@ -1287,16 +1982,34 @@ var SoftRender = memo(
1287
1982
  // configComponents / softComponentFields: reference equality (stable config).
1288
1983
  // softComponentFieldSettings: deep equality (may carry dynamic defaults).
1289
1984
  // props / softSubComponent: deep equality (primary render drivers).
1290
- (prev, next) => prev.configComponents === next.configComponents && prev.softComponentFields === next.softComponentFields && equal(prev.props, next.props) && equal(prev.softSubComponent, next.softSubComponent) && equal(prev.softComponentFieldSettings, next.softComponentFieldSettings)
1985
+ (prev, next) => prev.configComponents === next.configComponents && prev.softComponentFields === next.softComponentFields && equal3(prev.props, next.props) && equal3(prev.softSubComponent, next.softSubComponent) && equal3(prev.softComponentFieldSettings, next.softComponentFieldSettings)
1291
1986
  );
1292
1987
  SoftRender.displayName = "SoftRender";
1293
1988
 
1294
1989
  // src/puck/lib/create-versioned-component-config.tsx
1295
1990
  import { jsx as jsx6 } from "react/jsx-runtime";
1296
- var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true) => {
1991
+ var hydrateCustomField = (fieldName, field, fieldSettings, customFields) => {
1992
+ var _a;
1993
+ if (field.type !== "custom") {
1994
+ return field;
1995
+ }
1996
+ const fieldWithMeta = field;
1997
+ const customFieldType = fieldWithMeta.customFieldType || ((_a = fieldSettings == null ? void 0 : fieldSettings[fieldName]) == null ? void 0 : _a.customFieldType);
1998
+ if (!customFieldType) {
1999
+ return field;
2000
+ }
2001
+ const customField = customFields == null ? void 0 : customFields[customFieldType];
2002
+ if (!customField) {
2003
+ return field;
2004
+ }
2005
+ return __spreadProps(__spreadValues(__spreadValues({}, field), customField.field), {
2006
+ type: "custom",
2007
+ label: field.label || customField.field.label || fieldName
2008
+ });
2009
+ };
2010
+ var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true, customFields, overrides) => {
1297
2011
  var _a, _b;
1298
- const softConfig = config;
1299
- return {
2012
+ const baseConfig = {
1300
2013
  label: displayName,
1301
2014
  fields: Object.fromEntries(
1302
2015
  (Object.entries(
@@ -1321,7 +2034,12 @@ var createVersionedComponentConfig = (componentName, displayName, version, allVe
1321
2034
  };
1322
2035
  }
1323
2036
  Object.entries((versionedComponent == null ? void 0 : versionedComponent.fields) || {}).filter(([, field]) => field.type !== "slot").forEach(([key, field]) => {
1324
- fields[key] = field;
2037
+ fields[key] = hydrateCustomField(
2038
+ key,
2039
+ field,
2040
+ versionedComponent == null ? void 0 : versionedComponent.fieldSettings,
2041
+ customFields
2042
+ );
1325
2043
  });
1326
2044
  return fields;
1327
2045
  },
@@ -1335,12 +2053,16 @@ var createVersionedComponentConfig = (componentName, displayName, version, allVe
1335
2053
  softComponentFields: versionedComponent.fields,
1336
2054
  softComponentFieldSettings: versionedComponent.fieldSettings,
1337
2055
  softSubComponent: versionedComponent.components,
1338
- configComponents: softConfig.components,
2056
+ configComponents: config.components,
1339
2057
  props
1340
2058
  }
1341
2059
  );
1342
2060
  }
1343
2061
  };
2062
+ if (overrides == null ? void 0 : overrides.mapComponentConfig) {
2063
+ return __spreadValues(__spreadValues({}, baseConfig), overrides.mapComponentConfig(componentName, baseConfig));
2064
+ }
2065
+ return baseConfig;
1344
2066
  };
1345
2067
 
1346
2068
  // src/puck/lib/builder/sub-component-decomposer.tsx
@@ -1348,21 +2070,16 @@ var subComponentDecomposer = (componentRootData, softSubComponent) => {
1348
2070
  var _a;
1349
2071
  const resolvedProps = __spreadValues({}, softSubComponent.fixedProps);
1350
2072
  (_a = softSubComponent.map) == null ? void 0 : _a.forEach((mapItem) => {
1351
- const { from, to, transform } = mapItem || {};
1352
- const fromPaths = Array.isArray(from) ? from : from ? [from] : [];
1353
- const toPaths = Array.isArray(to) ? to : to ? [to] : [];
1354
- const inputs = fromPaths.map(
1355
- (path) => getFieldSettingsByPath(componentRootData.props || {}, path)
2073
+ const { newProps } = applyMapping(
2074
+ resolvedProps,
2075
+ {},
2076
+ [mapItem],
2077
+ "propsFirst",
2078
+ {
2079
+ sourceProps: componentRootData.props || {}
2080
+ }
1356
2081
  );
1357
- const runner = transform;
1358
- const result = runner ? runner(inputs, componentRootData.props) : inputs[0];
1359
- if (Array.isArray(result)) {
1360
- result.forEach((val, idx) => {
1361
- if (toPaths[idx]) setPropertyByPath(resolvedProps, toPaths[idx], val);
1362
- });
1363
- } else if (toPaths[0]) {
1364
- setPropertyByPath(resolvedProps, toPaths[0], result);
1365
- }
2082
+ Object.assign(resolvedProps, newProps);
1366
2083
  });
1367
2084
  softSubComponent.enabledSlots.forEach(({ slot, name }) => {
1368
2085
  var _a2, _b;
@@ -1385,9 +2102,22 @@ var subComponentDecomposer = (componentRootData, softSubComponent) => {
1385
2102
  return accItem;
1386
2103
  };
1387
2104
 
2105
+ // src/puck/lib/builder/resolve-soft-component-data.ts
2106
+ var resolveSoftComponentData = (props, _fieldSettings = {}) => {
2107
+ const map = props._map;
2108
+ if (!(map == null ? void 0 : map.length)) return __spreadValues({}, props);
2109
+ const { newProps } = applyMapping(
2110
+ props,
2111
+ _fieldSettings,
2112
+ map,
2113
+ "propsFirst"
2114
+ );
2115
+ return newProps;
2116
+ };
2117
+
1388
2118
  // src/puck/lib/decompose-soft-component.ts
1389
- function decomposeSoftComponent(componentData, softComponents) {
1390
- var _a, _b;
2119
+ function decomposeSoftComponent(componentData, softComponents, fieldSettings) {
2120
+ var _a, _b, _c, _d;
1391
2121
  if (!(componentData == null ? void 0 : componentData.type) || !(componentData == null ? void 0 : componentData.props.id)) {
1392
2122
  throw new Error("Component data must have type and id to decompose.");
1393
2123
  }
@@ -1398,9 +2128,19 @@ function decomposeSoftComponent(componentData, softComponents) {
1398
2128
  `Soft component "${componentData.type}" version "${version}" not found.`
1399
2129
  );
1400
2130
  }
2131
+ let resolvedComponentData = componentData;
2132
+ if (fieldSettings && ((_d = (_c = componentData.props) == null ? void 0 : _c._map) == null ? void 0 : _d.length)) {
2133
+ const resolvedProps = resolveSoftComponentData(
2134
+ componentData.props,
2135
+ fieldSettings
2136
+ );
2137
+ resolvedComponentData = __spreadProps(__spreadValues({}, componentData), {
2138
+ props: resolvedProps
2139
+ });
2140
+ }
1401
2141
  const decomposedComponentData = softComponent.components.map(
1402
2142
  (softSubComponent) => {
1403
- return subComponentDecomposer(componentData, softSubComponent);
2143
+ return subComponentDecomposer(resolvedComponentData, softSubComponent);
1404
2144
  }
1405
2145
  );
1406
2146
  return decomposedComponentData;
@@ -1470,7 +2210,14 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1470
2210
  });
1471
2211
  const config = __spreadValues({}, get().softConfig);
1472
2212
  const overrides = get().overrides;
1473
- const buildConfig = builderConfig(config, overrides, void 0, get().showVersionFields);
2213
+ const buildConfig = builderConfig(
2214
+ config,
2215
+ overrides,
2216
+ void 0,
2217
+ get().showVersionFields,
2218
+ void 0,
2219
+ get().customFields
2220
+ );
1474
2221
  const editableIds = /* @__PURE__ */ new Set([selectedItem.props.id]);
1475
2222
  const initialContent = [__spreadValues({}, selectedItem)];
1476
2223
  walkTree3(
@@ -1544,12 +2291,20 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1544
2291
  get().softConfig.components,
1545
2292
  get().overrides,
1546
2293
  (softComponentMeta == null ? void 0 : softComponentMeta.name) || softComponentName,
1547
- softComponentMeta == null ? void 0 : softComponentMeta.category
2294
+ softComponentMeta == null ? void 0 : softComponentMeta.category,
2295
+ get().customFields
1548
2296
  );
1549
2297
  const config = __spreadValues({}, get().softConfig);
1550
2298
  const overrides = get().overrides;
1551
2299
  const dependents = get().dependencyGraph.get(softComponentName) || /* @__PURE__ */ new Set();
1552
- const buildConfig = builderConfig(config, overrides, softComponentName, get().showVersionFields, dependents);
2300
+ const buildConfig = builderConfig(
2301
+ config,
2302
+ overrides,
2303
+ softComponentName,
2304
+ get().showVersionFields,
2305
+ dependents,
2306
+ get().customFields
2307
+ );
1553
2308
  const editableIds = /* @__PURE__ */ new Set([]);
1554
2309
  const decomposedComponents = get().builder.decompose(selectedItem);
1555
2310
  walkTree3(
@@ -1776,7 +2531,8 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1776
2531
  {
1777
2532
  name: displayName,
1778
2533
  category
1779
- }
2534
+ },
2535
+ get().customFields
1780
2536
  );
1781
2537
  const existingComponent = get().softComponents[componentName];
1782
2538
  const allVersions = Object.keys((existingComponent == null ? void 0 : existingComponent.versions) || {});
@@ -1795,7 +2551,8 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1795
2551
  })
1796
2552
  }),
1797
2553
  softComponent.defaultProps,
1798
- get().showVersionFields
2554
+ get().showVersionFields,
2555
+ get().customFields
1799
2556
  );
1800
2557
  get().setSoftComponent(componentName, version, softComponent);
1801
2558
  return [newSoftComponentConfig, version];
@@ -1849,7 +2606,8 @@ var createBuildersSlice = (set, get, initialConfig) => ({
1849
2606
  get().softConfig.components,
1850
2607
  get().overrides,
1851
2608
  (softComponentMeta == null ? void 0 : softComponentMeta.name) || componentName,
1852
- softComponentMeta == null ? void 0 : softComponentMeta.category
2609
+ softComponentMeta == null ? void 0 : softComponentMeta.category,
2610
+ get().customFields
1853
2611
  );
1854
2612
  puckDispatch({
1855
2613
  type: "setData",
@@ -1996,7 +2754,7 @@ function topologicalSort(softComponents, hardComponentNames) {
1996
2754
  }
1997
2755
  return sorted;
1998
2756
  }
1999
- function buildInitialSoftComponents(hardConfig, softComponents, overrides, showVersioning = false) {
2757
+ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showVersioning = false, customFields) {
2000
2758
  var _a, _b;
2001
2759
  if (!softComponents || Object.keys(softComponents).length === 0) {
2002
2760
  return {};
@@ -2032,7 +2790,9 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
2032
2790
  // Pass the accumulating config
2033
2791
  hydratedSoftComponents,
2034
2792
  versionedComponent.defaultProps,
2035
- showVersioning
2793
+ showVersioning,
2794
+ customFields,
2795
+ overrides
2036
2796
  );
2037
2797
  componentConfigs[name] = newSoftComponentConfig;
2038
2798
  buildingConfig.components[name] = newSoftComponentConfig;
@@ -2060,7 +2820,9 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
2060
2820
  hardConfig,
2061
2821
  hydratedSoftComponents,
2062
2822
  versionedComponent.defaultProps,
2063
- showVersioning
2823
+ showVersioning,
2824
+ customFields,
2825
+ overrides
2064
2826
  );
2065
2827
  componentConfigs[name] = newSoftComponentConfig;
2066
2828
  }
@@ -2126,9 +2888,9 @@ var clearEditVisibility = (doc) => {
2126
2888
  // src/puck/store/index.tsx
2127
2889
  var createSoftConfigStore = (hardConfig = {
2128
2890
  components: {}
2129
- }, softComponents = {}, overrides = {}, onActions, showVersionFields = true) => {
2891
+ }, softComponents = {}, overrides = {}, onActions, showVersionFields = true, customFields = {}) => {
2130
2892
  const normalizedSoftComponents = Object.fromEntries(
2131
- Object.entries(softComponents || {}).map(([key, value]) => [
2893
+ Object.entries(softComponents || {}).filter(([key]) => !hardConfig.components || !hardConfig.components[key]).map(([key, value]) => [
2132
2894
  key,
2133
2895
  __spreadProps(__spreadValues({}, value), {
2134
2896
  name: value.name || key
@@ -2149,6 +2911,7 @@ var createSoftConfigStore = (hardConfig = {
2149
2911
  state: "ready",
2150
2912
  originalHistory: [],
2151
2913
  overrides,
2914
+ customFields,
2152
2915
  onActions,
2153
2916
  iframeDocRef,
2154
2917
  showVersionFields,
@@ -2190,11 +2953,17 @@ var createSoftConfigStore = (hardConfig = {
2190
2953
  components: __spreadValues(__spreadValues({}, hardConfig.components), buildInitialSoftComponents(
2191
2954
  hardConfig,
2192
2955
  hydratedSoftComponents,
2193
- overrides
2956
+ overrides,
2957
+ showVersionFields,
2958
+ customFields
2194
2959
  )),
2195
2960
  categories: __spreadValues({}, hardConfig.categories || {})
2196
2961
  }),
2197
2962
  setSoftComponent: (name, version, component) => {
2963
+ if (hardConfig.components && hardConfig.components[name]) {
2964
+ console.warn(`Cannot set soft component "${name}" because it conflicts with a base hardConfig component.`);
2965
+ return;
2966
+ }
2198
2967
  const existing = get().softComponents[name];
2199
2968
  set((state) => {
2200
2969
  var _a, _b;
@@ -2217,6 +2986,9 @@ var createSoftConfigStore = (hardConfig = {
2217
2986
  const nextSoftComponents = __spreadValues({}, state.softComponents);
2218
2987
  const nextConfigComponents = __spreadValues({}, state.softConfig.components);
2219
2988
  Object.entries(incomingComponents).forEach(([name, data]) => {
2989
+ if (hardConfig.components && hardConfig.components[name]) {
2990
+ return;
2991
+ }
2220
2992
  const existing = nextSoftComponents[name];
2221
2993
  const finalComponentData = existing ? __spreadProps(__spreadValues(__spreadValues({}, existing), data), {
2222
2994
  name: data.name || existing.name || name,
@@ -2235,7 +3007,8 @@ var createSoftConfigStore = (hardConfig = {
2235
3007
  state.softConfig,
2236
3008
  nextSoftComponents,
2237
3009
  activeVersionData.defaultProps,
2238
- state.showVersionFields
3010
+ state.showVersionFields,
3011
+ state.customFields
2239
3012
  );
2240
3013
  }
2241
3014
  });
@@ -2266,7 +3039,8 @@ var createSoftConfigStore = (hardConfig = {
2266
3039
  softConfig,
2267
3040
  hydratedComponents,
2268
3041
  activeVersionData.defaultProps,
2269
- get().showVersionFields
3042
+ get().showVersionFields,
3043
+ get().customFields
2270
3044
  );
2271
3045
  }
2272
3046
  });
@@ -2297,7 +3071,8 @@ var createSoftConfigStore = (hardConfig = {
2297
3071
  get().softConfig,
2298
3072
  get().softComponents,
2299
3073
  softComponent.defaultProps,
2300
- get().showVersionFields
3074
+ get().showVersionFields,
3075
+ get().customFields
2301
3076
  );
2302
3077
  set((state) => ({
2303
3078
  softConfig: __spreadProps(__spreadValues({}, state.softConfig), {
@@ -2434,7 +3209,8 @@ var createSoftConfigStore = (hardConfig = {
2434
3209
  config,
2435
3210
  softComponents2,
2436
3211
  versionedComponent.defaultProps,
2437
- state.showVersionFields
3212
+ state.showVersionFields,
3213
+ state.customFields
2438
3214
  );
2439
3215
  config.components[dependentName] = newConfig;
2440
3216
  }
@@ -2452,14 +3228,29 @@ var SoftConfigProvider = ({
2452
3228
  children,
2453
3229
  hardConfig,
2454
3230
  softComponents,
3231
+ customFields,
2455
3232
  overrides,
2456
3233
  value,
2457
3234
  onActions,
2458
3235
  useVersioning = false
2459
3236
  }) => {
2460
3237
  const store = value != null ? value : useMemo2(
2461
- () => createSoftConfigStore(hardConfig, softComponents, overrides, onActions, useVersioning),
2462
- [hardConfig, softComponents, overrides, onActions, useVersioning]
3238
+ () => createSoftConfigStore(
3239
+ hardConfig,
3240
+ softComponents,
3241
+ overrides,
3242
+ onActions,
3243
+ useVersioning,
3244
+ customFields
3245
+ ),
3246
+ [
3247
+ hardConfig,
3248
+ softComponents,
3249
+ overrides,
3250
+ onActions,
3251
+ useVersioning,
3252
+ customFields
3253
+ ]
2463
3254
  );
2464
3255
  const [softConfig, setSoftConfig] = useState(
2465
3256
  () => store.getState().softConfig
@@ -3055,7 +3846,7 @@ var getClassName3 = get_class_name_factory_default("ActionBar", ActionBar_module
3055
3846
  var usePuck2 = createUsePuck11();
3056
3847
  var ActionBarOverride = (props) => {
3057
3848
  var _a, _b;
3058
- const { handleBuild } = useBuild("Custom Name");
3849
+ const { handleBuild } = useBuild(props.label ? props.label + " Soft Component" : "New Soft Component");
3059
3850
  const { handleRemodel } = useRemodel();
3060
3851
  const { handleDecompose } = useDecompose();
3061
3852
  const overrides = useSoftConfig((s) => s.overrides);
@@ -3087,10 +3878,17 @@ var ActionBarOverride = (props) => {
3087
3878
  const selectedId = (_a = selectedItem == null ? void 0 : selectedItem.props) == null ? void 0 : _a.id;
3088
3879
  const parentId = (_b = itemSelector == null ? void 0 : itemSelector.zone) == null ? void 0 : _b.split(":")[0];
3089
3880
  const isEditable = Boolean(selectedId && (editableIds.has(selectedId) || parentId && editableIds.has(parentId)));
3881
+ const displayName = useMemo3(() => {
3882
+ var _a2;
3883
+ if (isSoftComponent2) {
3884
+ return ((_a2 = softComponents[key]) == null ? void 0 : _a2.name) || getComponentNameFromKey(key, overrides);
3885
+ }
3886
+ return props.label || "";
3887
+ }, [isSoftComponent2, key, props.label, overrides, softComponents]);
3090
3888
  return /* @__PURE__ */ jsx9("div", { className: getClassName3(), children: /* @__PURE__ */ jsxs3(ActionBar, { children: [
3091
3889
  /* @__PURE__ */ jsxs3(ActionBar.Group, { children: [
3092
3890
  props.parentAction,
3093
- /* @__PURE__ */ jsx9(ActionBar.Label, { label: props.label })
3891
+ /* @__PURE__ */ jsx9(ActionBar.Label, { label: displayName })
3094
3892
  ] }),
3095
3893
  /* @__PURE__ */ jsxs3(ActionBar.Group, { children: [
3096
3894
  status === "ready" ? isSoftComponent2 ? /* @__PURE__ */ jsxs3(Fragment4, { children: [
@@ -3215,7 +4013,7 @@ var getClassName5 = get_class_name_factory_default("DrawerItem", DrawerItem_modu
3215
4013
  var usePuck3 = createUsePuck12();
3216
4014
  var DrawerItem = (props) => {
3217
4015
  const componentMeta = useSoftConfig((s) => s.softComponents[props.name]);
3218
- const displayName = (componentMeta == null ? void 0 : componentMeta.name) || props.name;
4016
+ const displayName = props.label || (componentMeta == null ? void 0 : componentMeta.name) || props.name;
3219
4017
  const softComponents = new Set(
3220
4018
  Object.keys(useSoftConfig((s) => s.softComponents, shallow2))
3221
4019
  );
@@ -3311,6 +4109,7 @@ var DrawerItem = (props) => {
3311
4109
  onMouseEnter: () => setIsHovering(true),
3312
4110
  onMouseLeave: () => setIsHovering(false),
3313
4111
  children: [
4112
+ props.label,
3314
4113
  /* @__PURE__ */ jsxs4("div", { className: getClassName5("content"), children: [
3315
4114
  /* @__PURE__ */ jsx11("div", { className: getClassName5("name"), children: displayName }),
3316
4115
  useVersioning && /* @__PURE__ */ jsxs4("div", { className: getClassName5("version"), children: [
@@ -3487,6 +4286,10 @@ var Drawer = (_props) => {
3487
4286
  })
3488
4287
  );
3489
4288
  const allKeys = Object.keys(config.components);
4289
+ const labels = Object.entries(config.components).reduce((acc, [key, comp]) => {
4290
+ acc[key] = comp.label || key;
4291
+ return acc;
4292
+ }, {});
3490
4293
  const otherKeys = allKeys.filter((k) => !categorised.has(k));
3491
4294
  const categoryEntries = Object.entries(categories).filter(
3492
4295
  ([, cat]) => cat.visible !== false
@@ -3505,6 +4308,7 @@ var Drawer = (_props) => {
3505
4308
  PuckDrawer.Item,
3506
4309
  {
3507
4310
  name: key,
4311
+ label: labels[key],
3508
4312
  isDragDisabled: !getPermissions({ type: key }).insert,
3509
4313
  children: DrawerItem
3510
4314
  },
@@ -3589,9 +4393,6 @@ function extractDependencies2(softComponents, componentName, version) {
3589
4393
  return dependencies;
3590
4394
  }
3591
4395
  function reverseTopologicalSort(softComponents, hardComponentNames) {
3592
- const sorted = [];
3593
- const visiting = /* @__PURE__ */ new Set();
3594
- const visited = /* @__PURE__ */ new Set();
3595
4396
  const dependencyGraph = /* @__PURE__ */ new Map();
3596
4397
  const dependents = /* @__PURE__ */ new Map();
3597
4398
  for (const [componentName, component] of Object.entries(softComponents)) {
@@ -3639,7 +4440,7 @@ function reverseTopologicalSort(softComponents, hardComponentNames) {
3639
4440
  const sortedByDepth = [...depths.entries()].sort(([, depthA], [, depthB]) => depthB - depthA).map(([name]) => name);
3640
4441
  return sortedByDepth;
3641
4442
  }
3642
- function dissolveComponentRecursively(componentData, softComponents, hardComponentNames, depth = 0) {
4443
+ function dissolveComponentRecursively(componentData, softComponents, hardComponentNames, depth = 0, fieldSettings) {
3643
4444
  const MAX_DEPTH = 50;
3644
4445
  if (depth > MAX_DEPTH) {
3645
4446
  console.error(
@@ -3649,11 +4450,11 @@ function dissolveComponentRecursively(componentData, softComponents, hardCompone
3649
4450
  }
3650
4451
  const componentType = componentData.type;
3651
4452
  if (!isSoftComponent(componentType, softComponents)) {
3652
- return [dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth)];
4453
+ return [dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth, fieldSettings)];
3653
4454
  }
3654
4455
  let decomposed;
3655
4456
  try {
3656
- decomposed = decomposeSoftComponent(componentData, softComponents);
4457
+ decomposed = decomposeSoftComponent(componentData, softComponents, fieldSettings);
3657
4458
  } catch (error) {
3658
4459
  console.warn(
3659
4460
  `Failed to decompose soft component "${componentType}":`,
@@ -3667,13 +4468,14 @@ function dissolveComponentRecursively(componentData, softComponents, hardCompone
3667
4468
  component,
3668
4469
  softComponents,
3669
4470
  hardComponentNames,
3670
- depth + 1
4471
+ depth + 1,
4472
+ fieldSettings
3671
4473
  );
3672
4474
  fullyDissolved.push(...dissolved);
3673
4475
  }
3674
4476
  return fullyDissolved;
3675
4477
  }
3676
- function dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth) {
4478
+ function dissolveComponentSlots(componentData, softComponents, hardComponentNames, depth, fieldSettings) {
3677
4479
  const newProps = __spreadValues({}, componentData.props);
3678
4480
  Object.entries(newProps).forEach(([key, value]) => {
3679
4481
  var _a;
@@ -3683,7 +4485,8 @@ function dissolveComponentSlots(componentData, softComponents, hardComponentName
3683
4485
  slotComponent,
3684
4486
  softComponents,
3685
4487
  hardComponentNames,
3686
- depth
4488
+ depth,
4489
+ fieldSettings
3687
4490
  )
3688
4491
  );
3689
4492
  }
@@ -3693,22 +4496,23 @@ function dissolveComponentSlots(componentData, softComponents, hardComponentName
3693
4496
  });
3694
4497
  }
3695
4498
  function dissolveAllSoftComponents(data, softComponents, config) {
4499
+ var _a;
3696
4500
  const hardComponentNames = new Set(
3697
4501
  Object.keys(config.components || {}).filter(
3698
4502
  (name) => !isSoftComponent(name, softComponents)
3699
4503
  )
3700
4504
  );
3701
- const dissolutionOrder = reverseTopologicalSort(
3702
- softComponents,
3703
- hardComponentNames
3704
- );
4505
+ reverseTopologicalSort(softComponents, hardComponentNames);
4506
+ const rootParams = ((_a = data.root) == null ? void 0 : _a.props) || {};
4507
+ const fieldSettings = __spreadValues(__spreadValues({}, rootParams._fieldSettings || {}), rootParams);
3705
4508
  const dissolveComponents = (components) => {
3706
4509
  return components.flatMap((componentData) => {
3707
4510
  return dissolveComponentRecursively(
3708
4511
  componentData,
3709
4512
  softComponents,
3710
4513
  hardComponentNames,
3711
- 0
4514
+ 0,
4515
+ fieldSettings
3712
4516
  );
3713
4517
  });
3714
4518
  };
@@ -3774,12 +4578,18 @@ export {
3774
4578
  Header,
3775
4579
  Modal,
3776
4580
  SoftConfigProvider,
4581
+ applyMapping,
3777
4582
  confirm,
3778
4583
  createActionCallback,
3779
4584
  createSoftConfigStore,
3780
4585
  createUseSoftConfig,
4586
+ filterToOptionsForFrom,
4587
+ getArrayBasePath,
4588
+ getArrayItemSubPath,
4589
+ isArrayMappingPath,
3781
4590
  notify,
3782
4591
  resolveSoftConfig,
4592
+ resolveValueByPath,
3783
4593
  setConfirmHandler,
3784
4594
  setNotificationHandler,
3785
4595
  useBuild,