@measured/puck 0.21.0-canary.b6ed9789 → 0.21.0-canary.bd7b613d

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.
@@ -24,7 +24,7 @@ import {
24
24
  walkAppState,
25
25
  walkField,
26
26
  walkTree
27
- } from "./chunk-XYKLHT4R.mjs";
27
+ } from "./chunk-FPQ7BWRD.mjs";
28
28
 
29
29
  // ../../node_modules/classnames/index.js
30
30
  var require_classnames = __commonJS({
@@ -88,6 +88,42 @@ var require_classnames = __commonJS({
88
88
  }
89
89
  });
90
90
 
91
+ // ../../node_modules/fast-deep-equal/index.js
92
+ var require_fast_deep_equal = __commonJS({
93
+ "../../node_modules/fast-deep-equal/index.js"(exports, module) {
94
+ "use strict";
95
+ init_react_import();
96
+ module.exports = function equal(a, b) {
97
+ if (a === b) return true;
98
+ if (a && b && typeof a == "object" && typeof b == "object") {
99
+ if (a.constructor !== b.constructor) return false;
100
+ var length, i, keys;
101
+ if (Array.isArray(a)) {
102
+ length = a.length;
103
+ if (length != b.length) return false;
104
+ for (i = length; i-- !== 0; )
105
+ if (!equal(a[i], b[i])) return false;
106
+ return true;
107
+ }
108
+ if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
109
+ if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
110
+ if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
111
+ keys = Object.keys(a);
112
+ length = keys.length;
113
+ if (length !== Object.keys(b).length) return false;
114
+ for (i = length; i-- !== 0; )
115
+ if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
116
+ for (i = length; i-- !== 0; ) {
117
+ var key = keys[i];
118
+ if (!equal(a[key], b[key])) return false;
119
+ }
120
+ return true;
121
+ }
122
+ return a !== a && b !== b;
123
+ };
124
+ }
125
+ });
126
+
91
127
  // types/API/Overrides.ts
92
128
  init_react_import();
93
129
  var overrideKeys = [
@@ -768,7 +804,9 @@ var keyCodeMap = {
768
804
  KeyW: "w",
769
805
  KeyX: "x",
770
806
  KeyY: "y",
771
- KeyZ: "z"
807
+ KeyZ: "z",
808
+ Delete: "delete",
809
+ Backspace: "backspace"
772
810
  };
773
811
  var useHotkeyStore = create()(
774
812
  subscribeWithSelector((set) => ({
@@ -792,8 +830,10 @@ var monitorHotkeys = (doc) => {
792
830
  ([key2, value]) => value === !!combo[key2]
793
831
  );
794
832
  if (conditionMet) {
795
- e.preventDefault();
796
- cb();
833
+ const handled = cb(e);
834
+ if (handled !== false) {
835
+ e.preventDefault();
836
+ }
797
837
  }
798
838
  });
799
839
  if (key !== "meta" && key !== "ctrl" && key !== "shift") {
@@ -1017,7 +1057,7 @@ var flattenData = (state, config) => {
1017
1057
  (content) => content,
1018
1058
  (item) => {
1019
1059
  data.push(item);
1020
- return null;
1060
+ return item;
1021
1061
  }
1022
1062
  );
1023
1063
  return data;
@@ -1173,6 +1213,7 @@ var useRegisterFieldsSlice = (appStore, id) => {
1173
1213
  (reset) => __async(void 0, null, function* () {
1174
1214
  var _a, _b;
1175
1215
  const { fields, lastResolvedData } = appStore.getState().fields;
1216
+ const metadata = appStore.getState().metadata;
1176
1217
  const nodes = appStore.getState().state.indexes.nodes;
1177
1218
  const node = nodes[id || "root"];
1178
1219
  const componentData = node == null ? void 0 : node.data;
@@ -1202,6 +1243,7 @@ var useRegisterFieldsSlice = (appStore, id) => {
1202
1243
  changed,
1203
1244
  fields: defaultFields2,
1204
1245
  lastFields,
1246
+ metadata: __spreadValues(__spreadValues({}, metadata), componentConfig.metadata),
1205
1247
  lastData,
1206
1248
  appState: makeStatePublic(state),
1207
1249
  parent
@@ -2670,8 +2712,7 @@ var NestedFieldProvider = ({
2670
2712
  name,
2671
2713
  subName,
2672
2714
  wildcardName = name,
2673
- readOnlyFields,
2674
- value
2715
+ readOnlyFields
2675
2716
  }) => {
2676
2717
  const subPath = `${name}.${subName}`;
2677
2718
  const wildcardSubPath = `${wildcardName}.${subName}`;
@@ -2694,7 +2735,7 @@ var NestedFieldProvider = ({
2694
2735
  return /* @__PURE__ */ jsx7(
2695
2736
  NestedFieldContext.Provider,
2696
2737
  {
2697
- value: { readOnlyFields: subReadOnlyFields, localName: subName, value },
2738
+ value: { readOnlyFields: subReadOnlyFields, localName: subName },
2698
2739
  children
2699
2740
  }
2700
2741
  );
@@ -2727,15 +2768,16 @@ var SubFieldInternal = ({
2727
2768
  subName,
2728
2769
  localName,
2729
2770
  onChange,
2730
- forceReadOnly
2771
+ forceReadOnly,
2772
+ value
2731
2773
  }) => {
2732
2774
  const indexName = typeof index !== "undefined" ? `${name}[${index}]` : name;
2733
- const subPath = `${indexName}.${subName}`;
2775
+ const subPath = name ? `${indexName}.${subName}` : subName;
2734
2776
  const localIndexName = typeof index !== "undefined" ? `${localName}[${index}]` : localName != null ? localName : subName;
2735
2777
  const localWildcardName = typeof index !== "undefined" ? `${localName}[*]` : localName;
2736
2778
  const localSubPath = `${localIndexName}.${subName}`;
2737
2779
  const localWildcardSubPath = `${localWildcardName}.${subName}`;
2738
- const { readOnlyFields, value } = useNestedFieldContext();
2780
+ const { readOnlyFields } = useNestedFieldContext();
2739
2781
  const subReadOnly = forceReadOnly ? forceReadOnly : typeof readOnlyFields[subPath] !== "undefined" ? readOnlyFields[localSubPath] : readOnlyFields[localWildcardSubPath];
2740
2782
  const label = field.label || subName;
2741
2783
  return /* @__PURE__ */ jsx8(
@@ -2759,7 +2801,6 @@ var SubFieldInternal = ({
2759
2801
  onChange: (val, ui) => {
2760
2802
  onChange(val, ui, subName);
2761
2803
  },
2762
- provideValue: typeof value !== "undefined",
2763
2804
  value: typeof value !== "undefined" ? getDeep(value, subPath) : void 0
2764
2805
  }
2765
2806
  )
@@ -2770,7 +2811,7 @@ var SubFieldInternal = ({
2770
2811
  var SubField = memo(SubFieldInternal);
2771
2812
 
2772
2813
  // components/AutoField/fields/ArrayField/index.tsx
2773
- import fdeq from "fast-deep-equal";
2814
+ var import_fast_deep_equal = __toESM(require_fast_deep_equal());
2774
2815
  import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
2775
2816
  var getClassName6 = get_class_name_factory_default("ArrayField", styles_module_default4);
2776
2817
  var getClassNameItem = get_class_name_factory_default("ArrayFieldItem", styles_module_default4);
@@ -2787,14 +2828,15 @@ var ArrayFieldItemInternal = ({
2787
2828
  actions,
2788
2829
  name,
2789
2830
  localName,
2790
- getValue
2831
+ getValue,
2832
+ value
2791
2833
  }) => {
2792
2834
  const isExpanded = useAppStore((s) => {
2793
2835
  var _a;
2794
2836
  return ((_a = s.state.ui.arrayState[arrayId]) == null ? void 0 : _a.openId) === id;
2795
2837
  });
2796
2838
  const itemSummary = useAppStore(() => {
2797
- const data = getValue();
2839
+ const data = value != null ? value : getValue();
2798
2840
  if (data && field.getItemSummary) {
2799
2841
  return field.getItemSummary(data, index);
2800
2842
  }
@@ -2845,7 +2887,8 @@ var ArrayFieldItemInternal = ({
2845
2887
  index,
2846
2888
  field: subField,
2847
2889
  onChange,
2848
- forceReadOnly: !canEdit
2890
+ forceReadOnly: !canEdit,
2891
+ value: value == null ? void 0 : value[index]
2849
2892
  },
2850
2893
  subName
2851
2894
  );
@@ -2870,16 +2913,19 @@ var ArrayField = ({
2870
2913
  const appStoreApi = useAppStoreApi();
2871
2914
  const { localName = name } = useNestedFieldContext();
2872
2915
  const getValue = useCallback2(() => {
2873
- var _a;
2916
+ var _a, _b;
2874
2917
  if (typeof value !== "undefined") return value;
2875
2918
  const { selectedItem } = appStoreApi.getState();
2876
2919
  const props = (_a = name ? selectedItem == null ? void 0 : selectedItem.props : {}) != null ? _a : {};
2877
- return name ? getDeep(props, name) : [];
2920
+ return name ? (_b = getDeep(props, name)) != null ? _b : [] : [];
2878
2921
  }, [appStoreApi, name, value]);
2879
2922
  const getArrayState = useCallback2(() => {
2923
+ var _a;
2880
2924
  const { state } = appStoreApi.getState();
2925
+ const thisState = state.ui.arrayState[id];
2926
+ if ((_a = thisState == null ? void 0 : thisState.items) == null ? void 0 : _a.length) return thisState;
2881
2927
  const value2 = getValue();
2882
- return state.ui.arrayState[id] || {
2928
+ return {
2883
2929
  items: Array.from(value2 || []).map((item, idx) => {
2884
2930
  return {
2885
2931
  _originalIndex: idx,
@@ -2889,11 +2935,12 @@ var ArrayField = ({
2889
2935
  }),
2890
2936
  openId: ""
2891
2937
  };
2892
- }, [appStoreApi]);
2938
+ }, [appStoreApi, id, getValue]);
2893
2939
  const numItems = useAppStore((s) => {
2894
2940
  var _a, _b;
2895
- const value2 = name ? (_b = (_a = appStoreApi.getState().selectedItem) == null ? void 0 : _a.props[name]) != null ? _b : [] : [];
2896
- return value2.length;
2941
+ const { selectedItem } = s;
2942
+ const props = (_a = name ? selectedItem == null ? void 0 : selectedItem.props : {}) != null ? _a : {};
2943
+ return (name ? (_b = getDeep(props, name)) != null ? _b : [] : []).length;
2897
2944
  });
2898
2945
  const [mirror, setLocalState] = useState4(getArrayState());
2899
2946
  const appStore = useAppStoreApi();
@@ -2981,7 +3028,25 @@ var ArrayField = ({
2981
3028
  },
2982
3029
  [regenerateArrayState, setUi, mapArrayStateToUi, onChange, setLocalState]
2983
3030
  );
3031
+ const reset = useCallback2(
3032
+ (value2) => {
3033
+ valueRef.current = value2;
3034
+ const newArrayState = regenerateArrayState(valueRef.current);
3035
+ if (!(0, import_fast_deep_equal.default)(newArrayState, getArrayState())) {
3036
+ setUi(mapArrayStateToUi(newArrayState), false);
3037
+ setLocalState(newArrayState);
3038
+ }
3039
+ },
3040
+ [
3041
+ regenerateArrayState,
3042
+ mapArrayStateToUi,
3043
+ setUi,
3044
+ setLocalState,
3045
+ getArrayState
3046
+ ]
3047
+ );
2984
3048
  useEffect6(() => {
3049
+ if (value) return;
2985
3050
  return appStoreApi.subscribe(
2986
3051
  ({ selectedItem }) => {
2987
3052
  var _a;
@@ -2989,15 +3054,15 @@ var ArrayField = ({
2989
3054
  return name ? getDeep(props, name) : [];
2990
3055
  },
2991
3056
  (val) => {
2992
- if (!fdeq(val, valueRef.current)) {
2993
- valueRef.current = val;
2994
- const newArrayState = regenerateArrayState(valueRef.current);
2995
- setUi(mapArrayStateToUi(newArrayState), false);
2996
- setLocalState(newArrayState);
3057
+ if (!(0, import_fast_deep_equal.default)(val, valueRef.current)) {
3058
+ reset(val);
2997
3059
  }
2998
3060
  }
2999
3061
  );
3000
- }, [appStoreApi]);
3062
+ }, [appStoreApi, name, value]);
3063
+ useEffect6(() => {
3064
+ reset(getValue());
3065
+ }, [reset, getValue, name]);
3001
3066
  if (field.type !== "array" || !field.arrayFields) {
3002
3067
  return null;
3003
3068
  }
@@ -3071,6 +3136,7 @@ var ArrayField = ({
3071
3136
  field,
3072
3137
  name,
3073
3138
  localName,
3139
+ value,
3074
3140
  getValue: () => {
3075
3141
  const value2 = getValue();
3076
3142
  return value2[_currentIndex];
@@ -3475,7 +3541,6 @@ var ExternalInput = ({
3475
3541
  id: `external_field_${fieldName}_filter`,
3476
3542
  label: filterField.label || fieldName,
3477
3543
  value: filters[fieldName],
3478
- provideValue: true,
3479
3544
  onChange: (value2) => {
3480
3545
  setFilters((filters2) => {
3481
3546
  const newFilters = __spreadProps(__spreadValues({}, filters2), {
@@ -3764,7 +3829,7 @@ var ObjectField = ({
3764
3829
  if (typeof value !== "undefined") return value;
3765
3830
  const { selectedItem } = appStoreApi.getState();
3766
3831
  const props = (_a = name ? selectedItem == null ? void 0 : selectedItem.props : {}) != null ? _a : {};
3767
- return name ? getDeep(props, name) : [];
3832
+ return name ? getDeep(props, name) : {};
3768
3833
  }, [appStoreApi, name, value]);
3769
3834
  if (field.type !== "object" || !field.objectFields) {
3770
3835
  return null;
@@ -3788,11 +3853,10 @@ var ObjectField = ({
3788
3853
  localName,
3789
3854
  field: subField,
3790
3855
  forceReadOnly: !canEdit,
3856
+ value,
3791
3857
  onChange: (subValue, ui, subName2) => {
3792
3858
  const value2 = getValue();
3793
- if (value2 && name) {
3794
- onChange(__spreadProps(__spreadValues({}, value2), { [subName2]: subValue }), ui);
3795
- }
3859
+ onChange(__spreadProps(__spreadValues({}, value2), { [subName2]: subValue }), ui);
3796
3860
  }
3797
3861
  },
3798
3862
  subPath
@@ -3873,18 +3937,13 @@ var defaultFields = {
3873
3937
  text: DefaultField,
3874
3938
  number: DefaultField
3875
3939
  };
3876
- function AutoFieldInternal(_a) {
3877
- var _b = _a, {
3878
- provideValue
3879
- } = _b, props = __objRest(_b, [
3880
- "provideValue"
3881
- ]);
3882
- var _a2;
3940
+ function AutoFieldInternal(props) {
3941
+ var _a;
3883
3942
  const dispatch = useAppStore((s) => s.dispatch);
3884
3943
  const overrides = useAppStore((s) => s.overrides);
3885
3944
  const readOnly = useAppStore(useShallow((s) => {
3886
- var _a3;
3887
- return (_a3 = s.selectedItem) == null ? void 0 : _a3.readOnly;
3945
+ var _a2;
3946
+ return (_a2 = s.selectedItem) == null ? void 0 : _a2.readOnly;
3888
3947
  }));
3889
3948
  const nestedFieldContext = useContext3(NestedFieldContext);
3890
3949
  const { id, Label: Label2 = FieldLabelInternal } = props;
@@ -3895,10 +3954,10 @@ function AutoFieldInternal(_a) {
3895
3954
  const resolvedId = id || defaultId;
3896
3955
  const render = useMemo3(
3897
3956
  () => {
3898
- var _a3, _b2, _c, _d, _e, _f, _g, _h;
3957
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
3899
3958
  return __spreadProps(__spreadValues({}, overrides.fieldTypes), {
3900
- array: ((_a3 = overrides.fieldTypes) == null ? void 0 : _a3.array) || defaultFields.array,
3901
- external: ((_b2 = overrides.fieldTypes) == null ? void 0 : _b2.external) || defaultFields.external,
3959
+ array: ((_a2 = overrides.fieldTypes) == null ? void 0 : _a2.array) || defaultFields.array,
3960
+ external: ((_b = overrides.fieldTypes) == null ? void 0 : _b.external) || defaultFields.external,
3902
3961
  object: ((_c = overrides.fieldTypes) == null ? void 0 : _c.object) || defaultFields.object,
3903
3962
  select: ((_d = overrides.fieldTypes) == null ? void 0 : _d.select) || defaultFields.select,
3904
3963
  textarea: ((_e = overrides.fieldTypes) == null ? void 0 : _e.textarea) || defaultFields.textarea,
@@ -3974,9 +4033,7 @@ function AutoFieldInternal(_a) {
3974
4033
  {
3975
4034
  value: {
3976
4035
  readOnlyFields: nestedFieldContext.readOnlyFields || readOnly || {},
3977
- localName: (_a2 = nestedFieldContext.localName) != null ? _a2 : mergedProps.name,
3978
- value: provideValue && mergedProps.name ? { [mergedProps.name]: mergedProps.value } : void 0
3979
- // Optionally provide value if this is used outside of app fields (i.e. external field filters)
4036
+ localName: (_a = nestedFieldContext.localName) != null ? _a : mergedProps.name
3980
4037
  },
3981
4038
  children: /* @__PURE__ */ jsx19(
3982
4039
  "div",
@@ -4055,13 +4112,7 @@ function AutoField(props) {
4055
4112
  if (props.field.type === "slot") {
4056
4113
  return null;
4057
4114
  }
4058
- return /* @__PURE__ */ jsx19(
4059
- AutoFieldInternal,
4060
- __spreadProps(__spreadValues({}, props), {
4061
- Label: DefaultLabel,
4062
- provideValue: true
4063
- })
4064
- );
4115
+ return /* @__PURE__ */ jsx19(AutoFieldInternal, __spreadProps(__spreadValues({}, props), { Label: DefaultLabel }));
4065
4116
  }
4066
4117
 
4067
4118
  // components/Render/index.tsx
@@ -5910,7 +5961,7 @@ var registerOverlayPortal = (el, opts = {}) => {
5910
5961
 
5911
5962
  // css-module:/home/runner/work/puck/puck/packages/core/components/InlineTextField/styles.module.css#css-module
5912
5963
  init_react_import();
5913
- var styles_module_default13 = { "InlineTextField": "_InlineTextField_ilw2a_1" };
5964
+ var styles_module_default13 = { "InlineTextField": "_InlineTextField_1xph6_1" };
5914
5965
 
5915
5966
  // lib/data/set-deep.ts
5916
5967
  init_react_import();
@@ -5992,7 +6043,11 @@ var InlineTextFieldInternal = ({
5992
6043
  const index = (_a2 = appStore2.state.indexes.zones[zoneCompound]) == null ? void 0 : _a2.contentIds.indexOf(
5993
6044
  componentId
5994
6045
  );
5995
- const newProps = setDeep(node.data.props, propPath, e.target.innerText);
6046
+ let value2 = e.target.innerText;
6047
+ if (disableLineBreaks) {
6048
+ value2 = value2.replaceAll(/\n/gm, "");
6049
+ }
6050
+ const newProps = setDeep(node.data.props, propPath, value2);
5996
6051
  const resolvedData = yield appStore2.resolveComponentData(
5997
6052
  __spreadProps(__spreadValues({}, node.data), { props: newProps }),
5998
6053
  "replace"
@@ -6011,7 +6066,7 @@ var InlineTextFieldInternal = ({
6011
6066
  cleanupPortal == null ? void 0 : cleanupPortal();
6012
6067
  };
6013
6068
  }
6014
- }, [appStoreApi, ref.current, value]);
6069
+ }, [appStoreApi, ref.current, value, disableLineBreaks]);
6015
6070
  const [isHovering, setIsHovering] = useState16(false);
6016
6071
  const [isFocused, setIsFocused] = useState16(false);
6017
6072
  return /* @__PURE__ */ jsx25(
@@ -6760,7 +6815,13 @@ var useComponentList = () => {
6760
6815
  let _componentList;
6761
6816
  _componentList = Object.entries(uiComponentList).map(
6762
6817
  ([categoryKey, category]) => {
6763
- if (category.visible === false || !category.components) {
6818
+ if (!category.components) {
6819
+ return null;
6820
+ }
6821
+ category.components.forEach((componentName) => {
6822
+ matchedComponents.push(componentName);
6823
+ });
6824
+ if (category.visible === false) {
6764
6825
  return null;
6765
6826
  }
6766
6827
  return /* @__PURE__ */ jsx30(
@@ -6770,7 +6831,6 @@ var useComponentList = () => {
6770
6831
  title: category.title || categoryKey,
6771
6832
  children: category.components.map((componentName, i) => {
6772
6833
  var _a2;
6773
- matchedComponents.push(componentName);
6774
6834
  const componentConf = config.components[componentName] || {};
6775
6835
  return /* @__PURE__ */ jsx30(
6776
6836
  ComponentList.Item,
@@ -7352,7 +7412,7 @@ var fieldsPlugin = ({ mobileOnly = true } = {}) => ({
7352
7412
  init_react_import();
7353
7413
  import {
7354
7414
  createContext as createContext8,
7355
- useCallback as useCallback21,
7415
+ useCallback as useCallback22,
7356
7416
  useContext as useContext13,
7357
7417
  useEffect as useEffect30,
7358
7418
  useMemo as useMemo21,
@@ -7842,7 +7902,7 @@ var useLoadedOverrides = ({
7842
7902
  };
7843
7903
 
7844
7904
  // components/Puck/index.tsx
7845
- import fdeq2 from "fast-deep-equal";
7905
+ var import_fast_deep_equal2 = __toESM(require_fast_deep_equal());
7846
7906
 
7847
7907
  // components/Puck/components/Layout/index.tsx
7848
7908
  init_react_import();
@@ -8259,88 +8319,98 @@ var ViewportControls = ({
8259
8319
  setActiveViewport(uiViewports.current.width);
8260
8320
  }, [uiViewports.current]);
8261
8321
  const [isExpanded, setIsExpanded] = useState22(false);
8262
- return /* @__PURE__ */ jsxs20("div", { className: getClassName31({ isExpanded, fullScreen }), children: [
8263
- /* @__PURE__ */ jsx45("div", { className: getClassName31("actions"), children: /* @__PURE__ */ jsxs20("div", { className: getClassName31("actionsInner"), children: [
8264
- viewports.map((viewport, i) => /* @__PURE__ */ jsx45(
8265
- ActionButton,
8266
- {
8267
- title: viewport.label ? `Switch to ${viewport.label} viewport` : "Switch viewport",
8268
- onClick: () => {
8269
- setActiveViewport(viewport.width);
8270
- onViewportChange(viewport);
8271
- },
8272
- isActive: activeViewport === viewport.width,
8273
- children: typeof viewport.icon === "string" ? icons[viewport.icon] || viewport.icon : viewport.icon || icons.Smartphone
8274
- },
8275
- i
8276
- )),
8277
- /* @__PURE__ */ jsx45("div", { className: getClassName31("divider") }),
8278
- /* @__PURE__ */ jsx45(
8279
- ActionButton,
8280
- {
8281
- title: "Zoom viewport out",
8282
- disabled: zoom <= ((_a = zoomOptions[0]) == null ? void 0 : _a.value),
8283
- onClick: (e) => {
8284
- e.stopPropagation();
8285
- onZoom(
8286
- zoomOptions[Math.max(
8287
- zoomOptions.findIndex((option) => option.value === zoom) - 1,
8288
- 0
8289
- )].value
8290
- );
8291
- },
8292
- children: /* @__PURE__ */ jsx45(ZoomOut, { size: 16 })
8293
- }
8294
- ),
8295
- /* @__PURE__ */ jsx45(
8296
- ActionButton,
8297
- {
8298
- title: "Zoom viewport in",
8299
- disabled: zoom >= ((_b = zoomOptions[zoomOptions.length - 1]) == null ? void 0 : _b.value),
8300
- onClick: (e) => {
8301
- e.stopPropagation();
8302
- onZoom(
8303
- zoomOptions[Math.min(
8304
- zoomOptions.findIndex((option) => option.value === zoom) + 1,
8305
- zoomOptions.length - 1
8306
- )].value
8307
- );
8308
- },
8309
- children: /* @__PURE__ */ jsx45(ZoomIn, { size: 16 })
8310
- }
8311
- ),
8312
- /* @__PURE__ */ jsxs20("div", { className: getClassName31("zoom"), children: [
8313
- /* @__PURE__ */ jsx45("div", { className: getClassName31("divider") }),
8314
- /* @__PURE__ */ jsx45(
8315
- "select",
8316
- {
8317
- className: getClassName31("zoomSelect"),
8318
- value: zoom.toString(),
8319
- onChange: (e) => {
8320
- onZoom(parseFloat(e.currentTarget.value));
8322
+ return /* @__PURE__ */ jsxs20(
8323
+ "div",
8324
+ {
8325
+ className: getClassName31({ isExpanded, fullScreen }),
8326
+ suppressHydrationWarning: true,
8327
+ children: [
8328
+ /* @__PURE__ */ jsx45("div", { className: getClassName31("actions"), children: /* @__PURE__ */ jsxs20("div", { className: getClassName31("actionsInner"), children: [
8329
+ viewports.map((viewport, i) => /* @__PURE__ */ jsx45(
8330
+ ActionButton,
8331
+ {
8332
+ title: viewport.label ? `Switch to ${viewport.label} viewport` : "Switch viewport",
8333
+ onClick: () => {
8334
+ setActiveViewport(viewport.width);
8335
+ onViewportChange(viewport);
8336
+ },
8337
+ isActive: activeViewport === viewport.width,
8338
+ children: typeof viewport.icon === "string" ? icons[viewport.icon] || viewport.icon : viewport.icon || icons.Smartphone
8321
8339
  },
8322
- children: zoomOptions.map((option) => /* @__PURE__ */ jsx45(
8323
- "option",
8324
- {
8325
- value: option.value,
8326
- label: option.label
8340
+ i
8341
+ )),
8342
+ /* @__PURE__ */ jsx45("div", { className: getClassName31("divider") }),
8343
+ /* @__PURE__ */ jsx45(
8344
+ ActionButton,
8345
+ {
8346
+ title: "Zoom viewport out",
8347
+ disabled: zoom <= ((_a = zoomOptions[0]) == null ? void 0 : _a.value),
8348
+ onClick: (e) => {
8349
+ e.stopPropagation();
8350
+ onZoom(
8351
+ zoomOptions[Math.max(
8352
+ zoomOptions.findIndex((option) => option.value === zoom) - 1,
8353
+ 0
8354
+ )].value
8355
+ );
8356
+ },
8357
+ children: /* @__PURE__ */ jsx45(ZoomOut, { size: 16 })
8358
+ }
8359
+ ),
8360
+ /* @__PURE__ */ jsx45(
8361
+ ActionButton,
8362
+ {
8363
+ title: "Zoom viewport in",
8364
+ disabled: zoom >= ((_b = zoomOptions[zoomOptions.length - 1]) == null ? void 0 : _b.value),
8365
+ onClick: (e) => {
8366
+ e.stopPropagation();
8367
+ onZoom(
8368
+ zoomOptions[Math.min(
8369
+ zoomOptions.findIndex((option) => option.value === zoom) + 1,
8370
+ zoomOptions.length - 1
8371
+ )].value
8372
+ );
8327
8373
  },
8328
- option.label
8329
- ))
8374
+ children: /* @__PURE__ */ jsx45(ZoomIn, { size: 16 })
8375
+ }
8376
+ ),
8377
+ /* @__PURE__ */ jsxs20("div", { className: getClassName31("zoom"), children: [
8378
+ /* @__PURE__ */ jsx45("div", { className: getClassName31("divider") }),
8379
+ /* @__PURE__ */ jsx45(
8380
+ "select",
8381
+ {
8382
+ className: getClassName31("zoomSelect"),
8383
+ value: zoom.toString(),
8384
+ onClick: (e) => {
8385
+ e.stopPropagation();
8386
+ },
8387
+ onChange: (e) => {
8388
+ onZoom(parseFloat(e.currentTarget.value));
8389
+ },
8390
+ children: zoomOptions.map((option) => /* @__PURE__ */ jsx45(
8391
+ "option",
8392
+ {
8393
+ value: option.value,
8394
+ label: option.label
8395
+ },
8396
+ option.label
8397
+ ))
8398
+ }
8399
+ )
8400
+ ] })
8401
+ ] }) }),
8402
+ /* @__PURE__ */ jsx45(
8403
+ "button",
8404
+ {
8405
+ className: getClassName31("toggleButton"),
8406
+ title: "Toggle viewport menu",
8407
+ onClick: () => setIsExpanded((s) => !s),
8408
+ children: isExpanded ? /* @__PURE__ */ jsx45(X, { size: 16 }) : /* @__PURE__ */ jsx45(Monitor, { size: 16 })
8330
8409
  }
8331
8410
  )
8332
- ] })
8333
- ] }) }),
8334
- /* @__PURE__ */ jsx45(
8335
- "button",
8336
- {
8337
- className: getClassName31("toggleButton"),
8338
- title: "Toggle viewport menu",
8339
- onClick: () => setIsExpanded((s) => !s),
8340
- children: isExpanded ? /* @__PURE__ */ jsx45(X, { size: 16 }) : /* @__PURE__ */ jsx45(Monitor, { size: 16 })
8341
- }
8342
- )
8343
- ] });
8411
+ ]
8412
+ }
8413
+ );
8344
8414
  };
8345
8415
 
8346
8416
  // css-module:/home/runner/work/puck/puck/packages/core/components/Puck/components/Canvas/styles.module.css#css-module
@@ -8515,8 +8585,7 @@ var Canvas = () => {
8515
8585
  zoom: zoomConfig.zoom
8516
8586
  });
8517
8587
  const newUi = {
8518
- viewports: __spreadProps(__spreadValues({}, viewports), { current: uiViewport }),
8519
- itemSelector: null
8588
+ viewports: __spreadProps(__spreadValues({}, viewports), { current: uiViewport })
8520
8589
  };
8521
8590
  setUi(newUi);
8522
8591
  if (ZOOM_ON_CHANGE) {
@@ -8758,6 +8827,67 @@ var Sidebar = ({
8758
8827
  ] });
8759
8828
  };
8760
8829
 
8830
+ // lib/use-delete-hotkeys.ts
8831
+ init_react_import();
8832
+ import { useCallback as useCallback21 } from "react";
8833
+ var isElementVisible = (element) => {
8834
+ let current = element;
8835
+ while (current && current !== document.body) {
8836
+ const style = window.getComputedStyle(current);
8837
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || current.getAttribute("aria-hidden") === "true" || current.hasAttribute("hidden")) {
8838
+ return false;
8839
+ }
8840
+ current = current.parentElement;
8841
+ }
8842
+ return true;
8843
+ };
8844
+ var shouldBlockDeleteHotkey = (e) => {
8845
+ var _a;
8846
+ if (e == null ? void 0 : e.defaultPrevented) return true;
8847
+ const origin = ((_a = e == null ? void 0 : e.composedPath) == null ? void 0 : _a.call(e)[0]) || (e == null ? void 0 : e.target) || document.activeElement;
8848
+ if (origin instanceof HTMLElement) {
8849
+ const tag = origin.tagName.toLowerCase();
8850
+ if (tag === "input" || tag === "textarea" || tag === "select") return true;
8851
+ if (origin.isContentEditable) return true;
8852
+ const role = origin.getAttribute("role");
8853
+ if (role === "textbox" || role === "combobox" || role === "searchbox" || role === "listbox" || role === "grid") {
8854
+ return true;
8855
+ }
8856
+ }
8857
+ const modal = document.querySelector(
8858
+ 'dialog[open], [aria-modal="true"], [role="dialog"], [role="alertdialog"]'
8859
+ );
8860
+ if (modal && isElementVisible(modal)) {
8861
+ return true;
8862
+ }
8863
+ return false;
8864
+ };
8865
+ var useDeleteHotkeys = () => {
8866
+ const appStore = useAppStoreApi();
8867
+ const deleteSelectedComponent = useCallback21(
8868
+ (e) => {
8869
+ var _a;
8870
+ if (shouldBlockDeleteHotkey(e)) {
8871
+ return false;
8872
+ }
8873
+ const { state, dispatch, permissions, selectedItem } = appStore.getState();
8874
+ const sel = (_a = state.ui) == null ? void 0 : _a.itemSelector;
8875
+ if (!(sel == null ? void 0 : sel.zone) || !selectedItem) return true;
8876
+ if (!permissions.getPermissions({ item: selectedItem }).delete)
8877
+ return true;
8878
+ dispatch({
8879
+ type: "remove",
8880
+ index: sel.index,
8881
+ zone: sel.zone
8882
+ });
8883
+ return true;
8884
+ },
8885
+ [appStore]
8886
+ );
8887
+ useHotkey({ delete: true }, deleteSelectedComponent);
8888
+ useHotkey({ backspace: true }, deleteSelectedComponent);
8889
+ };
8890
+
8761
8891
  // components/Puck/components/Nav/index.tsx
8762
8892
  init_react_import();
8763
8893
 
@@ -8889,6 +9019,7 @@ var Layout = ({ children }) => {
8889
9019
  }
8890
9020
  }, [ready, iframe.enabled]);
8891
9021
  usePreviewModeHotkeys();
9022
+ useDeleteHotkeys();
8892
9023
  const layoutOptions = {};
8893
9024
  if (leftWidth) {
8894
9025
  layoutOptions["--puck-user-left-side-bar-width"] = `${leftWidth}px`;
@@ -9098,12 +9229,12 @@ function PuckProvider({ children }) {
9098
9229
  const viewportDifferences = Object.entries(viewports).filter(([_, value]) => value.width !== "100%").map(([key, value]) => ({
9099
9230
  key,
9100
9231
  diff: Math.abs(
9101
- viewportWidth - (typeof value.width === "string" ? viewportWidth : viewportWidth)
9232
+ viewportWidth - (typeof value.width === "string" ? viewportWidth : value.width)
9102
9233
  ),
9103
9234
  value
9104
9235
  })).sort((a, b) => a.diff > b.diff ? 1 : -1);
9105
9236
  let closestViewport = viewportDifferences[0].value;
9106
- if (closestViewport.width > viewportWidth && containsFullWidthViewport) {
9237
+ if (closestViewport.width < viewportWidth && containsFullWidthViewport) {
9107
9238
  closestViewport = fullWidthViewport;
9108
9239
  }
9109
9240
  if (iframe.enabled) {
@@ -9178,7 +9309,7 @@ function PuckProvider({ children }) {
9178
9309
  return __spreadValues(__spreadValues({}, pluginFieldTransforms), fieldTransforms);
9179
9310
  }, [fieldTransforms, plugins]);
9180
9311
  const instanceId = useSafeId();
9181
- const generateAppStore = useCallback21(
9312
+ const generateAppStore = useCallback22(
9182
9313
  (state) => {
9183
9314
  return {
9184
9315
  instanceId,
@@ -9229,7 +9360,7 @@ function PuckProvider({ children }) {
9229
9360
  (s) => s.state.data,
9230
9361
  (data) => {
9231
9362
  if (onChange) {
9232
- if (fdeq2(data, previousData.current)) return;
9363
+ if ((0, import_fast_deep_equal2.default)(data, previousData.current)) return;
9233
9364
  onChange(data);
9234
9365
  previousData.current = data;
9235
9366
  }