@measured/puck 0.10.0-canary.ca4f4be → 0.10.0-canary.e308381

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
@@ -112,7 +112,11 @@ The plugin API follows a React paradigm. Each plugin passed to the Puck editor c
112
112
  - `renderRootFields` (`Component`): Render the root fields
113
113
  - `renderFields` (`Component`): Render the fields for the currently selected component
114
114
 
115
- Each render function receives the `children` prop, which you must render, and the `data` prop, which can be used to read the data model.
115
+ Each render function receives three props:
116
+
117
+ - **children** (`ReactNode`): The normal contents of the root or field. You must render this.
118
+ - **state** (`AppState`): The current application state, including data and UI state
119
+ - **dispatch** (`(action: PuckAction) => void`): The Puck dispatcher, used for making data changes or updating the UI. See the [action definitions](https://github.com/measuredco/puck/blob/main/packages/core/reducer/actions.tsx) for a full reference of available mutations.
116
120
 
117
121
  #### Example
118
122
 
@@ -285,9 +289,19 @@ A `Field` represents a user input field shown in the Puck interface.
285
289
  - **onChange** (`(value: any) => void`): Callback to change the value
286
290
  - **readOnly** (`boolean` | `undefined`): Whether or not the field should be in readOnly mode
287
291
 
292
+ ### `AppState`
293
+
294
+ The `AppState` object stores the puck application state.
295
+
296
+ - **data** (`Data`): The page data currently being rendered
297
+ - **ui** (`object`):
298
+ - **leftSideBarVisible** (boolean): Whether or not the left side bar is visible
299
+ - **itemSelector** (object): An object describing which item is selected
300
+ - **arrayState** (object): An object describing the internal state of array items
301
+
288
302
  ### `Data`
289
303
 
290
- The `Data` object stores the puck state.
304
+ The `Data` object stores the puck page data.
291
305
 
292
306
  - **root** (`object`):
293
307
  - **title** (string): Title of the content, typically used for the page title
package/dist/index.css CHANGED
@@ -723,33 +723,32 @@
723
723
  }
724
724
 
725
725
  /* css-module:/home/runner/work/puck/puck/packages/core/components/ComponentList/styles.module.css/#css-module-data */
