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

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 (4) hide show
  1. package/README.md +12 -1
  2. package/dist/admin.cjs +1295 -366
  3. package/dist/admin.mjs +1334 -368
  4. package/package.json +1 -1
package/dist/admin.cjs CHANGED
@@ -141,30 +141,35 @@ __export(strapi5_exports, {
141
141
  default: () => strapi5_default
142
142
  });
143
143
  module.exports = __toCommonJS(strapi5_exports);
144
- var React6 = __toESM(require("react"));
145
- var import_design_system6 = require("@strapi/design-system");
144
+ var React7 = __toESM(require("react"));
145
+ var import_design_system5 = require("@strapi/design-system");
146
146
  var import_admin3 = require("@strapi/strapi/admin");
147
147
  var import_strapi_admin2 = require("@strapi/content-manager/strapi-admin");
148
148
 
149
149
  // admin/Gallery.tsx
150
- var React = __toESM(require("react"));
151
- var import_react_dom = require("react-dom");
150
+ var React2 = __toESM(require("react"));
151
+ var import_react_dom2 = require("react-dom");
152
152
  var import_design_system = require("@strapi/design-system");
153
153
  var import_styled_components = __toESM(require("styled-components"));
154
154
 
155
155
  // admin/model.mjs
156
156
  var import_fractional_indexing = require("fractional-indexing");
