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

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.
Files changed (3) hide show
  1. package/dist/admin.cjs +955 -155
  2. package/dist/admin.mjs +976 -153
  3. package/package.json +9 -9
package/dist/admin.cjs CHANGED
@@ -4,6 +4,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
7
10
  var __export = (target, all) => {
8
11
  for (var name in all)
9
12
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -26,15 +29,122 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
29
  ));
27
30
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
31
 
29
- // admin/strapi4.tsx
30
- var strapi4_exports = {};
31
- __export(strapi4_exports, {
32
- default: () => strapi4_default
32
+ // server/groups.js
33
+ var require_groups = __commonJS({
34
+ "server/groups.js"(exports, module2) {
35
+ "use strict";
36
+ var UID = /^[a-z0-9-]+\.[a-z0-9-]+$/;
37
+ function safeGroups2(value, knownUids) {
38
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
39
+ const out = {};
40
+ for (const [open, close] of Object.entries(value)) {
41
+ if (!UID.test(open) || typeof close !== "string" || !UID.test(close) || open === close) continue;
42
+ if (knownUids && (!knownUids.includes(open) || !knownUids.includes(close))) continue;
43
+ out[open] = close;
44
+ }
45
+ for (const close of Object.values(out)) if (out[close]) return null;
46
+ return Object.keys(out).length ? out : null;
47
+ }
48
+ var uidOf = (row) => typeof row?.__component === "string" ? row.__component : "";
49
+ var isOpener = (row, g) => Boolean(g) && Object.prototype.hasOwnProperty.call(g, uidOf(row));
50
+ var isClose = (row, g) => Boolean(g) && Object.values(g).includes(uidOf(row));
51
+ var blockKey2 = (row) => row && row.id != null ? `${row.__component}#${row.id}` : row && row.__temp_key__ != null ? String(row.__temp_key__) : null;
52
+ function validateGroups2(rows, g) {
53
+ const errors = [];
54
+ if (!g || !Array.isArray(rows)) return errors;
55
+ const stack = [];
56
+ rows.forEach((row, index) => {
57
+ const uid = uidOf(row);
58
+ if (isOpener(row, g)) {
59
+ stack.push({ index, uid, close: g[uid] });
60
+ return;
61
+ }
62
+ if (!isClose(row, g)) return;
63
+ const top = stack[stack.length - 1];
64
+ if (!top) errors.push({ code: "closeBeforeOpen", index, uid });
65
+ else if (top.close !== uid) errors.push({ code: "mismatch", index, uid, expected: top.close, open: top.uid, openIndex: top.index });
66
+ else stack.pop();
67
+ });
68
+ for (const open of stack) errors.push({ code: "unclosed", index: open.index, uid: open.uid, expected: open.close });
69
+ return errors;
70
+ }
71
+ function groupRange2(rows, start, g) {
72
+ const stack = [g[uidOf(rows[start])]];
73
+ for (let i = start + 1; i < rows.length; i++) {
74
+ const row = rows[i];
75
+ if (isOpener(row, g)) stack.push(g[uidOf(row)]);
76
+ else if (isClose(row, g) && uidOf(row) === stack[stack.length - 1]) {
77
+ stack.pop();
78
+ if (!stack.length) return [start, i];
79
+ }
80
+ }
81
+ return [start, rows.length - 1];
82
+ }
83
+ function groupRows2(rows, g, depth = 0, offset = 0) {
84
+ const out = [];
85
+ let i = 0;
86
+ while (i < rows.length) {
87
+ const row = rows[i];
88
+ if (isOpener(row, g)) {
89
+ const [, end] = groupRange2(rows, i, g);
90
+ const closed = uidOf(rows[end]) === g[uidOf(row)] && end > i;
91
+ out.push({
92
+ type: "group",
93
+ key: blockKey2(row),
94
+ closeKey: closed ? blockKey2(rows[end]) : null,
95
+ row,
96
+ index: offset + i,
97
+ depth,
98
+ children: groupRows2(rows.slice(i + 1, closed ? end : end + 1), g, depth + 1, offset + i + 1)
99
+ });
100
+ i = end + 1;
101
+ continue;
102
+ }
103
+ out.push({ type: "block", key: blockKey2(row), row, index: offset + i, depth, stray: isClose(row, g) });
104
+ i++;
105
+ }
106
+ return out;
107
+ }
108
+ function topLevelRanges2(rows, g) {
109
+ const ranges = [];
110
+ let i = 0;
111
+ while (i < rows.length) {
112
+ const end = isOpener(rows[i], g) ? groupRange2(rows, i, g)[1] : i;
113
+ ranges.push([i, end]);
114
+ i = end + 1;
115
+ }
116
+ return ranges;
117
+ }
118
+ function moveGroup2(rows, key, direction, g) {
119
+ if (!g) return null;
120
+ const ranges = topLevelRanges2(rows, g);
121
+ const at = ranges.findIndex(([s]) => blockKey2(rows[s]) === String(key));
122
+ const to = at + (direction === "up" ? -1 : 1);
123
+ if (at < 0 || to < 0 || to >= ranges.length) return null;
124
+ const [a, b] = direction === "up" ? [ranges[to], ranges[at]] : [ranges[at], ranges[to]];
125
+ return [...rows.slice(0, a[0]), ...rows.slice(b[0], b[1] + 1), ...rows.slice(a[0], a[1] + 1), ...rows.slice(b[1] + 1)];
126
+ }
127
+ function removeGroup2(rows, key, g) {
128
+ if (!g) return null;
129
+ const start = rows.findIndex((row) => blockKey2(row) === String(key));
130
+ if (start < 0 || !isOpener(rows[start], g)) return null;
131
+ const [, end] = groupRange2(rows, start, g);
132
+ return [...rows.slice(0, start), ...rows.slice(end + 1)];
133
+ }
134
+ module2.exports = { safeGroups: safeGroups2, validateGroups: validateGroups2, groupRange: groupRange2, groupRows: groupRows2, topLevelRanges: topLevelRanges2, moveGroup: moveGroup2, removeGroup: removeGroup2, blockKey: blockKey2, isOpener, isClose };
135
+ }
136
+ });
137
+
138
+ // admin/strapi5.tsx
139
+ var strapi5_exports = {};
140
+ __export(strapi5_exports, {
141
+ default: () => strapi5_default
33
142
  });
34
- module.exports = __toCommonJS(strapi4_exports);
35
- var React4 = __toESM(require("react"));
36
- var import_design_system3 = require("@strapi/design-system");
37
- var import_helper_plugin = require("@strapi/helper-plugin");
143
+ module.exports = __toCommonJS(strapi5_exports);
144
+ var React6 = __toESM(require("react"));
145
+ var import_design_system6 = require("@strapi/design-system");
146
+ var import_admin3 = require("@strapi/strapi/admin");
147
+ var import_strapi_admin2 = require("@strapi/content-manager/strapi-admin");
38
148
 
39
149
  // admin/Gallery.tsx
40
150
  var React = __toESM(require("react"));
@@ -44,6 +154,25 @@ var import_styled_components = __toESM(require("styled-components"));
44
154
 
45
155
  // admin/model.mjs
46
156
  var import_fractional_indexing = require("fractional-indexing");
157
+ function componentDefaults(schema, components, stack = []) {
158
+ if (!schema || stack.includes(schema)) throw new Error("Invalid recursive component defaults");
159
+ const row = {};
160
+ for (const [name, attr] of Object.entries(schema.attributes || {})) {
161
+ if (Object.hasOwn(attr, "default")) {
162
+ const value = structuredClone(attr.default);
163
+ if (attr.type === "password") row[name] = "";
164
+ else if (attr.type === "relation") row[name] = { connect: [], disconnect: [] };
165
+ else if (value !== null || attr.type === "boolean") row[name] = value;
166
+ } else if (attr.type === "component" && attr.required) {
167
+ const create = () => componentDefaults(components[attr.component], components, [...stack, schema]);
168
+ if (attr.repeatable) {
169
+ const keys = (0, import_fractional_indexing.generateNKeysBetween)(null, null, attr.min || 0);
170
+ row[name] = keys.map((key) => ({ ...create(), __temp_key__: key }));
171
+ } else row[name] = create();
172
+ } else if (attr.type === "dynamiczone" && attr.required) row[name] = [];
173
+ }
174
+ return row;
175
+ }
47
176
  function editableZones(schema, values, canEdit, disabled = false) {
48
177
  if (disabled) return [];
49
178
  return Object.entries(schema?.attributes || {}).filter(([name, attr]) => attr.type === "dynamiczone" && !attr.conditions && canEdit(name)).map(([name, attr]) => {
@@ -1217,7 +1346,10 @@ function Card({ entry, palette, showFields, onSelect }) {
1217
1346
  showFields && entry.fields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { variant: "pi", textColor: "neutral500", style: { fontStyle: "italic" }, "data-testid": "block-fields", children: entry.fields.map((f) => `${f.name} (${f.type})`).join(", ") })
1218
1347
  ] });
1219
1348
  }
1220
- function ZoneGallery({ zone, components, add, Modal: Modal2, Toggle, get, controlled }) {
1349
+ function PickerModal({ zone, components, open, onOpenChange, onSelect, Modal: Modal3, Toggle, get }) {
1350
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ZoneGallery, { zone, components, Modal: Modal3, Toggle, get, controlled: { open, onOpenChange, onSelect } });
1351
+ }
1352
+ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, controlled }) {
1221
1353
  const t = useMessages();
1222
1354
  const [ownOpen, setOwnOpen] = React.useState(false);
1223
1355
  const open = controlled ? controlled.open : ownOpen;
@@ -1281,7 +1413,7 @@ function ZoneGallery({ zone, components, add, Modal: Modal2, Toggle, get, contro
1281
1413
  remember(SHOW_FIELDS_KEY, String(value));
1282
1414
  };
1283
1415
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1284
- Modal2,
1416
+ Modal3,
1285
1417
  {
1286
1418
  open,
1287
1419
  onOpenChange: setOpen,
@@ -1410,46 +1542,708 @@ function Gallery({ zones, editor, docKey, contentType, userId, ...props }) {
1410
1542
  ] }, zone.name)) });
