@measured/puck 0.11.0-canary.b28404f → 0.11.0-canary.c8c02fd

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # puck
2
2
 
3
- The self-hosted, drag and drop editor for React.
4
-
5
3
  <p align="left">
6
4
  <a aria-label="Measured logo" href="https://measured.co">
7
5
  <img src="https://img.shields.io/badge/MADE%20BY%20Measured-000000.svg?style=for-the-badge&labelColor=000">
@@ -17,7 +15,7 @@ The self-hosted, drag and drop editor for React.
17
15
  </a>
18
16
  </p>
19
17
 
20
- ## Features
18
+ The self-hosted, drag and drop editor for React.
21
19
 
22
20
  - 🖱️ **Drag and drop**: Visual editing for your existing React component library
23
21
  - 🌐 **Integrations**: Load your content from a 3rd party headless CMS
@@ -234,163 +232,6 @@ The current DropZone implementation has certain rules and limitations:
234
232
  3. You can't drag between DropZones that don't share a parent (or _area_)
235
233
  4. Your mouse must be directly over a DropZone for a collision to be detected
236
234
 
237
- ## Adaptors
238
-
239
- Adaptors can be used to import data from a third-party API, such as a headless CMS.
240
-
241
- ### Example
242
-
243
- The `external` field type enables us to use an adaptor to query data from a third party API:
244
-
245
- ```tsx
246
- const myAdaptor = {
247
- name: "My adaptor",
248
- fetchList: async () => {
249
- const response = await fetch("https://www.example.com/api");
250
-
251
- return {
252
- text: response.json().text,
253
- };
254
- },
255
- };
256
-
257
- const config = {
258
- components: {
259
- HeadingBlock: {
260
- fields: {
261
- myData: {
262
- type: "external",
263
- adaptor: myAdaptor,
264
- },
265
- },
266
- render: ({ myData }) => {
267
- return <h1>{myData.text}</h1>;
268
- },
269
- },
270
- },
271
- };
272
- ```
273
-
274
- When the user interacts with this adaptor, they'll be presented with a list of items to choose from. Once they select an item, the value will be mapped onto the prop. In this case, `myData`.
275
-
276
- ## Dynamic prop resolution
277
-
278
- Dynamic prop resolution allows developers to resolve props for components without saving the data to the Puck data model.
279
-
280
- ### resolveProps()
281
-
282
- `resolveProps` is defined in the component config, and allows the developer to make asynchronous calls to change the props after they've been set by Puck.
283
-
284
- #### Args
285
-
286
- - **props** (`object`): the current props for your component stored in the Puck data
287
-
288
- #### Response
289
-
290
- - **props** (`object`): the resolved props for your component. Will not be stored in the Puck data
291
- - **readOnly** (`object`): an object describing which fields on the component are currently read-only
292
- - **[prop]** (`boolean`): boolean describing whether or not the prop field is read-only
293
-
294
- #### Examples
295
-
296
- ##### Basic example
297
-
298
- In this example, we remap the `text` prop to the `title` prop and mark the `title` field as read-only.
299
-
300
- ```tsx
301
- const config = {
302
- components: {
303
- HeadingBlock: {
304
- fields: {
305
- text: {
306
- type: "text",
307
- },
308
- title: {
309
- type: "text",
310
- },
311
- },
312
- resolveProps: async (props) => {
313
- return {
314
- props: {
315
- title: props.text,
316
- },
317
- readOnly: {
318
- title: true,
319
- },
320
- };
321
- },
322
- render: ({ title }) => {
323
- return <h1>{title}</h1>;
324
- },
325
- },
326
- },
327
- };
328
- ```
329
-
330
- ##### Combining with adaptors
331
-
332
- A more advanced pattern is to combine the `resolveProps` method with the adaptors to dynamically fetch data when rendering the component.
333
-
334
- ```tsx
335
- const myAdaptor = {
336
- name: "My adaptor",
337
- fetchList: async () => {
338
- const response = await fetch("https://www.example.com/api");
339
-
340
- return {
341
- id: response.json().id,
342
- };
343
- },
344
- };
345
-
346
- const config = {
347
- components: {
348
- HeadingBlock: {
349
- fields: {
350
- myData: {
351
- type: "external",
352
- adaptor: myAdaptor,
353
- },
354
- title: {
355
- type: "text",
356
- },
357
- },
358
- resolveProps: async (props) => {
359
- if (!myData.id) {
360
- return { props, readOnly: { title: false } };
361
- }
362
-
363
- const latestData = await fetch(
364
- `https://www.example.com/api/${myData.id}`
365
- );
366
-
367
- return {
368
- props: {
369
- title: latestData.json().text,
370
- },
371
- readOnly: {
372
- title: true,
373
- },
374
- };
375
- },
376
- render: ({ title }) => {
377
- return <h1>{title}</h1>;
378
- },
379
- },
380
- },
381
- };
382
- ```
383
-
384
- ### resolveData()
385
-
386
- `resolveData` is a utility function exported by Puck to enable the developer to resolve their custom props before rendering their component with `<Render>`. This is ideally done on the server. If you're using `resolveProps`, you _must_ use `resolveData` before rendering.
387
-
388
- ```tsx
389
- import { resolveData } from "@measured/puck";
390
-
391
- const resolvedData = resolveData(data, config);
392
- ```
393
-
394
235
  ## Reference
395
236
 
396
237
  ### `<Puck>`
@@ -436,13 +277,6 @@ The `Config` object describes which components Puck should render, how they shou
436
277
  - **fields** (`Field`): The Field objects describing the input data stored against this component.
437
278
  - **render** (`Component`): Render function for your React component. Receives props as defined in fields.
438
279
  - **defaultProps** (`object` [optional]): Default props to pass to your component. Will show in fields.
439
- - **resolveProps** (`async (props: object) => object` [optional]): Function to dynamically change props before rendering the component.
440
- - Args
441
- - **props** (`object`): the current props for your component stored in the Puck data
442
- - Response
443
- - **props** (`object`): the resolved props for your component. Will not be stored in the Puck data
444
- - **readOnly** (`object`): an object describing which fields on the component are currently read-only
445
- - **[prop]** (`boolean`): boolean describing whether or not the prop field is read-only
446
280
  - **categories** (`object`): Component categories for rendering in the side bar or restricting in DropZones
447
281
  - **[categoryName]** (`object`)
448
282
  - **components** (`sting[]`, [optional]): Array containing the names of components in this category
@@ -454,58 +288,17 @@ The `Config` object describes which components Puck should render, how they shou
454
288
 
455
289
  A `Field` represents a user input field shown in the Puck interface.
456
290
 
457
- ### All Fields
458
-
291
+ - **type** (`text` | `textarea` | `number` | `select` | `radio` | `external` | `array` | `custom`): The input type to render
459
292
  - **label** (`text` [optional]): A label for the input. Will use the key if not provided.
460
-
461
- ### Text Fields
462
-
463
- - **type** (`"text"`)
464
-
465
- ### Textarea Fields
466
-
467
- - **type** (`"textarea"`)
468
-
469
- ### Number Fields
470
-
471
- - **type** (`"number"`)
472
-
473
- ### Select Fields
474
-
475
- - **type** (`"select"`)
476
- - **options** (`object[]`): array of items to render
477
- - **label** (`string`)
478
- - **value** (`string` | `number` | `boolean`)
479
-
480
- ### Radio Fields
481
-
482
- - **type** (`"radio"`)
483
- - **options** (`object[]`): array of items to render
484
- - **label** (`string`)
485
- - **value** (`string` | `number` | `boolean`)
486
-
487
- ### Array Fields
488
-
489
- - **type** (`"array"`)
490
- - **arrayFields** (`object`): Object describing sub-fields for each item
293
+ - **arrayFields** (`object`): Object describing sub-fields for items in an `array` input
491
294
  - **[fieldName]** (`Field`): The Field objects describing the input data for each item
492
- - **getItemSummary** (`(object, number) => string` [optional]): Function to get the label of each item
295
+ - **getItemSummary** (`(object, number) => string` [optional]): Function to get the name of each item when using the `array` or `external` field types
493
296
  - **defaultItemProps** (`object` [optional]): Default props to pass to each new item added, when using a `array` field type
494
-
495
- ### External Fields
496
-
497
- External fields can be used to load content from an external content repository, like Strapi.js, using an `Adaptor`.
498
-
499
- - **type** (`"external"`)
500
- - **adaptor** (`Adaptor`): Content adaptor responsible for fetching data to show in the table
501
- - **name** (`string`): The human-readable name of the adaptor
502
- - **fetchList** (`(adaptorParams: object) => object`): Fetch content from a third-party API and return an array
503
- - **mapProp** (`(selectedItem: object) => object`): Map the selected item into another shape
297
+ - **options** (`object[]`): array of items to render for select or radio inputs
298
+ - **label** (`string`)
299
+ - **value** (`string` | `number` | `boolean`)
300
+ - **adaptor** (`Adaptor`): Content adaptor if using the `external` input type
504
301
  - **adaptorParams** (`object`): Paramaters passed to the adaptor
505
-
506
- ### Custom Fields
507
-
508
- - **type** (`"custom"`)
509
302
  - **render** (`Component`): Render a custom field. Receives the props:
510
303
  - **field** (`Field`): Field configuration
511
304
  - **name** (`string`): Name of the field
@@ -540,6 +333,15 @@ The `Data` object stores the puck page data.
540
333
  - **props** (object):
541
334
  - **[prop]** (string): User defined data from component fields
542
335
 
336
+ ### `Adaptor`
337
+
338
+ An `Adaptor` can be used to load content from an external content repository, like Strapi.js.
339
+
340
+ - **name** (`string`): The human-readable name of the adaptor
341
+ - **fetchList** (`(adaptorParams: object) => object`): Fetch a list of content and return an array
342
+
343
+ > NB Using an adaptor on the reserved field name `_data` will spread the resulting data over your object, and lock the overridden fields.
344
+
543
345
  ### `Plugin`
544
346
 
545
347
  Plugins that can be used to enhance Puck.
package/dist/index.d.ts CHANGED
@@ -8,71 +8,39 @@ type ItemSelector = {
8
8
  zone?: string;
9
9
  };
10
10
 
11
- type Adaptor<AdaptorParams = {}, TableShape extends Record<string, any> = {}, PropShape = TableShape> = {
11
+ type Adaptor<AdaptorParams = {}> = {
12
12
  name: string;
13
- fetchList: (adaptorParams?: AdaptorParams) => Promise<TableShape[] | null>;
14
- mapProp?: (value: TableShape) => PropShape;
13
+ fetchList: (adaptorParams?: AdaptorParams) => Promise<Record<string, any>[] | null>;
15
14
  };
16
- type WithPuckProps<Props> = Props & {
15
+ type WithId<T> = T & {
17
16
  id: string;
18
- _meta?: {
19
- readOnly: Partial<Record<keyof Props, boolean>>;
20
- };
21
- };
22
- type BaseField = {
23
- label?: string;
24
- };
25
- type TextField = BaseField & {
26
- type: "text" | "number" | "textarea";
27
- };
28
- type SelectField = BaseField & {
29
- type: "select" | "radio";
30
- options: {
31
- label: string;
32
- value: string | number | boolean;
33
- }[];
34
- };
35
- type ArrayField<Props extends {
36
- [key: string]: any;
37
- } = {
38
- [key: string]: any;
39
- }> = BaseField & {
40
- type: "array";
41
- arrayFields: {
42
- [SubPropName in keyof Props[0]]: Field<Props[0][SubPropName]>;
43
- };
44
- defaultItemProps?: Props[0];
45
- getItemSummary?: (item: Props[0], index?: number) => string;
46
17
  };
47
- type ExternalField<Props extends {
18
+ type Field<Props extends {
48
19
  [key: string]: any;
49
20
  } = {
50
21
  [key: string]: any;
51
- }> = BaseField & {
52
- type: "external";
53
- adaptor: Adaptor<any, any, Props>;
22
+ }> = {
23
+ type: "text" | "textarea" | "number" | "select" | "array" | "external" | "radio" | "custom";
24
+ label?: string;
25
+ adaptor?: Adaptor;
54
26
  adaptorParams?: object;
55
- getItemSummary: (item: Props, index?: number) => string;
56
- };
57
- type CustomField<Props extends {
58
- [key: string]: any;
59
- } = {
60
- [key: string]: any;
61
- }> = BaseField & {
62
- type: "custom";
63
- render: (props: {
64
- field: CustomField;
27
+ arrayFields?: {
28
+ [SubPropName in keyof Props]: Field<Props[SubPropName][0]>;
29
+ };
30
+ getItemSummary?: (item: Props, index?: number) => string;
31
+ defaultItemProps?: Props;
32
+ render?: (props: {
33
+ field: Field;
65
34
  name: string;
66
35
  value: any;
67
- onChange: (value: Props) => void;
36
+ onChange: (value: any) => void;
68
37
  readOnly?: boolean;
69
38
  }) => ReactElement;
39
+ options?: {
40
+ label: string;
41
+ value: string | number | boolean;
42
+ }[];
70
43
  };
71
- type Field<Props extends {
72
- [key: string]: any;
73
- } = {
74
- [key: string]: any;
75
- }> = TextField | SelectField | ArrayField<Props> | ExternalField<Props> | CustomField;
76
44
  type DefaultRootProps = {
77
45
  children: ReactNode;
78
46
  title: string;
@@ -84,7 +52,7 @@ type DefaultComponentProps = {
84
52
  editMode?: boolean;
85
53
  };
86
54
  type Fields<ComponentProps extends DefaultComponentProps = DefaultComponentProps> = {
87
- [PropName in keyof Omit<Required<ComponentProps>, "children" | "editMode">]: Field<ComponentProps[PropName]>;
55
+ [PropName in keyof Omit<Required<ComponentProps>, "children" | "editMode">]: Field<ComponentProps[PropName][0]>;
88
56
  };
89
57
  type Content<Props extends {
90
58
  [key: string]: any;
@@ -92,13 +60,9 @@ type Content<Props extends {
92
60
  [key: string]: any;
93
61
  }> = MappedItem<Props>[];
94
62
  type ComponentConfig<ComponentProps extends DefaultComponentProps = DefaultComponentProps, DefaultProps = ComponentProps> = {
95
- render: (props: WithPuckProps<ComponentProps>) => ReactElement;
63
+ render: (props: WithId<ComponentProps>) => ReactElement;
96
64
  defaultProps?: DefaultProps;
97
65
  fields?: Fields<ComponentProps>;
98
- resolveProps?: (props: WithPuckProps<ComponentProps>) => Promise<{
99
- props: WithPuckProps<ComponentProps>;
100
- readOnly?: Partial<Record<keyof ComponentProps, boolean>>;
101
- }>;
102
66
  };
103
67
  type Category<ComponentName> = {
104
68
  components?: ComponentName[];
@@ -129,7 +93,7 @@ type MappedItem<Props extends {
129
93
  [key: string]: any;
130
94
  }> = {
131
95
  type: keyof Props;
132
- props: WithPuckProps<{
96
+ props: WithId<{
133
97
  [key: string]: any;
134
98
  }>;
135
99
  };
@@ -252,7 +216,6 @@ type PathData = Record<string, {
252
216
  type DropZoneContext = {
253
217
  data: Data;
254
218
  config: Config;
255
- dynamicProps?: Record<string, any>;
256
219
  itemSelector?: ItemSelector | null;
257
220
  setItemSelector?: (newIndex: ItemSelector | null) => void;
258
221
  dispatch?: (action: PuckAction) => void;
@@ -346,24 +309,10 @@ declare function Render({ config, data }: {
346
309
  data: Data;
347
310
  }): react_jsx_runtime.JSX.Element;
348
311
 
349
- declare const resolveData: (data: Data, config: Config) => Promise<{
350
- content: {
351
- props: any;
352
- type: string | number;
353
- }[];
354
- zones: Record<string, MappedItem<{
355
- [key: string]: any;
356
- }>[]>;
357
- root: {
358
- [key: string]: any;
359
- title: string;
360
- };
361
- }>;
362
-
363
312
  declare const FieldLabel: ({ children, icon, label, }: {
364
313
  children?: ReactNode;
365
314
  icon?: ReactNode;
366
315
  label: string;
367
316
  }) => react_jsx_runtime.JSX.Element;
368
317
 
369
- export { Adaptor, AppState, ArrayField, ArrayState, BaseField, Button, ComponentConfig, Config, Content, CustomField, Data, DefaultComponentProps, DefaultRootProps, DropZone, DropZoneProvider, ExternalField, Field, FieldLabel, Fields, IconButton, ItemWithId, MappedItem, Puck, Render, SelectField, TextField, UiState, dropZoneContext, resolveData };
318
+ export { Adaptor, AppState, ArrayState, Button, ComponentConfig, Config, Content, Data, DefaultComponentProps, DefaultRootProps, DropZone, DropZoneProvider, Field, FieldLabel, Fields, IconButton, ItemWithId, MappedItem, Puck, Render, UiState, dropZoneContext };
package/dist/index.js CHANGED
@@ -1109,8 +1109,7 @@ __export(core_exports, {
1109
1109
  IconButton: () => IconButton,
1110
1110
  Puck: () => Puck,
1111
1111
  Render: () => Render,
1112
- dropZoneContext: () => dropZoneContext,
1113
- resolveData: () => resolveData
1112
+ dropZoneContext: () => dropZoneContext
1114
1113
  });
1115
1114
  module.exports = __toCommonJS(core_exports);
1116
1115
  init_react_import();
@@ -2664,13 +2663,11 @@ var setupZone = (data, zoneKey) => {
2664
2663
  };
2665
2664
 
2666
2665
  // lib/get-item.ts
2667
- var getItem = (selector, data, dynamicProps = {}) => {
2666
+ var getItem = (selector, data) => {
2668
2667
  if (!selector.zone || selector.zone === rootDroppableId) {
2669
- const item2 = data.content[selector.index];
2670
- return __spreadProps(__spreadValues({}, item2), { props: dynamicProps[item2.props.id] || item2.props });
2668
+ return data.content[selector.index];
2671
2669
  }
2672
- const item = setupZone(data, selector.zone).zones[selector.zone][selector.index];
2673
- return __spreadProps(__spreadValues({}, item), { props: dynamicProps[item.props.id] || item.props });
2670
+ return setupZone(data, selector.zone).zones[selector.zone][selector.index];
2674
2671
  };
2675
2672
 
2676
2673
  // lib/index.ts
@@ -2678,6 +2675,14 @@ init_react_import();
2678
2675
 
2679
2676
  // lib/filter.ts
2680
2677
  init_react_import();
2678
+ var filter = (obj, validKeys) => {
2679
+ return validKeys.reduce((acc, item) => {
2680
+ if (typeof obj[item] !== "undefined") {
2681
+ return __spreadProps(__spreadValues({}, acc), { [item]: obj[item] });
2682
+ }
2683
+ return acc;
2684
+ }, {});
2685
+ };
2681
2686
 
2682
2687
  // lib/reorder.ts
2683
2688
  init_react_import();
@@ -2828,7 +2833,6 @@ function DropZoneEdit({ zone, style }) {
2828
2833
  const {
2829
2834
  // These all need setting via context
2830
2835
  data,
2831
- dynamicProps = {},
2832
2836
  dispatch = () => null,
2833
2837
  config,
2834
2838
  itemSelector,
@@ -2930,7 +2934,7 @@ function DropZoneEdit({ zone, style }) {
2930
2934
  content.map((item, i) => {
2931
2935
  var _a2;
2932
2936
  const componentId = item.props.id;
2933
- const defaultedProps = __spreadProps(__spreadValues(__spreadValues({}, (_a2 = config.components[item.type]) == null ? void 0 : _a2.defaultProps), dynamicProps[item.props.id] || item.props), {
2937
+ const defaultedProps = __spreadProps(__spreadValues(__spreadValues({}, (_a2 = config.components[item.type]) == null ? void 0 : _a2.defaultProps), item.props), {
2934
2938
  editMode: true
2935
2939
  });
2936
2940
  const isSelected = (selectedItem == null ? void 0 : selectedItem.props.id) === componentId || false;
@@ -3320,7 +3324,7 @@ var ArrayField = ({
3320
3324
  });
3321
3325
  setArrayState({ items: newItems });
3322
3326
  }, [value]);
3323
- if (field.type !== "array" || !field.arrayFields) {
3327
+ if (!field.arrayFields) {
3324
3328
  return null;
3325
3329
  }
3326
3330
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: getClassNameInput(), children: [
@@ -3519,7 +3523,6 @@ var ExternalInput = ({
3519
3523
  onChange,
3520
3524
  value = null
3521
3525
  }) => {
3522
- const { mapProp = (val) => val } = field.adaptor || {};
3523
3526
  const [data, setData] = (0, import_react27.useState)([]);
3524
3527
  const [isOpen, setOpen] = (0, import_react27.useState)(false);
3525
3528
  const [selectedData, setSelectedData] = (0, import_react27.useState)(value);
@@ -3597,9 +3600,9 @@ var ExternalInput = ({
3597
3600
  {
3598
3601
  style: { whiteSpace: "nowrap" },
3599
3602
  onClick: (e) => {
3600
- onChange(mapProp(item));
3603
+ onChange(item);
3601
3604
  setOpen(false);
3602
- setSelectedData(mapProp(item));
3605
+ setSelectedData(item);
3603
3606
  },
3604
3607
  children: keys.map((key) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { children: item[key] }, key))
3605
3608
  },
@@ -3621,18 +3624,16 @@ var getClassName9 = get_class_name_factory_default("Input", styles_module_defaul
3621
3624
  var ExternalField = ({
3622
3625
  field,
3623
3626
  onChange,
3627
+ readOnly,
3624
3628
  value,
3625
3629
  name,
3626
3630
  label
3627
3631
  }) => {
3628
- if (field.type !== "external" || !field.adaptor) {
3632
+ if (!field.adaptor) {
3629
3633
  return null;
3630
3634
  }
3631
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: getClassName9(), children: [
3632
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: getClassName9("label"), children: [
3633
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: getClassName9("labelIcon"), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(link_default, { size: 16 }) }),
3634
- label || name
3635
- ] }),
3635
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: getClassName9(""), children: [
3636
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: getClassName9("label"), children: name === "_data" ? "External content" : label || name }),
3636
3637
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ExternalInput, { field, onChange, value })
3637
3638
  ] });
3638
3639
  };
@@ -3648,7 +3649,7 @@ var RadioField = ({
3648
3649
  value,
3649
3650
  name
3650
3651
  }) => {
3651
- if (field.type !== "radio" || !field.options) {
3652
+ if (!field.options) {
3652
3653
  return null;
3653
3654
  }
3654
3655
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: getClassName10(), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: getClassName10("radioGroup"), children: [
@@ -3698,7 +3699,7 @@ var SelectField = ({
3698
3699
  value,
3699
3700
  name
3700
3701
  }) => {
3701
- if (field.type !== "select" || !field.options) {
3702
+ if (!field.options) {
3702
3703
  return null;
3703
3704
  }
3704
3705
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: getClassName11(), children: [
@@ -4745,26 +4746,6 @@ var useComponentList = (config, ui) => {
4745
4746
  return componentList;
4746
4747
  };
4747
4748
 
4748
- // lib/resolve-all-props.ts
4749
- init_react_import();
4750
- var resolveAllProps = (content, config) => __async(void 0, null, function* () {
4751
- return yield Promise.all(
4752
- content.map((item) => __async(void 0, null, function* () {
4753
- const configForItem = config.components[item.type];
4754
- if (configForItem.resolveProps) {
4755
- const { props: resolvedProps, readOnly = {} } = yield configForItem.resolveProps(item.props);
4756
- const { _meta: { readOnly: existingReadOnly = {} } = {} } = item.props || {};
4757
- return __spreadProps(__spreadValues({}, item), {
4758
- props: __spreadProps(__spreadValues({}, resolvedProps), {
4759
- _meta: { readOnly: __spreadValues(__spreadValues({}, existingReadOnly), readOnly) }
4760
- })
4761
- });
4762
- }
4763
- return item;
4764
- }))
4765
- );
4766
- });
4767
-
4768
4749
  // components/Puck/index.tsx
4769
4750
  var import_jsx_runtime22 = require("react/jsx-runtime");
4770
4751
  var defaultPageFields = {
@@ -4795,7 +4776,6 @@ function Puck({
4795
4776
  headerPath
4796
4777
  }) {
4797
4778
  var _a, _b;
4798
- const [dynamicProps, setDynamicProps] = (0, import_react34.useState)({});
4799
4779
  const [reducer] = (0, import_react34.useState)(() => createReducer({ config }));
4800
4780
  const initialAppState = __spreadProps(__spreadValues({}, defaultAppState), {
4801
4781
  data: initialData,
@@ -4821,21 +4801,6 @@ function Puck({
4821
4801
  flushZones(initialAppState)
4822
4802
  );
4823
4803
  const { data, ui } = appState;
4824
- (0, import_react34.useEffect)(() => {
4825
- const flatContent = Object.keys(data.zones || {}).reduce(
4826
- (acc, zone) => [...acc, ...data.zones[zone]],
4827
- data.content
4828
- );
4829
- resolveAllProps(flatContent, config).then((dynamicContent) => {
4830
- const newDynamicProps = dynamicContent.reduce(
4831
- (acc, item) => {
4832
- return __spreadProps(__spreadValues({}, acc), { [item.props.id]: item.props });
4833
- },
4834
- {}
4835
- );
4836
- setDynamicProps(newDynamicProps);
4837
- });
4838
- }, [data]);
4839
4804
  const { canForward, canRewind, rewind, forward } = usePuckHistory({
4840
4805
  appState,
4841
4806
  dispatch
@@ -4850,7 +4815,7 @@ function Puck({
4850
4815
  },
4851
4816
  []
4852
4817
  );
4853
- const selectedItem = itemSelector ? getItem(itemSelector, data, dynamicProps) : null;
4818
+ const selectedItem = itemSelector ? getItem(itemSelector, data) : null;
4854
4819
  const Page = (0, import_react34.useCallback)(
4855
4820
  (pageProps) => {
4856
4821
  var _a2, _b2;
@@ -4979,7 +4944,6 @@ function Puck({
4979
4944
  value: {
4980
4945
  data,
4981
4946
  itemSelector,
4982
- dynamicProps,
4983
4947
  setItemSelector,
4984
4948
  config,
4985
4949
  dispatch,
@@ -5260,18 +5224,42 @@ function Puck({
5260
5224
  showBreadcrumbs: true,
5261
5225
  title: selectedItem ? selectedItem.type : "Page",
5262
5226
  children: Object.keys(fields).map((fieldName) => {
5227
+ var _a2, _b2, _c, _d;
5263
5228
  const field = fields[fieldName];
5264
5229
  const onChange2 = (value) => {
5265
5230
  let currentProps;
5231
+ let newProps;
5266
5232
  if (selectedItem) {
5267
5233
  currentProps = selectedItem.props;
5268
5234
  } else {
5269
5235
  currentProps = data.root;
5270
5236
  }
5271
- const _a2 = currentProps._meta || {}, { readOnly } = _a2, _meta = __objRest(_a2, ["readOnly"]);
5272
- const newProps = __spreadProps(__spreadValues({}, currentProps), {
5273
- [fieldName]: value
5274
- });
5237
+ if (fieldName === "_data") {
5238
+ if (!value) {
5239
+ const _a3 = currentProps._meta || {}, { locked } = _a3, _meta = __objRest(_a3, ["locked"]);
5240
+ newProps = __spreadProps(__spreadValues({}, currentProps), {
5241
+ _data: void 0,
5242
+ _meta
5243
+ });
5244
+ } else {
5245
+ const changedFields = filter(
5246
+ // filter out anything not supported by this component
5247
+ value,
5248
+ Object.keys(fields)
5249
+ );
5250
+ newProps = __spreadProps(__spreadValues(__spreadValues({}, currentProps), changedFields), {
5251
+ _data: value,
5252
+ // TODO perf - this is duplicative and will make payload larger
5253
+ _meta: {
5254
+ locked: Object.keys(changedFields)
5255
+ }
5256
+ });
5257
+ }
5258
+ } else {
5259
+ newProps = __spreadProps(__spreadValues({}, currentProps), {
5260
+ [fieldName]: value
5261
+ });
5262
+ }
5275
5263
  if (itemSelector) {
5276
5264
  dispatch({
5277
5265
  type: "replace",
@@ -5287,28 +5275,31 @@ function Puck({
5287
5275
  }
5288
5276
  };
5289
5277
  if (selectedItem && itemSelector) {
5290
- const { readOnly = {} } = selectedItem.props._meta || {};
5291
5278
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5292
5279
  InputOrGroup,
5293
5280
  {
5294
5281
  field,
5295
5282
  name: fieldName,
5296
5283
  label: field.label,
5297
- readOnly: readOnly[fieldName],
5284
+ readOnly: ((_b2 = (_a2 = getItem(
5285
+ itemSelector,
5286
+ data
5287
+ ).props._meta) == null ? void 0 : _a2.locked) == null ? void 0 : _b2.indexOf(fieldName)) > -1,
5298
5288
  value: selectedItem.props[fieldName],
5299
5289
  onChange: onChange2
5300
5290
  },
5301
5291
  `${selectedItem.props.id}_${fieldName}`
5302
5292
  );
5303
5293
  } else {
5304
- const { readOnly = {} } = data.root._meta || {};
5305
5294
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5306
5295
  InputOrGroup,
5307
5296
  {
5308
5297
  field,
5309
5298
  name: fieldName,
5310
5299
  label: field.label,
5311
- readOnly: readOnly[fieldName],
5300
+ readOnly: ((_d = (_c = data.root._meta) == null ? void 0 : _c.locked) == null ? void 0 : _d.indexOf(
5301
+ fieldName
5302
+ )) > -1,
5312
5303
  value: data.root[fieldName],
5313
5304
  onChange: onChange2
5314
5305
  },
@@ -5339,22 +5330,6 @@ function Render({ config, data }) {
5339
5330
  }
5340
5331
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(DropZoneProvider, { value: { data, config, mode: "render" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(DropZone, { zone: rootDroppableId }) });
5341
5332
  }
5342
-
5343
- // lib/resolve-data.ts
5344
- init_react_import();
5345
- var resolveData = (data, config) => __async(void 0, null, function* () {
5346
- const { zones = {} } = data;
5347
- const zoneKeys = Object.keys(zones);
5348
- const resolvedZones = {};
5349
- for (let i = 0; i < zoneKeys.length; i++) {
5350
- const zoneKey = zoneKeys[i];
5351
- resolvedZones[zoneKey] = yield resolveAllProps(zones[zoneKey], config);
5352
- }
5353
- return __spreadProps(__spreadValues({}, data), {
5354
- content: yield resolveAllProps(data.content, config),
5355
- zones: resolvedZones
5356
- });
5357
- });
5358
5333
  // Annotate the CommonJS export names for ESM import in node:
5359
5334
  0 && (module.exports = {
5360
5335
  Button,
@@ -5364,8 +5339,7 @@ var resolveData = (data, config) => __async(void 0, null, function* () {
5364
5339
  IconButton,
5365
5340
  Puck,
5366
5341
  Render,
5367
- dropZoneContext,
5368
- resolveData
5342
+ dropZoneContext
5369
5343
  });
5370
5344
  /*! Bundled license information:
5371
5345
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@measured/puck",
3
- "version": "0.11.0-canary.b28404f",
3
+ "version": "0.11.0-canary.c8c02fd",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",