157
157
  function componentDefaults(schema, components, stack = []) {
158
- if (!schema || stack.includes(schema)) throw new Error("Invalid recursive component defaults");
158
+ if (!schema || stack.includes(schema))
159
+ throw new Error("Invalid recursive component defaults");
159
160
  const row = {};
160
161
  for (const [name, attr] of Object.entries(schema.attributes || {})) {
161
162
  if (Object.hasOwn(attr, "default")) {
162
163
  const value = structuredClone(attr.default);
163
164
  if (attr.type === "password") row[name] = "";
164
- else if (attr.type === "relation") row[name] = { connect: [], disconnect: [] };
165
+ else if (attr.type === "relation")
166
+ row[name] = { connect: [], disconnect: [] };
165
167
  else if (value !== null || attr.type === "boolean") row[name] = value;
166
168
  } else if (attr.type === "component" && attr.required) {
167
- const create = () => componentDefaults(components[attr.component], components, [...stack, schema]);
169
+ const create = () => componentDefaults(components[attr.component], components, [
170
+ ...stack,
171
+ schema
172
+ ]);
168
173
  if (attr.repeatable) {
169
174
  const keys = (0, import_fractional_indexing.generateNKeysBetween)(null, null, attr.min || 0);
170
175
  row[name] = keys.map((key) => ({ ...create(), __temp_key__: key }));
@@ -175,27 +180,58 @@ function componentDefaults(schema, components, stack = []) {
175
180
  }
176
181
  function editableZones(schema, values, canEdit, disabled = false) {
177
182
  if (disabled) return [];
178
- return Object.entries(schema?.attributes || {}).filter(([name, attr]) => attr.type === "dynamiczone" && !attr.conditions && canEdit(name)).map(([name, attr]) => {
179
- const count = Array.isArray(values?.[name]) ? values[name].length : 0;
180
- return { name, components: attr.components || [], max: attr.max, count, full: count >= (attr.max ?? Infinity) };
183
+ return Object.entries(schema?.attributes || {}).filter(
184
+ ([name, attr]) => attr.type === "dynamiczone" && !attr.conditions && canEdit(name)
185
+ ).map(([name, attr]) => {
186
+ const rows = Array.isArray(values?.[name]) ? values[name] : [];
187
+ return {
188
+ name,
189
+ components: attr.components || [],
190
+ max: attr.max,
191
+ count: rows.length,
192
+ uids: rows.map(
193
+ (row) => row && typeof row.__component === "string" ? row.__component : ""
194
+ ),
195
+ full: rows.length >= (attr.max ?? Infinity)
196
+ };
181
197
  });
182
198
  }
183
199
  function canInsert(zone, uid, values, components, count = 1) {
184
- return Boolean(zone?.components.includes(uid) && components[uid] && (Array.isArray(values?.[zone.name]) ? values[zone.name].length : 0) + count <= (zone.max ?? Infinity));
200
+ return Boolean(
201
+ zone?.components.includes(uid) && components[uid] && (Array.isArray(values?.[zone.name]) ? values[zone.name].length : 0) + count <= (zone.max ?? Infinity)
202
+ );
185
203
  }
186
204
  function candidatesFor(uid, meta = {}, config = {}) {
187
205
  const version = config.previewVersion ? `?v=${encodeURIComponent(config.previewVersion)}` : "";
188
206
  const base = (config.previewBaseUrl || "/block-previews").replace(/\/$/, "");
189
- return [meta.manualImage, meta.image, `${base}/${encodeURIComponent(uid)}.webp${version}`].filter(Boolean);
207
+ return [
208
+ meta.manualImage,
209
+ meta.image,
210
+ `${base}/${encodeURIComponent(uid)}.webp${version}`
211
+ ].filter(Boolean);
190
212
  }
191
- var SYSTEM_FIELDS = ["id", "documentId", "createdAt", "updatedAt", "publishedAt", "createdBy", "updatedBy", "locale", "localizations"];
213
+ var SYSTEM_FIELDS = [
214
+ "id",
215
+ "documentId",
216
+ "createdAt",
217
+ "updatedAt",
218
+ "publishedAt",
219
+ "createdBy",
220
+ "updatedBy",
221
+ "locale",
222
+ "localizations"
223
+ ];
192
224
  var fieldType = (attr) => attr?.type === "customField" ? String(attr.customField || "").includes("CKEditor") ? "richtext" : "customField" : attr?.type || "unknown";
193
225
  var fieldsOf = (schema) => Object.entries(schema?.attributes || {}).filter(([name]) => !SYSTEM_FIELDS.includes(name)).map(([name, attr]) => ({ name, type: fieldType(attr) }));
194
226
  var categoryOf = (uid, schema, meta = {}) => meta.category || schema?.category || uid.split(".")[0];
195
227
  var byCategory = (a, b) => (a === "admin" ? 1 : 0) - (b === "admin" ? 1 : 0) || a.localeCompare(b);
228
+ var pickable = (zone, config) => {
229
+ const closers = Object.values(config.groups || {});
230
+ return zone.components.filter((uid) => !closers.includes(uid));
231
+ };
196
232
  function entriesFor(zone, components, config, query, category = "all") {
197
233
  const needle = query.trim().toLocaleLowerCase();
198
- return zone.components.flatMap((uid) => {
234
+ return pickable(zone, config).flatMap((uid) => {
199
235
  const schema = components[uid];
200
236
  if (!schema) return [];
201
237
  const meta = config.components?.[uid] || {};
@@ -210,11 +246,13 @@ function entriesFor(zone, components, config, query, category = "all") {
210
246
  };
211
247
  if (category !== "all" && entry.category !== category) return [];
212
248
  return `${entry.label} ${entry.description} ${entry.category} ${uid} ${meta.keywords || ""}`.toLocaleLowerCase().includes(needle) ? [entry] : [];
213
- }).sort((a, b) => byCategory(a.category, b.category) || a.label.localeCompare(b.label));
249
+ }).sort(
250
+ (a, b) => byCategory(a.category, b.category) || a.label.localeCompare(b.label)
251
+ );
214
252
  }
215
253
  function categoriesFor(zone, components, config) {
216
254
  const counts = /* @__PURE__ */ new Map();
217
- for (const uid of zone.components) {
255
+ for (const uid of pickable(zone, config)) {
218
256
  const schema = components[uid];
219
257
  if (!schema) continue;
220
258
  const c = categoryOf(uid, schema, config.components?.[uid] || {});
@@ -224,8 +262,12 @@ function categoriesFor(zone, components, config) {
224
262
  }
225
263
  function groupEntries(entries) {
226
264
  const map = /* @__PURE__ */ new Map();
227
- for (const entry of entries) map.set(entry.category, [...map.get(entry.category) || [], entry]);
228
- return [...map.entries()].map(([category, items]) => ({ category, entries: items }));
265
+ for (const entry of entries)
266
+ map.set(entry.category, [...map.get(entry.category) || [], entry]);
267
+ return [...map.entries()].map(([category, items]) => ({
268
+ category,
269
+ entries: items
270
+ }));
229
271
  }
230
272
  function memoryKey({ base = "", userId, contentType, zone }) {
231
273
  if (!userId || !contentType || !zone) return null;
@@ -241,7 +283,8 @@ function readMemory(storage2, key) {
241
283
  }
242
284
  function writeMemory(storage2, key, value) {
243
285
  try {
244
- if (key && (value === "open" || value === "closed")) storage2?.setItem(key, value);
286
+ if (key && (value === "open" || value === "closed"))
287
+ storage2?.setItem(key, value);
245
288
  } catch {
246
289
  }
247
290
  }
@@ -327,6 +370,10 @@ function Wireframe({ template, palette, className, noPreview }) {
327
370
  );
328
371
  }
329
372
 
373
+ // admin/RowPreviews.tsx
374
+ var React = __toESM(require("react"));
375
+ var import_react_dom = require("react-dom");
376
+
330
377
  // admin/messages.ts
331
378
  var import_react_intl = require("react-intl");
332
379
 
@@ -441,7 +488,8 @@ var en_default = {
441
488
  columns: "Columns",
442
489
  noPreview: "no preview",
443
490
  "templates.none": "No preview",
444
- noChanges: "No unsaved changes"
491
+ noChanges: "No unsaved changes",
492
+ rowPreview: "Open the {label} preview"
445
493
  };
446
494
 
447
495
  // admin/translations/pt-BR.json
@@ -555,7 +603,8 @@ var pt_BR_default = {
555
603
  columns: "Colunas",
556
604
  noPreview: "sem preview",
557
605
  "templates.none": "Sem preview",
558
- noChanges: "Sem altera\xE7\xF5es pendentes"
606
+ noChanges: "Sem altera\xE7\xF5es pendentes",
607
+ rowPreview: "Abrir a pr\xE9via de {label}"
559
608
  };
560
609
 
561
610
  // admin/translations/pt.json
@@ -669,7 +718,8 @@ var pt_default = {
669
718
  columns: "Colunas",
670
719
  noPreview: "sem pr\xE9-visualiza\xE7\xE3o",
671
720
  "templates.none": "Sem pr\xE9-visualiza\xE7\xE3o",
672
- noChanges: "Sem altera\xE7\xF5es pendentes"
721
+ noChanges: "Sem altera\xE7\xF5es pendentes",
722
+ rowPreview: "Abrir a pr\xE9-visualiza\xE7\xE3o de {label}"
673
723
  };
674
724
 
675
725
  // admin/translations/fr.json
@@ -783,7 +833,8 @@ var fr_default = {
783
833
  columns: "Colonnes",
784
834
  noPreview: "pas d\u2019aper\xE7u",
785
835
  "templates.none": "Pas d\u2019aper\xE7u",
786
- noChanges: "Aucune modification en attente"
836
+ noChanges: "Aucune modification en attente",
837
+ rowPreview: "Ouvrir l\u2019aper\xE7u de {label}"
787
838
  };
788
839
 
789
840
  // admin/translations/es.json
@@ -897,7 +948,8 @@ var es_default = {
897
948
  columns: "Columnas",
898
949
  noPreview: "sin vista previa",
899
950
  "templates.none": "Sin vista previa",
900
- noChanges: "Sin cambios pendientes"
951
+ noChanges: "Sin cambios pendientes",
952
+ rowPreview: "Abrir la vista previa de {label}"
901
953
  };
902
954
 
903
955
  // admin/translations/de.json
@@ -1011,7 +1063,8 @@ var de_default = {
1011
1063
  columns: "Spalten",
1012
1064
  noPreview: "keine Vorschau",
1013
1065
  "templates.none": "Keine Vorschau",
1014
- noChanges: "Keine ungespeicherten \xC4nderungen"
1066
+ noChanges: "Keine ungespeicherten \xC4nderungen",
1067
+ rowPreview: "Vorschau von {label} \xF6ffnen"
1015
1068
  };
1016
1069
 
1017
1070
  // admin/translations/it.json
@@ -1125,7 +1178,8 @@ var it_default = {
1125
1178
  columns: "Colonne",
1126
1179
  noPreview: "nessuna anteprima",
1127
1180
  "templates.none": "Nessuna anteprima",
1128
- noChanges: "Nessuna modifica in sospeso"
1181
+ noChanges: "Nessuna modifica in sospeso",
1182
+ rowPreview: "Apri l\u2019anteprima di {label}"
1129
1183
  };
1130
1184
 
1131
1185
  // admin/translations/nl.json
@@ -1239,7 +1293,8 @@ var nl_default = {
1239
1293
  columns: "Kolommen",
1240
1294
  noPreview: "geen voorbeeld",
1241
1295
  "templates.none": "Geen voorbeeld",
1242
- noChanges: "Geen niet-opgeslagen wijzigingen"
1296
+ noChanges: "Geen niet-opgeslagen wijzigingen",
1297
+ rowPreview: "Voorbeeld van {label} openen"
1243
1298
  };
1244
1299
 
1245
1300
  // admin/messages.ts
@@ -1259,26 +1314,224 @@ function useMessages() {
1259
1314
  return out;
1260
1315
  }
1261
1316
 
1262
- // admin/Gallery.tsx
1317
+ // admin/RowPreviews.tsx
1263
1318
  var import_jsx_runtime2 = require("react/jsx-runtime");
1319
+ var ATTR = "data-blockscene-row-thumb";
1320
+ function useAnchors(zones, onOpen) {
1321
+ const [anchors, setAnchors] = React.useState([]);
1322
+ const open = React.useRef(onOpen);
1323
+ open.current = onOpen;
1324
+ const latest = React.useRef(zones);
1325
+ latest.current = zones;
1326
+ const sync = React.useRef(() => {
1327
+ });
1328
+ sync.current = () => {
1329
+ const next = [];
1330
+ for (const zone of latest.current) {
1331
+ const list = zone.uids?.length ? findZoneList(zone.label) : null;
1332
+ if (!list) continue;
1333
+ toggles(list).forEach((button, index) => {
1334
+ const uid = zone.uids[index];
1335
+ if (!uid) return;
1336
+ let el = button.querySelector(
1337
+ `:scope > [${ATTR}]`
1338
+ );
1339
+ if (!el) {
1340
+ el = document.createElement("span");
1341
+ el.setAttribute(ATTR, "");
1342
+ el.style.cssText = "display:inline-flex;align-items:center";
1343
+ const activate = (event) => {
1344
+ if (!event.currentTarget.getAttribute("role"))
1345
+ return;
1346
+ event.preventDefault();
1347
+ event.stopPropagation();
1348
+ open.current(
1349
+ String(event.currentTarget.dataset.uid || "")
1350
+ );
1351
+ };
1352
+ el.addEventListener("click", activate, true);
1353
+ el.addEventListener(
1354
+ "keydown",
1355
+ (event) => {
1356
+ if (event.key === "Enter" || event.key === " ") activate(event);
1357
+ },
1358
+ true
1359
+ );
1360
+ button.insertBefore(el, button.firstChild);
1361
+ }
1362
+ el.dataset.uid = uid;
1363
+ next.push({ el, uid, zone: zone.name, index });
1364
+ });
1365
+ }
1366
+ for (const el of document.querySelectorAll(`[${ATTR}]`))
1367
+ if (!next.some((a) => a.el === el)) el.remove();
1368
+ setAnchors(
1369
+ (prev) => prev.length === next.length && prev.every((a, i) => a.el === next[i].el && a.uid === next[i].uid) ? prev : next
1370
+ );
1371
+ };
1372
+ React.useEffect(() => {
1373
+ sync.current();
1374
+ });
1375
+ React.useEffect(() => {
1376
+ let frame = 0;
1377
+ const observer = new MutationObserver(() => {
1378
+ if (frame) return;
1379
+ frame = requestAnimationFrame(() => {
1380
+ frame = 0;
1381
+ sync.current();
1382
+ });
1383
+ });
1384
+ observer.observe(document.body, { childList: true, subtree: true });
1385
+ return () => {
1386
+ observer.disconnect();
1387
+ cancelAnimationFrame(frame);
1388
+ for (const el of document.querySelectorAll(`[${ATTR}]`)) el.remove();
1389
+ };
1390
+ }, []);
1391
+ return anchors;
1392
+ }
1393
+ function RowPreviews({ zones, components, catalog, Modal: Modal3 }) {
1394
+ const t = useMessages();
1395
+ const [resolved, setResolved] = React.useState({});
1396
+ const [open, setOpen] = React.useState(null);
1397
+ const anchors = useAnchors(zones, (uid) => setOpen(uid));
1398
+ const candidates = (uid) => candidatesFor(uid, catalog?.components?.[uid] || {}, catalog || {});
1399
+ const label = (uid) => catalog?.components?.[uid]?.label || components?.[uid]?.info?.displayName || uid;
1400
+ const srcOf = (uid) => candidates(uid)[resolved[uid] ?? -1] || "";
1401
+ React.useEffect(() => {
1402
+ for (const { el, uid } of anchors) {
1403
+ if (srcOf(uid)) {
1404
+ el.setAttribute("role", "button");
1405
+ el.setAttribute("tabindex", "0");
1406
+ el.setAttribute("aria-label", t.f("rowPreview", { label: label(uid) }));
1407
+ el.style.cursor = "zoom-in";
1408
+ } else
1409
+ for (const name of ["role", "tabindex", "aria-label"])
1410
+ el.removeAttribute(name);
1411
+ }
1412
+ });
1413
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1414
+ anchors.map(
1415
+ (a) => (0, import_react_dom.createPortal)(
1416
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1417
+ "span",
1418
+ {
1419
+ style: {
1420
+ display: "block",
1421
+ width: "6.4rem",
1422
+ marginRight: "8px",
1423
+ flex: "0 0 auto"
1424
+ },
1425
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1426
+ Thumb,
1427
+ {
1428
+ candidates: candidates(a.uid),
1429
+ blank: true,
1430
+ onResolved: (index) => setResolved(
1431
+ (prev) => prev[a.uid] === index ? prev : { ...prev, [a.uid]: index }
1432
+ )
1433
+ }
1434
+ )
1435
+ }
1436
+ ),
1437
+ a.el,
1438
+ `${a.zone}:${a.index}`
1439
+ )
1440
+ ),
1441
+ open && srcOf(open) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1442
+ Modal3,
1443
+ {
1444
+ open: true,
1445
+ onOpenChange: (value) => {
1446
+ if (!value) setOpen(null);
1447
+ },
1448
+ trigger: null,
1449
+ title: label(open),
1450
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1451
+ "img",
1452
+ {
1453
+ src: srcOf(open),
1454
+ alt: "",
1455
+ style: {
1456
+ display: "block",
1457
+ margin: "0 auto",
1458
+ maxWidth: "100%",
1459
+ maxHeight: "75vh",
1460
+ objectFit: "contain"
1461
+ }
1462
+ }
1463
+ )
1464
+ }
1465
+ )
1466
+ ] });
1467
+ }
1468
+
1469
+ // admin/Gallery.tsx
1470
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1264
1471
  var Columns = import_styled_components.default.div`
1265
- column-count: ${({ $columns }) => $columns}; column-gap: 12px;
1266
- > * { break-inside: avoid; -webkit-column-break-inside: avoid; margin-bottom: 12px; }
1472
+ column-count: ${({ $columns }) => $columns};
1473
+ column-gap: 12px;
1474
+ > * {
1475
+ break-inside: avoid;
1476
+ -webkit-column-break-inside: avoid;
1477
+ margin-bottom: 12px;
1478
+ }
1267
1479
  `;
1268
1480
  var Tile = import_styled_components.default.button`
1269
- display: flex; flex-direction: column; gap: 8px; text-align: left; width: 100%;
1270
- padding: 8px; border: 1px solid ${({ theme }) => theme.colors.neutral200};
1271
- border-radius: 4px; background: ${({ theme }) => theme.colors.neutral0}; cursor: pointer;
1272
- &:hover { border-color: ${({ theme }) => theme.colors.primary600}; }
1273
- &:focus-visible { outline: 2px solid ${({ theme }) => theme.colors.primary600}; outline-offset: 2px; }
1481
+ display: flex;
1482
+ flex-direction: column;
1483
+ gap: 8px;
1484
+ text-align: left;
1485
+ width: 100%;
1486
+ padding: 8px;
1487
+ border: 1px solid ${({ theme }) => theme.colors.neutral200};
1488
+ border-radius: 4px;
1489
+ background: ${({ theme }) => theme.colors.neutral0};
1490
+ cursor: pointer;
1491
+ &:hover {
1492
+ border-color: ${({ theme }) => theme.colors.primary600};
1493
+ }
1494
+ &:focus-visible {
1495
+ outline: 2px solid ${({ theme }) => theme.colors.primary600};
1496
+ outline-offset: 2px;
1497
+ }
1498
+ `;
1499
+ var Clamp = (0, import_styled_components.default)(import_design_system.Typography)`
1500
+ display: -webkit-box;
1501
+ -webkit-line-clamp: 2;
1502
+ -webkit-box-orient: vertical;
1503
+ overflow: hidden;
1274
1504
  `;
1275
- var Clamp = (0, import_styled_components.default)(import_design_system.Typography)` display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; `;
1276
1505
  var Slider = import_styled_components.default.input`
1277
- appearance: none; -webkit-appearance: none; width: 8rem; height: 0.4rem; border-radius: 0.4rem; cursor: pointer;
1506
+ appearance: none;
1507
+ -webkit-appearance: none;
1508
+ width: 8rem;
1509
+ height: 0.4rem;
1510
+ border-radius: 0.4rem;
1511
+ cursor: pointer;
1278
1512
  background: ${({ theme, $percent }) => `linear-gradient(to right, ${theme.colors.primary600} ${$percent}%, ${theme.colors.neutral200} ${$percent}%)`};
1279
- &::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: 1.6rem; height: 1.6rem; border-radius: 50%; background: ${({ theme }) => theme.colors.neutral0}; border: 0.2rem solid ${({ theme }) => theme.colors.primary600}; cursor: pointer; }
1280
- &::-moz-range-thumb { width: 1.6rem; height: 1.6rem; border-radius: 50%; background: ${({ theme }) => theme.colors.neutral0}; border: 0.2rem solid ${({ theme }) => theme.colors.primary600}; cursor: pointer; }
1281
- &:focus-visible { outline: 0.2rem solid ${({ theme }) => theme.colors.primary600}; outline-offset: 0.2rem; }
1513
+ &::-webkit-slider-thumb {
1514
+ appearance: none;
1515
+ -webkit-appearance: none;
1516
+ width: 1.6rem;
1517
+ height: 1.6rem;
1518
+ border-radius: 50%;
1519
+ background: ${({ theme }) => theme.colors.neutral0};
1520
+ border: 0.2rem solid ${({ theme }) => theme.colors.primary600};
1521
+ cursor: pointer;
1522
+ }
1523
+ &::-moz-range-thumb {
1524
+ width: 1.6rem;
1525
+ height: 1.6rem;
1526
+ border-radius: 50%;
1527
+ background: ${({ theme }) => theme.colors.neutral0};
1528
+ border: 0.2rem solid ${({ theme }) => theme.colors.primary600};
1529
+ cursor: pointer;
1530
+ }
1531
+ &:focus-visible {
1532
+ outline: 0.2rem solid ${({ theme }) => theme.colors.primary600};
1533
+ outline-offset: 0.2rem;
1534
+ }
1282
1535
  `;
1283
1536
  var COLUMNS = { key: "blockscene:columns", min: 1, max: 5, initial: 3 };
1284
1537
  var SHOW_FIELDS_KEY = "blockscene:show-fields";
@@ -1304,16 +1557,31 @@ var remember = (key, value) => {
1304
1557
  }
1305
1558
  };
1306
1559
  var Frame = import_styled_components.default.div`
1307
- width: 100%; overflow: hidden; border-radius: 4px; line-height: 0;
1560
+ width: 100%;
1561
+ overflow: hidden;
1562
+ border-radius: 4px;
1563
+ line-height: 0;
1308
1564
  aspect-ratio: ${({ $fixed }) => $fixed ? "16 / 9" : "auto"};
1309
1565
  background: ${({ theme }) => theme.colors.neutral100};
1310
- img { width: 100%; height: auto; display: block; }
1566
+ img {
1567
+ width: 100%;
1568
+ height: auto;
1569
+ display: block;
1570
+ }
1311
1571
  `;
1312
- function Thumb({ candidates, template, palette, onResolved, noPreview, eager }) {
1572
+ function Thumb({
1573
+ candidates,
1574
+ template,
1575
+ palette,
1576
+ onResolved,
1577
+ noPreview,
1578
+ eager,
1579
+ blank
1580
+ }) {
1313
1581
  const key = candidates.join("|");
1314
- const [state, setState] = React.useState({ key, index: 0 });
1582
+ const [state, setState] = React2.useState({ key, index: 0 });
1315
1583
  const index = state.key === key ? state.index : 0;
1316
- const resolved = React.useRef("");
1584
+ const resolved = React2.useRef("");
1317
1585
  const report = (value) => {
1318
1586
  const tag = `${key}:${value}`;
1319
1587
  if (resolved.current !== tag) {
@@ -1321,11 +1589,19 @@ function Thumb({ candidates, template, palette, onResolved, noPreview, eager })
1321
1589
  onResolved?.(value);
1322
1590
  }
1323
1591
  };
1324
- React.useEffect(() => {
1592
+ React2.useEffect(() => {
1325
1593
  if (index >= candidates.length) report(-1);
1326
1594
  });
1327
- if (index >= candidates.length) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Frame, { $fixed: true, "data-thumb": "wireframe", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Wireframe, { template, palette, noPreview }) });
1328
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Frame, { "data-thumb": String(index), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1595
+ if (index >= candidates.length)
1596
+ return blank ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Frame, { $fixed: true, "data-thumb": "wireframe", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1597
+ Wireframe,
1598
+ {
1599
+ template,
1600
+ palette,
1601
+ noPreview
1602
+ }
1603
+ ) });
1604
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Frame, { "data-thumb": String(index), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1329
1605
  "img",
1330
1606
  {
1331
1607
  src: candidates[index],
@@ -1339,28 +1615,90 @@ function Thumb({ candidates, template, palette, onResolved, noPreview, eager })
1339
1615
  }
1340
1616
  function Card({ entry, palette, showFields, onSelect }) {
1341
1617
  const t = useMessages();
1342
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Tile, { type: "button", onClick: onSelect, title: entry.uid, "data-testid": `blockscene-${entry.uid}`, children: [
1343
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Thumb, { candidates: entry.candidates, template: entry.template, palette, noPreview: t.noPreview }),
1344
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", ellipsis: true, children: entry.label }),
1345
- entry.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Clamp, { variant: "pi", textColor: "neutral600", children: entry.description }),
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(", ") })
1347
- ] });
1618
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1619
+ Tile,
1620
+ {
1621
+ type: "button",
1622
+ onClick: onSelect,
1623
+ title: entry.uid,
1624
+ "data-testid": `blockscene-${entry.uid}`,
1625
+ children: [
1626
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1627
+ Thumb,
1628
+ {
1629
+ candidates: entry.candidates,
1630
+ template: entry.template,
1631
+ palette,
1632
+ noPreview: t.noPreview
1633
+ }
1634
+ ),
1635
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1636
+ import_design_system.Typography,
1637
+ {
1638
+ variant: "pi",
1639
+ fontWeight: "bold",
1640
+ textColor: "neutral800",
1641
+ ellipsis: true,
1642
+ children: entry.label
1643
+ }
1644
+ ),
1645
+ entry.description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Clamp, { variant: "pi", textColor: "neutral600", children: entry.description }),
1646
+ showFields && entry.fields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1647
+ import_design_system.Typography,
1648
+ {
1649
+ variant: "pi",
1650
+ textColor: "neutral500",
1651
+ style: { fontStyle: "italic" },
1652
+ "data-testid": "block-fields",
1653
+ children: entry.fields.map((f) => `${f.name} (${f.type})`).join(", ")
1654
+ }
1655
+ )
1656
+ ]
1657
+ }
1658
+ );
1348
1659
  }
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 } });
1660
+ function PickerModal({
1661
+ zone,
1662
+ components,
1663
+ open,
1664
+ onOpenChange,
1665
+ onSelect,
1666
+ Modal: Modal3,
1667
+ Toggle,
1668
+ get
1669
+ }) {
1670
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1671
+ ZoneGallery,
1672
+ {
1673
+ zone,
1674
+ components,
1675
+ Modal: Modal3,
1676
+ Toggle,
1677
+ get,
1678
+ controlled: { open, onOpenChange, onSelect }
1679
+ }
1680
+ );
1351
1681
  }
