@aduptive/strapi-blockscene 2.0.0-alpha.1 → 2.0.0-alpha.3

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
@@ -292,10 +292,11 @@ the configured static base.
292
292
 
293
293
  ## Guarantees and limits
294
294
 
295
- Tested versions: Strapi 4.26.1 (Node 20) and 5.52.1 (Node 22) in the local
296
- labs of this repository, and 5.23.5 and 5.31.0 in two real site projects. The
297
- peer ranges (`>=5.23.0 <6`, `>=4.20.0 <5`) express what installs without
298
- overrides, not a promise for every minor in between.
295
+ Tested versions: Strapi 4.11.0 and 4.26.1 (Node 20), 5.0.0 and 5.52.1
296
+ (Node 22) in the local labs of this repository, and 5.23.5 and 5.31.0 in two
297
+ real site projects. The peer ranges (`>=5.0.0 <6`, `>=4.11.0 <5`) express what
298
+ installs without overrides, not a promise for every minor in between. Strapi
299
+ 4.0–4.10 is out of reach: those admins run React 17 and lack `useFetchClient`.
299
300
 
300
301
 
301
302
  - Native component payloads and ordinary Strapi save/publish flow.
package/dist/admin.cjs CHANGED
@@ -1857,6 +1857,7 @@ function PagePreview({ editor, groups = null, Toggle }) {
1857
1857
  const components = (0, import_admin2.useStrapiApp)("BlockscenePagePreview", (state) => state.components);
1858
1858
  const MediaLibraryDialog = components?.["media-library"];
1859
1859
  const addFieldRow = (0, import_admin2.useForm)("BlockscenePagePreview", (state) => state.addFieldRow);
1860
+ const moveFieldRow = (0, import_admin2.useForm)("BlockscenePagePreview", (state) => state.moveFieldRow);
1860
1861
  const fields = c.layout?.edit?.layout?.flat(3) || [];
1861
1862
  const readable = (name) => c.isCreatingEntry || (rbac.canReadFields || []).includes(name);
1862
1863
  const zone = React3.useMemo(() => editableZones(c.contentType, values, readable, c.isLoading)[0]?.name, [c.contentType, values, c.isLoading, rbac.canReadFields, c.isCreatingEntry]);
@@ -1906,6 +1907,11 @@ function PagePreview({ editor, groups = null, Toggle }) {
1906
1907
  const rows = zone && Array.isArray(values?.[zone]) ? values[zone] : [];
1907
1908
  const latest = React3.useRef(rows);
1908
1909
  latest.current = rows;
1910
+ const insertRows = (at, ...items) => items.forEach((item, i) => {
1911
+ const from = latest.current.length + i;
1912
+ addFieldRow(zone, item);
1913
+ if (at + i < from) moveFieldRow(zone, from, at + i);
1914
+ });
1909
1915
  const live = React3.useRef({ mode, canEdit, zoneLabel, components: c.components, setMode, onChange });
1910
1916
  live.current = { mode, canEdit, zoneLabel, components: c.components, setMode, onChange };
1911
1917
  const send = React3.useCallback(() => {
@@ -2002,8 +2008,7 @@ function PagePreview({ editor, groups = null, Toggle }) {
2002
2008
  toggleNotification({ type: "info", message: t.zoneFull });
2003
2009
  return;
2004
2010
  }
2005
- addFieldRow(zone, { ...componentDefaults(components2[uid2], components2), __component: uid2 }, index2);
2006
- addFieldRow(zone, { __component: close }, index2 + 1);
2011
+ insertRows(index2, { ...componentDefaults(components2[uid2], components2), __component: uid2 }, { __component: close });
2007
2012
  return;
2008
2013
  }
2009
2014
  const key = typeof event.data?.key === "string" ? event.data.key : "";
@@ -2065,7 +2070,7 @@ function PagePreview({ editor, groups = null, Toggle }) {
2065
2070
  const problems = groups ? (0, import_groups.validateGroups)(rows, groups) : [];
2066
2071
  const insertClose = (error) => {
2067
2072
  const end = (0, import_groups.groupRange)(latest.current, error.index, groups)[1];
2068
- addFieldRow(zone, { __component: error.expected }, end + 1);
2073
+ insertRows(end + 1, { __component: error.expected });
2069
2074
  };
2070
2075
  const diagnostics = problems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Box, { role: "alert", "data-testid": "page-preview-diagnostics", padding: 2, background: "danger100", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("details", { children: [
2071
2076
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("summary", { style: { cursor: "pointer" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Typography, { variant: "pi", fontWeight: "bold", textColor: "danger700", children: t.f("diagSummary", { count: problems.length }) }) }),
@@ -2166,8 +2171,7 @@ function PagePreview({ editor, groups = null, Toggle }) {
2166
2171
  toggleNotification({ type: "warning", message: close ? t.zoneFull : t.insertMoved });
2167
2172
  return;
2168
2173
  }
2169
- addFieldRow(zone, { ...componentDefaults(c.components[uid], c.components), __component: uid }, index);
2170
- if (close) addFieldRow(zone, { __component: close }, index + 1);
2174
+ insertRows(index, { ...componentDefaults(c.components[uid], c.components), __component: uid }, ...close ? [{ __component: close }] : []);
2171
2175
  }
2172
2176
  }
2173
2177
  ),
@@ -2525,14 +2529,16 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2525
2529
  ] })
2526
2530
  ] }) });