1411
1543
  }
1412
1544
 
1413
- // admin/Settings.tsx
1545
+ // admin/PagePreview.tsx
1546
+ var React3 = __toESM(require("react"));
1547
+ var import_react_dom2 = require("react-dom");
1548
+ var import_styled_components2 = __toESM(require("styled-components"));
1549
+ var import_design_system3 = require("@strapi/design-system");
1550
+ var import_admin2 = require("@strapi/strapi/admin");
1551
+ var import_design_system4 = require("@strapi/design-system");
1552
+ var import_strapi_admin = require("@strapi/content-manager/strapi-admin");
1553
+
1554
+ // admin/FieldEditorModal.tsx
1414
1555
  var React2 = __toESM(require("react"));
1556
+ var import_admin = require("@strapi/strapi/admin");
1415
1557
  var import_design_system2 = require("@strapi/design-system");
1416
- var import_styled_components2 = __toESM(require("styled-components"));
1417
1558
  var import_jsx_runtime3 = require("react/jsx-runtime");
1559
+ var Actions = ({ onApply, onCancel }) => {
1560
+ const t = useMessages();
1561
+ const value = (0, import_admin.useForm)("BlocksceneFieldEditor", (state) => state.values.value);
1562
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { gap: 2, justifyContent: "flex-end", children: [
1563
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Button, { variant: "tertiary", onClick: onCancel, children: t.cancel }),
1564
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Button, { onClick: () => onApply(value ?? null), "data-testid": "field-editor-apply", children: t.apply })
1565
+ ] });
1566
+ };
1567
+ function FieldEditorModal({ label, attribute, value, onApply, onCancel }) {
1568
+ const t = useMessages();
1569
+ const customFields = (0, import_admin.useStrapiApp)("BlocksceneFieldEditor", (state) => state.customFields);
1570
+ const [Input, setInput] = React2.useState(void 0);
1571
+ const isCustom = Boolean(attribute?.customField);
1572
+ const isText = attribute?.type === "string" || attribute?.type === "text";
1573
+ React2.useEffect(() => {
1574
+ let active = true;
1575
+ if (!isCustom) {
1576
+ setInput(null);
1577
+ return;
1578
+ }
1579
+ const field = customFields?.get?.(attribute.customField);
1580
+ if (!field?.components?.Input) {
1581
+ setInput(null);
1582
+ return;
1583
+ }
1584
+ Promise.resolve(field.components.Input()).then((mod) => {
1585
+ if (active) setInput(() => mod.default || mod);
1586
+ }).catch(() => {
1587
+ if (active) setInput(null);
1588
+ });
1589
+ return () => {
1590
+ active = false;
1591
+ };
1592
+ }, [attribute, customFields, isCustom]);
1593
+ const supported = isText || isCustom && Input;
1594
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Modal.Root, { open: true, onOpenChange: (open) => {
1595
+ if (!open) onCancel();
1596
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Modal.Content, { "aria-label": `${t.editText} ${label}`, children: [
1597
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Modal.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Modal.Title, { children: [
1598
+ t.editText,
1599
+ " \xB7 ",
1600
+ label
1601
+ ] }) }),
1602
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_admin.Form, { initialValues: { value: value ?? (isText ? "" : null) }, method: "PUT", onSubmit: () => {
1603
+ }, children: [
1604
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Modal.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "field-editor-modal", children: [
1605
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.editHelp }),
1606
+ isCustom && Input === void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { children: t.loading }),
1607
+ isCustom && Input && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Input, { name: "value", attribute, label, type: attribute.type }),
1608
+ isText && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_admin.InputRenderer, { type: attribute.type === "text" ? "text" : "string", name: "value", label }),
1609
+ (isCustom && Input === null || !isCustom && !isText) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { role: "alert", textColor: "danger600", children: t.editUnsupported })
1610
+ ] }) }),
1611
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Modal.Footer, { children: supported ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Actions, { onApply, onCancel }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Button, { variant: "tertiary", onClick: onCancel, children: t.close }) })
1612
+ ] })
1613
+ ] }) });
1614
+ }
1615
+
1616
+ // admin/preview.mjs
1617
+ var import_groups = __toESM(require_groups(), 1);
1618
+ var PROTOCOL = "blockscene:page-preview:v1";
1619
+ var TEXT_TYPES = ["string", "text"];
1620
+ var RICH_TYPES = ["richtext", "blocks", "customField"];
1621
+ var EDITABLE_TYPES = [...TEXT_TYPES, ...RICH_TYPES];
1622
+ var SCALAR = ["string", "text", "richtext", "email", "enumeration", "integer", "biginteger", "float", "decimal", "boolean", "date", "datetime", "time", "json", "blocks", "uid", "customField"];
1623
+ var blockKey = (row) => row && row.id != null ? `${row.__component}#${row.id}` : row && row.__temp_key__ != null ? String(row.__temp_key__) : null;
1624
+ function projectRow(row, schema, components, cmsOrigin, depth = 0) {
1625
+ if (!row || !schema || depth > 3) return null;
1626
+ const out = {};
1627
+ for (const [name, attr] of Object.entries(schema.attributes || {})) {
1628
+ const value = row[name];
1629
+ if (attr.type === "password" || attr.type === "relation" || attr.private) continue;
1630
+ if (SCALAR.includes(attr.type)) {
1631
+ if (value !== void 0) out[name] = typeof value === "string" ? value.slice(0, 2e5) : value;
1632
+ } else if (attr.type === "media") {
1633
+ const files = (attr.multiple ? Array.isArray(value) ? value : [] : value ? [value] : []).map((file) => projectMedia(file, cmsOrigin)).filter(Boolean);
1634
+ out[name] = attr.multiple ? files : files[0] || null;
1635
+ } else if (attr.type === "component") {
1636
+ const child = components?.[attr.component];
1637
+ out[name] = attr.repeatable ? (Array.isArray(value) ? value : []).slice(0, 100).map((item, i) => ({ ...projectRow(item, child, components, cmsOrigin, depth + 1), __key: blockKey(item) ?? String(i) })) : projectRow(value, child, components, cmsOrigin, depth + 1);
1638
+ }
1639
+ }
1640
+ return out;
1641
+ }
1642
+ function projectMedia(file, cmsOrigin) {
1643
+ if (!file || typeof file.url !== "string") return null;
1644
+ try {
1645
+ const url = new URL(file.url, cmsOrigin);
1646
+ if (!["http:", "https:"].includes(url.protocol)) return null;
1647
+ return { url: url.href, alternativeText: String(file.alternativeText || ""), caption: String(file.caption || ""), width: Number(file.width) || 0, height: Number(file.height) || 0, mime: String(file.mime || "") };
1648
+ } catch {
1649
+ return null;
1650
+ }
1651
+ }
1652
+ function resolveField(uid, field, components) {
1653
+ if (typeof field !== "string" || field.length > 200) return null;
1654
+ let schema = components?.[uid];
1655
+ const parts = field.split(".");
1656
+ for (let i = 0; i < parts.length; i++) {
1657
+ const attr = schema?.attributes?.[parts[i]];
1658
+ if (!attr || attr.private === true) return null;
1659
+ if (i === parts.length - 1) return attr;
1660
+ if (attr.type !== "component") return null;
1661
+ if (attr.repeatable) {
1662
+ if (!/^\d{1,3}$/.test(parts[i + 1] || "")) return null;
1663
+ i++;
1664
+ }
1665
+ schema = components?.[attr.component];
1666
+ }
1667
+ return null;
1668
+ }
1669
+ function editableFields(uid, row, components) {
1670
+ const schema = components?.[uid];
1671
+ const out = [];
1672
+ const SYSTEM = ["id", "documentId", "locale", "createdAt", "updatedAt", "publishedAt", "createdBy", "updatedBy", "localizations", "__component", "__temp_key__"];
1673
+ const push = (name, attr, label) => {
1674
+ if (!SYSTEM.includes(name.split(".").pop()) && attr?.private !== true && EDITABLE_TYPES.includes(attr?.type)) out.push({ name, type: attr.type, label });
1675
+ };
1676
+ for (const [name, attr] of Object.entries(schema?.attributes || {})) {
1677
+ if (attr.type === "component" && attr.repeatable) {
1678
+ (Array.isArray(row?.[name]) ? row[name] : []).slice(0, 50).forEach((_, i) => {
1679
+ for (const [child, childAttr] of Object.entries(components?.[attr.component]?.attributes || {})) push(`${name}.${i}.${child}`, childAttr, `${name} ${i + 1} \xB7 ${child}`);
1680
+ });
1681
+ } else push(name, attr, name);
1682
+ }
1683
+ return out;
1684
+ }
1685
+ function mediaFields(uid, row, components) {
1686
+ const media = {};
1687
+ for (const [name, attr] of Object.entries(components?.[uid]?.attributes || {})) {
1688
+ if (attr.type === "media" && attr.private !== true) media[name] = { required: attr.required === true, multiple: attr.multiple === true, present: attr.multiple ? Array.isArray(row?.[name]) && row[name].length > 0 : Boolean(row?.[name]) };
1689
+ }
1690
+ return media;
1691
+ }
1692
+ function projectPage(rows, components, cmsOrigin) {
1693
+ return (Array.isArray(rows) ? rows : []).slice(0, 200).flatMap((row, index) => {
1694
+ const uid = row?.__component;
1695
+ const key = blockKey(row);
1696
+ const schema = components?.[uid];
1697
+ if (!uid || key == null || !schema) return [];
1698
+ return [{
1699
+ key,
1700
+ index,
1701
+ uid,
1702
+ label: schema.info?.displayName || uid,
1703
+ data: projectRow(row, schema, components, cmsOrigin),
1704
+ fields: editableFields(uid, row, components),
1705
+ media: mediaFields(uid, row, components)
1706
+ }];
1707
+ });
1708
+ }
1709
+ var validateFocus = (uid, field, components) => {
1710
+ const attr = resolveField(uid, field, components);
1711
+ return attr && EDITABLE_TYPES.includes(attr.type) ? attr : null;
1712
+ };
1713
+ function validateEdit(uid, field, value, components) {
1714
+ if (typeof value !== "string" || value.length > 5e3) return null;
1715
+ const attr = resolveField(uid, field, components);
1716
+ return attr && TEXT_TYPES.includes(attr.type) ? value.replace(/[\r\n]+/g, " ") : null;
1717
+ }
1718
+ var mediaAttribute = (uid, field, components) => {
1719
+ const attr = resolveField(uid, field, components);
1720
+ return attr?.type === "media" ? attr : null;
1721
+ };
1722
+ function isPreviewMessage(event, origin, source, channel, type) {
1723
+ return event.origin === origin && event.source === source && event.data?.protocol === PROTOCOL && event.data?.channel === channel && event.data?.type === type;
1724
+ }
1725
+ function insertIndex(rows, after) {
1726
+ if (after === null || after === void 0) return 0;
1727
+ const index = (Array.isArray(rows) ? rows : []).findIndex((row) => blockKey(row) === String(after));
1728
+ return index < 0 ? -1 : index + 1;
1729
+ }
1730
+
1731
+ // admin/PagePreview.tsx
1732
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1733
+ var MODE_KEY = "blockscene:page-mode";
1734
+ var RATIO_KEY = "blockscene:page-split-ratio";
1735
+ var MIN_PANE = 360;
1736
+ var MIN_FORM = 520;
1737
+ var NARROW = 960;
1738
+ var KEY_STEP = 32;
1739
+ var MODAL_TYPES = ["customField", "string", "text"];
1740
+ var read = (key) => {
1741
+ try {
1742
+ return localStorage.getItem(key);
1743
+ } catch {
1744
+ return null;
1745
+ }
1746
+ };
1747
+ var write = (key, value) => {
1748
+ try {
1749
+ localStorage.setItem(key, value);
1750
+ } catch {
1751
+ }
1752
+ };
1753
+ var clampWidth = (width, vw) => Math.round(Math.min(Math.max(width, MIN_PANE), Math.max(MIN_PANE, vw - MIN_FORM)));
1754
+ var getIn = (object, path) => path.split(".").reduce((acc, part) => acc == null ? acc : acc[part], object);
1755
+ var Pane = import_styled_components2.default.aside`
1756
+ position: fixed; top: 0; bottom: 0; z-index: 2; display: flex; flex-direction: column;
1757
+ background: ${({ theme }) => theme.colors.neutral0}; border-left: 1px solid ${({ theme }) => theme.colors.neutral200};
1758
+ box-shadow: ${({ theme }) => theme.shadows.popupShadow};
1759
+ `;
1760
+ function useMainRect() {
1761
+ const [rect, setRect] = React3.useState(() => ({ left: 0, width: window.innerWidth }));
1762
+ React3.useEffect(() => {
1763
+ const main = document.getElementById("main-content");
1764
+ const measure = () => {
1765
+ const r = main?.getBoundingClientRect();
1766
+ setRect(r && r.width > 0 ? { left: Math.round(r.left), width: Math.round(r.width) } : { left: 0, width: window.innerWidth });
1767
+ };
1768
+ measure();
1769
+ const observer = main && "ResizeObserver" in window ? new ResizeObserver(measure) : null;
1770
+ if (main) observer?.observe(main);
1771
+ window.addEventListener("resize", measure);
1772
+ return () => {
1773
+ observer?.disconnect();
1774
+ window.removeEventListener("resize", measure);
1775
+ };
1776
+ }, []);
1777
+ return rect;
1778
+ }
1779
+ var Handle = import_styled_components2.default.div`
1780
+ position: absolute; top: 0; bottom: 0; left: -5px; width: 10px; cursor: col-resize; z-index: 3; touch-action: none;
1781
+ &::after { content: ''; position: absolute; top: 0; bottom: 0; left: 4px; width: 2px; }
1782
+ &:hover::after, &[data-dragging='true']::after, &:focus-visible::after { background: ${({ theme }) => theme.colors.primary600}; }
1783
+ &:focus-visible { outline: none; }
1784
+ `;
1785
+ var Frame2 = import_styled_components2.default.iframe` flex: 1; width: 100%; border: 0; background: white; `;
1786
+ var SPLIT_STYLE = `
1787
+ body.bp-split #main-content { padding-right: calc(var(--bp-pane, 50vw) + 1.6rem) !important; }
1788
+ body.bp-split [data-bp-grid] { display: flex !important; flex-direction: column-reverse; gap: 1.6rem; }
1789
+ body.bp-split [data-bp-panels] { width: 100%; }
1790
+ body.bp-split [data-bp-panels] > div { flex-direction: row; flex-wrap: wrap; align-items: flex-start; gap: 1.2rem; }
1791
+ body.bp-split [data-bp-panels] > div > * { flex: 1 1 24rem; }`;
1792
+ var markLayout = (anchor) => {
1793
+ let item = anchor;
1794
+ while (item?.parentElement && getComputedStyle(item.parentElement).display !== "grid") item = item.parentElement;
1795
+ if (!item?.parentElement) return;
1796
+ item.dataset.bpPanels = "";
1797
+ item.parentElement.dataset.bpGrid = "";
1798
+ };
1799
+ function usePreviewBase(override, model, documentId, locale) {
1800
+ const { get } = (0, import_admin2.useFetchClient)();
1801
+ const [native, setNative] = React3.useState(null);
1802
+ React3.useEffect(() => {
1803
+ if (override || !model) return;
1804
+ let active = true;
1805
+ const query = new URLSearchParams({ status: "draft", ...documentId ? { documentId } : {}, ...locale ? { locale } : {} });
1806
+ get(`/content-manager/preview/url/${model}?${query}`).then(({ data }) => {
1807
+ if (active && typeof data?.data?.url === "string") setNative(`${new URL(data.data.url).origin}/block-preview/page`);
1808
+ }).catch(() => {
1809
+ if (active) setNative(null);
1810
+ });
1811
+ return () => {
1812
+ active = false;
1813
+ };
1814
+ }, [get, model, documentId, locale, override]);
1815
+ return override ? { base: override, source: "custom" } : native ? { base: native, source: "native" } : { base: null, source: "none" };
1816
+ }
1817
+ function PickerDialog({ open, onOpenChange, trigger, title, children }) {
1818
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system4.Modal.Root, { open, onOpenChange, children: [
1819
+ trigger && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system4.Modal.Trigger, { children: trigger }),
1820
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system4.Modal.Content, { children: [
1821
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system4.Modal.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system4.Modal.Title, { children: title }) }),
1822
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system4.Modal.Body, { children })
1823
+ ] })
1824
+ ] });
1825
+ }
1826
+ var ACTION_TYPES = ["update", "publish"];
1827
+ var nativeButtons = () => document.querySelectorAll('#main-content button:not([data-testid="page-preview-pane"] button)');
1828
+ function ToolbarActions({ model, collectionType, documentId, locale }) {
1829
+ const plugins = (0, import_admin2.useStrapiApp)("BlocksceneToolbar", (state) => state.plugins);
1830
+ const [{ query }] = (0, import_admin2.useQueryParams)();
1831
+ const { document: doc, meta } = (0, import_strapi_admin.unstable_useDocument)({ model, collectionType, documentId, params: { locale } }, { skip: !documentId });
1832
+ const { toggleNotification } = (0, import_admin2.useNotification)();
1833
+ const t = useMessages();
1834
+ const descriptions = (plugins["content-manager"]?.apis?.getDocumentActions?.("panel") || []).filter((d) => ACTION_TYPES.includes(d.type));
1835
+ const props = { activeTab: query.status || "draft", model, documentId, document: doc, meta, collectionType };
1836
+ const run = async (action, event) => {
1837
+ const native = [...nativeButtons()].find((b) => b.textContent?.trim() === action.label);
1838
+ if (native) {
1839
+ native.click();
1840
+ return;
1841
+ }
1842
+ const mute = await action.onClick?.(event);
1843
+ if (action.dialog && !mute && action.dialog.type === "notification") toggleNotification({ title: action.dialog.title, message: action.dialog.content, type: action.dialog.status });
1844
+ };
1845
+ const typeOf = (action) => action.type || descriptions.find((d) => typeof action.id === "string" && action.id.startsWith(`${d.name || d.displayName}-`))?.type;
1846
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_admin2.DescriptionComponentRenderer, { props, descriptions, children: (actions) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Flex, { gap: 1, "data-testid": "page-preview-actions", children: [...actions].sort((a, b) => ACTION_TYPES.indexOf(typeOf(a)) - ACTION_TYPES.indexOf(typeOf(b))).map((action) => {
1847
+ const reason = action.disabled ? typeOf(action) === "publish" ? t.publishDisabledHint : t.saveDisabledHint : void 0;
1848
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { title: reason, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Button, { size: "S", variant: action.variant || "default", disabled: action.disabled, loading: action.loading, "aria-description": reason, onClick: (e) => run(action, e), children: action.label }) }, action.id);
1849
+ }) }) });
1850
+ }
1851
+ function PagePreview({ editor, groups = null, Toggle }) {
1852
+ const t = useMessages();
1853
+ const c = (0, import_strapi_admin.unstable_useContentManagerContext)();
1854
+ const rbac = (0, import_strapi_admin.useDocumentRBAC)("BlockscenePagePreview", (state) => state);
1855
+ const values = (0, import_admin2.useForm)("BlockscenePagePreview", (state) => state.values);
1856
+ const onChange = (0, import_admin2.useForm)("BlockscenePagePreview", (state) => state.onChange);
1857
+ const components = (0, import_admin2.useStrapiApp)("BlockscenePagePreview", (state) => state.components);
1858
+ const MediaLibraryDialog = components?.["media-library"];
1859
+ const addFieldRow = (0, import_admin2.useForm)("BlockscenePagePreview", (state) => state.addFieldRow);
1860
+ const fields = c.layout?.edit?.layout?.flat(3) || [];
1861
+ const readable = (name) => c.isCreatingEntry || (rbac.canReadFields || []).includes(name);
1862
+ const zone = React3.useMemo(() => editableZones(c.contentType, values, readable, c.isLoading)[0]?.name, [c.contentType, values, c.isLoading, rbac.canReadFields, c.isCreatingEntry]);
1863
+ const zoneLabel = fields.find((field) => field.name === zone)?.label || zone || "";
1864
+ const canEdit = Boolean(zone && ((c.isCreatingEntry ? rbac.canCreateFields : rbac.canUpdateFields) || []).includes(zone) && fields.find((field) => field.name === zone)?.disabled !== true && !c.form?.disabled && typeof addFieldRow === "function");
1865
+ const [mode, setModeState] = React3.useState(() => {
1866
+ const v = read(MODE_KEY);
1867
+ return v === "split" || v === "preview" ? v : editor?.previewMode || "form";
1868
+ });
1869
+ const setMode = (next) => {
1870
+ setModeState(next);
1871
+ write(MODE_KEY, next);
1872
+ };
1873
+ const [ratio, setRatio] = React3.useState(() => {
1874
+ const v = Number(read(RATIO_KEY));
1875
+ return v > 0 && v < 1 ? v : 0.5;
1876
+ });
1877
+ const main = useMainRect();
1878
+ const vw = main.width;
1879
+ const [dragging, setDragging] = React3.useState(false);
1880
+ const [ready, setReady] = React3.useState(false);
1881
+ const [failed, setFailed] = React3.useState(false);
1882
+ const [attempt, retry] = React3.useReducer((n) => n + 1, 0);
1883
+ const [picking, setPicking] = React3.useState(null);
1884
+ React3.useEffect(() => {
1885
+ setEditing(null);
1886
+ setPicking(null);
1887
+ setInserting(null);
1888
+ }, [c.id, c.form?.initialValues?.locale]);
1889
+ const [editing, setEditing] = React3.useState(null);
1890
+ const [inserting, setInserting] = React3.useState(null);
1891
+ const { get } = (0, import_admin2.useFetchClient)();
1892
+ const { toggleNotification } = (0, import_admin2.useNotification)();
1893
+ const zoneAttr = zone ? c.contentType?.attributes?.[zone] : null;
1894
+ const iframe = React3.useRef(null);
1895
+ const loaded = React3.useRef(false);
1896
+ const anchor = React3.useRef(null);
1897
+ const channel = React3.useMemo(() => crypto.randomUUID(), []);
1898
+ const { base, source } = usePreviewBase(editor?.previewUrl || "", c.model, c.isCreatingEntry ? void 0 : c.id, c.form?.initialValues?.locale);
1899
+ const url = base ? new URL(base) : null;
1900
+ url?.searchParams.set("channel", channel);
1901
+ const origin = url?.origin || "";
1902
+ const narrow = vw < NARROW;
1903
+ const paneWidth = clampWidth(ratio * vw, vw);
1904
+ const resizable = mode === "split" && !narrow;
1905
+ const active = mode !== "form" && Boolean(url) && Boolean(zone);
1906
+ const rows = zone && Array.isArray(values?.[zone]) ? values[zone] : [];
1907
+ const latest = React3.useRef(rows);
1908
+ latest.current = rows;
1909
+ const live = React3.useRef({ mode, canEdit, zoneLabel, components: c.components, setMode, onChange });
1910
+ live.current = { mode, canEdit, zoneLabel, components: c.components, setMode, onChange };
1911
+ const send = React3.useCallback(() => {
1912
+ iframe.current?.contentWindow?.postMessage({ protocol: PROTOCOL, channel, type: "update-page", blocks: projectPage(latest.current, live.current.components, window.location.origin), groups, locale: t.locale, mode: live.current.mode }, origin);
1913
+ }, [channel, origin]);
1914
+ const indexOf = (key) => latest.current.findIndex((row) => blockKey(row) === key);
1915
+ const path = (key, field) => `${zone}.${indexOf(key)}.${field}`;
1916
+ React3.useEffect(() => {
1917
+ if (resizable) markLayout(anchor.current);
1918
+ document.body.classList.toggle("bp-split", resizable);
1919
+ document.documentElement.style.setProperty("--bp-pane", `${paneWidth}px`);
1920
+ return () => document.body.classList.remove("bp-split");
1921
+ }, [resizable, paneWidth]);
1922
+ const applyWidth = (width, persist) => {
1923
+ const next = clampWidth(width, vw) / vw;
1924
+ setRatio(next);
1925
+ if (persist) write(RATIO_KEY, String(next));
1926
+ };
1927
+ const focusField = (index, field) => {
1928
+ const item = findZoneList(live.current.zoneLabel)?.querySelectorAll(":scope > li")[index];
1929
+ if (!item) return;
1930
+ const header = toggles(item.parentElement)[index];
1931
+ if (header?.getAttribute("aria-expanded") === "false") header.click();
1932
+ const parts = field.split(".");
1933
+ const escaped = CSS.escape(`${zone}.${index}.${field}`);
1934
+ let tries = 0;
1935
+ const timer = setInterval(() => {
1936
+ if (++tries > 40) return clearInterval(timer);
1937
+ let scope = item;
1938
+ for (let i = 0; i + 1 < parts.length; i += 2) {
1939
+ const nested = [...scope.querySelectorAll("button[aria-expanded][data-radix-collection-item]")].filter((b) => b !== header);
1940
+ const row = nested[Number(parts[i + 1])];
1941
+ if (!row) return;
1942
+ if (row.getAttribute("aria-expanded") === "false") row.click();
1943
+ scope = row.closest("li, div") || scope;
1944
+ }
1945
+ const target = document.querySelector(`[name="${escaped}"], label[for="${escaped}"]`);
1946
+ if (!target) return;
1947
+ const INPUT = '.ck-editor__editable, textarea, input:not([type="hidden"]), select';
1948
+ let container = target.matches(INPUT) ? target : target.parentElement;
1949
+ for (let depth = 0; container && depth < 4 && !container.matches(INPUT) && !container.querySelector(INPUT); depth++) container = container.parentElement;
1950
+ const editable = container?.matches(INPUT) ? container : container?.querySelector(INPUT);
1951
+ if (!editable) return;
1952
+ if (editable.classList.contains("ck-editor__editable") && !editable.isContentEditable) return;
1953
+ editable.focus();
1954
+ if (document.activeElement !== editable) return;
1955
+ clearInterval(timer);
1956
+ editable.scrollIntoView({ block: "center", behavior: "smooth" });
1957
+ }, 150);
1958
+ };
1959
+ React3.useEffect(() => {
1960
+ if (!active) return;
1961
+ setReady(false);
1962
+ setFailed(false);
1963
+ const timeout = setTimeout(() => setFailed(true), 15e3);
1964
+ const receive = (event) => {
1965
+ const is = (type) => isPreviewMessage(event, origin, iframe.current?.contentWindow, channel, type);
1966
+ const { mode: mode2, canEdit: canEdit2, zoneLabel: zoneLabel2, components: components2, setMode: setMode2, onChange: onChange2 } = live.current;
1967
+ if (is("ready")) {
1968
+ clearTimeout(timeout);
1969
+ setReady(true);
1970
+ setFailed(false);
1971
+ send();
1972
+ return;
1973
+ }
1974
+ if (is("insert") && canEdit2) {
1975
+ const after = event.data.after === null || event.data.after === void 0 ? null : String(event.data.after);
1976
+ if (after !== null && insertIndex(latest.current, after) < 0) return;
1977
+ if (latest.current.length >= (zoneAttr?.max ?? Infinity)) {
1978
+ toggleNotification({ type: "info", message: t.zoneFull });
1979
+ return;
1980
+ }
1981
+ setInserting({ after });
1982
+ return;
1983
+ }
1984
+ if (is("move-group") && canEdit2 && groups) {
1985
+ const next = (0, import_groups.moveGroup)(latest.current, String(event.data.key), event.data.direction === "up" ? "up" : "down", groups);
1986
+ if (next) onChange2(zone, next);
1987
+ return;
1988
+ }
1989
+ if (is("delete-group") && canEdit2 && groups) {
1990
+ const next = (0, import_groups.removeGroup)(latest.current, String(event.data.key), groups);
1991
+ if (next) onChange2(zone, next);
1992
+ return;
1993
+ }
1994
+ if (is("insert-group") && canEdit2 && groups) {
1995
+ const after = event.data.after === null || event.data.after === void 0 ? null : String(event.data.after);
1996
+ const index2 = insertIndex(latest.current, after);
1997
+ const uid2 = String(event.data.uid || "");
1998
+ const close = groups[uid2];
1999
+ const allowed = zoneAttr?.components || [];
2000
+ if (index2 < 0 || !close || !allowed.includes(uid2) || !allowed.includes(close)) return;
2001
+ if (latest.current.length + 2 > (zoneAttr?.max ?? Infinity)) {
2002
+ toggleNotification({ type: "info", message: t.zoneFull });
2003
+ return;
2004
+ }
2005
+ addFieldRow(zone, { ...componentDefaults(components2[uid2], components2), __component: uid2 }, index2);
2006
+ addFieldRow(zone, { __component: close }, index2 + 1);
2007
+ return;
2008
+ }
2009
+ const key = typeof event.data?.key === "string" ? event.data.key : "";
2010
+ const index = key ? indexOf(key) : -1;
2011
+ const uid = index >= 0 ? latest.current[index]?.__component : "";
2012
+ if (index < 0) return;
2013
+ if (is("select")) {
2014
+ const list = findZoneList(zoneLabel2);
2015
+ const item = list?.querySelectorAll(":scope > li")[index];
2016
+ const header = list ? toggles(list)[index] : null;
2017
+ if (header?.getAttribute("aria-expanded") === "false") header.click();
2018
+ item?.scrollIntoView({ block: "center", behavior: "smooth" });
2019
+ if (item) {
2020
+ item.style.outline = "2px solid #4945ff";
2021
+ setTimeout(() => {
2022
+ item.style.outline = "";
2023
+ }, 1500);
2024
+ }
2025
+ if (mode2 === "preview") setMode2("split");
2026
+ iframe.current?.contentWindow?.postMessage({ protocol: PROTOCOL, channel, type: "highlight", key }, origin);
2027
+ } else if (is("focus")) {
2028
+ const attr = validateFocus(uid, event.data.field, components2);
2029
+ if (!attr) return;
2030
+ if (mode2 === "preview" && canEdit2 && (attr.customField || MODAL_TYPES.includes(attr.type))) setEditing({ key, field: event.data.field, attr, label: `${components2[uid]?.info?.displayName || uid} \xB7 ${event.data.field}`, value: getIn(latest.current[index], event.data.field) });
2031
+ else focusField(index, event.data.field);
2032
+ } else if (is("media") && canEdit2) {
2033
+ const attr = mediaAttribute(uid, event.data.field, components2);
2034
+ if (attr) setPicking({ key, field: event.data.field, attr });
2035
+ } else if (is("media-remove") && canEdit2) {
2036
+ const attr = mediaAttribute(uid, event.data.field, components2);
2037
+ if (attr && !attr.required) onChange2(path(key, event.data.field), null);
2038
+ } else if (is("edit") && canEdit2) {
2039
+ const value = validateEdit(uid, event.data.field, event.data.value, components2);
2040
+ if (value !== null) onChange2(path(key, event.data.field), value);
2041
+ }
2042
+ };
2043
+ window.addEventListener("message", receive);
2044
+ if (loaded.current) iframe.current?.contentWindow?.postMessage({ protocol: PROTOCOL, channel, type: "ping" }, origin);
2045
+ return () => {
2046
+ clearTimeout(timeout);
2047
+ window.removeEventListener("message", receive);
2048
+ };
2049
+ }, [active, attempt, channel, origin, groups]);
2050
+ React3.useEffect(() => {
2051
+ if (!ready || !active) return;
2052
+ const timer = setTimeout(send, 120);
2053
+ return () => clearTimeout(timer);
2054
+ }, [values, c.components, ready, active, send, mode]);
2055
+ if (!zone) return null;
2056
+ const modes = [["form", t.modeForm], ["split", t.modeSplit], ["preview", t.modePreview]];
2057
+ const switcher = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Flex, { gap: 1, wrap: "wrap", "data-testid": "page-preview-modes", role: "group", "aria-label": t.modeGroup, children: modes.map(([value, label]) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Button, { type: "button", size: "S", variant: mode === value ? "default" : "tertiary", "aria-pressed": mode === value, onClick: () => setMode(value), disabled: !url && value !== "form", children: label }, value)) });
2058
+ const onKey = (event) => {
2059
+ const map = { ArrowLeft: paneWidth + KEY_STEP, ArrowRight: paneWidth - KEY_STEP, Home: MIN_PANE, End: vw - MIN_FORM };
2060
+ if (event.key in map) {
2061
+ event.preventDefault();
2062
+ applyWidth(map[event.key], true);
2063
+ }
2064
+ };
2065
+ const problems = groups ? (0, import_groups.validateGroups)(rows, groups) : [];
2066
+ const insertClose = (error) => {
2067
+ const end = (0, import_groups.groupRange)(latest.current, error.index, groups)[1];
2068
+ addFieldRow(zone, { __component: error.expected }, end + 1);
2069
+ };
2070
+ 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
+ /* @__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 }) }) }),
2072
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { style: { margin: "6px 0 0 16px", padding: 0 }, children: problems.map((error) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { style: { marginBottom: 6 }, children: [
2073
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Typography, { variant: "pi", textColor: "danger700", children: t.f(error.code === "closeBeforeOpen" ? "diagCloseBeforeOpen" : error.code === "mismatch" ? "diagMismatch" : "diagUnclosed", { n: error.index + 1, uid: error.uid, open: error.open || "", expected: error.expected || "" }) }),
2074
+ error.code === "unclosed" && canEdit && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Box, { paddingTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Button, { size: "S", variant: "danger-light", "data-testid": `diag-insert-close-${error.index}`, onClick: () => insertClose(error), children: t.f("diagInsertClose", { n: error.index + 1, expected: error.expected }) }) }),
2075
+ error.code === "closeBeforeOpen" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Typography, { variant: "pi", textColor: "neutral600", children: t.diagStrayHint })
2076
+ ] }, `${error.code}-${error.index}`)) })
2077
+ ] }) });
2078
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system3.Flex, { direction: "column", alignItems: "stretch", gap: 2, ref: anchor, children: [
2079
+ switcher,
2080
+ diagnostics,
2081
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Typography, { variant: "pi", textColor: "neutral600", children: url ? t.previewHelp : t.previewNoUrl }),
2082
+ active && (0, import_react_dom2.createPortal)(
2083
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2084
+ Pane,
2085
+ {
2086
+ "data-testid": "page-preview-pane",
2087
+ "aria-label": t.previewPane,
2088
+ style: { left: mode === "preview" || narrow ? main.left : main.left + main.width - paneWidth, width: mode === "preview" || narrow ? main.width : paneWidth, userSelect: dragging ? "none" : void 0 },
2089
+ children: [
2090
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: SPLIT_STYLE }),
2091
+ resizable && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2092
+ Handle,
2093
+ {
2094
+ role: "separator",
2095
+ "aria-orientation": "vertical",
2096
+ "aria-label": t.resize,
2097
+ tabIndex: 0,
2098
+ "aria-valuemin": MIN_PANE,
2099
+ "aria-valuemax": Math.max(MIN_PANE, vw - MIN_FORM),
2100
+ "aria-valuenow": paneWidth,
2101
+ "data-testid": "page-preview-resizer",
2102
+ "data-dragging": dragging,
2103
+ onPointerDown: (e) => {
2104
+ e.preventDefault();
2105
+ e.currentTarget.setPointerCapture(e.pointerId);
2106
+ setDragging(true);
2107
+ },
2108
+ onPointerMove: (e) => {
2109
+ if (dragging) applyWidth(main.left + main.width - e.clientX, false);
2110
+ },
2111
+ onPointerUp: (e) => {
2112
+ if (!dragging) return;
2113
+ setDragging(false);
2114
+ e.currentTarget.releasePointerCapture(e.pointerId);
2115
+ applyWidth(main.left + main.width - e.clientX, true);
2116
+ },
2117
+ onPointerCancel: () => setDragging(false),
2118
+ onKeyDown: onKey
2119
+ }
2120
+ ),
2121
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system3.Flex, { padding: 2, gap: 2, justifyContent: "space-between", alignItems: "center", background: "neutral100", wrap: "wrap", style: { position: "sticky", top: 0, zIndex: 2 }, children: [
2122
+ switcher,
2123
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system3.Flex, { gap: 2, alignItems: "center", wrap: "wrap", style: { marginLeft: "auto" }, children: [
2124
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Typography, { variant: "pi", role: "status", textColor: "neutral600", children: failed ? t.previewFailed : ready ? t.previewReady : t.previewLoading }),
2125
+ failed && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Button, { size: "S", variant: "secondary", onClick: retry, children: t.retry }),
2126
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ToolbarActions, { model: c.model, collectionType: c.collectionType, documentId: c.isCreatingEntry ? void 0 : c.id, locale: c.form?.initialValues?.locale })
2127
+ ] })
2128
+ ] }),
2129
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2130
+ Frame2,
2131
+ {
2132
+ ref: iframe,
2133
+ title: t.previewPane,
2134
+ src: url.href,
2135
+ sandbox: "allow-scripts allow-same-origin",
2136
+ referrerPolicy: "no-referrer",
2137
+ onLoad: () => {
2138
+ loaded.current = true;
2139
+ },
2140
+ style: dragging ? { pointerEvents: "none" } : void 0
2141
+ },
2142
+ attempt
2143
+ )
2144
+ ]
2145
+ }
2146
+ ),
2147
+ document.body
2148
+ ),
2149
+ inserting && zoneAttr && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2150
+ PickerModal,
2151
+ {
2152
+ zone: { name: zone, components: zoneAttr.components || [], max: zoneAttr.max },
2153
+ components: c.components,
2154
+ Modal: PickerDialog,
2155
+ Toggle,
2156
+ get,
2157
+ open: true,
2158
+ onOpenChange: (open) => {
2159
+ if (!open) setInserting(null);
2160
+ },
2161
+ onSelect: (uid) => {
2162
+ const index = insertIndex(latest.current, inserting.after);
2163
+ setInserting(null);
2164
+ const close = groups?.[uid];
2165
+ if (index < 0 || !(zoneAttr.components || []).includes(uid) || close && !(zoneAttr.components || []).includes(close) || latest.current.length + (close ? 2 : 1) > (zoneAttr.max ?? Infinity)) {
2166
+ toggleNotification({ type: "warning", message: close ? t.zoneFull : t.insertMoved });
2167
+ return;
2168
+ }
2169
+ addFieldRow(zone, { ...componentDefaults(c.components[uid], c.components), __component: uid }, index);
2170
+ if (close) addFieldRow(zone, { __component: close }, index + 1);
2171
+ }
2172
+ }
2173
+ ),
2174
+ editing && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2175
+ FieldEditorModal,
2176
+ {
2177
+ label: editing.label,
2178
+ attribute: editing.attr,
2179
+ value: editing.value,
2180
+ onCancel: () => setEditing(null),
2181
+ onApply: (value) => {
2182
+ const index = indexOf(editing.key);
2183
+ setEditing(null);
2184
+ if (index >= 0) onChange(`${zone}.${index}.${editing.field}`, value);
2185
+ }
2186
+ }
2187
+ ),
2188
+ picking && MediaLibraryDialog && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2189
+ MediaLibraryDialog,
2190
+ {
2191
+ allowedTypes: picking.attr.allowedTypes || ["images"],
2192
+ multiple: picking.attr.multiple === true,
2193
+ onClose: () => setPicking(null),
2194
+ onSelectAssets: (assets) => {
2195
+ const index = indexOf(picking.key);
2196
+ setPicking(null);
2197
+ if (index < 0 || !assets?.length) return;
2198
+ const current = getIn(latest.current[index], picking.field);
2199
+ onChange(`${zone}.${index}.${picking.field}`, picking.attr.multiple ? [...Array.isArray(current) ? current : [], ...assets] : assets[0]);
2200
+ }
2201
+ }
2202
+ ),
2203
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Box, { hidden: true, "data-testid": "page-preview-state", "data-mode": mode, "data-ready": ready, "data-failed": failed, "data-pane-width": paneWidth, "data-narrow": narrow, "data-preview-source": source, "data-editing": editing ? editing.field : "" })
2204
+ ] });
2205
+ }
2206
+
2207
+ // admin/Settings.tsx
2208
+ var React4 = __toESM(require("react"));
2209
+ var import_design_system5 = require("@strapi/design-system");
2210
+ var import_styled_components3 = __toESM(require("styled-components"));
2211
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1418
2212
  var COLOR2 = /^#[0-9A-Fa-f]{6}$/;
1419
- var Grid = import_styled_components2.default.div` display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: 16px; `;
1420
- var Card2 = import_styled_components2.default.div`
2213
+ var Grid = import_styled_components3.default.div` display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: 16px; `;
2214
+ var Card2 = import_styled_components3.default.div`
1421
2215
  display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: 4px;
1422
2216
  border: 1px solid ${({ theme }) => theme.colors.neutral200}; background: ${({ theme }) => theme.colors.neutral0};
1423
2217
  `;
1424
- var Bar = import_styled_components2.default.div`
2218
+ var Bar = import_styled_components3.default.div`
1425
2219
  position: fixed; top: 0; z-index: 4; padding: 12px 32px;
1426
2220
  background: ${({ theme }) => theme.colors.neutral100}; border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};
1427
2221
  box-shadow: 0 1px 4px rgba(33, 33, 52, 0.1);
1428
2222
  `;
1429
- function useMainRect(anchor) {
1430
- const [rect, setRect] = React2.useState({ left: 0, width: 0 });
1431
- React2.useEffect(() => {
1432
- const read = () => {
2223
+ function useMainRect2(anchor) {
2224
+ const [rect, setRect] = React4.useState({ left: 0, width: 0 });
2225
+ React4.useEffect(() => {
2226
+ const read2 = () => {
1433
2227
  let host = document.getElementById("main-content");
1434
2228
  for (let el = anchor.current?.parentElement; !host && el; el = el.parentElement) if (["auto", "scroll"].includes(getComputedStyle(el).overflowY) && el.scrollHeight > el.clientHeight) host = el;
1435
2229
  const r = (host || document.querySelector("main"))?.getBoundingClientRect();
1436
2230
  if (r) setRect({ left: Math.round(r.left), width: Math.round(r.width) });
1437
2231
  };
1438
- read();
1439
- window.addEventListener("resize", read);
1440
- return () => window.removeEventListener("resize", read);
2232
+ read2();
2233
+ window.addEventListener("resize", read2);
2234
+ return () => window.removeEventListener("resize", read2);
1441
2235
  });
1442
2236
  return rect;
1443
2237
  }
1444
- var Swatches = import_styled_components2.default.div` display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 12px; `;
1445
- var Label = import_styled_components2.default.label` display: flex; flex-direction: column; gap: 4px; font-size: 12px; `;
2238
+ var Swatches = import_styled_components3.default.div` display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 12px; `;
2239
+ var Label = import_styled_components3.default.label` display: flex; flex-direction: column; gap: 4px; font-size: 12px; `;
1446
2240
  function ColorField({ name, label, value, onChange, disabled }) {
1447
2241
  const valid = COLOR2.test(value);
1448
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Label, { children: [
1449
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
1450
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { gap: 2, children: [
1451
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "color", "aria-label": label, value: valid ? value : "#000000", disabled, onChange: (e) => onChange(e.target.value.toUpperCase()), style: { width: 40, height: 32, padding: 0, border: 0, background: "none" } }),
1452
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2242
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Label, { children: [
2243
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
2244
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { gap: 2, children: [
2245
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "color", "aria-label": label, value: valid ? value : "#000000", disabled, onChange: (e) => onChange(e.target.value.toUpperCase()), style: { width: 40, height: 32, padding: 0, border: 0, background: "none" } }),
2246
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1453
2247
  "input",
1454
2248
  {
1455
2249
  name,
@@ -1465,22 +2259,22 @@ function ColorField({ name, label, value, onChange, disabled }) {
1465
2259
  ] });
1466
2260
  }
1467
2261
  var permissions = { read: [{ action: "plugin::blockscene.settings.read", subject: null }], update: [{ action: "plugin::blockscene.settings.update", subject: null }] };
1468
- function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: MediaPicker2, ToggleField: ToggleField2, SelectField: SelectField2, TextField, previewSupported = false }) {
2262
+ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: MediaPicker2, ToggleField: ToggleField2, SelectField: SelectField2, TextField: TextField2, previewSupported = false }) {
1469
2263
  const t = useMessages();
1470
2264
  const { get, put } = useClient();
1471
2265
  const { canRead, canUpdate, isLoading } = usePermissions2();
1472
- const [data, setData] = React2.useState(null);
1473
- const [catalog, setCatalog] = React2.useState(null);
1474
- const [settings, setSettings] = React2.useState(null);
1475
- const [media, setMedia] = React2.useState({});
1476
- const [sources, setSources] = React2.useState({});
1477
- const [dirty, setDirty] = React2.useState(false);
1478
- const [saving, setSaving] = React2.useState(false);
1479
- const [status, setStatus] = React2.useState("");
1480
- const [failed, setFailed] = React2.useState(false);
1481
- const [filter, setFilter] = React2.useState("");
1482
- const [picking, setPicking] = React2.useState(null);
1483
- React2.useEffect(() => {
2266
+ const [data, setData] = React4.useState(null);
2267
+ const [catalog, setCatalog] = React4.useState(null);
2268
+ const [settings, setSettings] = React4.useState(null);
2269
+ const [media, setMedia] = React4.useState({});
2270
+ const [sources, setSources] = React4.useState({});
2271
+ const [dirty, setDirty] = React4.useState(false);
2272
+ const [saving, setSaving] = React4.useState(false);
2273
+ const [status, setStatus] = React4.useState("");
2274
+ const [failed, setFailed] = React4.useState(false);
2275
+ const [filter, setFilter] = React4.useState("");
2276
+ const [picking, setPicking] = React4.useState(null);
2277
+ React4.useEffect(() => {
1484
2278
  if (!canRead || isLoading) return;
1485
2279
  let active = true;
1486
2280
  Promise.all([get("/blockscene/settings"), get("/blockscene/catalog")]).then(([s, c]) => {
@@ -1528,35 +2322,35 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
1528
2322
  return index === 0 && manual ? t.manual : t.automatic;
1529
2323
  };
1530
2324
  const ready = !isLoading && canRead && !failed && settings && catalog;
1531
- const header = React2.useRef(null);
1532
- const [floating, setFloating] = React2.useState(false);
1533
- const main = useMainRect(header);
1534
- React2.useEffect(() => {
2325
+ const header = React4.useRef(null);
2326
+ const [floating, setFloating] = React4.useState(false);
2327
+ const main = useMainRect2(header);
2328
+ React4.useEffect(() => {
1535
2329
  const el = header.current;
1536
2330
  if (!el || typeof IntersectionObserver === "undefined") return;
1537
2331
  const observer = new IntersectionObserver(([entry]) => setFloating(!entry.isIntersecting && entry.boundingClientRect.top < 0));
1538
2332
  observer.observe(el);
1539
2333
  return () => observer.disconnect();
1540
2334
  }, [ready]);
1541
- const controls = (suffix) => ready && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
1542
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { role: "status", "aria-live": "polite", textColor: dirty ? "warning700" : "neutral600", "data-testid": `${dirty ? "unsaved-indicator" : "save-status"}${suffix}`, children: dirty ? t.unsaved : status || t.noChanges }),
1543
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Button, { onClick: save, disabled: !canUpdate || invalid || !dirty, loading: saving, "data-testid": `save-blockscene-settings${suffix}`, children: t.save })
2335
+ const controls = (suffix) => ready && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
2336
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { role: "status", "aria-live": "polite", textColor: dirty ? "warning700" : "neutral600", "data-testid": `${dirty ? "unsaved-indicator" : "save-status"}${suffix}`, children: dirty ? t.unsaved : status || t.noChanges }),
2337
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Button, { onClick: save, disabled: !canUpdate || invalid || !dirty, loading: saving, "data-testid": `save-blockscene-settings${suffix}`, children: t.save })
1544
2338
  ] });
1545
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Box, { padding: 8, background: "neutral100", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { direction: "column", alignItems: "stretch", gap: 5, children: [
1546
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: header, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
1547
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "alpha", tag: "h1", children: t.settingsTitle }),
2339
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Box, { padding: 8, background: "neutral100", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 5, children: [
2340
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: header, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
2341
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "alpha", tag: "h1", children: t.settingsTitle }),
1548
2342
  controls("")
1549
2343
  ] }) }),
1550
- floating && main.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Bar, { style: { left: main.left, width: main.width }, "data-testid": "settings-floating-bar", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
1551
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "beta", tag: "p", children: t.settingsTitle }),
2344
+ floating && main.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Bar, { style: { left: main.left, width: main.width }, "data-testid": "settings-floating-bar", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
2345
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "beta", tag: "p", children: t.settingsTitle }),
1552
2346
  controls("-floating")
1553
2347
  ] }) }),
1554
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { textColor: "neutral600", children: t.settingsIntro }),
1555
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { children: "\u2026" }) : !canRead ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { role: "alert", children: t.denied }) : failed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { role: "alert", children: t.loadFailed }) : !settings || !catalog ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1556
- data.disabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Box, { padding: 4, background: "warning100", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { role: "alert", textColor: "warning700", children: t.disabledByServer }) }),
1557
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
1558
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "beta", tag: "h2", children: t.palette }),
1559
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Swatches, { children: Object.keys(DEFAULT_PALETTE).map((key) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2348
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { textColor: "neutral600", children: t.settingsIntro }),
2349
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { children: "\u2026" }) : !canRead ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { role: "alert", children: t.denied }) : failed ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { role: "alert", children: t.loadFailed }) : !settings || !catalog ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2350
+ data.disabled && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Box, { padding: 4, background: "warning100", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { role: "alert", textColor: "warning700", children: t.disabledByServer }) }),
2351
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
2352
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.palette }),
2353
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Swatches, { children: Object.keys(DEFAULT_PALETTE).map((key) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1560
2354
  ColorField,
1561
2355
  {
1562
2356
  name: `palette-${key}`,
@@ -1570,33 +2364,33 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
1570
2364
  },
1571
2365
  key
1572
2366
  )) }),
1573
- invalid && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { role: "alert", textColor: "danger600", children: t.invalidColor }),
1574
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.previewLabel }),
1575
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Swatches, { "data-testid": "palette-preview", children: TEMPLATES.map((template) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { direction: "column", gap: 1, children: [
1576
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Box, { style: { aspectRatio: "16 / 9", overflow: "hidden" }, hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Wireframe, { template, palette: settings.palette }) }),
1577
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.templates[template] })
2367
+ invalid && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { role: "alert", textColor: "danger600", children: t.invalidColor }),
2368
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewLabel }),
2369
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Swatches, { "data-testid": "palette-preview", children: TEMPLATES.map((template) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { direction: "column", gap: 1, children: [
2370
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Box, { style: { aspectRatio: "16 / 9", overflow: "hidden" }, hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Wireframe, { template, palette: settings.palette }) }),
2371
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.templates[template] })
1578
2372
  ] }, template)) }),
1579
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Flex, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Button, { variant: "tertiary", size: "S", disabled: !canUpdate, onClick: () => update((s) => {
2373
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Flex, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Button, { variant: "tertiary", size: "S", disabled: !canUpdate, onClick: () => update((s) => {
1580
2374
  s.palette = { ...DEFAULT_PALETTE };
1581
2375
  return s;
1582
2376
  }), children: t.resetPalette }) })
1583
2377
  ] }) }),
1584
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
1585
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "beta", tag: "h2", children: t.editor }),
1586
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleField2, { name: "editor-enabled", label: t.enabled, value: editor.enabled, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
2378
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
2379
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.editor }),
2380
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleField2, { name: "editor-enabled", label: t.enabled, value: editor.enabled, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
1587
2381
  s.editor.enabled = v;
1588
2382
  return s;
1589
2383
  }) }),
1590
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.enabledHelp }),
1591
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleField2, { name: "editor-showOpenAll", label: t.showOpenAll, value: editor.showOpenAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
2384
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.enabledHelp }),
2385
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleField2, { name: "editor-showOpenAll", label: t.showOpenAll, value: editor.showOpenAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
1592
2386
  s.editor.showOpenAll = v;
1593
2387
  return s;
1594
2388
  }) }),
1595
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleField2, { name: "editor-showCloseAll", label: t.showCloseAll, value: editor.showCloseAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
2389
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleField2, { name: "editor-showCloseAll", label: t.showCloseAll, value: editor.showCloseAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
1596
2390
  s.editor.showCloseAll = v;
1597
2391
  return s;
1598
2392
  }) }),
1599
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2393
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1600
2394
  SelectField2,
1601
2395
  {
1602
2396
  name: "editor-initialState",
@@ -1610,10 +2404,10 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
1610
2404
  })
1611
2405
  }
1612
2406
  ),
1613
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.rememberHelp }),
1614
- previewSupported ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1615
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1616
- TextField,
2407
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.rememberHelp }),
2408
+ previewSupported ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2409
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2410
+ TextField2,
1617
2411
  {
1618
2412
  name: "editor-previewUrl",
1619
2413
  label: t.previewUrl,
@@ -1626,8 +2420,8 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
1626
2420
  })
1627
2421
  }
1628
2422
  ),
1629
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.previewUrlHelp }),
1630
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2423
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewUrlHelp }),
2424
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1631
2425
  SelectField2,
1632
2426
  {
1633
2427
  name: "editor-previewMode",
@@ -1641,26 +2435,26 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
1641
2435
  })
1642
2436
  }
1643
2437
  ),
1644
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.previewModeHelp }),
1645
- data.blockPreviewAvailable && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1646
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
2438
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewModeHelp }),
2439
+ data.blockPreviewAvailable && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2440
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
1647
2441
  s.editor.blockPreviewInForm = v;
1648
2442
  return s;
1649
2443
  }) }),
1650
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
2444
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
1651
2445
  ] })
1652
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.previewV4 })
2446
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewV4 })
1653
2447
  ] }) }),
1654
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
1655
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "beta", tag: "h2", children: t.components }),
1656
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Searchbar, { name: "component-filter", value: filter, placeholder: t.filter, clearLabel: t.clear, onClear: () => setFilter(""), onChange: (e) => setFilter(e.target.value), children: t.filter }),
1657
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", "data-testid": "components-count", children: t.f("countAll", { count: components.length }) }),
1658
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Grid, { "data-testid": "components-grid", children: components.map((component) => {
2448
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
2449
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.components }),
2450
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Searchbar, { name: "component-filter", value: filter, placeholder: t.filter, clearLabel: t.clear, onClear: () => setFilter(""), onChange: (e) => setFilter(e.target.value), children: t.filter }),
2451
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", "data-testid": "components-count", children: t.f("countAll", { count: components.length }) }),
2452
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Grid, { "data-testid": "components-grid", children: components.map((component) => {
1659
2453
  const entry = settings.components[component.uid] || {};
1660
2454
  const meta = { ...catalog.components?.[component.uid] || {}, ...media[component.uid] || {} };
1661
2455
  const candidates = candidatesFor(component.uid, meta, catalog);
1662
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Card2, { "data-testid": `settings-${component.uid}`, children: [
1663
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2456
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Card2, { "data-testid": `settings-${component.uid}`, children: [
2457
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1664
2458
  Thumb,
1665
2459
  {
1666
2460
  candidates,
@@ -1671,23 +2465,23 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
1671
2465
  onResolved: (index) => setSources((current) => current[component.uid] === index ? current : { ...current, [component.uid]: index })
1672
2466
  }
1673
2467
  ),
1674
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
1675
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { fontWeight: "bold", textColor: "neutral800", children: component.displayName }),
1676
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: [
2468
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
2469
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { fontWeight: "bold", textColor: "neutral800", children: component.displayName }),
2470
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: [
1677
2471
  component.uid,
1678
2472
  " \xB7 ",
1679
2473
  component.category
1680
2474
  ] }),
1681
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Typography, { variant: "pi", "data-testid": `source-${component.uid}`, children: [
2475
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Typography, { variant: "pi", "data-testid": `source-${component.uid}`, children: [
1682
2476
  t.source,
1683
2477
  ": ",
1684
2478
  sourceOf(component.uid, Boolean(meta.manualImage)),
1685
2479
  meta.manualName ? ` (${meta.manualName})` : ""
1686
2480
  ] }),
1687
- meta.manualMissing && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Typography, { variant: "pi", role: "alert", textColor: "danger600", children: t.brokenMedia }),
1688
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system2.Flex, { gap: 2, wrap: "wrap", children: [
1689
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Button, { variant: "secondary", size: "S", disabled: !canUpdate || saving, onClick: () => setPicking(component.uid), children: entry.mediaId ? t.replace : t.choose }),
1690
- entry.mediaId && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Button, { variant: "tertiary", size: "S", disabled: !canUpdate || saving, onClick: () => {
2481
+ meta.manualMissing && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", role: "alert", textColor: "danger600", children: t.brokenMedia }),
2482
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { gap: 2, wrap: "wrap", children: [
2483
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Button, { variant: "secondary", size: "S", disabled: !canUpdate || saving, onClick: () => setPicking(component.uid), children: entry.mediaId ? t.replace : t.choose }),
2484
+ entry.mediaId && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Button, { variant: "tertiary", size: "S", disabled: !canUpdate || saving, onClick: () => {
1691
2485
  update((s) => {
1692
2486
  delete s.components[component.uid]?.mediaId;
1693
2487
  if (!Object.keys(s.components[component.uid] || {}).length) delete s.components[component.uid];
@@ -1700,7 +2494,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
1700
2494
  });
1701
2495
  }, children: t.useAutomatic })
1702
2496
  ] }),
1703
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2497
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1704
2498
  SelectField2,
1705
2499
  {
1706
2500
  name: `template-${component.uid}`,
@@ -1718,7 +2512,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
1718
2512
  ] }, component.uid);
1719
2513
  }) })
1720
2514
  ] }) }),
1721
- picking && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MediaPicker2, { onClose: () => setPicking(null), onSelect: (asset) => {
2515
+ picking && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MediaPicker2, { onClose: () => setPicking(null), onSelect: (asset) => {
1722
2516
  const uid = picking;
1723
2517
  setPicking(null);
1724
2518
  if (!asset?.id) return;
@@ -1745,10 +2539,10 @@ function register(app, Component) {
1745
2539
  }
1746
2540
 
1747
2541
  // admin/catalog.ts
1748
- var React3 = __toESM(require("react"));
2542
+ var React5 = __toESM(require("react"));
1749
2543
  function useCatalog(get) {
1750
- const [catalog, setCatalog] = React3.useState(null);
1751
- React3.useEffect(() => {
2544
+ const [catalog, setCatalog] = React5.useState(null);
2545
+ React5.useEffect(() => {
1752
2546
  let active = true;
1753
2547
  get("/blockscene/catalog").then(({ data }) => {
1754
2548
  if (active) setCatalog(data);
@@ -1762,77 +2556,83 @@ function useCatalog(get) {
1762
2556
  return catalog;
1763
2557
  }
1764
2558
 
1765
- // admin/strapi4.tsx
1766
- var import_jsx_runtime4 = require("react/jsx-runtime");
1767
- function Modal({ open, onOpenChange, trigger, title, children }) {
1768
- const id = React4.useId();
1769
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
1770
- trigger,
1771
- open && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system3.ModalLayout, { onClose: () => onOpenChange(false), labelledBy: id, children: [
1772
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.ModalHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Typography, { id, variant: "beta", children: title }) }),
1773
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.ModalBody, { children })
2559
+ // admin/strapi5.tsx
2560
+ var import_jsx_runtime6 = require("react/jsx-runtime");
2561
+ function Modal2({ open, onOpenChange, trigger, title, children }) {
2562
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Modal.Root, { open, onOpenChange, children: [
2563
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Modal.Trigger, { children: trigger }),
2564
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Modal.Content, { style: { width: "80vw", maxWidth: "80vw" }, children: [
2565
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Modal.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Modal.Title, { children: title }) }),
2566
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Modal.Body, { children })
1774
2567
  ] })
1775
2568
  ] });
1776
2569
  }
1777
- function Picker() {
1778
- const c = (0, import_helper_plugin.useCMEditViewDataManager)();
1779
- const { get } = (0, import_helper_plugin.useFetchClient)();
2570
+ function Panel() {
2571
+ const c = (0, import_strapi_admin2.unstable_useContentManagerContext)();
2572
+ const rbac = (0, import_strapi_admin2.useDocumentRBAC)("Blockscene", (state) => state);
2573
+ const { get } = (0, import_admin3.useFetchClient)();
2574
+ const t = useMessages();
2575
+ const user = (0, import_admin3.useAuth)("Blockscene", (state) => state.user);
2576
+ const formValues = (0, import_admin3.useForm)("Blockscene", (state) => state.values);
1780
2577
  const catalog = useCatalog(get);
1781
- const components = c.allLayoutData?.components || {};
1782
- const schema = c.layout || c.allLayoutData?.contentType;
1783
- const allowed = (c.isCreatingEntry ? c.createActionAllowedFields : c.updateActionAllowedFields) || [];
1784
- const zones = editableZones(schema, c.modifiedData, (name) => allowed.includes(name) && schema?.metadatas?.[name]?.edit?.editable !== false, !c.addComponentToDynamicZone).map((zone) => ({ ...zone, label: schema?.metadatas?.[zone.name]?.edit?.label || zone.name }));
2578
+ const creating = !c.id && !c.form?.initialValues?.id && !c.form?.initialValues?.documentId;
2579
+ const allowed = (creating ? rbac.canCreateFields : rbac.canUpdateFields) || [];
2580
+ const fields = c.layout?.edit?.layout?.flat(3) || [];
2581
+ const zones = editableZones(
2582
+ c.contentType,
2583
+ formValues ?? c.form?.values,
2584
+ (name) => allowed.includes(name) && (creating || (rbac.canReadFields || []).includes(name)) && fields.find((field) => field.name === name)?.disabled !== true,
2585
+ c.isLoading || c.form?.disabled || !c.form?.addFieldRow
2586
+ ).map((zone) => ({ ...zone, label: fields.find((field) => field.name === zone.name)?.label || zone.name }));
1785
2587
  const add = (zone, uid) => {
2588
+ const values = formValues ?? c.form.values;
1786
2589
  const close = catalog?.groups?.[uid];
1787
- if (!canInsert(zone, uid, c.modifiedData, components, close ? 2 : 1) || close && !zone.components.includes(close)) return false;
1788
- c.addComponentToDynamicZone(zone.name, components[uid], components, Boolean(c.formErrors?.[zone.name]));
1789
- if (close) c.addComponentToDynamicZone(zone.name, components[close], components, Boolean(c.formErrors?.[zone.name]));
2590
+ if (c.form.disabled || !canInsert(zone, uid, values, c.components, close ? 2 : 1) || close && !zone.components.includes(close)) return false;
2591
+ const at = Array.isArray(values?.[zone.name]) ? values[zone.name].length : 0;
2592
+ c.form.addFieldRow(zone.name, { ...componentDefaults(c.components[uid], c.components), __component: uid }, at);
2593
+ if (close) c.form.addFieldRow(zone.name, { __component: close }, at + 1);
1790
2594
  return true;
1791
2595
  };
1792
- if (!catalog?.editor?.enabled) return null;
1793
- const docKey = `${c.slug}:${c.isCreatingEntry ? "new" : c.initialData?.id}:${c.initialData?.locale || ""}`;
1794
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1795
- Gallery,
1796
- {
1797
- zones,
1798
- components,
1799
- add,
1800
- Modal,
1801
- Toggle: ToggleField,
1802
- get,
1803
- editor: catalog.editor,
1804
- docKey,
1805
- contentType: c.slug,
1806
- userId: import_helper_plugin.auth.getUserInfo?.()?.id
1807
- }
1808
- );
2596
+ if (!zones.length || !catalog?.editor?.enabled) return null;
2597
+ const docKey = `${c.model}:${creating ? "new" : c.id}:${c.form?.initialValues?.locale || ""}`;
2598
+ return { title: t.gallery, content: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
2599
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Gallery, { zones, components: c.components, add, Modal: Modal2, Toggle: ToggleField, get, editor: catalog.editor, docKey, contentType: c.model, userId: user?.id }),
2600
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PagePreview, { editor: catalog.editor, groups: catalog.groups || null, Toggle: ToggleField })
2601
+ ] }) };
1809
2602
  }
1810
- var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system3.Flex, { gap: 3, children: [
1811
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Switch, { name, "aria-label": label, selected: Boolean(value), disabled, onChange: () => onChange(!value) }),
1812
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Typography, { children: label })
2603
+ var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Flex, { gap: 3, children: [
2604
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Switch, { name, "aria-label": label, checked: Boolean(value), disabled, onCheckedChange: onChange }),
2605
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Typography, { children: label })
2606
+ ] });
2607
+ var TextField = ({ name, label, value, onChange, disabled, placeholder }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Field.Root, { name, children: [
2608
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Field.Label, { children: label }),
2609
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.TextInput, { name, value, disabled, placeholder, onChange: (e) => onChange(e.target.value) })
2610
+ ] });
2611
+ var SelectField = ({ name, label, value, onChange, disabled, options }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Field.Root, { name, children: [
2612
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Field.Label, { children: label }),
2613
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.SingleSelect, { value, disabled, onChange: (v) => onChange(String(v)), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.SingleSelectOption, { value: o.value, children: o.label }, o.value)) })
1813
2614
  ] });
1814
- var SelectField = ({ name, label, value, onChange, disabled, options }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.SingleSelect, { name, label, value, disabled, onChange: (v) => onChange(String(v)), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.SingleSelectOption, { value: o.value, children: o.label }, o.value)) });
1815
2615
  function MediaPicker({ onClose, onSelect }) {
1816
- const { components } = (0, import_helper_plugin.useLibrary)();
1817
- const Dialog = components?.["media-library"];
1818
- if (!Dialog) {
1819
- onClose();
1820
- return null;
1821
- }
1822
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Dialog, { onClose, allowedTypes: ["images"], onSelectAssets: (assets) => onSelect(assets?.[0]) });
2616
+ const components = (0, import_admin3.useStrapiApp)("Blockscene", (state) => state.components);
2617
+ const Dialog3 = components?.["media-library"];
2618
+ React6.useEffect(() => {
2619
+ if (!Dialog3) onClose();
2620
+ }, [Dialog3, onClose]);
2621
+ if (!Dialog3) return null;
2622
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Dialog3, { onClose, allowedTypes: ["images"], multiple: false, onSelectAssets: (assets) => onSelect(assets?.[0]) });
1823
2623
  }
1824
2624
  function usePermissions() {
1825
- const { allowedActions, isLoading } = (0, import_helper_plugin.useRBAC)(permissions);
2625
+ const { allowedActions, isLoading } = (0, import_admin3.useRBAC)(permissions);
1826
2626
  return { canRead: allowedActions.canRead, canUpdate: allowedActions.canUpdate, isLoading };
1827
2627
  }
1828
- var SettingsPage = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Settings, { useClient: import_helper_plugin.useFetchClient, usePermissions, MediaPicker, ToggleField, SelectField, previewSupported: false });
1829
- var strapi4_default = {
2628
+ var SettingsPage = () => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Settings, { useClient: import_admin3.useFetchClient, usePermissions, MediaPicker, ToggleField, SelectField, TextField, previewSupported: true });
2629
+ var strapi5_default = {
1830
2630
  register(app) {
1831
2631
  register(app, SettingsPage);
1832
2632
  app.registerPlugin({ id: "blockscene", name: "Blockscene" });
1833
2633
  },
1834
2634
  registerTrads,
1835
2635
  bootstrap(app) {
1836
- app.injectContentManagerComponent("editView", "right-links", { name: "blockscene", Component: Picker });
2636
+ app.getPlugin("content-manager").apis.addEditViewSidePanel([Panel]);
1837
2637
  }
1838
2638
  };