1352
- function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, controlled }) {
1682
+ function ZoneGallery({
1683
+ zone,
1684
+ components,
1685
+ add,
1686
+ Modal: Modal3,
1687
+ Toggle,
1688
+ get,
1689
+ controlled
1690
+ }) {
1353
1691
  const t = useMessages();
1354
- const [ownOpen, setOwnOpen] = React.useState(false);
1692
+ const [ownOpen, setOwnOpen] = React2.useState(false);
1355
1693
  const open = controlled ? controlled.open : ownOpen;
1356
1694
  const setOpen = controlled ? controlled.onOpenChange : setOwnOpen;
1357
- const [query, setQuery] = React.useState("");
1358
- const [category, setCategory] = React.useState("all");
1359
- const [showFields, setShowFields] = React.useState(readShowFields);
1360
- const [columns, setColumns] = React.useState(readColumns);
1361
- const [config, setConfig] = React.useState(null);
1362
- const [error, setError] = React.useState("");
1363
- React.useEffect(() => {
1695
+ const [query, setQuery] = React2.useState("");
1696
+ const [category, setCategory] = React2.useState("all");
1697
+ const [showFields, setShowFields] = React2.useState(readShowFields);
1698
+ const [columns, setColumns] = React2.useState(readColumns);
1699
+ const [config, setConfig] = React2.useState(null);
1700
+ const [error, setError] = React2.useState("");
1701
+ React2.useEffect(() => {
1364
1702
  if (controlled) return;
1365
1703
  const onClick = (event) => {
1366
1704
  const button = event.target?.closest?.("button");
@@ -1372,7 +1710,7 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
1372
1710
  document.addEventListener("click", onClick, true);
1373
1711
  return () => document.removeEventListener("click", onClick, true);
1374
1712
  }, [controlled, zone.name, zone.label]);
1375
- React.useEffect(() => {
1713
+ React2.useEffect(() => {
1376
1714
  if (!open) return;
1377
1715
  let active = true;
1378
1716
  setError("");
@@ -1388,7 +1726,10 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
1388
1726
  }, [open, get, t.failed]);
1389
1727
  const entries = config ? entriesFor(zone, components, config, query, category) : [];
1390
1728
  const categories = config ? categoriesFor(zone, components, config) : [];
1391
- const total = categories.reduce((sum, [, count]) => sum + count, 0);
1729
+ const total = categories.reduce(
1730
+ (sum, [, count]) => sum + count,
1731
+ 0
1732
+ );
1392
1733
  const filtering = query.trim() !== "" || category !== "all";
1393
1734
  const reset = () => {
1394
1735
  setQuery("");
@@ -1412,21 +1753,41 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
1412
1753
  setShowFields(value);
1413
1754
  remember(SHOW_FIELDS_KEY, String(value));
1414
1755
  };
1415
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1756
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1416
1757
  Modal3,
1417
1758
  {
1418
1759
  open,
1419
1760
  onOpenChange: setOpen,
1420
1761
  title: t.gallery,
1421
- trigger: controlled ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system.Button, { variant: "secondary", fullWidth: true, onClick: () => setOpen(true), "data-testid": `open-gallery-${zone.name}`, children: [
1422
- t.add,
1423
- ": ",
1424
- zone.name
1425
- ] }),
1426
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system.Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
1427
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system.Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
1428
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { variant: "omega", fontWeight: "bold", textColor: "neutral800", style: { whiteSpace: "nowrap" }, "data-testid": `block-count-${zone.name}`, "aria-live": "polite", children: filtering ? t.f("countFiltered", { shown: entries.length, total }) : t.f("countAll", { count: total }) }),
1429
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Box, { style: { flex: 1, minWidth: "12rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1762
+ trigger: controlled ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1763
+ import_design_system.Button,
1764
+ {
1765
+ variant: "secondary",
1766
+ fullWidth: true,
1767
+ onClick: () => setOpen(true),
1768
+ "data-testid": `open-gallery-${zone.name}`,
1769
+ children: [
1770
+ t.add,
1771
+ ": ",
1772
+ zone.name
1773
+ ]
1774
+ }
1775
+ ),
1776
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system.Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
1777
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system.Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
1778
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1779
+ import_design_system.Typography,
1780
+ {
1781
+ variant: "omega",
1782
+ fontWeight: "bold",
1783
+ textColor: "neutral800",
1784
+ style: { whiteSpace: "nowrap" },
1785
+ "data-testid": `block-count-${zone.name}`,
1786
+ "aria-live": "polite",
1787
+ children: filtering ? t.f("countFiltered", { shown: entries.length, total }) : t.f("countAll", { count: total })
1788
+ }
1789
+ ),
1790
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system.Box, { style: { flex: 1, minWidth: "12rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1430
1791
  import_design_system.Searchbar,
1431
1792
  {
1432
1793
  name: `block-search-${zone.name}`,
@@ -1438,14 +1799,54 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
1438
1799
  children: t.search
1439
1800
  }
1440
1801
  ) }),
1441
- categories.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Box, { style: { width: "14rem" }, "data-testid": `block-category-${zone.name}`, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system.SingleSelect, { "aria-label": t.filterCategory, size: "S", value: category, onChange: (value) => setCategory(String(value)), children: [
1442
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.SingleSelectOption, { value: "all", children: t.allCategories }),
1443
- categories.map(([name, count]) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.SingleSelectOption, { value: name, children: `${name} (${count})` }, name))
1444
- ] }) }),
1445
- Toggle && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Toggle, { name: `block-fields-${zone.name}`, label: t.showFields, hint: t.showFieldsHint, value: showFields, onChange: changeShowFields }),
1446
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system.Flex, { gap: 2, alignItems: "center", children: [
1447
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { variant: "pi", textColor: "neutral600", id: `block-columns-${zone.name}`, children: t.columns }),
1448
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1802
+ categories.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1803
+ import_design_system.Box,
1804
+ {
1805
+ style: { width: "14rem" },
1806
+ "data-testid": `block-category-${zone.name}`,
1807
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1808
+ import_design_system.SingleSelect,
1809
+ {
1810
+ "aria-label": t.filterCategory,
1811
+ size: "S",
1812
+ value: category,
1813
+ onChange: (value) => setCategory(String(value)),
1814
+ children: [
1815
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system.SingleSelectOption, { value: "all", children: t.allCategories }),
1816
+ categories.map(([name, count]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1817
+ import_design_system.SingleSelectOption,
1818
+ {
1819
+ value: name,
1820
+ children: `${name} (${count})`
1821
+ },
1822
+ name
1823
+ ))
1824
+ ]
1825
+ }
1826
+ )
1827
+ }
1828
+ ),
1829
+ Toggle && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1830
+ Toggle,
1831
+ {
1832
+ name: `block-fields-${zone.name}`,
1833
+ label: t.showFields,
1834
+ hint: t.showFieldsHint,
1835
+ value: showFields,
1836
+ onChange: changeShowFields
1837
+ }
1838
+ ),
1839
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system.Flex, { gap: 2, alignItems: "center", children: [
1840
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1841
+ import_design_system.Typography,
1842
+ {
1843
+ variant: "pi",
1844
+ textColor: "neutral600",
1845
+ id: `block-columns-${zone.name}`,
1846
+ children: t.columns
1847
+ }
1848
+ ),
1849
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1449
1850
  Slider,
1450
1851
  {
1451
1852
  type: "range",
@@ -1458,16 +1859,52 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
1458
1859
  onChange: (e) => changeColumns(Number(e.target.value))
1459
1860
  }
1460
1861
  ),
1461
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { variant: "pi", fontWeight: "bold", children: columns })
1862
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system.Typography, { variant: "pi", fontWeight: "bold", children: columns })
1462
1863
  ] })
1463
1864
  ] }),
1464
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { variant: "pi", textColor: "neutral600", children: t.example }),
1465
- error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { role: "alert", textColor: "danger600", children: error }) : !config ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { children: t.loading }) : entries.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Flex, { direction: "column", alignItems: "stretch", gap: 4, style: { overflowY: "auto", maxHeight: "60vh", padding: "4px" }, children: groupEntries(entries).map(({ category: name, entries: items }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
1466
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { variant: "sigma", textColor: "neutral600", "data-testid": `block-group-${name}`, children: `${name} (${items.length})` }),
1467
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Columns, { $columns: columns, children: items.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Card, { entry, palette: config.palette, showFields, onSelect: () => select(entry.uid) }) }, entry.uid)) })
1468
- ] }, name)) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system.Flex, { gap: 3, alignItems: "center", children: [
1469
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Typography, { children: t.empty }),
1470
- filtering && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Button, { variant: "tertiary", size: "S", onClick: reset, children: t.clear })
1865
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system.Typography, { variant: "pi", textColor: "neutral600", children: t.example }),
1866
+ error ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system.Typography, { role: "alert", textColor: "danger600", children: error }) : !config ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system.Typography, { children: t.loading }) : entries.length ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1867
+ import_design_system.Flex,
1868
+ {
1869
+ direction: "column",
1870
+ alignItems: "stretch",
1871
+ gap: 4,
1872
+ style: { overflowY: "auto", maxHeight: "60vh", padding: "4px" },
1873
+ children: groupEntries(entries).map(
1874
+ ({ category: name, entries: items }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1875
+ import_design_system.Flex,
1876
+ {
1877
+ direction: "column",
1878
+ alignItems: "stretch",
1879
+ gap: 2,
1880
+ children: [
1881
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1882
+ import_design_system.Typography,
1883
+ {
1884
+ variant: "sigma",
1885
+ textColor: "neutral600",
1886
+ "data-testid": `block-group-${name}`,
1887
+ children: `${name} (${items.length})`
1888
+ }
1889
+ ),
1890
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Columns, { $columns: columns, children: items.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1891
+ Card,
1892
+ {
1893
+ entry,
1894
+ palette: config.palette,
1895
+ showFields,
1896
+ onSelect: () => select(entry.uid)
1897
+ }
1898
+ ) }, entry.uid)) })
1899
+ ]
1900
+ },
1901
+ name
1902
+ )
1903
+ )
1904
+ }
1905
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system.Flex, { gap: 3, alignItems: "center", children: [
1906
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system.Typography, { children: t.empty }),
1907
+ filtering && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system.Button, { variant: "tertiary", size: "S", onClick: reset, children: t.clear })
1471
1908
  ] })
1472
1909
  ] })
1473
1910
  }
@@ -1481,13 +1918,19 @@ var storage = () => {
1481
1918
  }
1482
1919
  };
1483
1920
  var memoryBase = () => `${window.location.origin}${window.location.pathname.split("/content-manager")[0]}`;
1484
- function useInitialAccordions({ zones, editor, docKey, contentType, userId }) {
1485
- const applied = React.useRef("");
1486
- const user = React.useRef(userId);
1921
+ function useInitialAccordions({
1922
+ zones,
1923
+ editor,
1924
+ docKey,
1925
+ contentType,
1926
+ userId
1927
+ }) {
1928
+ const applied = React2.useRef("");
1929
+ const user = React2.useRef(userId);
1487
1930
  user.current = userId;
1488
- const latest = React.useRef(zones);
1931
+ const latest = React2.useRef(zones);
1489
1932
  latest.current = zones;
1490
- React.useEffect(() => {
1933
+ React2.useEffect(() => {
1491
1934
  if (!editor?.enabled || !docKey || applied.current === docKey) return;
1492
1935
  if (applied.current.startsWith(`${contentType}:new`) && docKey.startsWith(`${contentType}:`)) {
1493
1936
  applied.current = docKey;
@@ -1496,7 +1939,10 @@ function useInitialAccordions({ zones, editor, docKey, contentType, userId }) {
1496
1939
  applied.current = docKey;
1497
1940
  let tries = 0;
1498
1941
  const cancel = (event) => {
1499
- if (event.target?.closest?.('button[aria-expanded], [data-testid^="block-accordion-controls-"]')) stop();
1942
+ if (event.target?.closest?.(
1943
+ 'button[aria-expanded], [data-testid^="block-accordion-controls-"]'
1944
+ ))
1945
+ stop();
1500
1946
  };
1501
1947
  const stop = () => {
1502
1948
  clearInterval(timer);
@@ -1514,8 +1960,17 @@ function useInitialAccordions({ zones, editor, docKey, contentType, userId }) {
1514
1960
  for (const zone of pending) {
1515
1961
  const list = findZoneList(zone.label);
1516
1962
  if (!list) continue;
1517
- const key = memoryKey({ base: memoryBase(), userId: user.current, contentType, zone: zone.name });
1518
- setAll(list, initialState(editor, readMemory(storage(), key)) === "open", import_react_dom.unstable_batchedUpdates);
1963
+ const key = memoryKey({
1964
+ base: memoryBase(),
1965
+ userId: user.current,
1966
+ contentType,
1967
+ zone: zone.name
1968
+ });
1969
+ setAll(
1970
+ list,
1971
+ initialState(editor, readMemory(storage(), key)) === "open",
1972
+ import_react_dom2.unstable_batchedUpdates
1973
+ );
1519
1974
  }
1520
1975
  }, 200);
1521
1976
  return stop;
@@ -1526,51 +1981,107 @@ function ZoneControls({ zone, editor, contentType, userId }) {
1526
1981
  if (!zone.count || !(editor.showOpenAll || editor.showCloseAll)) return null;
1527
1982
  const apply = (open) => {
1528
1983
  const list = findZoneList(zone.label);
1529
- if (list) setAll(list, open, import_react_dom.unstable_batchedUpdates);
1530
- writeMemory(storage(), memoryKey({ base: memoryBase(), userId, contentType, zone: zone.name }), open ? "open" : "closed");
1984
+ if (list) setAll(list, open, import_react_dom2.unstable_batchedUpdates);
1985
+ writeMemory(
1986
+ storage(),
1987
+ memoryKey({ base: memoryBase(), userId, contentType, zone: zone.name }),
1988
+ open ? "open" : "closed"
1989
+ );
1531
1990
  };
1532
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system.Flex, { gap: 2, wrap: "wrap", "data-testid": `block-accordion-controls-${zone.name}`, children: [
1533
- editor.showOpenAll && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Button, { type: "button", variant: "tertiary", size: "S", onClick: () => apply(true), children: t.openAll }),
1534
- editor.showCloseAll && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Button, { type: "button", variant: "tertiary", size: "S", onClick: () => apply(false), children: t.closeAll })
1535
- ] });
1991
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1992
+ import_design_system.Flex,
1993
+ {
1994
+ gap: 2,
1995
+ wrap: "wrap",
1996
+ "data-testid": `block-accordion-controls-${zone.name}`,
1997
+ children: [
1998
+ editor.showOpenAll && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1999
+ import_design_system.Button,
2000
+ {
2001
+ type: "button",
2002
+ variant: "tertiary",
2003
+ size: "S",
2004
+ onClick: () => apply(true),
2005
+ children: t.openAll
2006
+ }
2007
+ ),
2008
+ editor.showCloseAll && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2009
+ import_design_system.Button,
2010
+ {
2011
+ type: "button",
2012
+ variant: "tertiary",
2013
+ size: "S",
2014
+ onClick: () => apply(false),
2015
+ children: t.closeAll
2016
+ }
2017
+ )
2018
+ ]
2019
+ }
2020
+ );
1536
2021
  }
1537
- function Gallery({ zones, editor, docKey, contentType, userId, ...props }) {
2022
+ function Gallery({
2023
+ zones,
2024
+ editor,
2025
+ docKey,
2026
+ contentType,
2027
+ userId,
2028
+ catalog,
2029
+ ...props
2030
+ }) {
1538
2031
  useInitialAccordions({ zones, editor, docKey, contentType, userId });
1539
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_design_system.Flex, { direction: "column", alignItems: "stretch", gap: 3, children: zones.map((zone) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_design_system.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
1540
- !zone.full && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ZoneGallery, { zone, ...props }),
1541
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ZoneControls, { zone, editor, contentType, userId })
1542
- ] }, zone.name)) });
2032
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system.Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
2033
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2034
+ RowPreviews,
2035
+ {
2036
+ zones,
2037
+ components: props.components,
2038
+ catalog,
2039
+ Modal: props.Modal
2040
+ }
2041
+ ),
2042
+ zones.map((zone) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_design_system.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
2043
+ !zone.full && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ZoneGallery, { zone, ...props }),
2044
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2045
+ ZoneControls,
2046
+ {
2047
+ zone,
2048
+ editor,
2049
+ contentType,
2050
+ userId
2051
+ }
2052
+ )
2053
+ ] }, zone.name))
2054
+ ] });
1543
2055
  }