2527
2531
  }
2528
- function register(app, Component) {
2532
+ function register(app, Component, to) {
2529
2533
  app.createSettingSection(
2530
2534
  { id: "blockscene", intlLabel: { id: "blockscene.title", defaultMessage: "Blockscene" } },
2531
2535
  [{
2532
2536
  id: "blockscene-settings",
2533
- to: "/settings/blockscene",
2537
+ to,
2534
2538
  intlLabel: { id: "blockscene.settings", defaultMessage: "Gallery" },
2535
- Component: async () => Component,
2539
+ // Module shape: older Strapi 4 (e.g. 4.11) only reads `.default` from the loader result.
2540
+ // Not an `async` function: Strapi 5 warns on AsyncFunction loaders.
2541
+ Component: () => Promise.resolve({ default: Component }),
2536
2542
  permissions: permissions.read
2537
2543
  }]
2538
2544
  );
@@ -2622,13 +2628,13 @@ function MediaPicker({ onClose, onSelect }) {
2622
2628
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Dialog3, { onClose, allowedTypes: ["images"], multiple: false, onSelectAssets: (assets) => onSelect(assets?.[0]) });
2623
2629
  }
2624
2630
  function usePermissions() {
2625
- const { allowedActions, isLoading } = (0, import_admin3.useRBAC)(permissions);
2631
+ const { allowedActions, isLoading } = (0, import_admin3.useRBAC)(Object.values(permissions).flat());
2626
2632
  return { canRead: allowedActions.canRead, canUpdate: allowedActions.canUpdate, isLoading };
2627
2633
  }
2628
2634
  var SettingsPage = () => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Settings, { useClient: import_admin3.useFetchClient, usePermissions, MediaPicker, ToggleField, SelectField, TextField, previewSupported: true });
2629
2635
  var strapi5_default = {
2630
2636
  register(app) {
2631
- register(app, SettingsPage);
2637
+ register(app, SettingsPage, "blockscene");
2632
2638
  app.registerPlugin({ id: "blockscene", name: "Blockscene" });
2633
2639
  },
2634
2640
  registerTrads,
package/dist/admin.mjs CHANGED
@@ -1847,6 +1847,7 @@ function PagePreview({ editor, groups = null, Toggle }) {
1847
1847
  const components = useStrapiApp2("BlockscenePagePreview", (state) => state.components);
1848
1848
  const MediaLibraryDialog = components?.["media-library"];
1849
1849
  const addFieldRow = useForm2("BlockscenePagePreview", (state) => state.addFieldRow);
1850
+ const moveFieldRow = useForm2("BlockscenePagePreview", (state) => state.moveFieldRow);
1850
1851
  const fields = c.layout?.edit?.layout?.flat(3) || [];
1851
1852
  const readable = (name) => c.isCreatingEntry || (rbac.canReadFields || []).includes(name);
1852
1853
  const zone = React3.useMemo(() => editableZones(c.contentType, values, readable, c.isLoading)[0]?.name, [c.contentType, values, c.isLoading, rbac.canReadFields, c.isCreatingEntry]);
@@ -1896,6 +1897,11 @@ function PagePreview({ editor, groups = null, Toggle }) {
1896
1897
  const rows = zone && Array.isArray(values?.[zone]) ? values[zone] : [];
1897
1898
  const latest = React3.useRef(rows);
1898
1899
  latest.current = rows;
1900
+ const insertRows = (at, ...items) => items.forEach((item, i) => {
1901
+ const from = latest.current.length + i;
1902
+ addFieldRow(zone, item);
1903
+ if (at + i < from) moveFieldRow(zone, from, at + i);
1904
+ });
1899
1905
  const live = React3.useRef({ mode, canEdit, zoneLabel, components: c.components, setMode, onChange });
1900
1906
  live.current = { mode, canEdit, zoneLabel, components: c.components, setMode, onChange };
1901
1907
  const send = React3.useCallback(() => {
@@ -1992,8 +1998,7 @@ function PagePreview({ editor, groups = null, Toggle }) {
1992
1998
  toggleNotification({ type: "info", message: t.zoneFull });
1993
1999
  return;
1994
2000
  }
1995
- addFieldRow(zone, { ...componentDefaults(components2[uid2], components2), __component: uid2 }, index2);
1996
- addFieldRow(zone, { __component: close }, index2 + 1);
2001
+ insertRows(index2, { ...componentDefaults(components2[uid2], components2), __component: uid2 }, { __component: close });
1997
2002
  return;
1998
2003
  }
1999
2004
  const key = typeof event.data?.key === "string" ? event.data.key : "";
@@ -2055,7 +2060,7 @@ function PagePreview({ editor, groups = null, Toggle }) {
2055
2060
  const problems = groups ? (0, import_groups.validateGroups)(rows, groups) : [];
2056
2061
  const insertClose = (error) => {
2057
2062
  const end = (0, import_groups.groupRange)(latest.current, error.index, groups)[1];
2058
- addFieldRow(zone, { __component: error.expected }, end + 1);
2063
+ insertRows(end + 1, { __component: error.expected });
2059
2064
  };
2060
2065
  const diagnostics = problems.length > 0 && /* @__PURE__ */ jsx4(Box2, { role: "alert", "data-testid": "page-preview-diagnostics", padding: 2, background: "danger100", hasRadius: true, children: /* @__PURE__ */ jsxs3("details", { children: [
2061
2066
  /* @__PURE__ */ jsx4("summary", { style: { cursor: "pointer" }, children: /* @__PURE__ */ jsx4(Typography3, { variant: "pi", fontWeight: "bold", textColor: "danger700", children: t.f("diagSummary", { count: problems.length }) }) }),
@@ -2156,8 +2161,7 @@ function PagePreview({ editor, groups = null, Toggle }) {
2156
2161
  toggleNotification({ type: "warning", message: close ? t.zoneFull : t.insertMoved });
2157
2162
  return;
2158
2163
  }
2159
- addFieldRow(zone, { ...componentDefaults(c.components[uid], c.components), __component: uid }, index);
2160
- if (close) addFieldRow(zone, { __component: close }, index + 1);
2164
+ insertRows(index, { ...componentDefaults(c.components[uid], c.components), __component: uid }, ...close ? [{ __component: close }] : []);
2161
2165
  }
2162
2166
  }
2163
2167
  ),
@@ -2515,14 +2519,16 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2515
2519
  ] })
2516
2520
  ] }) });
