@measured/puck 0.10.0-canary.ca4f4be → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -112,19 +112,32 @@ 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
 
119
- Here's a basic plugin that renders a "My plugin" heading in the root field area:
123
+ Here's an example plugin that creates a button to toggle the left side-bar:
120
124
 
121
125
  ```jsx
122
126
  const myPlugin = {
123
- renderRootFields: (props) => (
127
+ renderRootFields: ({ children, dispatch, state }) => (
124
128
  <div>
125
- {props.children}
126
-
127
- <h2>My plugin</h2>
129
+ {children}
130
+
131
+ <button
132
+ onClick={() => {
133
+ dispatch({
134
+ type: "setUi",
135
+ ui: { leftSideBarVisible: !state.ui.leftSideBarVisible },
136
+ });
137
+ }}
138
+ >
139
+ Toggle side-bar
140
+ </button>
128
141
  </div>
129
142
  ),
130
143
  };
@@ -285,9 +298,19 @@ A `Field` represents a user input field shown in the Puck interface.
285
298
  - **onChange** (`(value: any) => void`): Callback to change the value
286
299
  - **readOnly** (`boolean` | `undefined`): Whether or not the field should be in readOnly mode
287
300
 
301
+ ### `AppState`
302
+
303
+ The `AppState` object stores the puck application state.
304
+
305
+ - **data** (`Data`): The page data currently being rendered
306
+ - **ui** (`object`):
307
+ - **leftSideBarVisible** (boolean): Whether or not the left side bar is visible
308
+ - **itemSelector** (object): An object describing which item is selected
309
+ - **arrayState** (object): An object describing the internal state of array items
310
+
288
311
  ### `Data`
289
312
 
290
- The `Data` object stores the puck state.
313
+ The `Data` object stores the puck page data.
291
314
 
292
315
  - **root** (`object`):
293
316
  - **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",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",