1544
2056
 
1545
2057
  // admin/PagePreview.tsx
1546
- var React3 = __toESM(require("react"));
1547
- var import_react_dom2 = require("react-dom");
2058
+ var React4 = __toESM(require("react"));
2059
+ var import_react_dom3 = require("react-dom");
1548
2060
  var import_styled_components2 = __toESM(require("styled-components"));
1549
2061
  var import_design_system3 = require("@strapi/design-system");
1550
2062
  var import_admin2 = require("@strapi/strapi/admin");
1551
- var import_design_system4 = require("@strapi/design-system");
1552
2063
  var import_strapi_admin = require("@strapi/content-manager/strapi-admin");
1553
2064
 
1554
2065
  // admin/FieldEditorModal.tsx
1555
- var React2 = __toESM(require("react"));
2066
+ var React3 = __toESM(require("react"));
1556
2067
  var import_admin = require("@strapi/strapi/admin");
1557
2068
  var import_design_system2 = require("@strapi/design-system");
1558
- var import_jsx_runtime3 = require("react/jsx-runtime");
2069
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1559
2070
  var Actions = ({ onApply, onCancel }) => {
1560
2071
  const t = useMessages();
1561
2072
  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 })
2073
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system2.Flex, { gap: 2, justifyContent: "flex-end", children: [
2074
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Button, { variant: "tertiary", onClick: onCancel, children: t.cancel }),
2075
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Button, { onClick: () => onApply(value ?? null), "data-testid": "field-editor-apply", children: t.apply })
1565
2076
  ] });
1566
2077
  };
1567
2078
  function FieldEditorModal({ label, attribute, value, onApply, onCancel }) {
1568
2079
  const t = useMessages();
1569
2080
  const customFields = (0, import_admin.useStrapiApp)("BlocksceneFieldEditor", (state) => state.customFields);
1570
- const [Input, setInput] = React2.useState(void 0);
2081
+ const [Input, setInput] = React3.useState(void 0);
1571
2082
  const isCustom = Boolean(attribute?.customField);
1572
2083
  const isText = attribute?.type === "string" || attribute?.type === "text";
1573
- React2.useEffect(() => {
2084
+ React3.useEffect(() => {
1574
2085
  let active = true;
1575
2086
  if (!isCustom) {
1576
2087
  setInput(null);
@@ -1591,24 +2102,24 @@ function FieldEditorModal({ label, attribute, value, onApply, onCancel }) {
1591
2102
  };
1592
2103
  }, [attribute, customFields, isCustom]);
1593
2104
  const supported = isText || isCustom && Input;
1594
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_design_system2.Modal.Root, { open: true, onOpenChange: (open) => {
2105
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Modal.Root, { open: true, onOpenChange: (open) => {
1595
2106
  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: [
2107
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system2.Modal.Content, { "aria-label": `${t.editText} ${label}`, children: [
2108
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Modal.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system2.Modal.Title, { children: [
1598
2109
  t.editText,
1599
2110
  " \xB7 ",
1600
2111
  label
1601
2112
  ] }) }),
1602
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_admin.Form, { initialValues: { value: value ?? (isText ? "" : null) }, method: "PUT", onSubmit: () => {
2113
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_admin.Form, { initialValues: { value: value ?? (isText ? "" : null) }, method: "PUT", onSubmit: () => {
1603
2114
  }, 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 })
2115
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Modal.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system2.Flex, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "field-editor-modal", children: [
2116
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Typography, { variant: "pi", textColor: "neutral600", children: t.editHelp }),
2117
+ isCustom && Input === void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Typography, { children: t.loading }),
2118
+ isCustom && Input && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Input, { name: "value", attribute, label, type: attribute.type }),
2119
+ isText && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_admin.InputRenderer, { type: attribute.type === "text" ? "text" : "string", name: "value", label }),
2120
+ (isCustom && Input === null || !isCustom && !isText) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Typography, { role: "alert", textColor: "danger600", children: t.editUnsupported })
1610
2121
  ] }) }),
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 }) })
2122
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Modal.Footer, { children: supported ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Actions, { onApply, onCancel }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system2.Button, { variant: "tertiary", onClick: onCancel, children: t.close }) })
1612
2123
  ] })
1613
2124
  ] }) });
1614
2125
  }
@@ -1719,6 +2230,7 @@ var mediaAttribute = (uid, field, components) => {
1719
2230
  const attr = resolveField(uid, field, components);
1720
2231
  return attr?.type === "media" ? attr : null;
1721
2232
  };
2233
+ var getIn = (row, path) => String(path).split(".").reduce((value, key) => value == null ? void 0 : value[key], row);
1722
2234
  function isPreviewMessage(event, origin, source, channel, type) {
1723
2235
  return event.origin === origin && event.source === source && event.data?.protocol === PROTOCOL && event.data?.channel === channel && event.data?.type === type;
1724
2236
  }
@@ -1729,7 +2241,7 @@ function insertIndex(rows, after) {
1729
2241
  }
1730
2242
 
1731
2243
  // admin/PagePreview.tsx
1732
- var import_jsx_runtime4 = require("react/jsx-runtime");
2244
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1733
2245
  var MODE_KEY = "blockscene:page-mode";
1734
2246
  var RATIO_KEY = "blockscene:page-split-ratio";
1735
2247
  var MIN_PANE = 360;
@@ -1750,20 +2262,32 @@ var write = (key, value) => {
1750
2262
  } catch {
1751
2263
  }
1752
2264
  };
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);
2265
+ var clampWidth = (width, vw) => Math.round(
2266
+ Math.min(Math.max(width, MIN_PANE), Math.max(MIN_PANE, vw - MIN_FORM))
2267
+ );
1755
2268
  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};
2269
+ position: fixed;
2270
+ top: 0;
2271
+ bottom: 0;
2272
+ z-index: 2;
2273
+ display: flex;
2274
+ flex-direction: column;
2275
+ background: ${({ theme }) => theme.colors.neutral0};
2276
+ border-left: 1px solid ${({ theme }) => theme.colors.neutral200};
1758
2277
  box-shadow: ${({ theme }) => theme.shadows.popupShadow};
1759
2278
  `;
1760
2279
  function useMainRect() {
1761
- const [rect, setRect] = React3.useState(() => ({ left: 0, width: window.innerWidth }));
1762
- React3.useEffect(() => {
2280
+ const [rect, setRect] = React4.useState(() => ({
2281
+ left: 0,
2282
+ width: window.innerWidth
2283
+ }));
2284
+ React4.useEffect(() => {
1763
2285
  const main = document.getElementById("main-content");
1764
2286
  const measure = () => {
1765
2287
  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 });
2288
+ setRect(
2289
+ r && r.width > 0 ? { left: Math.round(r.left), width: Math.round(r.width) } : { left: 0, width: window.innerWidth }
2290
+ );
1767
2291
  };
1768
2292
  measure();
1769
2293
  const observer = main && "ResizeObserver" in window ? new ResizeObserver(measure) : null;
@@ -1777,12 +2301,37 @@ function useMainRect() {
1777
2301
  return rect;
1778
2302
  }
1779
2303
  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; }
2304
+ position: absolute;
2305
+ top: 0;
2306
+ bottom: 0;
2307
+ left: -5px;
2308
+ width: 10px;
2309
+ cursor: col-resize;
2310
+ z-index: 3;
2311
+ touch-action: none;
2312
+ &::after {
2313
+ content: "";
2314
+ position: absolute;
2315
+ top: 0;
2316
+ bottom: 0;
2317
+ left: 4px;
2318
+ width: 2px;
2319
+ }
2320
+ &:hover::after,
2321
+ &[data-dragging="true"]::after,
2322
+ &:focus-visible::after {
2323
+ background: ${({ theme }) => theme.colors.primary600};
2324
+ }
2325
+ &:focus-visible {
2326
+ outline: none;
2327
+ }
2328
+ `;
2329
+ var Frame2 = import_styled_components2.default.iframe`
2330
+ flex: 1;
2331
+ width: 100%;
2332
+ border: 0;
2333
+ background: white;
1784
2334
  `;
1785
- var Frame2 = import_styled_components2.default.iframe` flex: 1; width: 100%; border: 0; background: white; `;
1786
2335
  var SPLIT_STYLE = `
1787
2336
  body.bp-split #main-content { padding-right: calc(var(--bp-pane, 50vw) + 1.6rem) !important; }
1788
2337
  body.bp-split [data-bp-grid] { display: flex !important; flex-direction: column-reverse; gap: 1.6rem; }
@@ -1791,20 +2340,26 @@ body.bp-split [data-bp-panels] > div { flex-direction: row; flex-wrap: wrap; ali
1791
2340
  body.bp-split [data-bp-panels] > div > * { flex: 1 1 24rem; }`;
1792
2341
  var markLayout = (anchor) => {
1793
2342
  let item = anchor;
1794
- while (item?.parentElement && getComputedStyle(item.parentElement).display !== "grid") item = item.parentElement;
2343
+ while (item?.parentElement && getComputedStyle(item.parentElement).display !== "grid")
2344
+ item = item.parentElement;
1795
2345
  if (!item?.parentElement) return;
1796
2346
  item.dataset.bpPanels = "";
1797
2347
  item.parentElement.dataset.bpGrid = "";
1798
2348
  };