726
- ._ComponentList_1f52d_1 {
727
- display: grid;
726
+ ._ComponentList_bvy0z_1 {
728
727
  font-family: var(--puck-font-stack);
729
- grid-template-columns: 1fr;
730
728
  max-width: 100%;
731
- grid-gap: 12px;
732
729
  }
733
- ._ComponentList-item_1f52d_9 {
730
+ ._ComponentList-item_bvy0z_6 {
734
731
  background: white;
735
732
  padding: 12px;
736
733
  display: flex;
737
734
  border: 1px var(--puck-color-grey-8) solid;
738
- border-radius: 8px;
735
+ border-radius: 4px;
739
736
  font-size: var(--puck-font-size-xxs);
740
737
  justify-content: space-between;
741
738
  align-items: center;
742
739
  gap: 12px;
743
740
  cursor: grab;
741
+ margin-bottom: 12px;
744
742
  }
745
- ._ComponentList-item_1f52d_9:last-of-type {
743
+ ._ComponentList-item_bvy0z_6:last-of-type {
746
744
  margin-bottom: 0px;
747
745
  }
748
- ._ComponentList-itemIcon_1f52d_26 {
746
+ ._ComponentList-itemIcon_bvy0z_24 {
749
747
  color: var(--puck-color-grey-4);
750
748
  }
751
- ._ComponentList_1f52d_1:not(._ComponentList--isDraggingFrom_1f52d_30) ._ComponentList-item_1f52d_9:hover {
749
+ ._ComponentList_bvy0z_1:not(._ComponentList--isDraggingFrom_bvy0z_28) ._ComponentList-item_bvy0z_6:hover {
752
750
  background-color: var(--puck-color-azure-9);
751
+ color: var(--puck-color-azure-4);
753
752
  }
754
753
 
755
754
  /* css-module:/home/runner/work/puck/puck/packages/core/components/SidebarSection/styles.module.css/#css-module-data */
package/dist/index.d.ts CHANGED
@@ -111,14 +111,14 @@ type ArrayState = {
111
111
  items: ItemWithId[];
112
112
  openId: string;
113
113
  };
114
- type AppState = {
114
+ type UiState = {
115
115
  leftSideBarVisible: boolean;
116
- itemSelector?: ItemSelector | null;
116
+ itemSelector: ItemSelector | null;
117
117
  arrayState: Record<string, ArrayState | undefined>;
118
118
  };
119
- type AppData = {
119
+ type AppState = {
120
120
  data: Data;
121
- state: AppState;
121
+ ui: UiState;
122
122
  };
123
123
 
124
124
  declare const Button: ({ children, href, onClick, variant, type, disabled, tabIndex, newTab, fullWidth, icon, size, }: {
@@ -171,8 +171,8 @@ type RemoveAction = {
171
171
  zone: string;
172
172
  };
173
173
  type SetStateAction = {
174
- type: "setState";
175
- state: Partial<AppState>;
174
+ type: "setUi";
175
+ ui: Partial<UiState>;
176
176
  };
177
177
  type SetDataAction = {
178
178
  type: "setData";
@@ -180,7 +180,7 @@ type SetDataAction = {
180
180
  };
181
181
  type SetAction = {
182
182
  type: "set";
183
- appData: Partial<AppData>;
183
+ state: Partial<AppState>;
184
184
  };
185
185
  type RegisterZoneAction = {
186
186
  type: "registerZone";
@@ -195,9 +195,9 @@ type PuckAction = {
195
195
  } & (ReorderAction | InsertAction | MoveAction | ReplaceAction | RemoveAction | DuplicateAction | SetAction | SetDataAction | SetStateAction | RegisterZoneAction | UnregisterZoneAction);
196
196
 
197
197
  type PathData = Record<string, {
198
- selector: ItemSelector | null;
198
+ path: string[];
199
199
  label: string;
200
- }[]>;
200
+ }>;
201
201
  type DropZoneContext = {
202
202
  data: Data;
203
203
  config: Config;
@@ -250,15 +250,18 @@ declare const IconButton: ({ children, href, onClick, variant, type, disabled, t
250
250
  type Plugin = {
251
251
  renderRootFields?: (props: {
252
252
  children: ReactNode;
253
- data: Data;
253
+ dispatch: (action: PuckAction) => void;
254
+ state: AppState;
254
255
  }) => ReactElement<any>;
255
256
  renderRoot?: (props: {
256
257
  children: ReactNode;
257
- data: Data;
258
+ dispatch: (action: PuckAction) => void;
259
+ state: AppState;
258
260
  }) => ReactElement<any>;
259
261
  renderFields?: (props: {
260
262
  children: ReactNode;
261
- data: Data;
263
+ dispatch: (action: PuckAction) => void;
264
+ state: AppState;
262
265
  }) => ReactElement<any>;
263
266
  };
264
267
 
@@ -270,11 +273,11 @@ declare function Puck({ config, data: initialData, onChange, onPublish, plugins,
270
273
  plugins?: Plugin[];
271
274
  renderHeader?: (props: {
272
275
  children: ReactNode;
273
- data: Data;
274
276
  dispatch: (action: PuckAction) => void;
277
+ state: AppState;
275
278
  }) => ReactElement;
276
279
  renderHeaderActions?: (props: {
277
- data: Data;
280
+ state: AppState;
278
281
  dispatch: (action: PuckAction) => void;
279
282
  }) => ReactElement;
280
283
  headerTitle?: string;
@@ -292,4 +295,4 @@ declare const FieldLabel: ({ children, icon, label, }: {
292
295
  label: string;
293
296
  }) => react_jsx_runtime.JSX.Element;
294
297
 
295
- export { Adaptor, AppData, AppState, ArrayState, Button, ComponentConfig, Config, Content, Data, DefaultComponentProps, DefaultRootProps, DropZone, DropZoneProvider, Field, FieldLabel, Fields, IconButton, ItemWithId, Puck, Render, dropZoneContext };
298
+ 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
@@ -327,7 +327,7 @@ var require_react_is_development = __commonJS({
327
327
  var ContextProvider = REACT_PROVIDER_TYPE;
328
328
  var Element = REACT_ELEMENT_TYPE;
329
329
  var ForwardRef = REACT_FORWARD_REF_TYPE;
330
- var Fragment10 = REACT_FRAGMENT_TYPE;
330
+ var Fragment11 = REACT_FRAGMENT_TYPE;
331
331
  var Lazy = REACT_LAZY_TYPE;
332
332
  var Memo = REACT_MEMO_TYPE;
333
333
  var Portal = REACT_PORTAL_TYPE;
@@ -386,7 +386,7 @@ var require_react_is_development = __commonJS({
386
386
  exports.ContextProvider = ContextProvider;
387
387
  exports.Element = Element;
388
388
  exports.ForwardRef = ForwardRef;
389
- exports.Fragment = Fragment10;
389
+ exports.Fragment = Fragment11;
390
390
  exports.Lazy = Lazy;
391
391
  exports.Memo = Memo;
392
392
  exports.Portal = Portal;
@@ -2646,7 +2646,7 @@ var getZoneId = (zoneCompound) => {
2646
2646
  if (zoneCompound && zoneCompound.indexOf(":") > -1) {
2647
2647
  return zoneCompound.split(":");
2648
2648
  }
2649
- return ["root", zoneCompound];
2649
+ return [rootDroppableId, zoneCompound];
2650
2650
  };
2651
2651
 
2652
2652
  // components/DropZone/context.tsx
@@ -2713,15 +2713,15 @@ var DropZoneProvider = ({
2713
2713
  }
2714
2714
  const [area] = getZoneId(selector.zone);
2715
2715
  setPathData((latestPathData = {}) => {
2716
- const pathData2 = latestPathData[area] || [];
2716
+ const parentPathData = latestPathData[area] || { path: [] };
2717
2717
  return __spreadProps(__spreadValues({}, latestPathData), {
2718
- [item.props.id]: [
2719
- ...pathData2,
2720
- {
2721
- selector,
2722
- label: item.type
2723
- }
2724
- ]
2718
+ [item.props.id]: {
2719
+ path: [
2720
+ ...parentPathData.path,
2721
+ ...selector.zone ? [selector.zone] : []
2722
+ ],
2723
+ label: item.type
2724
+ }
2725
2725
  });
2726
2726
  });
2727
2727
  },
@@ -3090,7 +3090,7 @@ var IconButton = ({
3090
3090
 
3091
3091
  // components/Puck/index.tsx
3092
3092
  init_react_import();
3093
- var import_react31 = require("react");
3093
+ var import_react32 = require("react");
3094
3094
  var import_react_beautiful_dnd5 = require("react-beautiful-dnd");
3095
3095
 
3096
3096
  // components/InputOrGroup/index.tsx
@@ -3140,7 +3140,14 @@ var Draggable2 = ({
3140
3140
  children: children(provided, snapshot)
3141
3141
  })
3142
3142
  ),
3143
- showShadow && snapshot.isDragging && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { transform: "none !important" }, children: children(provided, snapshot) })
3143
+ showShadow && snapshot.isDragging && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3144
+ "div",
3145
+ {
3146
+ className: className && className(provided, snapshot),
3147
+ style: { transform: "none !important" },
3148
+ children: children(provided, snapshot)
3149
+ }
3150
+ )
3144
3151
  ] });
3145
3152
  } });
3146
3153
  };
@@ -3168,26 +3175,29 @@ var DragIcon = () => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { class
3168
3175
  // components/Puck/context.tsx
3169
3176
  init_react_import();
3170
3177
  var import_react24 = require("react");
3171
- var defaultAppData = {
3178
+ var defaultAppState = {
3172
3179
  data: { content: [], root: { title: "" } },
3173
- state: {
3180
+ ui: {
3174
3181
  leftSideBarVisible: true,
3175
- arrayState: {}
3182
+ arrayState: {},
3183
+ itemSelector: null
3176
3184
  }
3177
3185
  };
3178
3186
  var appContext = (0, import_react24.createContext)({
3179
- appData: defaultAppData,
3187
+ state: defaultAppState,
3180
3188
  dispatch: () => null
3181
3189
  });
3182
3190
  var AppProvider = appContext.Provider;
3183
3191
  var useAppContext = () => {
3184
3192
  const mainContext = (0, import_react24.useContext)(appContext);
3193
+ const selectedItem = mainContext.state.ui.itemSelector ? getItem(mainContext.state.ui.itemSelector, mainContext.state.data) : void 0;
3185
3194
  return __spreadProps(__spreadValues({}, mainContext), {
3186
- // Helper
3187
- setState: (state, recordHistory) => {
3195
+ // Helpers
3196
+ selectedItem,
3197
+ setUi: (ui, recordHistory) => {
3188
3198
  return mainContext.dispatch({
3189
- type: "setState",
3190
- state,
3199
+ type: "setUi",
3200
+ ui,
3191
3201
  recordHistory
3192
3202
  });
3193
3203
  }
@@ -3207,8 +3217,8 @@ var ArrayField = ({
3207
3217
  label
3208
3218
  }) => {
3209
3219
  const [arrayFieldId] = (0, import_react25.useState)(generateId("ArrayField"));
3210
- const { appData, setState } = useAppContext();
3211
- const arrayState = appData.state.arrayState[arrayFieldId] || {
3220
+ const { state, setUi } = useAppContext();
3221
+ const arrayState = state.ui.arrayState[arrayFieldId] || {
3212
3222
  items: Array.from(value).map((v) => ({
3213
3223
  _arrayId: generateId("ArrayItem"),
3214
3224
  data: v
@@ -3217,9 +3227,9 @@ var ArrayField = ({
3217
3227
  };
3218
3228
  const setArrayState = (0, import_react25.useCallback)(
3219
3229
  (newArrayState, recordHistory = false) => {
3220
- setState(
3230
+ setUi(
3221
3231
  {
3222
- arrayState: __spreadProps(__spreadValues({}, appData.state.arrayState), {
3232
+ arrayState: __spreadProps(__spreadValues({}, state.ui.arrayState), {
3223
3233
  [arrayFieldId]: __spreadValues(__spreadValues({}, arrayState), newArrayState)
3224
3234
  })
3225
3235
  },
@@ -3440,12 +3450,17 @@ var ExternalInput = ({
3440
3450
  const [data, setData] = (0, import_react26.useState)([]);
3441
3451
  const [isOpen, setOpen] = (0, import_react26.useState)(false);
3442
3452
  const [selectedData, setSelectedData] = (0, import_react26.useState)(value);
3443
- const keys = (0, import_react26.useMemo)(
3444
- () => Object.keys(data).filter(
3445
- (key) => typeof data[key] === "string" || typeof data[key] === "number"
3446
- ),
3447
- [data]
3448
- );
3453
+ const keys = (0, import_react26.useMemo)(() => {
3454
+ const validKeys = /* @__PURE__ */ new Set();
3455
+ for (const item of data) {
3456
+ for (const key of Object.keys(item)) {
3457
+ if (typeof item[key] === "string" || typeof item[key] === "number") {
3458
+ validKeys.add(key);
3459
+ }
3460
+ }
3461
+ }
3462
+ return Array.from(validKeys);
3463
+ }, [data]);
3449
3464
  (0, import_react26.useEffect)(() => {
3450
3465
  (() => __async(void 0, null, function* () {
3451
3466
  if (field.adaptor) {
@@ -3725,7 +3740,7 @@ init_react_import();
3725
3740
 
3726
3741
  // css-module:/home/runner/work/puck/puck/packages/core/components/ComponentList/styles.module.css#css-module
3727
3742
  init_react_import();
3728
- var styles_module_default7 = { "ComponentList": "_ComponentList_1f52d_1", "ComponentList-item": "_ComponentList-item_1f52d_9", "ComponentList-itemIcon": "_ComponentList-itemIcon_1f52d_26", "ComponentList--isDraggingFrom": "_ComponentList--isDraggingFrom_1f52d_30" };
3743
+ var styles_module_default7 = { "ComponentList": "_ComponentList_bvy0z_1", "ComponentList-item": "_ComponentList-item_bvy0z_6", "ComponentList-itemIcon": "_ComponentList-itemIcon_bvy0z_24", "ComponentList--isDraggingFrom": "_ComponentList--isDraggingFrom_bvy0z_28" };
3729
3744
 
3730
3745
  // components/ComponentList/index.tsx
3731
3746
  var import_jsx_runtime17 = require("react/jsx-runtime");
@@ -3747,15 +3762,16 @@ var ComponentList = ({ config }) => {
3747
3762
  index: i,
3748
3763
  showShadow: true,
3749
3764
  disableAnimations: true,
3750
- children: () => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: getClassName14("item"), children: [
3765
+ className: () => getClassName14("item"),
3766
+ children: () => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
3751
3767
  componentKey,
3752
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: getClassName14("itemIcon"), children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(grid_default, { size: 18 }) })
3768
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: getClassName14("itemIcon"), children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DragIcon, {}) })
3753
3769
  ] })
3754
3770
  },
3755
3771
  componentKey
3756
3772
  );
3757
3773
  }),
3758
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: { display: "none" }, children: provided.placeholder })
3774
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { display: "none" }, children: provided.placeholder })
3759
3775
  ]
3760
3776
  })
3761
3777
  ) });
@@ -3839,6 +3855,72 @@ var Heading = ({ children, rank, size = "m" }) => {
3839
3855
  );
3840
3856
  };
3841
3857
 
3858
+ // lib/use-breadcrumbs.ts
3859
+ init_react_import();
3860
+ var import_react28 = require("react");
3861
+ var convertPathDataToBreadcrumbs = (selectedItem, pathData, data) => {
3862
+ const id = selectedItem ? selectedItem == null ? void 0 : selectedItem.props.id : "";
3863
+ const currentPathData = pathData && id && pathData[id] ? __spreadValues({}, pathData[id]) : { label: "Page", path: [] };
3864
+ if (!id) {
3865
+ return [];
3866
+ }
3867
+ return currentPathData == null ? void 0 : currentPathData.path.reduce((acc, zoneCompound) => {
3868
+ const [area] = getZoneId(zoneCompound);
3869
+ if (area === rootDroppableId) {
3870
+ return [
3871
+ {
3872
+ label: "Page",
3873
+ selector: null
3874
+ }
3875
+ ];
3876
+ }
3877
+ const parentZoneCompound = acc.length > 0 ? acc[acc.length - 1].zoneCompound : rootDroppableId;
3878
+ let parentZone = data.content;
3879
+ if (parentZoneCompound && parentZoneCompound !== rootDroppableId) {
3880
+ parentZone = data.zones[parentZoneCompound];
3881
+ }
3882
+ if (!parentZone) {
3883
+ return acc;
3884
+ }
3885
+ const itemIndex = parentZone.findIndex(
3886
+ (queryItem) => queryItem.props.id === area
3887
+ );
3888
+ const item = parentZone[itemIndex];
3889
+ if (!item) {
3890
+ return acc;
3891
+ }
3892
+ return [
3893
+ ...acc,
3894
+ {
3895
+ label: item.type.toString(),
3896
+ selector: {
3897
+ index: itemIndex,
3898
+ zone: parentZoneCompound
3899
+ },
3900
+ zoneCompound
3901
+ }
3902
+ ];
3903
+ }, []);
3904
+ };
3905
+ var useBreadcrumbs = (renderCount) => {
3906
+ const {
3907
+ state: { data },
3908
+ selectedItem
3909
+ } = useAppContext();
3910
+ const dzContext = (0, import_react28.useContext)(dropZoneContext);
3911
+ return (0, import_react28.useMemo)(() => {
3912
+ const breadcrumbs = convertPathDataToBreadcrumbs(
3913
+ selectedItem,
3914
+ dzContext == null ? void 0 : dzContext.pathData,
3915
+ data
3916
+ );
3917
+ if (renderCount) {
3918
+ return breadcrumbs.slice(breadcrumbs.length - renderCount);
3919
+ }
3920
+ return breadcrumbs;
3921
+ }, [selectedItem, dzContext == null ? void 0 : dzContext.pathData, renderCount]);
3922
+ };
3923
+
3842
3924
  // components/SidebarSection/index.tsx
3843
3925
  var import_jsx_runtime19 = require("react/jsx-runtime");
3844
3926
  var getClassName16 = get_class_name_factory_default("SidebarSection", styles_module_default8);
@@ -3846,23 +3928,24 @@ var SidebarSection = ({
3846
3928
  children,
3847
3929
  title,
3848
3930
  background,
3849
- breadcrumbs = [],
3850
- breadcrumbClick,
3931
+ showBreadcrumbs,
3851
3932
  noPadding
3852
3933
  }) => {
3934
+ const { setUi } = useAppContext();
3935
+ const breadcrumbs = useBreadcrumbs(1);
3853
3936
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: getClassName16({ noPadding }), style: { background }, children: [
3854
3937
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: getClassName16("title"), children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: getClassName16("breadcrumbs"), children: [
3855
- breadcrumbs.map((breadcrumb, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: getClassName16("breadcrumb"), children: [
3938
+ showBreadcrumbs ? breadcrumbs.map((breadcrumb, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: getClassName16("breadcrumb"), children: [
3856
3939
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3857
3940
  "div",
3858
3941
  {
3859
3942
  className: getClassName16("breadcrumbLabel"),
3860
- onClick: () => breadcrumbClick && breadcrumbClick(breadcrumb),
3943
+ onClick: () => setUi({ itemSelector: breadcrumb.selector }),
3861
3944
  children: breadcrumb.label
3862
3945
  }
3863
3946
  ),
3864
3947
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(chevron_right_default, { size: 16 })
3865
- ] }, i)),
3948
+ ] }, i)) : null,
3866
3949
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: getClassName16("heading"), children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Heading, { rank: 2, size: "xs", children: title }) })
3867
3950
  ] }) }),
3868
3951
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: getClassName16("content"), children })
@@ -3874,15 +3957,15 @@ init_react_import();
3874
3957
 
3875
3958
  // lib/use-puck-history.ts
3876
3959
  init_react_import();
3877
- var import_react29 = require("react");
3960
+ var import_react30 = require("react");
3878
3961
 
3879
3962
  // lib/use-action-history.ts
3880
3963
  init_react_import();
3881
- var import_react28 = require("react");
3964
+ var import_react29 = require("react");
3882
3965
  var EMPTY_HISTORY_INDEX = -1;
3883
3966
  function useActionHistory() {
3884
- const [histories, setHistories] = (0, import_react28.useState)([]);
3885
- const [currentHistoryIndex, setCurrentHistoryIndex] = (0, import_react28.useState)(EMPTY_HISTORY_INDEX);
3967
+ const [histories, setHistories] = (0, import_react29.useState)([]);
3968
+ const [currentHistoryIndex, setCurrentHistoryIndex] = (0, import_react29.useState)(EMPTY_HISTORY_INDEX);
3886
3969
  const currentHistory = histories[currentHistoryIndex];
3887
3970
  const canRewind = currentHistoryIndex > EMPTY_HISTORY_INDEX;
3888
3971
  const canForward = currentHistoryIndex < histories.length - 1;
@@ -3926,35 +4009,42 @@ var import_use_debounce2 = require("use-debounce");
3926
4009
  var DEBOUNCE_TIME = 250;
3927
4010
  var RECORD_DIFF = "RECORD_DIFF";
3928
4011
  var historyEmitter = (0, import_event_emitter.default)();
3929
- var recordDiff = (newAppData) => historyEmitter.emit(RECORD_DIFF, newAppData);
3930
- var _recordHistory = ({ snapshot, newSnapshot, record, dispatch }) => {
4012
+ var recordDiff = (newAppState) => historyEmitter.emit(RECORD_DIFF, newAppState);
4013
+ var _recordHistory = ({
4014
+ snapshot,
4015
+ newSnapshot,
4016
+ record,
4017
+ dispatch
4018
+ }) => {
4019
+ if (JSON.stringify(snapshot) === JSON.stringify(newSnapshot))
4020
+ return;
3931
4021
  record({
3932
4022
  forward: () => {
3933
- dispatch({ type: "set", appData: newSnapshot });
4023
+ dispatch({ type: "set", state: newSnapshot });
3934
4024
  },
3935
4025
  rewind: () => {
3936
- dispatch({ type: "set", appData: snapshot });
4026
+ dispatch({ type: "set", state: snapshot });
3937
4027
  }
3938
4028
  });
3939
4029
  };
3940
4030
  function usePuckHistory({
3941
- appData,
4031
+ appState,
3942
4032
  dispatch
3943
4033
  }) {
3944
4034
  const { canForward, canRewind, rewind, forward, record } = useActionHistory();
3945
4035
  (0, import_react_hotkeys_hook.useHotkeys)("meta+z", rewind, { preventDefault: true });
3946
4036
  (0, import_react_hotkeys_hook.useHotkeys)("meta+shift+z", forward, { preventDefault: true });
3947
4037
  (0, import_react_hotkeys_hook.useHotkeys)("meta+y", forward, { preventDefault: true });
3948
- const [snapshot] = (0, import_use_debounce2.useDebounce)(appData, DEBOUNCE_TIME);
3949
- const handleRecordDiff = (0, import_use_debounce2.useDebouncedCallback)((newAppData) => {
4038
+ const [snapshot] = (0, import_use_debounce2.useDebounce)(appState, DEBOUNCE_TIME);
4039
+ const handleRecordDiff = (0, import_use_debounce2.useDebouncedCallback)((newAppState) => {
3950
4040
  return _recordHistory({
3951
4041
  snapshot,
3952
- newSnapshot: newAppData,
4042
+ newSnapshot: newAppState,
3953
4043
  record,
3954
4044
  dispatch
3955
4045
  });
3956
4046
  }, DEBOUNCE_TIME);
3957
- (0, import_react29.useEffect)(() => {
4047
+ (0, import_react30.useEffect)(() => {
3958
4048
  historyEmitter.on(RECORD_DIFF, handleRecordDiff);
3959
4049
  return () => {
3960
4050
  historyEmitter.off(RECORD_DIFF, handleRecordDiff);
@@ -4244,11 +4334,11 @@ var reduceData = (data, action, config) => {
4244
4334
 
4245
4335
  // reducer/state.ts
4246
4336
  init_react_import();
4247
- var reduceState = (state, action) => {
4248
- if (action.type === "setState") {
4249
- return __spreadValues(__spreadValues({}, state), action.state);
4337
+ var reduceState = (ui, action) => {
4338
+ if (action.type === "setUi") {
4339
+ return __spreadValues(__spreadValues({}, ui), action.ui);
4250
4340
  }
4251
- return state;
4341
+ return ui;
4252
4342
  };
4253
4343
 
4254
4344
  // reducer/actions.tsx
@@ -4256,8 +4346,8 @@ init_react_import();
4256
4346
 
4257
4347
  // reducer/index.ts
4258
4348
  var storeInterceptor = (reducer) => {
4259
- return (appData, action) => {
4260
- const newAppData = reducer(appData, action);
4349
+ return (state, action) => {
4350
+ const newAppState = reducer(state, action);
4261
4351
  const isValidType = ![
4262
4352
  "registerZone",
4263
4353
  "unregisterZone",
@@ -4266,18 +4356,18 @@ var storeInterceptor = (reducer) => {
4266
4356
  "set"
4267
4357
  ].includes(action.type);
4268
4358
  if (typeof action.recordHistory !== "undefined" ? action.recordHistory : isValidType) {
4269
- recordDiff(newAppData);
4359
+ recordDiff(newAppState);
4270
4360
  }
4271
- return newAppData;
4361
+ return newAppState;
4272
4362
  };
4273
4363
  };
4274
- var createReducer = ({ config }) => storeInterceptor((appData, action) => {
4275
- const data = reduceData(appData.data, action, config);
4276
- const state = reduceState(appData.state, action);
4364
+ var createReducer = ({ config }) => storeInterceptor((state, action) => {
4365
+ const data = reduceData(state.data, action, config);
4366
+ const ui = reduceState(state.ui, action);
4277
4367
  if (action.type === "set") {
4278
- return __spreadValues(__spreadValues({}, appData), action.appData);
4368
+ return __spreadValues(__spreadValues({}, state), action.state);
4279
4369
  }
4280
- return { data, state };
4370
+ return { data, ui };
4281
4371
  });
4282
4372
 
4283
4373
  // components/LayerTree/index.tsx
@@ -4299,7 +4389,7 @@ var scrollIntoView = (el) => {
4299
4389
  };
4300
4390
 
4301
4391
  // components/LayerTree/index.tsx
4302
- var import_react30 = require("react");
4392
+ var import_react31 = require("react");
4303
4393
 
4304
4394
  // lib/find-zones-for-area.ts
4305
4395
  init_react_import();
@@ -4318,12 +4408,9 @@ init_react_import();
4318
4408
  var isChildOfZone = (item, maybeChild, ctx) => {
4319
4409
  var _a;
4320
4410
  const { data, pathData = {} } = ctx || {};
4321
- return maybeChild && data ? !!((_a = pathData[maybeChild.props.id]) == null ? void 0 : _a.find((path) => {
4322
- if (path.selector) {
4323
- const pathItem = getItem(path.selector, data);
4324
- return (pathItem == null ? void 0 : pathItem.props.id) === item.props.id;
4325
- }
4326
- return false;
4411
+ return maybeChild && data ? !!((_a = pathData[maybeChild.props.id]) == null ? void 0 : _a.path.find((zoneCompound) => {
4412
+ const [area] = getZoneId(zoneCompound);
4413
+ return area === item.props.id;
4327
4414
  })) : false;
4328
4415
  };
4329
4416
 
@@ -4340,7 +4427,7 @@ var LayerTree = ({
4340
4427
  label
4341
4428
  }) => {
4342
4429
  const zones = data.zones || {};
4343
- const ctx = (0, import_react30.useContext)(dropZoneContext);
4430
+ const ctx = (0, import_react31.useContext)(dropZoneContext);
4344
4431
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
4345
4432
  label && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: getClassName17("zoneTitle"), children: [
4346
4433
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: getClassName17("zoneIcon"), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(layers_default, { size: "16" }) }),
@@ -4448,19 +4535,19 @@ var areaContainsZones = (data, area) => {
4448
4535
 
4449
4536
  // lib/flush-zones.ts
4450
4537
  init_react_import();
4451
- var flushZones = (appData) => {
4452
- const containsZones = typeof appData.data.zones !== "undefined";
4538
+ var flushZones = (appState) => {
4539
+ const containsZones = typeof appState.data.zones !== "undefined";
4453
4540
  if (containsZones) {
4454
- Object.keys(appData.data.zones || {}).forEach((zone) => {
4455
- addToZoneCache(zone, appData.data.zones[zone]);
4541
+ Object.keys(appState.data.zones || {}).forEach((zone) => {
4542
+ addToZoneCache(zone, appState.data.zones[zone]);
4456
4543
  });
4457
- return __spreadProps(__spreadValues({}, appData), {
4458
- data: __spreadProps(__spreadValues({}, appData.data), {
4544
+ return __spreadProps(__spreadValues({}, appState), {
4545
+ data: __spreadProps(__spreadValues({}, appState.data), {
4459
4546
  zones: {}
4460
4547
  })
4461
4548
  });
4462
4549
  }
4463
- return appData;
4550
+ return appState;
4464
4551
  };
4465
4552
 
4466
4553
  // components/Puck/index.tsx
@@ -4470,12 +4557,13 @@ var defaultPageFields = {
4470
4557
  };
4471
4558
  var PluginRenderer = ({
4472
4559
  children,
4473
- data,
4560
+ dispatch,
4561
+ state,
4474
4562
  plugins,
4475
4563
  renderMethod
4476
4564
  }) => {
4477
4565
  return plugins.filter((item) => item[renderMethod]).map((item) => item[renderMethod]).reduce(
4478
- (accChildren, Item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Item, { data, children: accChildren }),
4566
+ (accChildren, Item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Item, { dispatch, state, children: accChildren }),
4479
4567
  children
4480
4568
  );
4481
4569
  };
@@ -4491,35 +4579,31 @@ function Puck({
4491
4579
  headerPath
4492
4580
  }) {
4493
4581
  var _a, _b;
4494
- const [reducer] = (0, import_react31.useState)(() => createReducer({ config }));
4495
- const initialAppData = {
4496
- data: initialData,
4497
- state: {
4498
- leftSideBarVisible: true,
4499
- arrayState: {}
4500
- }
4501
- };
4502
- const [appData, dispatch] = (0, import_react31.useReducer)(
4582
+ const [reducer] = (0, import_react32.useState)(() => createReducer({ config }));
4583
+ const initialAppState = __spreadProps(__spreadValues({}, defaultAppState), {
4584
+ data: initialData
4585
+ });
4586
+ const [appState, dispatch] = (0, import_react32.useReducer)(
4503
4587
  reducer,
4504
- flushZones(initialAppData)
4588
+ flushZones(initialAppState)
4505
4589
  );
4506
- const { data, state } = appData;
4590
+ const { data, ui } = appState;
4507
4591
  const { canForward, canRewind, rewind, forward } = usePuckHistory({
4508
- appData,
4592
+ appState,
4509
4593
  dispatch
4510
4594
  });
4511
- const { itemSelector, leftSideBarVisible } = state;
4512
- const setItemSelector = (0, import_react31.useCallback)(
4595
+ const { itemSelector, leftSideBarVisible } = ui;
4596
+ const setItemSelector = (0, import_react32.useCallback)(
4513
4597
  (newItemSelector) => {
4514
4598
  dispatch({
4515
- type: "setState",
4516
- state: { itemSelector: newItemSelector }
4599
+ type: "setUi",
4600
+ ui: { itemSelector: newItemSelector }
4517
4601
  });
4518
4602
  },
4519
4603
  []
4520
4604
  );
4521
4605
  const selectedItem = itemSelector ? getItem(itemSelector, data) : null;
4522
- const Page = (0, import_react31.useCallback)(
4606
+ const Page = (0, import_react32.useCallback)(
4523
4607
  (pageProps) => {
4524
4608
  var _a2, _b2;
4525
4609
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
@@ -4527,32 +4611,35 @@ function Puck({
4527
4611
  {
4528
4612
  plugins,
4529
4613
  renderMethod: "renderRoot",
4530
- data: pageProps.data,
4614
+ dispatch: pageProps.dispatch,
4615
+ state: pageProps.state,
4531
4616
  children: ((_a2 = config.root) == null ? void 0 : _a2.render) ? (_b2 = config.root) == null ? void 0 : _b2.render(__spreadProps(__spreadValues({}, pageProps), { editMode: true })) : pageProps.children
4532
4617
  }
4533
4618
  );
4534
4619
  },
4535
4620
  [config.root]
4536
4621
  );
4537
- const PageFieldWrapper = (0, import_react31.useCallback)(
4622
+ const PageFieldWrapper = (0, import_react32.useCallback)(
4538
4623
  (props) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4539
4624
  PluginRenderer,
4540
4625
  {
4541
4626
  plugins,
4542
4627
  renderMethod: "renderRootFields",
4543
- data: props.data,
4628
+ dispatch: props.dispatch,
4629
+ state: props.state,
4544
4630
  children: props.children
4545
4631
  }
4546
4632
  ),
4547
4633
  []
4548
4634
  );
4549
- const ComponentFieldWrapper = (0, import_react31.useCallback)(
4635
+ const ComponentFieldWrapper = (0, import_react32.useCallback)(
4550
4636
  (props) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4551
4637
  PluginRenderer,
4552
4638
  {
4553
4639
  plugins,
4554
4640
  renderMethod: "renderFields",
4555
- data: props.data,
4641
+ dispatch: props.dispatch,
4642
+ state: props.state,
4556
4643
  children: props.children
4557
4644
  }
4558
4645
  ),
@@ -4561,13 +4648,13 @@ function Puck({
4561
4648
  const FieldWrapper = itemSelector ? ComponentFieldWrapper : PageFieldWrapper;
4562
4649
  const rootFields = ((_a = config.root) == null ? void 0 : _a.fields) || defaultPageFields;
4563
4650
  let fields = selectedItem ? ((_b = config.components[selectedItem.type]) == null ? void 0 : _b.fields) || {} : rootFields;
4564
- (0, import_react31.useEffect)(() => {
4651
+ (0, import_react32.useEffect)(() => {
4565
4652
  if (onChange)
4566
4653
  onChange(data);
4567
4654
  }, [data]);
4568
4655
  const { onDragStartOrUpdate, placeholderStyle } = usePlaceholderStyle();
4569
- const [draggedItem, setDraggedItem] = (0, import_react31.useState)();
4570
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "puck", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AppProvider, { value: { appData, dispatch }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4656
+ const [draggedItem, setDraggedItem] = (0, import_react32.useState)();
4657
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "puck", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AppProvider, { value: { state: appState, dispatch }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4571
4658
  import_react_beautiful_dnd5.DragDropContext,
4572
4659
  {
4573
4660
  onDragUpdate: (update) => {
@@ -4634,11 +4721,6 @@ function Puck({
4634
4721
  areaId: "root"
4635
4722
  },
4636
4723
  children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(dropZoneContext.Consumer, { children: (ctx) => {
4637
- let path = (ctx == null ? void 0 : ctx.pathData) && selectedItem ? ctx == null ? void 0 : ctx.pathData[selectedItem == null ? void 0 : selectedItem.props.id] : void 0;
4638
- if (path) {
4639
- path = [{ label: "Page", selector: null }, ...path];
4640
- path = path.slice(path.length - 2, path.length - 1);
4641
- }
4642
4724
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4643
4725
  "div",
4644
4726
  {
@@ -4675,8 +4757,8 @@ function Puck({
4675
4757
  children: "Publish"
4676
4758
  }
4677
4759
  ),
4678
- data,
4679
- dispatch
4760
+ dispatch,
4761
+ state: appState
4680
4762
  }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4681
4763
  "div",
4682
4764
  {
@@ -4699,8 +4781,8 @@ function Puck({
4699
4781
  IconButton,
4700
4782
  {
4701
4783
  onClick: () => dispatch({
4702
- type: "setState",
4703
- state: {
4784
+ type: "setUi",
4785
+ ui: {
4704
4786
  leftSideBarVisible: !leftSideBarVisible
4705
4787
  }
4706
4788
  }),
@@ -4771,7 +4853,10 @@ function Puck({
4771
4853
  }
4772
4854
  )
4773
4855
  ] }),
4774
- renderHeaderActions && renderHeaderActions({ data, dispatch }),
4856
+ renderHeaderActions && renderHeaderActions({
4857
+ state: appState,
4858
+ dispatch
4859
+ }),
4775
4860
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4776
4861
  Button,
4777
4862
  {
@@ -4862,7 +4947,15 @@ function Puck({
4862
4947
  style: {
4863
4948
  border: "1px solid var(--puck-color-grey-8)"
4864
4949
  },
4865
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Page, __spreadProps(__spreadValues({ data }, data.root), { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropZone, { zone: rootDroppableId }) }))
4950
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4951
+ Page,
4952
+ __spreadProps(__spreadValues({
4953
+ dispatch,
4954
+ state: appState
4955
+ }, data.root), {
4956
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropZone, { zone: rootDroppableId })
4957
+ })
4958
+ )
4866
4959
  }
4867
4960
  )
4868
4961
  }
@@ -4892,12 +4985,11 @@ function Puck({
4892
4985
  flexDirection: "column",
4893
4986
  background: "var(--puck-color-white)"
4894
4987
  },
4895
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FieldWrapper, { data, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4988
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FieldWrapper, { dispatch, state: appState, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4896
4989
  SidebarSection,
4897
4990
  {
4898
4991
  noPadding: true,
4899
- breadcrumbs: path,
4900
- breadcrumbClick: (breadcrumb) => setItemSelector(breadcrumb.selector),
4992
+ showBreadcrumbs: true,
4901
4993
  title: selectedItem ? selectedItem.type : "Page",
4902
4994
  children: Object.keys(fields).map((fieldName) => {
4903
4995
  var _a2, _b2, _c, _d;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@measured/puck",
3
- "version": "0.10.0-canary.ca4f4be",
3
+ "version": "0.10.0-canary.e308381",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",