2517
2521
  }
2518
- function register(app, Component) {
2522
+ function register(app, Component, to) {
2519
2523
  app.createSettingSection(
2520
2524
  { id: "blockscene", intlLabel: { id: "blockscene.title", defaultMessage: "Blockscene" } },
2521
2525
  [{
2522
2526
  id: "blockscene-settings",
2523
- to: "/settings/blockscene",
2527
+ to,
2524
2528
  intlLabel: { id: "blockscene.settings", defaultMessage: "Gallery" },
2525
- Component: async () => Component,
2529
+ // Module shape: older Strapi 4 (e.g. 4.11) only reads `.default` from the loader result.
2530
+ // Not an `async` function: Strapi 5 warns on AsyncFunction loaders.
2531
+ Component: () => Promise.resolve({ default: Component }),
2526
2532
  permissions: permissions.read
2527
2533
  }]
2528
2534
  );
@@ -2612,13 +2618,13 @@ function MediaPicker({ onClose, onSelect }) {
2612
2618
  return /* @__PURE__ */ jsx6(Dialog3, { onClose, allowedTypes: ["images"], multiple: false, onSelectAssets: (assets) => onSelect(assets?.[0]) });
2613
2619
  }
2614
2620
  function usePermissions() {
2615
- const { allowedActions, isLoading } = useRBAC(permissions);
2621
+ const { allowedActions, isLoading } = useRBAC(Object.values(permissions).flat());
2616
2622
  return { canRead: allowedActions.canRead, canUpdate: allowedActions.canUpdate, isLoading };
2617
2623
  }
2618
2624
  var SettingsPage = () => /* @__PURE__ */ jsx6(Settings, { useClient: useFetchClient2, usePermissions, MediaPicker, ToggleField, SelectField, TextField, previewSupported: true });
2619
2625
  var strapi5_default = {
2620
2626
  register(app) {
2621
- register(app, SettingsPage);
2627
+ register(app, SettingsPage, "blockscene");
2622
2628
  app.registerPlugin({ id: "blockscene", name: "Blockscene" });
2623
2629
  },
2624
2630
  registerTrads,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aduptive/strapi-blockscene",
3
- "version": "2.0.0-alpha.1",
3
+ "version": "2.0.0-alpha.3",
4
4
  "description": "Visual component gallery for native Strapi dynamic zones.",
5
5
  "license": "MIT",
6
6
  "author": "Andrea Scarpello <aduptive@gmail.com>",
@@ -39,14 +39,12 @@
39
39
  "node": ">=20 <27"
40
40
  },
41
41
  "peerDependencies": {
42
- "@strapi/strapi": ">=5.23.0 <6",
42
+ "@strapi/strapi": ">=5.0.0 <6",
43
43
  "@strapi/design-system": "^2.0.0",
44
44
  "react": "^18.0.0",
45
45
  "react-dom": "^18.0.0",
46
46
  "styled-components": "^6.0.0",
47
- "react-intl": "^6.0.0",
48
- "@strapi/content-manager": ">=5.23.0 <6",
49
- "@strapi/admin": ">=5.23.0 <6"
47
+ "react-intl": "^6.0.0"
50
48
  },
51
49
  "dependencies": {
52
50
  "fractional-indexing": "3.2.0"