1799
2349
  function usePreviewBase(override, model, documentId, locale) {
1800
2350
  const { get } = (0, import_admin2.useFetchClient)();
1801
- const [native, setNative] = React3.useState(null);
1802
- React3.useEffect(() => {
2351
+ const [native, setNative] = React4.useState(null);
2352
+ React4.useEffect(() => {
1803
2353
  if (override || !model) return;
1804
2354
  let active = true;
1805
- const query = new URLSearchParams({ status: "draft", ...documentId ? { documentId } : {}, ...locale ? { locale } : {} });
2355
+ const query = new URLSearchParams({
2356
+ status: "draft",
2357
+ ...documentId ? { documentId } : {},
2358
+ ...locale ? { locale } : {}
2359
+ });
1806
2360
  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`);
2361
+ if (active && typeof data?.data?.url === "string")
2362
+ setNative(`${new URL(data.data.url).origin}/block-preview/page`);
1808
2363
  }).catch(() => {
1809
2364
  if (active) setNative(null);
1810
2365
  });
@@ -1814,56 +2369,109 @@ function usePreviewBase(override, model, documentId, locale) {
1814
2369
  }, [get, model, documentId, locale, override]);
1815
2370
  return override ? { base: override, source: "custom" } : native ? { base: native, source: "native" } : { base: null, source: "none" };
1816
2371
  }
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
2372
  var ACTION_TYPES = ["update", "publish"];
1827
- var nativeButtons = () => document.querySelectorAll('#main-content button:not([data-testid="page-preview-pane"] button)');
2373
+ var nativeButtons = () => document.querySelectorAll(
2374
+ '#main-content button:not([data-testid="page-preview-pane"] button)'
2375
+ );
1828
2376
  function ToolbarActions({ model, collectionType, documentId, locale }) {
1829
- const plugins = (0, import_admin2.useStrapiApp)("BlocksceneToolbar", (state) => state.plugins);
2377
+ const plugins = (0, import_admin2.useStrapiApp)(
2378
+ "BlocksceneToolbar",
2379
+ (state) => state.plugins
2380
+ );
1830
2381
  const [{ query }] = (0, import_admin2.useQueryParams)();
1831
- const { document: doc, meta } = (0, import_strapi_admin.unstable_useDocument)({ model, collectionType, documentId, params: { locale } }, { skip: !documentId });
2382
+ const { document: doc, meta } = (0, import_strapi_admin.unstable_useDocument)(
2383
+ { model, collectionType, documentId, params: { locale } },
2384
+ { skip: !documentId }
2385
+ );
1832
2386
  const { toggleNotification } = (0, import_admin2.useNotification)();
1833
2387
  const t = useMessages();
1834
2388
  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 };
2389
+ const props = {
2390
+ activeTab: query.status || "draft",
2391
+ model,
2392
+ documentId,
2393
+ document: doc,
2394
+ meta,
2395
+ collectionType
2396
+ };
1836
2397
  const run = async (action, event) => {
1837
- const native = [...nativeButtons()].find((b) => b.textContent?.trim() === action.label);
2398
+ const native = [...nativeButtons()].find(
2399
+ (b) => b.textContent?.trim() === action.label
2400
+ );
1838
2401
  if (native) {
1839
2402
  native.click();
1840
2403
  return;
1841
2404
  }
1842
2405
  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 });
2406
+ if (action.dialog && !mute && action.dialog.type === "notification")
2407
+ toggleNotification({
2408
+ title: action.dialog.title,
2409
+ message: action.dialog.content,
2410
+ type: action.dialog.status
2411
+ });
1844
2412
  };
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) => {
2413
+ const typeOf = (action) => action.type || descriptions.find(
2414
+ (d) => typeof action.id === "string" && action.id.startsWith(`${d.name || d.displayName}-`)
2415
+ )?.type;
2416
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_admin2.DescriptionComponentRenderer, { props, descriptions, children: (actions) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system3.Flex, { gap: 1, "data-testid": "page-preview-actions", children: [...actions].sort(
2417
+ (a, b) => ACTION_TYPES.indexOf(typeOf(a)) - ACTION_TYPES.indexOf(typeOf(b))
2418
+ ).map((action) => {
1847
2419
  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);
2420
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { title: reason, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2421
+ import_design_system3.Button,
2422
+ {
2423
+ size: "S",
2424
+ variant: action.variant || "default",
2425
+ disabled: action.disabled,
2426
+ loading: action.loading,
2427
+ "aria-description": reason,
2428
+ onClick: (e) => run(action, e),
2429
+ children: action.label
2430
+ }
2431
+ ) }, action.id);
1849
2432
  }) }) });
1850
2433
  }
1851
- function PagePreview({ editor, groups = null, Toggle }) {
2434
+ function PagePreview({
2435
+ editor,
2436
+ groups = null,
2437
+ Modal: Modal3,
2438
+ Toggle
2439
+ }) {
1852
2440
  const t = useMessages();
1853
2441
  const c = (0, import_strapi_admin.unstable_useContentManagerContext)();
1854
- const rbac = (0, import_strapi_admin.useDocumentRBAC)("BlockscenePagePreview", (state) => state);
2442
+ const rbac = (0, import_strapi_admin.useDocumentRBAC)(
2443
+ "BlockscenePagePreview",
2444
+ (state) => state
2445
+ );
1855
2446
  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);
2447
+ const onChange = (0, import_admin2.useForm)(
2448
+ "BlockscenePagePreview",
2449
+ (state) => state.onChange
2450
+ );
2451
+ const components = (0, import_admin2.useStrapiApp)(
2452
+ "BlockscenePagePreview",
2453
+ (state) => state.components
2454
+ );
1858
2455
  const MediaLibraryDialog = components?.["media-library"];
1859
- const addFieldRow = (0, import_admin2.useForm)("BlockscenePagePreview", (state) => state.addFieldRow);
1860
- const moveFieldRow = (0, import_admin2.useForm)("BlockscenePagePreview", (state) => state.moveFieldRow);
2456
+ const addFieldRow = (0, import_admin2.useForm)(
2457
+ "BlockscenePagePreview",
2458
+ (state) => state.addFieldRow
2459
+ );
2460
+ const moveFieldRow = (0, import_admin2.useForm)(
2461
+ "BlockscenePagePreview",
2462
+ (state) => state.moveFieldRow
2463
+ );
1861
2464
  const fields = c.layout?.edit?.layout?.flat(3) || [];
1862
2465
  const readable = (name) => c.isCreatingEntry || (rbac.canReadFields || []).includes(name);
1863
- const zone = React3.useMemo(() => editableZones(c.contentType, values, readable, c.isLoading)[0]?.name, [c.contentType, values, c.isLoading, rbac.canReadFields, c.isCreatingEntry]);
2466
+ const zone = React4.useMemo(
2467
+ () => editableZones(c.contentType, values, readable, c.isLoading)[0]?.name,
2468
+ [c.contentType, values, c.isLoading, rbac.canReadFields, c.isCreatingEntry]
2469
+ );
1864
2470
  const zoneLabel = fields.find((field) => field.name === zone)?.label || zone || "";
1865
- 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");
1866
- const [mode, setModeState] = React3.useState(() => {
2471
+ const canEdit = Boolean(
2472
+ zone && ((c.isCreatingEntry ? rbac.canCreateFields : rbac.canUpdateFields) || []).includes(zone) && fields.find((field) => field.name === zone)?.disabled !== true && !c.form?.disabled && typeof addFieldRow === "function"
2473
+ );
2474
+ const [mode, setModeState] = React4.useState(() => {
1867
2475
  const v = read(MODE_KEY);
1868
2476
  return v === "split" || v === "preview" ? v : editor?.previewMode || "form";
1869
2477
  });
@@ -1871,32 +2479,37 @@ function PagePreview({ editor, groups = null, Toggle }) {
1871
2479
  setModeState(next);
1872
2480
  write(MODE_KEY, next);
1873
2481
  };
1874
- const [ratio, setRatio] = React3.useState(() => {
2482
+ const [ratio, setRatio] = React4.useState(() => {
1875
2483
  const v = Number(read(RATIO_KEY));
1876
2484
  return v > 0 && v < 1 ? v : 0.5;
1877
2485
  });
1878
2486
  const main = useMainRect();
1879
2487
  const vw = main.width;
1880
- const [dragging, setDragging] = React3.useState(false);
1881
- const [ready, setReady] = React3.useState(false);
1882
- const [failed, setFailed] = React3.useState(false);
1883
- const [attempt, retry] = React3.useReducer((n) => n + 1, 0);
1884
- const [picking, setPicking] = React3.useState(null);
1885
- React3.useEffect(() => {
2488
+ const [dragging, setDragging] = React4.useState(false);
2489
+ const [ready, setReady] = React4.useState(false);
2490
+ const [failed, setFailed] = React4.useState(false);
2491
+ const [attempt, retry] = React4.useReducer((n) => n + 1, 0);
2492
+ const [picking, setPicking] = React4.useState(null);
2493
+ React4.useEffect(() => {
1886
2494
  setEditing(null);
1887
2495
  setPicking(null);
1888
2496
  setInserting(null);
1889
2497
  }, [c.id, c.form?.initialValues?.locale]);
1890
- const [editing, setEditing] = React3.useState(null);
1891
- const [inserting, setInserting] = React3.useState(null);
2498
+ const [editing, setEditing] = React4.useState(null);
2499
+ const [inserting, setInserting] = React4.useState(null);
1892
2500
  const { get } = (0, import_admin2.useFetchClient)();
1893
2501
  const { toggleNotification } = (0, import_admin2.useNotification)();
1894
2502
  const zoneAttr = zone ? c.contentType?.attributes?.[zone] : null;
1895
- const iframe = React3.useRef(null);
1896
- const loaded = React3.useRef(false);
1897
- const anchor = React3.useRef(null);
1898
- const channel = React3.useMemo(() => crypto.randomUUID(), []);
1899
- const { base, source } = usePreviewBase(editor?.previewUrl || "", c.model, c.isCreatingEntry ? void 0 : c.id, c.form?.initialValues?.locale);
2503
+ const iframe = React4.useRef(null);
2504
+ const loaded = React4.useRef(false);
2505
+ const anchor = React4.useRef(null);
2506
+ const channel = React4.useMemo(() => crypto.randomUUID(), []);
2507
+ const { base, source } = usePreviewBase(
2508
+ editor?.previewUrl || "",
2509
+ c.model,
2510
+ c.isCreatingEntry ? void 0 : c.id,
2511
+ c.form?.initialValues?.locale
2512
+ );
1900
2513
  const url = base ? new URL(base) : null;
1901
2514
  url?.searchParams.set("channel", channel);
1902
2515
  const origin = url?.origin || "";
@@ -1905,21 +2518,50 @@ function PagePreview({ editor, groups = null, Toggle }) {
1905
2518
  const resizable = mode === "split" && !narrow;
1906
2519
  const active = mode !== "form" && Boolean(url) && Boolean(zone);
1907
2520
  const rows = zone && Array.isArray(values?.[zone]) ? values[zone] : [];
1908
- const latest = React3.useRef(rows);
2521
+ const latest = React4.useRef(rows);
1909
2522
  latest.current = rows;
1910
2523
  const insertRows = (at, ...items) => items.forEach((item, i) => {
1911
2524
  const from = latest.current.length + i;
1912
2525
  addFieldRow(zone, item);
1913
2526
  if (at + i < from) moveFieldRow(zone, from, at + i);
1914
2527
  });
1915
- const live = React3.useRef({ mode, canEdit, zoneLabel, components: c.components, setMode, onChange });
1916
- live.current = { mode, canEdit, zoneLabel, components: c.components, setMode, onChange };
1917
- const send = React3.useCallback(() => {
1918
- 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);
2528
+ const live = React4.useRef({
2529
+ mode,
2530
+ canEdit,
2531
+ zoneLabel,
2532
+ components: c.components,
2533
+ setMode,
2534
+ onChange
2535
+ });
2536
+ live.current = {
2537
+ mode,
2538
+ canEdit,
2539
+ zoneLabel,
2540
+ components: c.components,
2541
+ setMode,
2542
+ onChange
2543
+ };
2544
+ const send = React4.useCallback(() => {
2545
+ iframe.current?.contentWindow?.postMessage(
2546
+ {
2547
+ protocol: PROTOCOL,
2548
+ channel,
2549
+ type: "update-page",
2550
+ blocks: projectPage(
2551
+ latest.current,
2552
+ live.current.components,
2553
+ window.location.origin
2554
+ ),
2555
+ groups,
2556
+ locale: t.locale,
2557
+ mode: live.current.mode
2558
+ },
2559
+ origin
2560
+ );
1919
2561
  }, [channel, origin]);
1920
2562
  const indexOf = (key) => latest.current.findIndex((row) => blockKey(row) === key);
1921
2563
  const path = (key, field) => `${zone}.${indexOf(key)}.${field}`;
1922
- React3.useEffect(() => {
2564
+ React4.useEffect(() => {
1923
2565
  if (resizable) markLayout(anchor.current);
1924
2566
  document.body.classList.toggle("bp-split", resizable);
1925
2567
  document.documentElement.style.setProperty("--bp-pane", `${paneWidth}px`);
@@ -1931,7 +2573,9 @@ function PagePreview({ editor, groups = null, Toggle }) {
1931
2573
  if (persist) write(RATIO_KEY, String(next));
1932
2574
  };
1933
2575
  const focusField = (index, field) => {
1934
- const item = findZoneList(live.current.zoneLabel)?.querySelectorAll(":scope > li")[index];
2576
+ const item = findZoneList(live.current.zoneLabel)?.querySelectorAll(
2577
+ ":scope > li"
2578
+ )[index];
1935
2579
  if (!item) return;
1936
2580
  const header = toggles(item.parentElement)[index];
1937
2581
  if (header?.getAttribute("aria-expanded") === "false") header.click();
@@ -1942,33 +2586,47 @@ function PagePreview({ editor, groups = null, Toggle }) {
1942
2586
  if (++tries > 40) return clearInterval(timer);
1943
2587
  let scope = item;
1944
2588
  for (let i = 0; i + 1 < parts.length; i += 2) {
1945
- const nested = [...scope.querySelectorAll("button[aria-expanded][data-radix-collection-item]")].filter((b) => b !== header);
2589
+ const nested = [
2590
+ ...scope.querySelectorAll(
2591
+ "button[aria-expanded][data-radix-collection-item]"
2592
+ )
2593
+ ].filter((b) => b !== header);
1946
2594
  const row = nested[Number(parts[i + 1])];
1947
2595
  if (!row) return;
1948
2596
  if (row.getAttribute("aria-expanded") === "false") row.click();
1949
2597
  scope = row.closest("li, div") || scope;
1950
2598
  }
1951
- const target = document.querySelector(`[name="${escaped}"], label[for="${escaped}"]`);
2599
+ const target = document.querySelector(
2600
+ `[name="${escaped}"], label[for="${escaped}"]`
2601
+ );
1952
2602
  if (!target) return;
1953
2603
  const INPUT = '.ck-editor__editable, textarea, input:not([type="hidden"]), select';
1954
2604
  let container = target.matches(INPUT) ? target : target.parentElement;
1955
- for (let depth = 0; container && depth < 4 && !container.matches(INPUT) && !container.querySelector(INPUT); depth++) container = container.parentElement;
2605
+ for (let depth = 0; container && depth < 4 && !container.matches(INPUT) && !container.querySelector(INPUT); depth++)
2606
+ container = container.parentElement;
1956
2607
  const editable = container?.matches(INPUT) ? container : container?.querySelector(INPUT);
1957
2608
  if (!editable) return;
1958
- if (editable.classList.contains("ck-editor__editable") && !editable.isContentEditable) return;
2609
+ if (editable.classList.contains("ck-editor__editable") && !editable.isContentEditable)
2610
+ return;
1959
2611
  editable.focus();
1960
2612
  if (document.activeElement !== editable) return;
1961
2613
  clearInterval(timer);
1962
2614
  editable.scrollIntoView({ block: "center", behavior: "smooth" });
1963
2615
  }, 150);
1964
2616
  };
1965
- React3.useEffect(() => {
2617
+ React4.useEffect(() => {
1966
2618
  if (!active) return;
1967
2619
  setReady(false);
1968
2620
  setFailed(false);
1969
2621
  const timeout = setTimeout(() => setFailed(true), 15e3);
1970
2622
  const receive = (event) => {
1971
- const is = (type) => isPreviewMessage(event, origin, iframe.current?.contentWindow, channel, type);
2623
+ const is = (type) => isPreviewMessage(
2624
+ event,
2625
+ origin,
2626
+ iframe.current?.contentWindow,
2627
+ channel,
2628
+ type
2629
+ );
1972
2630
  const { mode: mode2, canEdit: canEdit2, zoneLabel: zoneLabel2, components: components2, setMode: setMode2, onChange: onChange2 } = live.current;
1973
2631
  if (is("ready")) {
1974
2632
  clearTimeout(timeout);
@@ -1988,12 +2646,21 @@ function PagePreview({ editor, groups = null, Toggle }) {
1988
2646
  return;
1989
2647
  }
1990
2648
  if (is("move-group") && canEdit2 && groups) {
1991
- const next = (0, import_groups.moveGroup)(latest.current, String(event.data.key), event.data.direction === "up" ? "up" : "down", groups);
2649
+ const next = (0, import_groups.moveGroup)(
2650
+ latest.current,
2651
+ String(event.data.key),
2652
+ event.data.direction === "up" ? "up" : "down",
2653
+ groups
2654
+ );
1992
2655
  if (next) onChange2(zone, next);
1993
2656
  return;
1994
2657
  }
1995
2658
  if (is("delete-group") && canEdit2 && groups) {
1996
- const next = (0, import_groups.removeGroup)(latest.current, String(event.data.key), groups);
2659
+ const next = (0, import_groups.removeGroup)(
2660
+ latest.current,
2661
+ String(event.data.key),
2662
+ groups
2663
+ );
1997
2664
  if (next) onChange2(zone, next);
1998
2665
  return;
1999
2666
  }
@@ -2003,12 +2670,20 @@ function PagePreview({ editor, groups = null, Toggle }) {
2003
2670
  const uid2 = String(event.data.uid || "");
2004
2671
  const close = groups[uid2];
2005
2672
  const allowed = zoneAttr?.components || [];
2006
- if (index2 < 0 || !close || !allowed.includes(uid2) || !allowed.includes(close)) return;
2673
+ if (index2 < 0 || !close || !allowed.includes(uid2) || !allowed.includes(close))
2674
+ return;
2007
2675
  if (latest.current.length + 2 > (zoneAttr?.max ?? Infinity)) {
2008
2676
  toggleNotification({ type: "info", message: t.zoneFull });
2009
2677
  return;
2010
2678
  }
2011
- insertRows(index2, { ...componentDefaults(components2[uid2], components2), __component: uid2 }, { __component: close });
2679
+ insertRows(
2680
+ index2,
2681
+ {
2682
+ ...componentDefaults(components2[uid2], components2),
2683
+ __component: uid2
2684
+ },
2685
+ { __component: close }
2686
+ );
2012
2687
  return;
2013
2688
  }
2014
2689
  const key = typeof event.data?.key === "string" ? event.data.key : "";
@@ -2028,11 +2703,21 @@ function PagePreview({ editor, groups = null, Toggle }) {
2028
2703
  }, 1500);
2029
2704
  }
2030
2705
  if (mode2 === "preview") setMode2("split");
2031
- iframe.current?.contentWindow?.postMessage({ protocol: PROTOCOL, channel, type: "highlight", key }, origin);
2706
+ iframe.current?.contentWindow?.postMessage(
2707
+ { protocol: PROTOCOL, channel, type: "highlight", key },
2708
+ origin
2709
+ );
2032
2710
  } else if (is("focus")) {
2033
2711
  const attr = validateFocus(uid, event.data.field, components2);
2034
2712
  if (!attr) return;
2035
- 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) });
2713
+ if (mode2 === "preview" && canEdit2 && (attr.customField || MODAL_TYPES.includes(attr.type)))
2714
+ setEditing({
2715
+ key,
2716
+ field: event.data.field,
2717
+ attr,
2718
+ label: `${components2[uid]?.info?.displayName || uid} \xB7 ${event.data.field}`,
2719
+ value: getIn(latest.current[index], event.data.field)
2720
+ });
2036
2721
  else focusField(index, event.data.field);
2037
2722
  } else if (is("media") && canEdit2) {
2038
2723
  const attr = mediaAttribute(uid, event.data.field, components2);
@@ -2041,27 +2726,67 @@ function PagePreview({ editor, groups = null, Toggle }) {
2041
2726
  const attr = mediaAttribute(uid, event.data.field, components2);
2042
2727
  if (attr && !attr.required) onChange2(path(key, event.data.field), null);
2043
2728
  } else if (is("edit") && canEdit2) {
2044
- const value = validateEdit(uid, event.data.field, event.data.value, components2);
2729
+ const value = validateEdit(
2730
+ uid,
2731
+ event.data.field,
2732
+ event.data.value,
2733
+ components2
2734
+ );
2045
2735
  if (value !== null) onChange2(path(key, event.data.field), value);
2046
2736
  }
2047
2737
  };
2048
2738
  window.addEventListener("message", receive);
2049
- if (loaded.current) iframe.current?.contentWindow?.postMessage({ protocol: PROTOCOL, channel, type: "ping" }, origin);
2739
+ if (loaded.current)
2740
+ iframe.current?.contentWindow?.postMessage(
2741
+ { protocol: PROTOCOL, channel, type: "ping" },
2742
+ origin
2743
+ );
2050
2744
  return () => {
2051
2745
  clearTimeout(timeout);
2052
2746
  window.removeEventListener("message", receive);
2053
2747
  };
2054
2748
  }, [active, attempt, channel, origin, groups]);
2055
- React3.useEffect(() => {
2749
+ React4.useEffect(() => {
2056
2750
  if (!ready || !active) return;
2057
2751
  const timer = setTimeout(send, 120);
2058
2752
  return () => clearTimeout(timer);
2059
2753
  }, [values, c.components, ready, active, send, mode]);
2060
2754
  if (!zone) return null;
2061
- const modes = [["form", t.modeForm], ["split", t.modeSplit], ["preview", t.modePreview]];
2062
- 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)) });
2755
+ const modes = [
2756
+ ["form", t.modeForm],
2757
+ ["split", t.modeSplit],
2758
+ ["preview", t.modePreview]
2759
+ ];
2760
+ const switcher = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2761
+ import_design_system3.Flex,
2762
+ {
2763
+ gap: 1,
2764
+ wrap: "wrap",
2765
+ "data-testid": "page-preview-modes",
2766
+ role: "group",
2767
+ "aria-label": t.modeGroup,
2768
+ children: modes.map(([value, label]) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2769
+ import_design_system3.Button,
2770
+ {
2771
+ type: "button",
2772
+ size: "S",
2773
+ variant: mode === value ? "default" : "tertiary",
2774
+ "aria-pressed": mode === value,
2775
+ onClick: () => setMode(value),
2776
+ disabled: !url && value !== "form",
2777
+ children: label
2778
+ },
2779
+ value
2780
+ ))
2781
+ }
2782
+ );
2063
2783
  const onKey = (event) => {
2064
- const map = { ArrowLeft: paneWidth + KEY_STEP, ArrowRight: paneWidth - KEY_STEP, Home: MIN_PANE, End: vw - MIN_FORM };
2784
+ const map = {
2785
+ ArrowLeft: paneWidth + KEY_STEP,
2786
+ ArrowRight: paneWidth - KEY_STEP,
2787
+ Home: MIN_PANE,
2788
+ End: vw - MIN_FORM
2789
+ };
2065
2790
  if (event.key in map) {
2066
2791
  event.preventDefault();
2067
2792
  applyWidth(map[event.key], true);
@@ -2072,28 +2797,69 @@ function PagePreview({ editor, groups = null, Toggle }) {
2072
2797
  const end = (0, import_groups.groupRange)(latest.current, error.index, groups)[1];
2073
2798
  insertRows(end + 1, { __component: error.expected });
2074
2799
  };
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: [
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 }) }) }),
2077
- /* @__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: [
2078
- /* @__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 || "" }) }),
2079
- 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 }) }) }),
2080
- error.code === "closeBeforeOpen" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Typography, { variant: "pi", textColor: "neutral600", children: t.diagStrayHint })
2081
- ] }, `${error.code}-${error.index}`)) })
2082
- ] }) });
2083
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system3.Flex, { direction: "column", alignItems: "stretch", gap: 2, ref: anchor, children: [
2800
+ const diagnostics = problems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2801
+ import_design_system3.Box,
2802
+ {
2803
+ role: "alert",
2804
+ "data-testid": "page-preview-diagnostics",
2805
+ padding: 2,
2806
+ background: "danger100",
2807
+ hasRadius: true,
2808
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("details", { children: [
2809
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("summary", { style: { cursor: "pointer" }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system3.Typography, { variant: "pi", fontWeight: "bold", textColor: "danger700", children: t.f("diagSummary", { count: problems.length }) }) }),
2810
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { style: { margin: "6px 0 0 16px", padding: 0 }, children: problems.map((error) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2811
+ "li",
2812
+ {
2813
+ style: { marginBottom: 6 },
2814
+ children: [
2815
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system3.Typography, { variant: "pi", textColor: "danger700", children: t.f(
2816
+ error.code === "closeBeforeOpen" ? "diagCloseBeforeOpen" : error.code === "mismatch" ? "diagMismatch" : "diagUnclosed",
2817
+ {
2818
+ n: error.index + 1,
2819
+ uid: error.uid,
2820
+ open: error.open || "",
2821
+ expected: error.expected || ""
2822
+ }
2823
+ ) }),
2824
+ error.code === "unclosed" && canEdit && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system3.Box, { paddingTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2825
+ import_design_system3.Button,
2826
+ {
2827
+ size: "S",
2828
+ variant: "danger-light",
2829
+ "data-testid": `diag-insert-close-${error.index}`,
2830
+ onClick: () => insertClose(error),
2831
+ children: t.f("diagInsertClose", {
2832
+ n: error.index + 1,
2833
+ expected: error.expected
2834
+ })
2835
+ }
2836
+ ) }),
2837
+ error.code === "closeBeforeOpen" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system3.Typography, { variant: "pi", textColor: "neutral600", children: t.diagStrayHint })
2838
+ ]
2839
+ },
2840
+ `${error.code}-${error.index}`
2841
+ )) })
2842
+ ] })
2843
+ }
2844
+ );
2845
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system3.Flex, { direction: "column", alignItems: "stretch", gap: 2, ref: anchor, children: [
2084
2846
  switcher,
2085
2847
  diagnostics,
2086
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Typography, { variant: "pi", textColor: "neutral600", children: url ? t.previewHelp : t.previewNoUrl }),
2087
- active && (0, import_react_dom2.createPortal)(
2088
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2848
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system3.Typography, { variant: "pi", textColor: "neutral600", children: url ? t.previewHelp : t.previewNoUrl }),
2849
+ active && (0, import_react_dom3.createPortal)(
2850
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2089
2851
  Pane,
2090
2852
  {
2091
2853
  "data-testid": "page-preview-pane",
2092
2854
  "aria-label": t.previewPane,
2093
- style: { left: mode === "preview" || narrow ? main.left : main.left + main.width - paneWidth, width: mode === "preview" || narrow ? main.width : paneWidth, userSelect: dragging ? "none" : void 0 },
2855
+ style: {
2856
+ left: mode === "preview" || narrow ? main.left : main.left + main.width - paneWidth,
2857
+ width: mode === "preview" || narrow ? main.width : paneWidth,
2858
+ userSelect: dragging ? "none" : void 0
2859
+ },
2094
2860
  children: [
2095
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: SPLIT_STYLE }),
2096
- resizable && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2861
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: SPLIT_STYLE }),
2862
+ resizable && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2097
2863
  Handle,
2098
2864
  {
2099
2865
  role: "separator",
@@ -2111,7 +2877,8 @@ function PagePreview({ editor, groups = null, Toggle }) {
2111
2877
  setDragging(true);
2112
2878
  },
2113
2879
  onPointerMove: (e) => {
2114
- if (dragging) applyWidth(main.left + main.width - e.clientX, false);
2880
+ if (dragging)
2881
+ applyWidth(main.left + main.width - e.clientX, false);
2115
2882
  },
2116
2883
  onPointerUp: (e) => {
2117
2884
  if (!dragging) return;
@@ -2123,15 +2890,44 @@ function PagePreview({ editor, groups = null, Toggle }) {
2123
2890
  onKeyDown: onKey
2124
2891
  }
2125
2892
  ),
2126
- /* @__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: [
2127
- switcher,
2128
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system3.Flex, { gap: 2, alignItems: "center", wrap: "wrap", style: { marginLeft: "auto" }, children: [
2129
- /* @__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 }),
2130
- failed && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.Button, { size: "S", variant: "secondary", onClick: retry, children: t.retry }),
2131
- /* @__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 })
2132
- ] })
2133
- ] }),
2134
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2893
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2894
+ import_design_system3.Flex,
2895
+ {
2896
+ padding: 2,
2897
+ gap: 2,
2898
+ justifyContent: "space-between",
2899
+ alignItems: "center",
2900
+ background: "neutral100",
2901
+ wrap: "wrap",
2902
+ style: { position: "sticky", top: 0, zIndex: 2 },
2903
+ children: [
2904
+ switcher,
2905
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2906
+ import_design_system3.Flex,
2907
+ {
2908
+ gap: 2,
2909
+ alignItems: "center",
2910
+ wrap: "wrap",
2911
+ style: { marginLeft: "auto" },
2912
+ children: [
2913
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system3.Typography, { variant: "pi", role: "status", textColor: "neutral600", children: failed ? t.previewFailed : ready ? t.previewReady : t.previewLoading }),
2914
+ failed && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system3.Button, { size: "S", variant: "secondary", onClick: retry, children: t.retry }),
2915
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2916
+ ToolbarActions,
2917
+ {
2918
+ model: c.model,
2919
+ collectionType: c.collectionType,
2920
+ documentId: c.isCreatingEntry ? void 0 : c.id,
2921
+ locale: c.form?.initialValues?.locale
2922
+ }
2923
+ )
2924
+ ]
2925
+ }
2926
+ )
2927
+ ]
2928
+ }
2929
+ ),
2930
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2135
2931
  Frame2,
2136
2932
  {
2137
2933
  ref: iframe,
@@ -2151,12 +2947,16 @@ function PagePreview({ editor, groups = null, Toggle }) {
2151
2947
  ),
2152
2948
  document.body
2153
2949
  ),
2154
- inserting && zoneAttr && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2950
+ inserting && zoneAttr && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2155
2951
  PickerModal,
2156
2952
  {
2157
- zone: { name: zone, components: zoneAttr.components || [], max: zoneAttr.max },
2953
+ zone: {
2954
+ name: zone,
2955
+ components: zoneAttr.components || [],
2956
+ max: zoneAttr.max
2957
+ },
2158
2958
  components: c.components,
2159
- Modal: PickerDialog,
2959
+ Modal: Modal3,
2160
2960
  Toggle,
2161
2961
  get,
2162
2962
  open: true,
@@ -2168,14 +2968,24 @@ function PagePreview({ editor, groups = null, Toggle }) {
2168
2968
  setInserting(null);
2169
2969
  const close = groups?.[uid];
2170
2970
  if (index < 0 || !(zoneAttr.components || []).includes(uid) || close && !(zoneAttr.components || []).includes(close) || latest.current.length + (close ? 2 : 1) > (zoneAttr.max ?? Infinity)) {
2171
- toggleNotification({ type: "warning", message: close ? t.zoneFull : t.insertMoved });
2971
+ toggleNotification({
2972
+ type: "warning",
2973
+ message: close ? t.zoneFull : t.insertMoved
2974
+ });
2172
2975
  return;
2173
2976
  }
2174
- insertRows(index, { ...componentDefaults(c.components[uid], c.components), __component: uid }, ...close ? [{ __component: close }] : []);
2977
+ insertRows(
2978
+ index,
2979
+ {
2980
+ ...componentDefaults(c.components[uid], c.components),
2981
+ __component: uid
2982
+ },
2983
+ ...close ? [{ __component: close }] : []
2984
+ );
2175
2985
  }
2176
2986
  }
2177
2987
  ),
2178
- editing && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2988
+ editing && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2179
2989
  FieldEditorModal,
2180
2990
  {
2181
2991
  label: editing.label,
@@ -2185,11 +2995,12 @@ function PagePreview({ editor, groups = null, Toggle }) {
2185
2995
  onApply: (value) => {
2186
2996
  const index = indexOf(editing.key);
2187
2997
  setEditing(null);
2188
- if (index >= 0) onChange(`${zone}.${index}.${editing.field}`, value);
2998
+ if (index >= 0)
2999
+ onChange(`${zone}.${index}.${editing.field}`, value);
2189
3000
  }
2190
3001
  }
2191
3002
  ),
2192
- picking && MediaLibraryDialog && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3003
+ picking && MediaLibraryDialog && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2193
3004
  MediaLibraryDialog,
2194
3005
  {
2195
3006
  allowedTypes: picking.attr.allowedTypes || ["images"],
@@ -2200,19 +3011,32 @@ function PagePreview({ editor, groups = null, Toggle }) {
2200
3011
  setPicking(null);
2201
3012
  if (index < 0 || !assets?.length) return;
2202
3013
  const current = getIn(latest.current[index], picking.field);
2203
- onChange(`${zone}.${index}.${picking.field}`, picking.attr.multiple ? [...Array.isArray(current) ? current : [], ...assets] : assets[0]);
3014
+ onChange(
3015
+ `${zone}.${index}.${picking.field}`,
3016
+ picking.attr.multiple ? [...Array.isArray(current) ? current : [], ...assets] : assets[0]
3017
+ );
2204
3018
  }
2205
3019
  }
2206
3020
  ),
2207
- /* @__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 : "" })
3021
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3022
+ import_design_system3.Box,
3023
+ {
3024
+ hidden: true,
3025
+ "data-testid": "page-preview-state",
3026
+ "data-mode": mode,
3027
+ "data-ready": ready,
3028
+ "data-failed": failed,
3029
+ "data-preview-source": source
3030
+ }
3031
+ )
2208
3032
  ] });
2209
3033
  }
2210
3034
 
2211
3035
  // admin/Settings.tsx
2212
- var React4 = __toESM(require("react"));
2213
- var import_design_system5 = require("@strapi/design-system");
3036
+ var React5 = __toESM(require("react"));
3037
+ var import_design_system4 = require("@strapi/design-system");
2214
3038
  var import_styled_components3 = __toESM(require("styled-components"));
2215
- var import_jsx_runtime5 = require("react/jsx-runtime");
3039
+ var import_jsx_runtime6 = require("react/jsx-runtime");
2216
3040
  var COLOR2 = /^#[0-9A-Fa-f]{6}$/;
2217
3041
  var Grid = import_styled_components3.default.div` display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: 16px; `;
2218
3042
  var Card2 = import_styled_components3.default.div`
@@ -2225,8 +3049,8 @@ var Bar = import_styled_components3.default.div`
2225
3049
  box-shadow: 0 1px 4px rgba(33, 33, 52, 0.1);
2226
3050
  `;
2227
3051
  function useMainRect2(anchor) {
2228
- const [rect, setRect] = React4.useState({ left: 0, width: 0 });
2229
- React4.useEffect(() => {
3052
+ const [rect, setRect] = React5.useState({ left: 0, width: 0 });
3053
+ React5.useEffect(() => {
2230
3054
  const read2 = () => {
2231
3055
  let host = document.getElementById("main-content");
2232
3056
  for (let el = anchor.current?.parentElement; !host && el; el = el.parentElement) if (["auto", "scroll"].includes(getComputedStyle(el).overflowY) && el.scrollHeight > el.clientHeight) host = el;
@@ -2243,11 +3067,11 @@ var Swatches = import_styled_components3.default.div` display: grid; grid-templa
2243
3067
  var Label = import_styled_components3.default.label` display: flex; flex-direction: column; gap: 4px; font-size: 12px; `;
2244
3068
  function ColorField({ name, label, value, onChange, disabled }) {
2245
3069
  const valid = COLOR2.test(value);
2246
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Label, { children: [
2247
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
2248
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { gap: 2, children: [
2249
- /* @__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" } }),
2250
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3070
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Label, { children: [
3071
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
3072
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { gap: 2, children: [
3073
+ /* @__PURE__ */ (0, import_jsx_runtime6.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" } }),
3074
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2251
3075
  "input",
2252
3076
  {
2253
3077
  name,
@@ -2267,18 +3091,18 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2267
3091
  const t = useMessages();
2268
3092
  const { get, put } = useClient();
2269
3093
  const { canRead, canUpdate, isLoading } = usePermissions2();
2270
- const [data, setData] = React4.useState(null);
2271
- const [catalog, setCatalog] = React4.useState(null);
2272
- const [settings, setSettings] = React4.useState(null);
2273
- const [media, setMedia] = React4.useState({});
2274
- const [sources, setSources] = React4.useState({});
2275
- const [dirty, setDirty] = React4.useState(false);
2276
- const [saving, setSaving] = React4.useState(false);
2277
- const [status, setStatus] = React4.useState("");
2278
- const [failed, setFailed] = React4.useState(false);
2279
- const [filter, setFilter] = React4.useState("");
2280
- const [picking, setPicking] = React4.useState(null);
2281
- React4.useEffect(() => {
3094
+ const [data, setData] = React5.useState(null);
3095
+ const [catalog, setCatalog] = React5.useState(null);
3096
+ const [settings, setSettings] = React5.useState(null);
3097
+ const [media, setMedia] = React5.useState({});
3098
+ const [sources, setSources] = React5.useState({});
3099
+ const [dirty, setDirty] = React5.useState(false);
3100
+ const [saving, setSaving] = React5.useState(false);
3101
+ const [status, setStatus] = React5.useState("");
3102
+ const [failed, setFailed] = React5.useState(false);
3103
+ const [filter, setFilter] = React5.useState("");
3104
+ const [picking, setPicking] = React5.useState(null);
3105
+ React5.useEffect(() => {
2282
3106
  if (!canRead || isLoading) return;
2283
3107
  let active = true;
2284
3108
  Promise.all([get("/blockscene/settings"), get("/blockscene/catalog")]).then(([s, c]) => {
@@ -2326,35 +3150,35 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2326
3150
  return index === 0 && manual ? t.manual : t.automatic;
2327
3151
  };
2328
3152
  const ready = !isLoading && canRead && !failed && settings && catalog;
2329
- const header = React4.useRef(null);
2330
- const [floating, setFloating] = React4.useState(false);
3153
+ const header = React5.useRef(null);
3154
+ const [floating, setFloating] = React5.useState(false);
2331
3155
  const main = useMainRect2(header);
2332
- React4.useEffect(() => {
3156
+ React5.useEffect(() => {
2333
3157
  const el = header.current;
2334
3158
  if (!el || typeof IntersectionObserver === "undefined") return;
2335
3159
  const observer = new IntersectionObserver(([entry]) => setFloating(!entry.isIntersecting && entry.boundingClientRect.top < 0));
2336
3160
  observer.observe(el);
2337
3161
  return () => observer.disconnect();
2338
3162
  }, [ready]);
2339
- const controls = (suffix) => ready && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
2340
- /* @__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 }),
2341
- /* @__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 })
3163
+ const controls = (suffix) => ready && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
3164
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.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 }),
3165
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Button, { onClick: save, disabled: !canUpdate || invalid || !dirty, loading: saving, "data-testid": `save-blockscene-settings${suffix}`, children: t.save })
2342
3166
  ] });
2343
- 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: [
2344
- /* @__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: [
2345
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "alpha", tag: "h1", children: t.settingsTitle }),
3167
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Box, { padding: 8, background: "neutral100", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 5, children: [
3168
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: header, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
3169
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "alpha", tag: "h1", children: t.settingsTitle }),
2346
3170
  controls("")
2347
3171
  ] }) }),
2348
- 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: [
2349
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "beta", tag: "p", children: t.settingsTitle }),
3172
+ floating && main.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Bar, { style: { left: main.left, width: main.width }, "data-testid": "settings-floating-bar", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
3173
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "beta", tag: "p", children: t.settingsTitle }),
2350
3174
  controls("-floating")
2351
3175
  ] }) }),
2352
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { textColor: "neutral600", children: t.settingsIntro }),
2353
- 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: [
2354
- 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 }) }),
2355
- /* @__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: [
2356
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.palette }),
2357
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Swatches, { children: Object.keys(DEFAULT_PALETTE).map((key) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3176
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { textColor: "neutral600", children: t.settingsIntro }),
3177
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { children: "\u2026" }) : !canRead ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { role: "alert", children: t.denied }) : failed ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { role: "alert", children: t.loadFailed }) : !settings || !catalog ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3178
+ data.disabled && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Box, { padding: 4, background: "warning100", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { role: "alert", textColor: "warning700", children: t.disabledByServer }) }),
3179
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
3180
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "beta", tag: "h2", children: t.palette }),
3181
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Swatches, { children: Object.keys(DEFAULT_PALETTE).map((key) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2358
3182
  ColorField,
2359
3183
  {
2360
3184
  name: `palette-${key}`,
@@ -2368,33 +3192,33 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2368
3192
  },
2369
3193
  key
2370
3194
  )) }),
2371
- invalid && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { role: "alert", textColor: "danger600", children: t.invalidColor }),
2372
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewLabel }),
2373
- /* @__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: [
2374
- /* @__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 }) }),
2375
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.templates[template] })
3195
+ invalid && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { role: "alert", textColor: "danger600", children: t.invalidColor }),
3196
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.previewLabel }),
3197
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Swatches, { "data-testid": "palette-preview", children: TEMPLATES.map((template) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { direction: "column", gap: 1, children: [
3198
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Box, { style: { aspectRatio: "16 / 9", overflow: "hidden" }, hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Wireframe, { template, palette: settings.palette }) }),
3199
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.templates[template] })
2376
3200
  ] }, template)) }),
2377
- /* @__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) => {
3201
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Flex, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Button, { variant: "tertiary", size: "S", disabled: !canUpdate, onClick: () => update((s) => {
2378
3202
  s.palette = { ...DEFAULT_PALETTE };
2379
3203
  return s;
2380
3204
  }), children: t.resetPalette }) })
2381
3205
  ] }) }),
2382
- /* @__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: [
2383
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.editor }),
2384
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleField2, { name: "editor-enabled", label: t.enabled, value: editor.enabled, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
3206
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
3207
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "beta", tag: "h2", children: t.editor }),
3208
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToggleField2, { name: "editor-enabled", label: t.enabled, value: editor.enabled, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
2385
3209
  s.editor.enabled = v;
2386
3210
  return s;
2387
3211
  }) }),
2388
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.enabledHelp }),
2389
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleField2, { name: "editor-showOpenAll", label: t.showOpenAll, value: editor.showOpenAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
3212
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.enabledHelp }),
3213
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToggleField2, { name: "editor-showOpenAll", label: t.showOpenAll, value: editor.showOpenAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
2390
3214
  s.editor.showOpenAll = v;
2391
3215
  return s;
2392
3216
  }) }),
2393
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleField2, { name: "editor-showCloseAll", label: t.showCloseAll, value: editor.showCloseAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
3217
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToggleField2, { name: "editor-showCloseAll", label: t.showCloseAll, value: editor.showCloseAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
2394
3218
  s.editor.showCloseAll = v;
2395
3219
  return s;
2396
3220
  }) }),
2397
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3221
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2398
3222
  SelectField2,
2399
3223
  {
2400
3224
  name: "editor-initialState",
@@ -2408,9 +3232,9 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2408
3232
  })
2409
3233
  }
2410
3234
  ),
2411
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.rememberHelp }),
2412
- previewSupported ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2413
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3235
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.rememberHelp }),
3236
+ previewSupported ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3237
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2414
3238
  TextField2,
2415
3239
  {
2416
3240
  name: "editor-previewUrl",
@@ -2424,8 +3248,8 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2424
3248
  })
2425
3249
  }
2426
3250
  ),
2427
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewUrlHelp }),
2428
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3251
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.previewUrlHelp }),
3252
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2429
3253
  SelectField2,
2430
3254
  {
2431
3255
  name: "editor-previewMode",
@@ -2439,26 +3263,26 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2439
3263
  })
2440
3264
  }
2441
3265
  ),
2442
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewModeHelp }),
2443
- data.blockPreviewAvailable && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
2444
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
3266
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.previewModeHelp }),
3267
+ data.blockPreviewAvailable && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3268
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
2445
3269
  s.editor.blockPreviewInForm = v;
2446
3270
  return s;
2447
3271
  }) }),
2448
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
3272
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
2449
3273
  ] })
2450
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewV4 })
3274
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.previewV4 })
2451
3275
  ] }) }),
2452
- /* @__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: [
2453
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.components }),
2454
- /* @__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 }),
2455
- /* @__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 }) }),
2456
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Grid, { "data-testid": "components-grid", children: components.map((component) => {
3276
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
3277
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "beta", tag: "h2", children: t.components }),
3278
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Searchbar, { name: "component-filter", value: filter, placeholder: t.filter, clearLabel: t.clear, onClear: () => setFilter(""), onChange: (e) => setFilter(e.target.value), children: t.filter }),
3279
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", "data-testid": "components-count", children: t.f("countAll", { count: components.length }) }),
3280
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Grid, { "data-testid": "components-grid", children: components.map((component) => {
2457
3281
  const entry = settings.components[component.uid] || {};
2458
3282
  const meta = { ...catalog.components?.[component.uid] || {}, ...media[component.uid] || {} };
2459
3283
  const candidates = candidatesFor(component.uid, meta, catalog);
2460
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Card2, { "data-testid": `settings-${component.uid}`, children: [
2461
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3284
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Card2, { "data-testid": `settings-${component.uid}`, children: [
3285
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2462
3286
  Thumb,
2463
3287
  {
2464
3288
  candidates,
@@ -2469,23 +3293,23 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2469
3293
  onResolved: (index) => setSources((current) => current[component.uid] === index ? current : { ...current, [component.uid]: index })
2470
3294
  }
2471
3295
  ),
2472
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
2473
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { fontWeight: "bold", textColor: "neutral800", children: component.displayName }),
2474
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: [
3296
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
3297
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { fontWeight: "bold", textColor: "neutral800", children: component.displayName }),
3298
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: [
2475
3299
  component.uid,
2476
3300
  " \xB7 ",
2477
3301
  component.category
2478
3302
  ] }),
2479
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Typography, { variant: "pi", "data-testid": `source-${component.uid}`, children: [
3303
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Typography, { variant: "pi", "data-testid": `source-${component.uid}`, children: [
2480
3304
  t.source,
2481
3305
  ": ",
2482
3306
  sourceOf(component.uid, Boolean(meta.manualImage)),
2483
3307
  meta.manualName ? ` (${meta.manualName})` : ""
2484
3308
  ] }),
2485
- meta.manualMissing && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Typography, { variant: "pi", role: "alert", textColor: "danger600", children: t.brokenMedia }),
2486
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system5.Flex, { gap: 2, wrap: "wrap", children: [
2487
- /* @__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 }),
2488
- entry.mediaId && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system5.Button, { variant: "tertiary", size: "S", disabled: !canUpdate || saving, onClick: () => {
3309
+ meta.manualMissing && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Typography, { variant: "pi", role: "alert", textColor: "danger600", children: t.brokenMedia }),
3310
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system4.Flex, { gap: 2, wrap: "wrap", children: [
3311
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Button, { variant: "secondary", size: "S", disabled: !canUpdate || saving, onClick: () => setPicking(component.uid), children: entry.mediaId ? t.replace : t.choose }),
3312
+ entry.mediaId && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system4.Button, { variant: "tertiary", size: "S", disabled: !canUpdate || saving, onClick: () => {
2489
3313
  update((s) => {
2490
3314
  delete s.components[component.uid]?.mediaId;
2491
3315
  if (!Object.keys(s.components[component.uid] || {}).length) delete s.components[component.uid];
@@ -2498,7 +3322,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2498
3322
  });
2499
3323
  }, children: t.useAutomatic })
2500
3324
  ] }),
2501
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3325
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2502
3326
  SelectField2,
2503
3327
  {
2504
3328
  name: `template-${component.uid}`,
@@ -2516,7 +3340,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
2516
3340
  ] }, component.uid);
2517
3341
  }) })
2518
3342
  ] }) }),
2519
- picking && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MediaPicker2, { onClose: () => setPicking(null), onSelect: (asset) => {
3343
+ picking && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MediaPicker2, { onClose: () => setPicking(null), onSelect: (asset) => {
2520
3344
  const uid = picking;
2521
3345
  setPicking(null);
2522
3346
  if (!asset?.id) return;
@@ -2545,10 +3369,10 @@ function register(app, Component, to) {
2545
3369
  }
2546
3370
 
2547
3371
  // admin/catalog.ts
2548
- var React5 = __toESM(require("react"));
3372
+ var React6 = __toESM(require("react"));
2549
3373
  function useCatalog(get) {
2550
- const [catalog, setCatalog] = React5.useState(null);
2551
- React5.useEffect(() => {
3374
+ const [catalog, setCatalog] = React6.useState(null);
3375
+ React6.useEffect(() => {
2552
3376
  let active = true;
2553
3377
  get("/blockscene/catalog").then(({ data }) => {
2554
3378
  if (active) setCatalog(data);
@@ -2563,13 +3387,13 @@ function useCatalog(get) {
2563
3387
  }
2564
3388
 
2565
3389
  // admin/strapi5.tsx
2566
- var import_jsx_runtime6 = require("react/jsx-runtime");
3390
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2567
3391
  function Modal2({ open, onOpenChange, trigger, title, children }) {
2568
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Modal.Root, { open, onOpenChange, children: [
2569
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Modal.Trigger, { children: trigger }),
2570
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Modal.Content, { style: { width: "80vw", maxWidth: "80vw" }, children: [
2571
- /* @__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 }) }),
2572
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Modal.Body, { children })
3392
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system5.Modal.Root, { open, onOpenChange, children: [
3393
+ trigger && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system5.Modal.Trigger, { children: trigger }),
3394
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system5.Modal.Content, { style: { width: "80vw", maxWidth: "80vw" }, children: [
3395
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system5.Modal.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system5.Modal.Title, { children: title }) }),
3396
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system5.Modal.Body, { children })
2573
3397
  ] })
2574
3398
  ] });
2575
3399
  }
@@ -2589,49 +3413,154 @@ function Panel() {
2589
3413
  formValues ?? c.form?.values,
2590
3414
  (name) => allowed.includes(name) && (creating || (rbac.canReadFields || []).includes(name)) && fields.find((field) => field.name === name)?.disabled !== true,
2591
3415
  c.isLoading || c.form?.disabled || !c.form?.addFieldRow
2592
- ).map((zone) => ({ ...zone, label: fields.find((field) => field.name === zone.name)?.label || zone.name }));
3416
+ ).map((zone) => ({
3417
+ ...zone,
3418
+ label: fields.find((field) => field.name === zone.name)?.label || zone.name
3419
+ }));
2593
3420
  const add = (zone, uid) => {
2594
3421
  const values = formValues ?? c.form.values;
2595
3422
  const close = catalog?.groups?.[uid];
2596
- if (c.form.disabled || !canInsert(zone, uid, values, c.components, close ? 2 : 1) || close && !zone.components.includes(close)) return false;
3423
+ if (c.form.disabled || !canInsert(zone, uid, values, c.components, close ? 2 : 1) || close && !zone.components.includes(close))
3424
+ return false;
2597
3425
  const at = Array.isArray(values?.[zone.name]) ? values[zone.name].length : 0;
2598
- c.form.addFieldRow(zone.name, { ...componentDefaults(c.components[uid], c.components), __component: uid }, at);
3426
+ c.form.addFieldRow(
3427
+ zone.name,
3428
+ {
3429
+ ...componentDefaults(c.components[uid], c.components),
3430
+ __component: uid
3431
+ },
3432
+ at
3433
+ );
2599
3434
  if (close) c.form.addFieldRow(zone.name, { __component: close }, at + 1);
2600
3435
  return true;
2601
3436
  };
2602
3437
  if (!zones.length || !catalog?.editor?.enabled) return null;
2603
3438
  const docKey = `${c.model}:${creating ? "new" : c.id}:${c.form?.initialValues?.locale || ""}`;
2604
- return { title: t.gallery, content: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
2605
- /* @__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 }),
2606
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PagePreview, { editor: catalog.editor, groups: catalog.groups || null, Toggle: ToggleField })
2607
- ] }) };
3439
+ return {
3440
+ title: t.gallery,
3441
+ content: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
3442
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3443
+ Gallery,
3444
+ {
3445
+ zones,
3446
+ components: c.components,
3447
+ add,
3448
+ Modal: Modal2,
3449
+ Toggle: ToggleField,
3450
+ get,
3451
+ editor: catalog.editor,
3452
+ catalog,
3453
+ docKey,
3454
+ contentType: c.model,
3455
+ userId: user?.id
3456
+ }
3457
+ ),
3458
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3459
+ PagePreview,
3460
+ {
3461
+ editor: catalog.editor,
3462
+ groups: catalog.groups || null,
3463
+ Modal: Modal2,
3464
+ Toggle: ToggleField
3465
+ }
3466
+ )
3467
+ ] })
3468
+ };
2608
3469
  }
2609
- var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Flex, { gap: 3, children: [
2610
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Switch, { name, "aria-label": label, checked: Boolean(value), disabled, onCheckedChange: onChange }),
2611
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Typography, { children: label })
3470
+ var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system5.Flex, { gap: 3, children: [
3471
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3472
+ import_design_system5.Switch,
3473
+ {
3474
+ name,
3475
+ "aria-label": label,
3476
+ checked: Boolean(value),
3477
+ disabled,
3478
+ onCheckedChange: onChange
3479
+ }
3480
+ ),
3481
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system5.Typography, { children: label })
2612
3482
  ] });
2613
- var TextField = ({ name, label, value, onChange, disabled, placeholder }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Field.Root, { name, children: [
2614
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Field.Label, { children: label }),
2615
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.TextInput, { name, value, disabled, placeholder, onChange: (e) => onChange(e.target.value) })
3483
+ var TextField = ({
3484
+ name,
3485
+ label,
3486
+ value,
3487
+ onChange,
3488
+ disabled,
3489
+ placeholder
3490
+ }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system5.Field.Root, { name, children: [
3491
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system5.Field.Label, { children: label }),
3492
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3493
+ import_design_system5.TextInput,
3494
+ {
3495
+ name,
3496
+ value,
3497
+ disabled,
3498
+ placeholder,
3499
+ onChange: (e) => onChange(e.target.value)
3500
+ }
3501
+ )
2616
3502
  ] });
2617
- var SelectField = ({ name, label, value, onChange, disabled, options }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system6.Field.Root, { name, children: [
2618
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system6.Field.Label, { children: label }),
2619
- /* @__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)) })
3503
+ var SelectField = ({
3504
+ name,
3505
+ label,
3506
+ value,
3507
+ onChange,
3508
+ disabled,
3509
+ options
3510
+ }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system5.Field.Root, { name, children: [
3511
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system5.Field.Label, { children: label }),
3512
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3513
+ import_design_system5.SingleSelect,
3514
+ {
3515
+ value,
3516
+ disabled,
3517
+ onChange: (v) => onChange(String(v)),
3518
+ children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system5.SingleSelectOption, { value: o.value, children: o.label }, o.value))
3519
+ }
3520
+ )
2620
3521
  ] });
2621
3522
  function MediaPicker({ onClose, onSelect }) {
2622
- const components = (0, import_admin3.useStrapiApp)("Blockscene", (state) => state.components);
2623
- const Dialog3 = components?.["media-library"];
2624
- React6.useEffect(() => {
2625
- if (!Dialog3) onClose();
2626
- }, [Dialog3, onClose]);
2627
- if (!Dialog3) return null;
2628
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Dialog3, { onClose, allowedTypes: ["images"], multiple: false, onSelectAssets: (assets) => onSelect(assets?.[0]) });
3523
+ const components = (0, import_admin3.useStrapiApp)(
3524
+ "Blockscene",
3525
+ (state) => state.components
3526
+ );
3527
+ const Dialog2 = components?.["media-library"];
3528
+ React7.useEffect(() => {
3529
+ if (!Dialog2) onClose();
3530
+ }, [Dialog2, onClose]);
3531
+ if (!Dialog2) return null;
3532
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3533
+ Dialog2,
3534
+ {
3535
+ onClose,
3536
+ allowedTypes: ["images"],
3537
+ multiple: false,
3538
+ onSelectAssets: (assets) => onSelect(assets?.[0])
3539
+ }
3540
+ );
2629
3541
  }
2630
3542
  function usePermissions() {
2631
- const { allowedActions, isLoading } = (0, import_admin3.useRBAC)(Object.values(permissions).flat());
2632
- return { canRead: allowedActions.canRead, canUpdate: allowedActions.canUpdate, isLoading };
3543
+ const { allowedActions, isLoading } = (0, import_admin3.useRBAC)(
3544
+ Object.values(permissions).flat()
3545
+ );
3546
+ return {
3547
+ canRead: allowedActions.canRead,
3548
+ canUpdate: allowedActions.canUpdate,
3549
+ isLoading
3550
+ };
2633
3551
  }
2634
- var SettingsPage = () => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Settings, { useClient: import_admin3.useFetchClient, usePermissions, MediaPicker, ToggleField, SelectField, TextField, previewSupported: true });
3552
+ var SettingsPage = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3553
+ Settings,
3554
+ {
3555
+ useClient: import_admin3.useFetchClient,
3556
+ usePermissions,
3557
+ MediaPicker,
3558
+ ToggleField,
3559
+ SelectField,
3560
+ TextField,
3561
+ previewSupported: true
3562
+ }
3563
+ );
2635
3564
  var strapi5_default = {
2636
3565
  register(app) {
2637
3566
  register(app, SettingsPage, "blockscene");