@aduptive/strapi-blockscene 1.0.0-alpha.10 → 1.0.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/admin.mjs CHANGED
@@ -125,13 +125,22 @@ var require_groups = __commonJS({
125
125
  const [a, b] = direction === "up" ? [ranges[to], ranges[at]] : [ranges[at], ranges[to]];
126
126
  return [...rows.slice(0, a[0]), ...rows.slice(b[0], b[1] + 1), ...rows.slice(a[0], a[1] + 1), ...rows.slice(b[1] + 1)];
127
127
  }
128
- function removeGroup2(rows, key, g) {
128
+ function removeGroup3(rows, key, g) {
129
129
  if (!g) return null;
130
130
  const start = rows.findIndex((row) => blockKey3(row) === String(key));
131
131
  if (start < 0 || !isOpener2(rows[start], g)) return null;
132
132
  const [, end] = groupRange3(rows, start, g);
133
+ if (end <= start || uidOf(rows[end]) !== g[uidOf(rows[start])]) return null;
133
134
  return [...rows.slice(0, start), ...rows.slice(end + 1)];
134
135
  }
136
+ function unwrapGroup3(rows, key, g) {
137
+ if (!g) return null;
138
+ const start = rows.findIndex((row) => blockKey3(row) === String(key));
139
+ if (start < 0 || !isOpener2(rows[start], g)) return null;
140
+ const [, end] = groupRange3(rows, start, g);
141
+ if (end <= start || uidOf(rows[end]) !== g[uidOf(rows[start])]) return null;
142
+ return [...rows.slice(0, start), ...rows.slice(start + 1, end), ...rows.slice(end + 1)];
143
+ }
135
144
  var MAX_COLUMNS = 12;
136
145
  var parseColumns = (value) => {
137
146
  const n = typeof value === "number" ? value : typeof value === "string" && /^\s*\d{1,3}\s*$/.test(value) ? Number(value) : NaN;
@@ -158,7 +167,8 @@ var require_groups = __commonJS({
158
167
  groupRows: groupRows2,
159
168
  topLevelRanges: topLevelRanges2,
160
169
  moveGroup: moveGroup2,
161
- removeGroup: removeGroup2,
170
+ removeGroup: removeGroup3,
171
+ unwrapGroup: unwrapGroup3,
162
172
  blockKey: blockKey3,
163
173
  isOpener: isOpener2,
164
174
  isClose: isClose2,
@@ -172,18 +182,18 @@ var require_groups = __commonJS({
172
182
  });
173
183
 
174
184
  // admin/strapi4.tsx
175
- import * as React12 from "react";
185
+ import * as React13 from "react";
176
186
  import {
177
- Button as Button5,
187
+ Button as Button6,
178
188
  MenuItem as MenuItem2,
179
189
  SimpleMenu as SimpleMenu2,
180
190
  ModalLayout,
181
191
  ModalHeader,
182
192
  ModalBody,
183
- Typography as Typography6,
193
+ Typography as Typography7,
184
194
  Status,
185
195
  Switch,
186
- Flex as Flex6,
196
+ Flex as Flex7,
187
197
  SingleSelect,
188
198
  SingleSelectOption,
189
199
  TextInput
@@ -253,6 +263,26 @@ function variantRow(schema, components, values, keys = fractional) {
253
263
  }
254
264
  return row;
255
265
  }
266
+ function starterKitRows(kit, zones, components, form) {
267
+ const out = {};
268
+ for (const [name, items2] of Object.entries(kit?.zones || {})) {
269
+ const zone = zones.find((entry) => entry.name === name);
270
+ const current = form.rows(name);
271
+ if (!zone || current.length || current.length + items2.length > (zone.max ?? Infinity) || items2.some((item) => !zone.components.includes(item.__component) || !components[item.__component])) return null;
272
+ const keys = form.keys(current, current.length, items2.length);
273
+ out[name] = items2.map((item, index) => ({ ...variantRow(components[item.__component], components, item.values), __component: item.__component, __temp_key__: keys[index] }));
274
+ }
275
+ return out;
276
+ }
277
+ function starterKitsForLocale(kits, locale) {
278
+ if (!Array.isArray(kits)) return [];
279
+ const current = String(locale || "").toLowerCase();
280
+ const language = current.split("-")[0];
281
+ return kits.filter((kit) => !Array.isArray(kit.locales) || kit.locales.some((entry) => {
282
+ const wanted = String(entry).toLowerCase();
283
+ return wanted === current || !wanted.includes("-") && wanted === language;
284
+ }));
285
+ }
256
286
  function editableZones(schema, values, canEdit, disabled = false) {
257
287
  if (disabled) return [];
258
288
  return Object.entries(schema?.attributes || {}).filter(
@@ -317,6 +347,12 @@ var pickable = (zone, config) => {
317
347
  const closers = Object.values(config.groups || {});
318
348
  return zone.components.filter((uid) => !closers.includes(uid));
319
349
  };
350
+ function showRowThumbnail(uid, config = {}) {
351
+ const configured = config.components?.[uid]?.showRowThumbnail;
352
+ if (typeof configured === "boolean") return configured;
353
+ const groups = config.groups || {};
354
+ return !Object.prototype.hasOwnProperty.call(groups, uid) && !Object.values(groups).includes(uid);
355
+ }
320
356
  function entryOf(uid, schema, config) {
321
357
  const meta = config.components?.[uid] || {};
322
358
  return {
@@ -453,13 +489,74 @@ var TEXT_TYPES = ["string", "text"];
453
489
  var RICH_TYPES = ["richtext", "blocks", "customField"];
454
490
  var EDITABLE_TYPES = [...TEXT_TYPES, ...RICH_TYPES];
455
491
  var SCALAR = ["string", "text", "richtext", "email", "enumeration", "integer", "biginteger", "float", "decimal", "boolean", "date", "datetime", "time", "json", "blocks", "uid", "customField"];
492
+ var ENTRY_SYSTEM = ["id", "documentId", "locale", "createdAt", "updatedAt", "publishedAt"];
493
+ var privateAttribute = (attr) => attr?.private === true || attr?.pluginOptions?.blockscene?.private === true;
494
+ var fieldReadable = (path, allowed, all = false) => {
495
+ if (all) return true;
496
+ const fields = Array.isArray(allowed) ? allowed : [];
497
+ const parts = String(path).split(".");
498
+ return parts.some((_, index) => fields.includes(parts.slice(0, index + 1).join("."))) || fields.some((field) => field.startsWith(`${path}.`));
499
+ };
456
500
  var blockKey = (row) => row && row.id != null ? `${row.__component}#${row.id}` : row && row.__temp_key__ != null ? String(row.__temp_key__) : null;
501
+ function plainValue(value, depth = 0) {
502
+ if (value == null || typeof value === "number" || typeof value === "boolean") return value;
503
+ if (typeof value === "string") return value.slice(0, 2e5);
504
+ if (typeof value !== "object" || depth > 8) return void 0;
505
+ if (Array.isArray(value)) return value.slice(0, 500).map((item) => plainValue(item, depth + 1)).filter((item) => item !== void 0);
506
+ const out = {};
507
+ for (const [name, child] of Object.entries(value).slice(0, 500)) {
508
+ const projected = plainValue(child, depth + 1);
509
+ if (projected !== void 0) out[name] = projected;
510
+ }
511
+ return out;
512
+ }
513
+ function projectEntryValue(value, attr, components, cmsOrigin, depth = 0, readable = () => true, path = "") {
514
+ if (privateAttribute(attr) || attr?.type === "password" || depth > 8) return void 0;
515
+ if (attr?.type === "media") {
516
+ const files = (attr.multiple ? Array.isArray(value) ? value : [] : value ? [value] : []).map((file) => projectMedia(file, cmsOrigin)).filter(Boolean);
517
+ return attr.multiple ? files : files[0] || null;
518
+ }
519
+ if (attr?.type === "component") {
520
+ const schema = components?.[attr.component];
521
+ const one = (item) => {
522
+ if (!item || !schema) return null;
523
+ const projected = projectEntryObject(item, schema, components, cmsOrigin, depth + 1, readable, path);
524
+ return item.id != null ? { id: item.id, ...projected } : projected;
525
+ };
526
+ return attr.repeatable ? (Array.isArray(value) ? value : []).slice(0, 500).map(one).filter(Boolean) : one(value);
527
+ }
528
+ if (attr?.type === "dynamiczone") {
529
+ return (Array.isArray(value) ? value : []).slice(0, 500).flatMap((item) => {
530
+ const uid = item?.__component;
531
+ const schema = components?.[uid];
532
+ if (!uid || !schema) return [];
533
+ const projected = projectEntryObject(item, schema, components, cmsOrigin, depth + 1, readable, path);
534
+ return [{ ...item.id != null && { id: item.id }, __component: uid, ...projected }];
535
+ });
536
+ }
537
+ return plainValue(value, depth);
538
+ }
539
+ function projectEntryObject(values, schema, components, cmsOrigin, depth = 0, readable = () => true, prefix2 = "") {
540
+ const out = {};
541
+ for (const [name, attr] of Object.entries(schema?.attributes || {})) {
542
+ const path = prefix2 ? `${prefix2}.${name}` : name;
543
+ if (!readable(path) || privateAttribute(attr) || attr.type === "password" || values?.[name] === void 0) continue;
544
+ const projected = projectEntryValue(values[name], attr, components, cmsOrigin, depth, readable, path);
545
+ if (projected !== void 0) out[name] = projected;
546
+ }
547
+ return out;
548
+ }
549
+ function projectEntry(values, schema, components, cmsOrigin, readable = () => true) {
550
+ const out = projectEntryObject(values, schema, components, cmsOrigin, 0, readable);
551
+ for (const name of ENTRY_SYSTEM) if (values?.[name] !== void 0) out[name] = plainValue(values[name]);
552
+ return out;
553
+ }
457
554
  function projectRow(row, schema, components, cmsOrigin, depth = 0) {
458
555
  if (!row || !schema || depth > 3) return null;
459
556
  const out = {};
460
557
  for (const [name, attr] of Object.entries(schema.attributes || {})) {
461
558
  const value = row[name];
462
- if (attr.type === "password" || attr.type === "relation" || attr.private) continue;
559
+ if (attr.type === "password" || attr.type === "relation" || privateAttribute(attr)) continue;
463
560
  if (SCALAR.includes(attr.type)) {
464
561
  if (value !== void 0) out[name] = typeof value === "string" ? value.slice(0, 2e5) : value;
465
562
  } else if (attr.type === "media") {
@@ -488,7 +585,7 @@ function resolveField(uid, field, components) {
488
585
  const parts = field.split(".");
489
586
  for (let i = 0; i < parts.length; i++) {
490
587
  const attr = schema?.attributes?.[parts[i]];
491
- if (!attr || attr.private === true) return null;
588
+ if (!attr || privateAttribute(attr)) return null;
492
589
  if (i === parts.length - 1) return attr;
493
590
  if (attr.type !== "component") return null;
494
591
  if (attr.repeatable) {
@@ -504,7 +601,7 @@ function editableFields(uid, row, components) {
504
601
  const out = [];
505
602
  const SYSTEM = ["id", "documentId", "locale", "createdAt", "updatedAt", "publishedAt", "createdBy", "updatedBy", "localizations", "__component", "__temp_key__"];
506
603
  const push = (name, attr, label) => {
507
- if (!SYSTEM.includes(name.split(".").pop()) && attr?.private !== true && EDITABLE_TYPES.includes(attr?.type)) out.push({ name, type: attr.type, label });
604
+ if (!SYSTEM.includes(name.split(".").pop()) && !privateAttribute(attr) && EDITABLE_TYPES.includes(attr?.type)) out.push({ name, type: attr.type, label });
508
605
  };
509
606
  for (const [name, attr] of Object.entries(schema?.attributes || {})) {
510
607
  if (attr.type === "component" && attr.repeatable) {
@@ -518,7 +615,7 @@ function editableFields(uid, row, components) {
518
615
  function mediaFields(uid, row, components) {
519
616
  const media = {};
520
617
  for (const [name, attr] of Object.entries(components?.[uid]?.attributes || {})) {
521
- if (attr.type === "media" && attr.private !== true) media[name] = { required: attr.required === true, multiple: attr.multiple === true, present: attr.multiple ? Array.isArray(row?.[name]) && row[name].length > 0 : Boolean(row?.[name]) };
618
+ if (attr.type === "media" && !privateAttribute(attr)) media[name] = { required: attr.required === true, multiple: attr.multiple === true, present: attr.multiple ? Array.isArray(row?.[name]) && row[name].length > 0 : Boolean(row?.[name]) };
522
619
  }
523
620
  return media;
524
621
  }
@@ -558,6 +655,7 @@ var hoverKey = (key, rows) => key === null ? null : typeof key === "string" && k
558
655
  function isPreviewMessage(event, origin, source, channel, type) {
559
656
  return event.origin === origin && event.source === source && event.data?.protocol === PROTOCOL && event.data?.channel === channel && event.data?.type === type;
560
657
  }
658
+ var previewMessageAllowed = (event, origin, source, channel, readOnly) => isPreviewMessage(event, origin, source, channel, event.data?.type) && (!readOnly || event.data?.type === "ready");
561
659
  function insertIndex(rows, after) {
562
660
  if (after === null || after === void 0) return 0;
563
661
  const index = (Array.isArray(rows) ? rows : []).findIndex((row) => blockKey(row) === String(after));
@@ -760,7 +858,7 @@ import { useIntl } from "react-intl";
760
858
  // admin/translations/en.json
761
859
  var en_default = {
762
860
  title: "Blockscene",
763
- settings: "Gallery",
861
+ settings: "General",
764
862
  gallery: "Block gallery",
765
863
  search: "Search blocks",
766
864
  clear: "Clear search",
@@ -776,6 +874,17 @@ var en_default = {
776
874
  moreActions: "More actions",
777
875
  settingsTitle: "Blockscene",
778
876
  settingsIntro: "Gallery thumbnails, wireframe palette and editor preferences. Changes apply the next time the gallery opens; no rebuild is needed.",
877
+ settingsGeneral: "General",
878
+ settingsGeneralIntro: "Choose how Blockscene behaves in the editor and which row actions are available.",
879
+ settingsPreview: "Page preview",
880
+ settingsPreviewIntro: "Connect the frontend preview and configure its modes, toolbar and responsive widths.",
881
+ settingsContentTypes: "Content types",
882
+ settingsContentTypesIntro: "Choose where Blockscene is enabled and tailor the visual editor for each content type.",
883
+ settingsGallery: "Block gallery",
884
+ settingsGalleryIntro: "Configure gallery thumbnails, wireframe colors, block types and filters.",
885
+ settingsHistory: "History & trash",
886
+ settingsHistoryIntro: "Control version snapshots, activity retention and recoverable deletions.",
887
+ historyUnavailable: "History and trash settings require Strapi 5.",
779
888
  palette: "Wireframe palette",
780
889
  background: "Background",
781
890
  surface: "Surfaces",
@@ -805,6 +914,7 @@ var en_default = {
805
914
  showCloseAll: 'Show "Collapse all"',
806
915
  toggleHelp: "The zone bar shows one button: with both on it expands while any block is collapsed and collapses them all otherwise; with only one on, it offers that action alone.",
807
916
  showRowThumbnails: "Show block thumbnails in the rows",
917
+ componentRowThumbnail: "Show thumbnail in the editor row",
808
918
  initialState: "Initial accordion state",
809
919
  "states.closed": "All closed",
810
920
  "states.open": "All open",
@@ -812,10 +922,10 @@ var en_default = {
812
922
  rememberHelp: "Only the explicit open all / close all buttons update the memory, per user and browser. Opening one block does not.",
813
923
  previewUrl: "Preview route base URL",
814
924
  previewUrlHelp: "Full URL of your frontend page-preview route, e.g. https://site.test/block-preview/page. Leave empty to reuse the origin of Strapi's native Preview (when configured for the content type) with /block-preview/page. The route must implement the bridge (see README).",
815
- previewUrlEmpty: "No preview URL is set: editors get the Fields + page and Visual editor modes only on content types where Strapi's native Preview is configured. Elsewhere the mode menu is not shown.",
925
+ previewUrlEmpty: "No preview URL is set: editors get the Fields + preview and Visual editor modes only on content types where Strapi's native Preview is configured. Elsewhere the mode menu is not shown.",
816
926
  previewMode: "Initial preview mode",
817
- "modes.form": "Fields",
818
- "modes.split": "Fields + page",
927
+ "modes.form": "Fields only",
928
+ "modes.split": "Fields + preview",
819
929
  "modes.preview": "Visual editor",
820
930
  previewModeHelp: "Every edit view opens in this mode, unless its content type sets its own below. Editors can switch while they edit; the switch is not remembered.",
821
931
  lazyEdit: "Click to edit",
@@ -823,8 +933,8 @@ var en_default = {
823
933
  lazyFields: "Custom fields loaded on demand",
824
934
  lazyEditorsHelp: "Listed custom fields show a read-only preview until clicked or focused, so opening large pages stays fast. Separate uids with commas.",
825
935
  lazyFieldsInvalid: "Use up to {max} custom field uids such as plugin::ckeditor5.CKEditor or global::my-field.",
826
- modeForm: "Fields",
827
- modeSplit: "Fields + page",
936
+ modeForm: "Fields only",
937
+ modeSplit: "Fields + preview",
828
938
  modePreview: "Visual editor",
829
939
  previewPane: "Page preview",
830
940
  resize: "Resize preview pane",
@@ -851,6 +961,7 @@ var en_default = {
851
961
  denied: "Access denied.",
852
962
  loadFailed: "Could not load settings. Reload to try again.",
853
963
  invalidColor: "Colors must use #RRGGBB.",
964
+ invalidUrl: "Preview URLs must be complete HTTP or HTTPS URLs.",
854
965
  previewLabel: "Palette preview",
855
966
  removeGroup: "Remove group",
856
967
  diagTitle: "Block groups need attention; publishing is refused until they are fixed:",
@@ -885,6 +996,7 @@ var en_default = {
885
996
  contentTypes: "Content types",
886
997
  contentTypesHelp: 'The gallery, accordions and page preview work on these content types (the ones with a Dynamic Zone). Turn one off to leave its edit view native. "Opens in" is how every edit view of that type starts; editors can still switch while they edit.',
887
998
  typeMode: "Opens in",
999
+ typeAdvanced: "Visual editor options",
888
1000
  modeDefault: "Default ({mode})",
889
1001
  blockModalDone: "Done",
890
1002
  crashed: "Blockscene stopped here after an error. The native editor is unaffected. If it happens again, turn Blockscene off in Settings, Blockscene.",
@@ -919,6 +1031,9 @@ var en_default = {
919
1031
  unstar: "Remove star",
920
1032
  quickInsert: "Insert {label}",
921
1033
  insert: "Insert",
1034
+ starterKits: "Start with a kit",
1035
+ starterKitsHelp: "Choose a starting structure. Everything is inserted as an unsaved, editable draft.",
1036
+ startBlank: "Start blank",
922
1037
  closeDetail: "Close details",
923
1038
  typology: "Typology",
924
1039
  typologyAuto: "Automatic ({name})",
@@ -973,6 +1088,11 @@ var en_default = {
973
1088
  confirmDeleteTitle: "Delete block",
974
1089
  confirmDelete: "Delete block {name}?",
975
1090
  confirmDeleteMarker: "This is a group marker: only the marker is removed, not the blocks inside the group, and the group stays unbalanced until it is fixed.",
1091
+ confirmDeleteGroupTitle: "Delete group",
1092
+ confirmDeleteGroup: "Delete group {name}?",
1093
+ confirmDeleteGroupHint: "This group contains {count, plural, one {# block} other {# blocks}}. Choose whether to delete them or keep them on the page without the group.",
1094
+ keepGroupBlocks: "Remove group, keep blocks",
1095
+ deleteGroupAndBlocks: "{count, plural, =0 {Delete group} one {Delete group and # block} other {Delete group and # blocks}}",
976
1096
  delete: "Delete",
977
1097
  selectBlocks: "Select blocks",
978
1098
  selectAll: "Select all",
@@ -1167,6 +1287,7 @@ var en_default = {
1167
1287
  gridCellMenu: "More actions for {label}",
1168
1288
  removeFromGroup: "Remove from group",
1169
1289
  gridAdd: "Add a block",
1290
+ groupAdd: "Add block inside {label}",
1170
1291
  gridShowList: "Show group {label} as a list",
1171
1292
  gridShowGrid: "Show group {label} as a grid",
1172
1293
  layoutColumnsField: "Layout grid: columns field",
@@ -1175,13 +1296,29 @@ var en_default = {
1175
1296
  layoutOff: "No grid",
1176
1297
  layoutNoMobile: "None",
1177
1298
  layoutHelp: "The group's blocks show as a grid in the form, with the column count this block holds.",
1178
- layoutNoFields: "This block has no field that can hold a column count."
1299
+ layoutNoFields: "This block has no field that can hold a column count.",
1300
+ "toolbar.versions": "Version history",
1301
+ versionsDenied: "Ask an administrator to grant the Blockscene Read version history permission.",
1302
+ versionsDisabled: "History is not enabled for this content type. Ask an administrator to enable it in Settings > Blockscene (settings.history.enabled).",
1303
+ versionsNew: "Save this entry first to start its history.",
1304
+ versionsPerson: "Filter by person",
1305
+ versionsEveryone: "Everyone",
1306
+ versionsCounts: "{total} blocks",
1307
+ versionsCountsMissing: "Block counts unavailable (older or unrecorded event).",
1308
+ versionsPage: "Page {page} of {count}",
1309
+ versionsPrevious: "Previous",
1310
+ versionsNext: "Next",
1311
+ versionsViewing: "Viewing version of {date} by {person} (read-only).",
1312
+ versionsCurrent: "Back to current draft",
1313
+ versionsMissing: "Some blocks, fields, media or relations are no longer available in this preview.",
1314
+ versionsBridgeLegacy: "This preview bridge does not support read-only browsing. Interaction is disabled; update the bridge to support readOnly.",
1315
+ historyExpired: "Snapshot no longer available"
1179
1316
  };
1180
1317
 
1181
1318
  // admin/translations/pt-BR.json
1182
1319
  var pt_BR_default = {
1183
1320
  title: "Blockscene",
1184
- settings: "Galeria",
1321
+ settings: "Geral",
1185
1322
  gallery: "Galeria de blocos",
1186
1323
  search: "Buscar blocos",
1187
1324
  clear: "Limpar busca",
@@ -1197,6 +1334,17 @@ var pt_BR_default = {
1197
1334
  moreActions: "Mais a\xE7\xF5es",
1198
1335
  settingsTitle: "Blockscene",
1199
1336
  settingsIntro: "Miniaturas da galeria, paleta dos wireframes e prefer\xEAncias do editor. As mudan\xE7as valem na pr\xF3xima abertura da galeria; n\xE3o \xE9 preciso rebuild.",
1337
+ settingsGeneral: "Geral",
1338
+ settingsGeneralIntro: "Defina como o Blockscene funciona no editor e quais a\xE7\xF5es ficam dispon\xEDveis nas linhas.",
1339
+ settingsPreview: "Preview da p\xE1gina",
1340
+ settingsPreviewIntro: "Conecte a preview do frontend e configure modos, barra de ferramentas e larguras responsivas.",
1341
+ settingsContentTypes: "Tipos de conte\xFAdo",
1342
+ settingsContentTypesIntro: "Escolha onde o Blockscene fica ativo e personalize o editor visual de cada tipo de conte\xFAdo.",
1343
+ settingsGallery: "Galeria de blocos",
1344
+ settingsGalleryIntro: "Configure miniaturas, cores dos wireframes, tipos e filtros da galeria.",
1345
+ settingsHistory: "Hist\xF3rico e lixeira",
1346
+ settingsHistoryIntro: "Controle vers\xF5es, reten\xE7\xE3o de atividades e exclus\xF5es recuper\xE1veis.",
1347
+ historyUnavailable: "As configura\xE7\xF5es de hist\xF3rico e lixeira exigem o Strapi 5.",
1200
1348
  palette: "Paleta dos wireframes",
1201
1349
  background: "Fundo",
1202
1350
  surface: "Superf\xEDcies",
@@ -1226,6 +1374,7 @@ var pt_BR_default = {
1226
1374
  showCloseAll: 'Mostrar "Recolher tudo"',
1227
1375
  toggleHelp: "A barra da zona mostra um \xFAnico bot\xE3o: com as duas op\xE7\xF5es ligadas, ele expande enquanto houver algum bloco recolhido e, sen\xE3o, recolhe todos; com s\xF3 uma ligada, oferece apenas essa a\xE7\xE3o.",
1228
1376
  showRowThumbnails: "Mostrar miniaturas dos blocos nas linhas",
1377
+ componentRowThumbnail: "Mostrar miniatura na linha do editor",
1229
1378
  initialState: "Estado inicial dos accordions",
1230
1379
  "states.closed": "Todos fechados",
1231
1380
  "states.open": "Todos abertos",
@@ -1233,10 +1382,10 @@ var pt_BR_default = {
1233
1382
  rememberHelp: "Somente os bot\xF5es de abrir/fechar todos atualizam a mem\xF3ria, por usu\xE1rio e navegador. Abrir um bloco isolado n\xE3o muda.",
1234
1383
  previewUrl: "URL base da rota de preview",
1235
1384
  previewUrlHelp: "URL completa da rota de preview de p\xE1gina do seu frontend, por exemplo https://site.test/block-preview/page. Vazio reutiliza a origem da Preview nativa do Strapi (quando configurada para o tipo de conte\xFAdo) com /block-preview/page. A rota precisa implementar a bridge (ver README).",
1236
- previewUrlEmpty: "Nenhuma URL de preview definida: os editores s\xF3 t\xEAm os modos Campos + p\xE1gina e Editor visual nos tipos de conte\xFAdo com o Preview nativo do Strapi configurado. Nos demais, o menu de modos n\xE3o aparece.",
1385
+ previewUrlEmpty: "Nenhuma URL de preview definida: os editores s\xF3 t\xEAm os modos Campos + preview e Editor visual nos tipos de conte\xFAdo com o Preview nativo do Strapi configurado. Nos demais, o menu de modos n\xE3o aparece.",
1237
1386
  previewMode: "Modo inicial da preview",
1238
- "modes.form": "Campos",
1239
- "modes.split": "Campos + p\xE1gina",
1387
+ "modes.form": "Somente campos",
1388
+ "modes.split": "Campos + preview",
1240
1389
  "modes.preview": "Editor visual",
1241
1390
  previewModeHelp: "Toda tela de edi\xE7\xE3o abre neste modo, a menos que o tipo de conte\xFAdo defina o seu abaixo. Quem edita pode trocar durante a edi\xE7\xE3o; a troca n\xE3o fica gravada.",
1242
1391
  lazyEdit: "Clique para editar",
@@ -1244,8 +1393,8 @@ var pt_BR_default = {
1244
1393
  lazyFields: "Campos personalizados carregados sob demanda",
1245
1394
  lazyEditorsHelp: "Os campos personalizados listados mostram uma pr\xE9via somente leitura at\xE9 receberem clique ou foco, para que p\xE1ginas grandes abram r\xE1pido. Separe os uids com v\xEDrgulas.",
1246
1395
  lazyFieldsInvalid: "Use at\xE9 {max} uids de campos personalizados, como plugin::ckeditor5.CKEditor ou global::meu-campo.",
1247
- modeForm: "Campos",
1248
- modeSplit: "Campos + p\xE1gina",
1396
+ modeForm: "Somente campos",
1397
+ modeSplit: "Campos + preview",
1249
1398
  modePreview: "Editor visual",
1250
1399
  previewPane: "Preview da p\xE1gina",
1251
1400
  resize: "Redimensionar painel de preview",
@@ -1272,6 +1421,7 @@ var pt_BR_default = {
1272
1421
  denied: "Acesso negado.",
1273
1422
  loadFailed: "N\xE3o foi poss\xEDvel carregar. Recarregue para tentar novamente.",
1274
1423
  invalidColor: "As cores devem usar #RRGGBB.",
1424
+ invalidUrl: "As URLs de preview devem ser URLs HTTP ou HTTPS completas.",
1275
1425
  previewLabel: "Pr\xE9via da paleta",
1276
1426
  removeGroup: "Remover grupo",
1277
1427
  diagTitle: "Os grupos de blocos precisam de aten\xE7\xE3o; a publica\xE7\xE3o \xE9 recusada at\xE9 a corre\xE7\xE3o:",
@@ -1306,6 +1456,7 @@ var pt_BR_default = {
1306
1456
  contentTypes: "Tipos de conte\xFAdo",
1307
1457
  contentTypesHelp: 'A galeria, os accordions e o preview da p\xE1gina funcionam nestes tipos de conte\xFAdo (os que t\xEAm uma zona din\xE2mica). Desligue um para deixar a edi\xE7\xE3o dele nativa. "Abre em" \xE9 como toda tela de edi\xE7\xE3o desse tipo come\xE7a; quem edita ainda pode trocar durante a edi\xE7\xE3o.',
1308
1458
  typeMode: "Abre em",
1459
+ typeAdvanced: "Op\xE7\xF5es do editor visual",
1309
1460
  modeDefault: "Padr\xE3o ({mode})",
1310
1461
  blockModalDone: "Concluir",
1311
1462
  crashed: "O Blockscene parou aqui por causa de um erro. O editor nativo n\xE3o foi afetado. Se acontecer de novo, desligue o Blockscene em Settings, Blockscene.",
@@ -1340,6 +1491,9 @@ var pt_BR_default = {
1340
1491
  unstar: "Remover dos favoritos",
1341
1492
  quickInsert: "Inserir {label}",
1342
1493
  insert: "Inserir",
1494
+ starterKits: "Come\xE7ar com um kit",
1495
+ starterKitsHelp: "Escolha uma estrutura inicial. Tudo \xE9 inserido como rascunho edit\xE1vel e ainda n\xE3o salvo.",
1496
+ startBlank: "Come\xE7ar em branco",
1343
1497
  closeDetail: "Fechar detalhes",
1344
1498
  typology: "Tipologia",
1345
1499
  typologyAuto: "Autom\xE1tica ({name})",
@@ -1394,6 +1548,11 @@ var pt_BR_default = {
1394
1548
  confirmDeleteTitle: "Excluir bloco",
1395
1549
  confirmDelete: "Excluir o bloco {name}?",
1396
1550
  confirmDeleteMarker: "Este \xE9 um marcador de grupo: s\xF3 o marcador \xE9 removido, n\xE3o os blocos dentro do grupo, e o grupo fica desbalanceado at\xE9 ser corrigido.",
1551
+ confirmDeleteGroupTitle: "Excluir grupo",
1552
+ confirmDeleteGroup: "Excluir o grupo {name}?",
1553
+ confirmDeleteGroupHint: "Este grupo cont\xE9m {count, plural, one {# bloco} other {# blocos}}. Escolha entre exclu\xED-los ou mant\xEA-los na p\xE1gina sem o grupo.",
1554
+ keepGroupBlocks: "Remover grupo e manter blocos",
1555
+ deleteGroupAndBlocks: "{count, plural, =0 {Excluir grupo} one {Excluir grupo e # bloco} other {Excluir grupo e # blocos}}",
1397
1556
  delete: "Excluir",
1398
1557
  selectBlocks: "Selecionar blocos",
1399
1558
  selectAll: "Selecionar todos",
@@ -1588,6 +1747,7 @@ var pt_BR_default = {
1588
1747
  gridCellMenu: "Mais a\xE7\xF5es para {label}",
1589
1748
  removeFromGroup: "Remover do grupo",
1590
1749
  gridAdd: "Adicionar bloco",
1750
+ groupAdd: "Adicionar bloco dentro de {label}",
1591
1751
  gridShowList: "Mostrar o grupo {label} como lista",
1592
1752
  gridShowGrid: "Mostrar o grupo {label} como grade",
1593
1753
  layoutColumnsField: "Grade do layout: campo das colunas",
@@ -1596,13 +1756,29 @@ var pt_BR_default = {
1596
1756
  layoutOff: "Sem grade",
1597
1757
  layoutNoMobile: "Nenhum",
1598
1758
  layoutHelp: "Os blocos do grupo aparecem em grade no formul\xE1rio, com o n\xFAmero de colunas deste bloco.",
1599
- layoutNoFields: "Este bloco n\xE3o tem campo que guarde um n\xFAmero de colunas."
1759
+ layoutNoFields: "Este bloco n\xE3o tem campo que guarde um n\xFAmero de colunas.",
1760
+ "toolbar.versions": "Hist\xF3rico de vers\xF5es",
1761
+ versionsDenied: "Pe\xE7a a um administrador a permiss\xE3o Ler hist\xF3rico de vers\xF5es do Blockscene.",
1762
+ versionsDisabled: "O hist\xF3rico n\xE3o est\xE1 ativo para este tipo de conte\xFAdo. Pe\xE7a a um administrador para ativ\xE1-lo em Settings > Blockscene (settings.history.enabled).",
1763
+ versionsNew: "Salve este conte\xFAdo primeiro para iniciar seu hist\xF3rico.",
1764
+ versionsPerson: "Filtrar por pessoa",
1765
+ versionsEveryone: "Todas as pessoas",
1766
+ versionsCounts: "{total} blocos",
1767
+ versionsCountsMissing: "Contagem de blocos indispon\xEDvel (evento antigo ou n\xE3o registrado).",
1768
+ versionsPage: "P\xE1gina {page} de {count}",
1769
+ versionsPrevious: "Anterior",
1770
+ versionsNext: "Pr\xF3xima",
1771
+ versionsViewing: "Vendo vers\xE3o de {date} por {person} (somente leitura).",
1772
+ versionsCurrent: "Voltar ao rascunho atual",
1773
+ versionsMissing: "Alguns blocos, campos, m\xEDdias ou rela\xE7\xF5es n\xE3o est\xE3o mais dispon\xEDveis nesta preview.",
1774
+ versionsBridgeLegacy: "Esta bridge n\xE3o suporta navega\xE7\xE3o somente leitura. A intera\xE7\xE3o est\xE1 desativada; atualize a bridge para suportar readOnly.",
1775
+ historyExpired: "Snapshot n\xE3o est\xE1 mais dispon\xEDvel"
1600
1776
  };
1601
1777
 
1602
1778
  // admin/translations/pt.json
1603
1779
  var pt_default = {
1604
1780
  title: "Blockscene",
1605
- settings: "Galeria",
1781
+ settings: "Geral",
1606
1782
  gallery: "Galeria de blocos",
1607
1783
  search: "Pesquisar blocos",
1608
1784
  clear: "Limpar pesquisa",
@@ -1618,6 +1794,17 @@ var pt_default = {
1618
1794
  moreActions: "Mais a\xE7\xF5es",
1619
1795
  settingsTitle: "Blockscene",
1620
1796
  settingsIntro: "Miniaturas da galeria, paleta dos wireframes e prefer\xEAncias do editor. As mudan\xE7as valem na pr\xF3xima abertura da galeria; n\xE3o \xE9 preciso rebuild.",
1797
+ settingsGeneral: "Geral",
1798
+ settingsGeneralIntro: "Defina como o Blockscene funciona no editor e quais a\xE7\xF5es ficam dispon\xEDveis nas linhas.",
1799
+ settingsPreview: "Pr\xE9-visualiza\xE7\xE3o da p\xE1gina",
1800
+ settingsPreviewIntro: "Ligue a pr\xE9-visualiza\xE7\xE3o do frontend e configure modos, barra de ferramentas e larguras responsivas.",
1801
+ settingsContentTypes: "Tipos de conte\xFAdo",
1802
+ settingsContentTypesIntro: "Escolha onde o Blockscene fica ativo e personalize o editor visual de cada tipo de conte\xFAdo.",
1803
+ settingsGallery: "Galeria de blocos",
1804
+ settingsGalleryIntro: "Configure miniaturas, cores dos wireframes, tipos e filtros da galeria.",
1805
+ settingsHistory: "Hist\xF3rico e lixo",
1806
+ settingsHistoryIntro: "Controle vers\xF5es, reten\xE7\xE3o de atividades e elimina\xE7\xF5es recuper\xE1veis.",
1807
+ historyUnavailable: "As configura\xE7\xF5es de hist\xF3rico e lixo exigem o Strapi 5.",
1621
1808
  palette: "Paleta dos wireframes",
1622
1809
  background: "Fundo",
1623
1810
  surface: "Superf\xEDcies",
@@ -1647,6 +1834,7 @@ var pt_default = {
1647
1834
  showCloseAll: 'Mostrar "Recolher tudo"',
1648
1835
  toggleHelp: "A barra da zona mostra um \xFAnico bot\xE3o: com as duas op\xE7\xF5es ativas, expande enquanto houver algum bloco recolhido e, caso contr\xE1rio, recolhe todos; com apenas uma ativa, oferece s\xF3 essa a\xE7\xE3o.",
1649
1836
  showRowThumbnails: "Mostrar miniaturas dos blocos nas linhas",
1837
+ componentRowThumbnail: "Mostrar miniatura na linha do editor",
1650
1838
  initialState: "Estado inicial dos accordions",
1651
1839
  "states.closed": "Todos fechados",
1652
1840
  "states.open": "Todos abertos",
@@ -1654,10 +1842,10 @@ var pt_default = {
1654
1842
  rememberHelp: "Somente os bot\xF5es de abrir/fechar todos atualizam a mem\xF3ria, por usu\xE1rio e navegador. Abrir um bloco isolado n\xE3o muda.",
1655
1843
  previewUrl: "URL base da rota de pr\xE9-visualiza\xE7\xE3o",
1656
1844
  previewUrlHelp: "URL completa da rota de preview de p\xE1gina do seu frontend, por exemplo https://site.test/block-preview/page. Vazio reutiliza a origem da Preview nativa do Strapi (quando configurada para o tipo de conte\xFAdo) com /block-preview/page. A rota precisa implementar a bridge (ver README).",
1657
- previewUrlEmpty: "Nenhum URL de pr\xE9-visualiza\xE7\xE3o definido: os editores s\xF3 t\xEAm os modos Campos + p\xE1gina e Editor visual nos tipos de conte\xFAdo com a Preview nativa do Strapi configurada. Nos restantes, o menu de modos n\xE3o aparece.",
1845
+ previewUrlEmpty: "Nenhum URL de pr\xE9-visualiza\xE7\xE3o definido: os editores s\xF3 t\xEAm os modos Campos + pr\xE9-visualiza\xE7\xE3o e Editor visual nos tipos de conte\xFAdo com a Preview nativa do Strapi configurada. Nos restantes, o menu de modos n\xE3o aparece.",
1658
1846
  previewMode: "Modo inicial da pr\xE9-visualiza\xE7\xE3o",
1659
- "modes.form": "Campos",
1660
- "modes.split": "Campos + p\xE1gina",
1847
+ "modes.form": "Apenas campos",
1848
+ "modes.split": "Campos + pr\xE9-visualiza\xE7\xE3o",
1661
1849
  "modes.preview": "Editor visual",
1662
1850
  previewModeHelp: "Cada ecr\xE3 de edi\xE7\xE3o abre neste modo, salvo se o tipo de conte\xFAdo definir o seu abaixo. Quem edita pode mudar durante a edi\xE7\xE3o; a mudan\xE7a n\xE3o fica guardada.",
1663
1851
  lazyEdit: "Clique para editar",
@@ -1665,8 +1853,8 @@ var pt_default = {
1665
1853
  lazyFields: "Campos personalizados carregados a pedido",
1666
1854
  lazyEditorsHelp: "Os campos personalizados indicados mostram uma pr\xE9-visualiza\xE7\xE3o s\xF3 de leitura at\xE9 receberem clique ou foco, para que p\xE1ginas grandes abram depressa. Separe os uids com v\xEDrgulas.",
1667
1855
  lazyFieldsInvalid: "Use at\xE9 {max} uids de campos personalizados, como plugin::ckeditor5.CKEditor ou global::meu-campo.",
1668
- modeForm: "Campos",
1669
- modeSplit: "Campos + p\xE1gina",
1856
+ modeForm: "Apenas campos",
1857
+ modeSplit: "Campos + pr\xE9-visualiza\xE7\xE3o",
1670
1858
  modePreview: "Editor visual",
1671
1859
  previewPane: "Pr\xE9-visualiza\xE7\xE3o da p\xE1gina",
1672
1860
  resize: "Redimensionar painel de pr\xE9-visualiza\xE7\xE3o",
@@ -1693,6 +1881,7 @@ var pt_default = {
1693
1881
  denied: "Acesso negado.",
1694
1882
  loadFailed: "N\xE3o foi poss\xEDvel carregar. Recarregue para tentar novamente.",
1695
1883
  invalidColor: "As cores devem usar #RRGGBB.",
1884
+ invalidUrl: "Os URL de pr\xE9-visualiza\xE7\xE3o devem ser endere\xE7os HTTP ou HTTPS completos.",
1696
1885
  previewLabel: "Pr\xE9-visualiza\xE7\xE3o da paleta",
1697
1886
  removeGroup: "Remover grupo",
1698
1887
  diagTitle: "Os grupos de blocos precisam de aten\xE7\xE3o; a publica\xE7\xE3o \xE9 recusada at\xE9 \xE0 corre\xE7\xE3o:",
@@ -1727,6 +1916,7 @@ var pt_default = {
1727
1916
  contentTypes: "Tipos de conte\xFAdo",
1728
1917
  contentTypesHelp: 'A galeria, os acorde\xF5es e a pr\xE9-visualiza\xE7\xE3o da p\xE1gina funcionam nestes tipos de conte\xFAdo (os que t\xEAm uma zona din\xE2mica). Desligue um para manter a edi\xE7\xE3o nativa. "Abre em" \xE9 como come\xE7a cada ecr\xE3 de edi\xE7\xE3o desse tipo; quem edita pode sempre mudar durante a edi\xE7\xE3o.',
1729
1918
  typeMode: "Abre em",
1919
+ typeAdvanced: "Op\xE7\xF5es do editor visual",
1730
1920
  modeDefault: "Predefini\xE7\xE3o ({mode})",
1731
1921
  blockModalDone: "Concluir",
1732
1922
  crashed: "O Blockscene parou aqui devido a um erro. O editor nativo n\xE3o foi afetado. Se voltar a acontecer, desligue o Blockscene em Settings, Blockscene.",
@@ -1761,6 +1951,9 @@ var pt_default = {
1761
1951
  unstar: "Remover dos favoritos",
1762
1952
  quickInsert: "Inserir {label}",
1763
1953
  insert: "Inserir",
1954
+ starterKits: "Come\xE7ar com um kit",
1955
+ starterKitsHelp: "Escolha uma estrutura inicial. Tudo \xE9 inserido como um rascunho edit\xE1vel e ainda n\xE3o guardado.",
1956
+ startBlank: "Come\xE7ar em branco",
1764
1957
  closeDetail: "Fechar detalhes",
1765
1958
  typology: "Tipologia",
1766
1959
  typologyAuto: "Autom\xE1tica ({name})",
@@ -1815,6 +2008,11 @@ var pt_default = {
1815
2008
  confirmDeleteTitle: "Eliminar bloco",
1816
2009
  confirmDelete: "Eliminar o bloco {name}?",
1817
2010
  confirmDeleteMarker: "Este \xE9 um marcador de grupo: s\xF3 o marcador \xE9 removido, n\xE3o os blocos dentro do grupo, e o grupo fica desequilibrado at\xE9 ser corrigido.",
2011
+ confirmDeleteGroupTitle: "Eliminar grupo",
2012
+ confirmDeleteGroup: "Eliminar o grupo {name}?",
2013
+ confirmDeleteGroupHint: "Este grupo cont\xE9m {count, plural, one {# bloco} other {# blocos}}. Escolha entre elimin\xE1-los ou mant\xEA-los na p\xE1gina sem o grupo.",
2014
+ keepGroupBlocks: "Eliminar grupo e manter blocos",
2015
+ deleteGroupAndBlocks: "{count, plural, =0 {Eliminar grupo} one {Eliminar grupo e # bloco} other {Eliminar grupo e # blocos}}",
1818
2016
  delete: "Eliminar",
1819
2017
  selectBlocks: "Selecionar blocos",
1820
2018
  selectAll: "Selecionar todos",
@@ -2009,6 +2207,7 @@ var pt_default = {
2009
2207
  gridCellMenu: "Mais a\xE7\xF5es para {label}",
2010
2208
  removeFromGroup: "Remover do grupo",
2011
2209
  gridAdd: "Adicionar bloco",
2210
+ groupAdd: "Adicionar bloco dentro de {label}",
2012
2211
  gridShowList: "Mostrar o grupo {label} como lista",
2013
2212
  gridShowGrid: "Mostrar o grupo {label} como grelha",
2014
2213
  layoutColumnsField: "Grelha do layout: campo das colunas",
@@ -2017,13 +2216,29 @@ var pt_default = {
2017
2216
  layoutOff: "Sem grelha",
2018
2217
  layoutNoMobile: "Nenhum",
2019
2218
  layoutHelp: "Os blocos do grupo aparecem em grelha no formul\xE1rio, com o n\xFAmero de colunas deste bloco.",
2020
- layoutNoFields: "Este bloco n\xE3o tem campo que guarde um n\xFAmero de colunas."
2219
+ layoutNoFields: "Este bloco n\xE3o tem campo que guarde um n\xFAmero de colunas.",
2220
+ "toolbar.versions": "Hist\xF3rico de vers\xF5es",
2221
+ versionsDenied: "Pe\xE7a a um administrador a permiss\xE3o Ler hist\xF3rico de vers\xF5es do Blockscene.",
2222
+ versionsDisabled: "O hist\xF3rico n\xE3o est\xE1 ativo para este tipo de conte\xFAdo. Pe\xE7a a um administrador para o ativar em Settings > Blockscene (settings.history.enabled).",
2223
+ versionsNew: "Guarde este conte\xFAdo primeiro para iniciar o hist\xF3rico.",
2224
+ versionsPerson: "Filtrar por pessoa",
2225
+ versionsEveryone: "Todas as pessoas",
2226
+ versionsCounts: "{total} blocos",
2227
+ versionsCountsMissing: "Contagem de blocos indispon\xEDvel (evento antigo ou n\xE3o registado).",
2228
+ versionsPage: "P\xE1gina {page} de {count}",
2229
+ versionsPrevious: "Anterior",
2230
+ versionsNext: "Seguinte",
2231
+ versionsViewing: "A ver a vers\xE3o de {date} por {person} (s\xF3 de leitura).",
2232
+ versionsCurrent: "Voltar ao rascunho atual",
2233
+ versionsMissing: "Alguns blocos, campos, ficheiros ou rela\xE7\xF5es j\xE1 n\xE3o est\xE3o dispon\xEDveis nesta pr\xE9via.",
2234
+ versionsBridgeLegacy: "Esta bridge n\xE3o suporta navega\xE7\xE3o s\xF3 de leitura. A intera\xE7\xE3o est\xE1 desativada; atualize a bridge para suportar readOnly.",
2235
+ historyExpired: "Snapshot j\xE1 n\xE3o est\xE1 dispon\xEDvel"
2021
2236
  };
2022
2237
 
2023
2238
  // admin/translations/fr.json
2024
2239
  var fr_default = {
2025
2240
  title: "Blockscene",
2026
- settings: "Galerie",
2241
+ settings: "G\xE9n\xE9ral",
2027
2242
  gallery: "Galerie de blocs",
2028
2243
  search: "Rechercher des blocs",
2029
2244
  clear: "Effacer la recherche",
@@ -2039,6 +2254,17 @@ var fr_default = {
2039
2254
  moreActions: "Plus d'actions",
2040
2255
  settingsTitle: "Blockscene",
2041
2256
  settingsIntro: "Vignettes de la galerie, palette des wireframes et pr\xE9f\xE9rences de l'\xE9diteur. Les changements s'appliquent \xE0 la prochaine ouverture de la galerie ; aucun rebuild n'est n\xE9cessaire.",
2257
+ settingsGeneral: "G\xE9n\xE9ral",
2258
+ settingsGeneralIntro: "D\xE9finissez le comportement de Blockscene dans l'\xE9diteur et les actions disponibles sur les lignes.",
2259
+ settingsPreview: "Aper\xE7u de page",
2260
+ settingsPreviewIntro: "Connectez l'aper\xE7u du frontend et configurez ses modes, sa barre d'outils et ses largeurs responsives.",
2261
+ settingsContentTypes: "Types de contenu",
2262
+ settingsContentTypesIntro: "Choisissez o\xF9 Blockscene est actif et personnalisez l'\xE9diteur visuel pour chaque type de contenu.",
2263
+ settingsGallery: "Galerie de blocs",
2264
+ settingsGalleryIntro: "Configurez les vignettes, les couleurs des wireframes, les types et les filtres de la galerie.",
2265
+ settingsHistory: "Historique et corbeille",
2266
+ settingsHistoryIntro: "G\xE9rez les versions, la conservation des activit\xE9s et les suppressions r\xE9cup\xE9rables.",
2267
+ historyUnavailable: "Les r\xE9glages d'historique et de corbeille n\xE9cessitent Strapi 5.",
2042
2268
  palette: "Palette des wireframes",
2043
2269
  background: "Fond",
2044
2270
  surface: "Surfaces",
@@ -2068,6 +2294,7 @@ var fr_default = {
2068
2294
  showCloseAll: "Afficher \xAB Tout replier \xBB",
2069
2295
  toggleHelp: "La barre de la zone affiche un seul bouton : avec les deux options activ\xE9es, il d\xE9plie tant qu'un bloc est repli\xE9 et sinon les replie tous ; avec une seule, il ne propose que cette action.",
2070
2296
  showRowThumbnails: "Afficher les miniatures des blocs dans les lignes",
2297
+ componentRowThumbnail: "Afficher la miniature dans la ligne de l'\xE9diteur",
2071
2298
  initialState: "\xC9tat initial des accord\xE9ons",
2072
2299
  "states.closed": "Tous ferm\xE9s",
2073
2300
  "states.open": "Tous ouverts",
@@ -2075,10 +2302,10 @@ var fr_default = {
2075
2302
  rememberHelp: "Seuls les boutons explicites tout ouvrir / tout fermer mettent la m\xE9moire \xE0 jour, par utilisateur et navigateur. Ouvrir un seul bloc ne change rien.",
2076
2303
  previewUrl: "URL de base de la route d'aper\xE7u",
2077
2304
  previewUrlHelp: "URL compl\xE8te de la route d'aper\xE7u de page de votre frontend, par ex. https://site.test/block-preview/page. Laissez vide pour r\xE9utiliser l'origine de l'aper\xE7u natif de Strapi (s'il est configur\xE9 pour le type de contenu) avec /block-preview/page. La route doit impl\xE9menter le pont (voir README).",
2078
- previewUrlEmpty: "Aucune URL d'aper\xE7u : les \xE9diteurs n'ont les modes Champs + page et \xC9diteur visuel que sur les types de contenu o\xF9 l'aper\xE7u natif de Strapi est configur\xE9. Ailleurs, le menu des modes n'appara\xEEt pas.",
2305
+ previewUrlEmpty: "Aucune URL d'aper\xE7u : les \xE9diteurs n'ont les modes Champs + aper\xE7u et \xC9diteur visuel que sur les types de contenu o\xF9 l'aper\xE7u natif de Strapi est configur\xE9. Ailleurs, le menu des modes n'appara\xEEt pas.",
2079
2306
  previewMode: "Mode d'aper\xE7u initial",
2080
- "modes.form": "Champs",
2081
- "modes.split": "Champs + page",
2307
+ "modes.form": "Champs uniquement",
2308
+ "modes.split": "Champs + aper\xE7u",
2082
2309
  "modes.preview": "\xC9diteur visuel",
2083
2310
  previewModeHelp: "Chaque vue d'\xE9dition s'ouvre dans ce mode, sauf si son type de contenu d\xE9finit le sien ci-dessous. L'\xE9diteur peut changer pendant l'\xE9dition ; ce choix n'est pas m\xE9moris\xE9.",
2084
2311
  lazyEdit: "Cliquer pour modifier",
@@ -2086,8 +2313,8 @@ var fr_default = {
2086
2313
  lazyFields: "Champs personnalis\xE9s charg\xE9s \xE0 la demande",
2087
2314
  lazyEditorsHelp: "Les champs personnalis\xE9s list\xE9s affichent un aper\xE7u en lecture seule jusqu'au clic ou au focus, pour que les grandes pages s'ouvrent vite. S\xE9parez les uids par des virgules.",
2088
2315
  lazyFieldsInvalid: "Utilisez jusqu'\xE0 {max} uids de champs personnalis\xE9s, comme plugin::ckeditor5.CKEditor ou global::mon-champ.",
2089
- modeForm: "Champs",
2090
- modeSplit: "Champs + page",
2316
+ modeForm: "Champs uniquement",
2317
+ modeSplit: "Champs + aper\xE7u",
2091
2318
  modePreview: "\xC9diteur visuel",
2092
2319
  previewPane: "Aper\xE7u de la page",
2093
2320
  resize: "Redimensionner le panneau d'aper\xE7u",
@@ -2114,6 +2341,7 @@ var fr_default = {
2114
2341
  denied: "Acc\xE8s refus\xE9.",
2115
2342
  loadFailed: "Impossible de charger les param\xE8tres. Rechargez pour r\xE9essayer.",
2116
2343
  invalidColor: "Les couleurs doivent utiliser #RRGGBB.",
2344
+ invalidUrl: "Les URL d'aper\xE7u doivent \xEAtre des adresses HTTP ou HTTPS compl\xE8tes.",
2117
2345
  previewLabel: "Aper\xE7u de la palette",
2118
2346
  removeGroup: "Supprimer le groupe",
2119
2347
  diagTitle: "Les groupes de blocs demandent une correction ; la publication est refus\xE9e tant qu'ils ne sont pas corrig\xE9s :",
@@ -2148,6 +2376,7 @@ var fr_default = {
2148
2376
  contentTypes: "Types de contenu",
2149
2377
  contentTypesHelp: "La galerie, les accord\xE9ons et l'aper\xE7u de page fonctionnent sur ces types de contenu (ceux qui ont une Dynamic Zone). D\xE9sactivez-en un pour garder son \xE9dition native. \xAB S'ouvre en \xBB d\xE9finit le mode de d\xE9part de chaque vue d'\xE9dition de ce type ; l'\xE9diteur peut toujours changer pendant l'\xE9dition.",
2150
2378
  typeMode: "S'ouvre en",
2379
+ typeAdvanced: "Options de l'\xE9diteur visuel",
2151
2380
  modeDefault: "Par d\xE9faut ({mode})",
2152
2381
  blockModalDone: "Termin\xE9",
2153
2382
  crashed: "Blockscene s'est arr\xEAt\xE9 ici \xE0 cause d'une erreur. L'\xE9diteur natif n'est pas touch\xE9. Si cela se reproduit, d\xE9sactivez Blockscene dans Settings, Blockscene.",
@@ -2182,6 +2411,9 @@ var fr_default = {
2182
2411
  unstar: "Retirer des favoris",
2183
2412
  quickInsert: "Ins\xE9rer {label}",
2184
2413
  insert: "Ins\xE9rer",
2414
+ starterKits: "D\xE9marrer avec un kit",
2415
+ starterKitsHelp: "Choisissez une structure de d\xE9part. Tout est ins\xE9r\xE9 comme brouillon modifiable et non enregistr\xE9.",
2416
+ startBlank: "Commencer vide",
2185
2417
  closeDetail: "Fermer les d\xE9tails",
2186
2418
  typology: "Typologie",
2187
2419
  typologyAuto: "Automatique ({name})",
@@ -2236,6 +2468,11 @@ var fr_default = {
2236
2468
  confirmDeleteTitle: "Supprimer le bloc",
2237
2469
  confirmDelete: "Supprimer le bloc {name} ?",
2238
2470
  confirmDeleteMarker: "C'est un marqueur de groupe : seul le marqueur est supprim\xE9, pas les blocs du groupe, et le groupe reste d\xE9s\xE9quilibr\xE9 jusqu'\xE0 sa correction.",
2471
+ confirmDeleteGroupTitle: "Supprimer le groupe",
2472
+ confirmDeleteGroup: "Supprimer le groupe {name} ?",
2473
+ confirmDeleteGroupHint: "Ce groupe contient {count, plural, one {# bloc} other {# blocs}}. Choisissez de les supprimer ou de les conserver dans la page sans le groupe.",
2474
+ keepGroupBlocks: "Supprimer le groupe, conserver les blocs",
2475
+ deleteGroupAndBlocks: "{count, plural, =0 {Supprimer le groupe} one {Supprimer le groupe et # bloc} other {Supprimer le groupe et # blocs}}",
2239
2476
  delete: "Supprimer",
2240
2477
  selectBlocks: "S\xE9lectionner des blocs",
2241
2478
  selectAll: "Tout s\xE9lectionner",
@@ -2430,6 +2667,7 @@ var fr_default = {
2430
2667
  gridCellMenu: "Plus d'actions pour {label}",
2431
2668
  removeFromGroup: "Retirer du groupe",
2432
2669
  gridAdd: "Ajouter un bloc",
2670
+ groupAdd: "Ajouter un bloc dans {label}",
2433
2671
  gridShowList: "Afficher le groupe {label} en liste",
2434
2672
  gridShowGrid: "Afficher le groupe {label} en grille",
2435
2673
  layoutColumnsField: "Grille de mise en page : champ des colonnes",
@@ -2438,13 +2676,29 @@ var fr_default = {
2438
2676
  layoutOff: "Pas de grille",
2439
2677
  layoutNoMobile: "Aucun",
2440
2678
  layoutHelp: "Les blocs du groupe s'affichent en grille dans le formulaire, avec le nombre de colonnes de ce bloc.",
2441
- layoutNoFields: "Ce bloc n'a aucun champ pouvant contenir un nombre de colonnes."
2679
+ layoutNoFields: "Ce bloc n'a aucun champ pouvant contenir un nombre de colonnes.",
2680
+ "toolbar.versions": "Historique des versions",
2681
+ versionsDenied: "Demandez \xE0 un administrateur la permission Lire l\u2019historique des versions de Blockscene.",
2682
+ versionsDisabled: "L\u2019historique n\u2019est pas activ\xE9 pour ce type de contenu. Demandez \xE0 un administrateur de l\u2019activer dans Settings > Blockscene (settings.history.enabled).",
2683
+ versionsNew: "Enregistrez d\u2019abord ce contenu pour commencer son historique.",
2684
+ versionsPerson: "Filtrer par personne",
2685
+ versionsEveryone: "Tout le monde",
2686
+ versionsCounts: "{total} blocs",
2687
+ versionsCountsMissing: "Nombre de blocs indisponible (\xE9v\xE9nement ancien ou non enregistr\xE9).",
2688
+ versionsPage: "Page {page} sur {count}",
2689
+ versionsPrevious: "Pr\xE9c\xE9dente",
2690
+ versionsNext: "Suivante",
2691
+ versionsViewing: "Version du {date} par {person} (lecture seule).",
2692
+ versionsCurrent: "Revenir au brouillon actuel",
2693
+ versionsMissing: "Certains blocs, champs, m\xE9dias ou relations ne sont plus disponibles dans cet aper\xE7u.",
2694
+ versionsBridgeLegacy: "Cette bridge ne prend pas en charge la navigation en lecture seule. L\u2019interaction est d\xE9sactiv\xE9e ; mettez la bridge \xE0 jour pour prendre en charge readOnly.",
2695
+ historyExpired: "Snapshot indisponible"
2442
2696
  };
2443
2697
 
2444
2698
  // admin/translations/es.json
2445
2699
  var es_default = {
2446
2700
  title: "Blockscene",
2447
- settings: "Galer\xEDa",
2701
+ settings: "General",
2448
2702
  gallery: "Galer\xEDa de bloques",
2449
2703
  search: "Buscar bloques",
2450
2704
  clear: "Borrar b\xFAsqueda",
@@ -2460,6 +2714,17 @@ var es_default = {
2460
2714
  moreActions: "M\xE1s acciones",
2461
2715
  settingsTitle: "Blockscene",
2462
2716
  settingsIntro: "Miniaturas de la galer\xEDa, paleta de los wireframes y preferencias del editor. Los cambios se aplican la pr\xF3xima vez que se abra la galer\xEDa; no hace falta rebuild.",
2717
+ settingsGeneral: "General",
2718
+ settingsGeneralIntro: "Define c\xF3mo funciona Blockscene en el editor y qu\xE9 acciones est\xE1n disponibles en las filas.",
2719
+ settingsPreview: "Vista previa de p\xE1gina",
2720
+ settingsPreviewIntro: "Conecta la vista previa del frontend y configura sus modos, barra de herramientas y anchos adaptables.",
2721
+ settingsContentTypes: "Tipos de contenido",
2722
+ settingsContentTypesIntro: "Elige d\xF3nde se activa Blockscene y personaliza el editor visual de cada tipo de contenido.",
2723
+ settingsGallery: "Galer\xEDa de bloques",
2724
+ settingsGalleryIntro: "Configura miniaturas, colores de wireframes, tipos y filtros de la galer\xEDa.",
2725
+ settingsHistory: "Historial y papelera",
2726
+ settingsHistoryIntro: "Controla versiones, retenci\xF3n de actividad y eliminaciones recuperables.",
2727
+ historyUnavailable: "La configuraci\xF3n de historial y papelera requiere Strapi 5.",
2463
2728
  palette: "Paleta de wireframes",
2464
2729
  background: "Fondo",
2465
2730
  surface: "Superficies",
@@ -2489,6 +2754,7 @@ var es_default = {
2489
2754
  showCloseAll: "Mostrar \xABContraer todo\xBB",
2490
2755
  toggleHelp: "La barra de la zona muestra un solo bot\xF3n: con ambas opciones activadas expande mientras haya alg\xFAn bloque contra\xEDdo y, si no, los contrae todos; con solo una, ofrece \xFAnicamente esa acci\xF3n.",
2491
2756
  showRowThumbnails: "Mostrar miniaturas de los bloques en las filas",
2757
+ componentRowThumbnail: "Mostrar miniatura en la fila del editor",
2492
2758
  initialState: "Estado inicial de los acordeones",
2493
2759
  "states.closed": "Todos cerrados",
2494
2760
  "states.open": "Todos abiertos",
@@ -2496,10 +2762,10 @@ var es_default = {
2496
2762
  rememberHelp: "Solo los botones expl\xEDcitos de abrir/cerrar todos actualizan la memoria, por usuario y navegador. Abrir un solo bloque no la cambia.",
2497
2763
  previewUrl: "URL base de la ruta de vista previa",
2498
2764
  previewUrlHelp: "URL completa de la ruta de vista previa de p\xE1gina de su frontend, p. ej. https://site.test/block-preview/page. D\xE9jela vac\xEDa para reutilizar el origen de la Vista previa nativa de Strapi (si est\xE1 configurada para el tipo de contenido) con /block-preview/page. La ruta debe implementar el puente (ver README).",
2499
- previewUrlEmpty: "No hay URL de vista previa: los editores solo tienen los modos Campos + p\xE1gina y Editor visual en los tipos de contenido con la vista previa nativa de Strapi configurada. En los dem\xE1s no aparece el men\xFA de modos.",
2765
+ previewUrlEmpty: "No hay URL de vista previa: los editores solo tienen los modos Campos + vista previa y Editor visual en los tipos de contenido con la vista previa nativa de Strapi configurada. En los dem\xE1s no aparece el men\xFA de modos.",
2500
2766
  previewMode: "Modo inicial de la vista previa",
2501
- "modes.form": "Campos",
2502
- "modes.split": "Campos + p\xE1gina",
2767
+ "modes.form": "Solo campos",
2768
+ "modes.split": "Campos + vista previa",
2503
2769
  "modes.preview": "Editor visual",
2504
2770
  previewModeHelp: "Cada vista de edici\xF3n se abre en este modo, salvo que su tipo de contenido defina el suyo abajo. Quien edita puede cambiarlo mientras edita; el cambio no se recuerda.",
2505
2771
  lazyEdit: "Haz clic para editar",
@@ -2507,8 +2773,8 @@ var es_default = {
2507
2773
  lazyFields: "Campos personalizados cargados bajo demanda",
2508
2774
  lazyEditorsHelp: "Los campos personalizados de la lista muestran una vista previa de solo lectura hasta recibir un clic o el foco, para que las p\xE1ginas grandes abran r\xE1pido. Separa los uids con comas.",
2509
2775
  lazyFieldsInvalid: "Usa hasta {max} uids de campos personalizados, como plugin::ckeditor5.CKEditor o global::mi-campo.",
2510
- modeForm: "Campos",
2511
- modeSplit: "Campos + p\xE1gina",
2776
+ modeForm: "Solo campos",
2777
+ modeSplit: "Campos + vista previa",
2512
2778
  modePreview: "Editor visual",
2513
2779
  previewPane: "Vista previa de la p\xE1gina",
2514
2780
  resize: "Redimensionar el panel de vista previa",
@@ -2535,6 +2801,7 @@ var es_default = {
2535
2801
  denied: "Acceso denegado.",
2536
2802
  loadFailed: "No se pudieron cargar los ajustes. Recargue para reintentar.",
2537
2803
  invalidColor: "Los colores deben usar #RRGGBB.",
2804
+ invalidUrl: "Las URL de vista previa deben ser direcciones HTTP o HTTPS completas.",
2538
2805
  previewLabel: "Vista previa de la paleta",
2539
2806
  removeGroup: "Eliminar grupo",
2540
2807
  diagTitle: "Los grupos de bloques necesitan atenci\xF3n; la publicaci\xF3n se rechaza hasta corregirlos:",
@@ -2569,6 +2836,7 @@ var es_default = {
2569
2836
  contentTypes: "Tipos de contenido",
2570
2837
  contentTypesHelp: 'La galer\xEDa, los acordeones y la vista previa de p\xE1gina funcionan en estos tipos de contenido (los que tienen una Dynamic Zone). Desactiva uno para dejar su edici\xF3n nativa. "Se abre en" define c\xF3mo empieza cada vista de edici\xF3n de ese tipo; quien edita puede cambiarlo mientras edita.',
2571
2838
  typeMode: "Se abre en",
2839
+ typeAdvanced: "Opciones del editor visual",
2572
2840
  modeDefault: "Predeterminado ({mode})",
2573
2841
  blockModalDone: "Listo",
2574
2842
  crashed: "Blockscene se detuvo aqu\xED por un error. El editor nativo no se ve afectado. Si vuelve a pasar, desactiva Blockscene en Settings, Blockscene.",
@@ -2603,6 +2871,9 @@ var es_default = {
2603
2871
  unstar: "Quitar de favoritos",
2604
2872
  quickInsert: "Insertar {label}",
2605
2873
  insert: "Insertar",
2874
+ starterKits: "Comenzar con un kit",
2875
+ starterKitsHelp: "Elige una estructura inicial. Todo se inserta como un borrador editable y sin guardar.",
2876
+ startBlank: "Comenzar en blanco",
2606
2877
  closeDetail: "Cerrar detalles",
2607
2878
  typology: "Tipolog\xEDa",
2608
2879
  typologyAuto: "Autom\xE1tica ({name})",
@@ -2657,6 +2928,11 @@ var es_default = {
2657
2928
  confirmDeleteTitle: "Eliminar bloque",
2658
2929
  confirmDelete: "\xBFEliminar el bloque {name}?",
2659
2930
  confirmDeleteMarker: "Es un marcador de grupo: solo se elimina el marcador, no los bloques del grupo, y el grupo queda desequilibrado hasta corregirlo.",
2931
+ confirmDeleteGroupTitle: "Eliminar grupo",
2932
+ confirmDeleteGroup: "\xBFEliminar el grupo {name}?",
2933
+ confirmDeleteGroupHint: "Este grupo contiene {count, plural, one {# bloque} other {# bloques}}. Elige si eliminarlos o conservarlos en la p\xE1gina sin el grupo.",
2934
+ keepGroupBlocks: "Eliminar grupo y conservar bloques",
2935
+ deleteGroupAndBlocks: "{count, plural, =0 {Eliminar grupo} one {Eliminar grupo y # bloque} other {Eliminar grupo y # bloques}}",
2660
2936
  delete: "Eliminar",
2661
2937
  selectBlocks: "Seleccionar bloques",
2662
2938
  selectAll: "Seleccionar todos",
@@ -2851,6 +3127,7 @@ var es_default = {
2851
3127
  gridCellMenu: "M\xE1s acciones para {label}",
2852
3128
  removeFromGroup: "Quitar del grupo",
2853
3129
  gridAdd: "A\xF1adir un bloque",
3130
+ groupAdd: "A\xF1adir un bloque dentro de {label}",
2854
3131
  gridShowList: "Mostrar el grupo {label} como lista",
2855
3132
  gridShowGrid: "Mostrar el grupo {label} como cuadr\xEDcula",
2856
3133
  layoutColumnsField: "Cuadr\xEDcula de dise\xF1o: campo de columnas",
@@ -2859,13 +3136,29 @@ var es_default = {
2859
3136
  layoutOff: "Sin cuadr\xEDcula",
2860
3137
  layoutNoMobile: "Ninguno",
2861
3138
  layoutHelp: "Los bloques del grupo se muestran en cuadr\xEDcula en el formulario, con el n\xFAmero de columnas de este bloque.",
2862
- layoutNoFields: "Este bloque no tiene ning\xFAn campo que pueda guardar un n\xFAmero de columnas."
3139
+ layoutNoFields: "Este bloque no tiene ning\xFAn campo que pueda guardar un n\xFAmero de columnas.",
3140
+ "toolbar.versions": "Historial de versiones",
3141
+ versionsDenied: "Pide a un administrador el permiso Leer historial de versiones de Blockscene.",
3142
+ versionsDisabled: "El historial no est\xE1 activo para este tipo de contenido. Pide a un administrador que lo active en Settings > Blockscene (settings.history.enabled).",
3143
+ versionsNew: "Guarda primero este contenido para iniciar su historial.",
3144
+ versionsPerson: "Filtrar por persona",
3145
+ versionsEveryone: "Todas las personas",
3146
+ versionsCounts: "{total} bloques",
3147
+ versionsCountsMissing: "Recuento de bloques no disponible (evento antiguo o no registrado).",
3148
+ versionsPage: "P\xE1gina {page} de {count}",
3149
+ versionsPrevious: "Anterior",
3150
+ versionsNext: "Siguiente",
3151
+ versionsViewing: "Viendo la versi\xF3n del {date} por {person} (solo lectura).",
3152
+ versionsCurrent: "Volver al borrador actual",
3153
+ versionsMissing: "Algunos bloques, campos, archivos o relaciones ya no est\xE1n disponibles en esta vista previa.",
3154
+ versionsBridgeLegacy: "Esta bridge no admite navegaci\xF3n de solo lectura. La interacci\xF3n est\xE1 desactivada; actualiza la bridge para admitir readOnly.",
3155
+ historyExpired: "Snapshot ya no disponible"
2863
3156
  };
2864
3157
 
2865
3158
  // admin/translations/de.json
2866
3159
  var de_default = {
2867
3160
  title: "Blockscene",
2868
- settings: "Galerie",
3161
+ settings: "Allgemein",
2869
3162
  gallery: "Blockgalerie",
2870
3163
  search: "Bl\xF6cke suchen",
2871
3164
  clear: "Suche l\xF6schen",
@@ -2881,6 +3174,17 @@ var de_default = {
2881
3174
  moreActions: "Weitere Aktionen",
2882
3175
  settingsTitle: "Blockscene",
2883
3176
  settingsIntro: "Galerie-Vorschaubilder, Wireframe-Palette und Editor-Einstellungen. \xC4nderungen gelten beim n\xE4chsten \xD6ffnen der Galerie; kein Rebuild n\xF6tig.",
3177
+ settingsGeneral: "Allgemein",
3178
+ settingsGeneralIntro: "Lege fest, wie Blockscene im Editor arbeitet und welche Zeilenaktionen verf\xFCgbar sind.",
3179
+ settingsPreview: "Seitenvorschau",
3180
+ settingsPreviewIntro: "Verbinde die Frontend-Vorschau und konfiguriere Modi, Werkzeugleiste und responsive Breiten.",
3181
+ settingsContentTypes: "Inhaltstypen",
3182
+ settingsContentTypesIntro: "W\xE4hle, wo Blockscene aktiv ist, und passe den visuellen Editor je Inhaltstyp an.",
3183
+ settingsGallery: "Blockgalerie",
3184
+ settingsGalleryIntro: "Konfiguriere Vorschaubilder, Wireframe-Farben, Blocktypen und Filter.",
3185
+ settingsHistory: "Verlauf und Papierkorb",
3186
+ settingsHistoryIntro: "Steuere Versionen, Aufbewahrung von Aktivit\xE4ten und wiederherstellbare L\xF6schungen.",
3187
+ historyUnavailable: "Verlauf und Papierkorb erfordern Strapi 5.",
2884
3188
  palette: "Wireframe-Palette",
2885
3189
  background: "Hintergrund",
2886
3190
  surface: "Fl\xE4chen",
@@ -2910,6 +3214,7 @@ var de_default = {
2910
3214
  showCloseAll: "\u201EAlle zuklappen\u201C anzeigen",
2911
3215
  toggleHelp: "Die Zonenleiste zeigt einen einzigen Button: Sind beide Optionen an, klappt er auf, solange ein Block zugeklappt ist, sonst klappt er alle zu; ist nur eine an, bietet er nur diese Aktion.",
2912
3216
  showRowThumbnails: "Blockvorschaubilder in den Zeilen anzeigen",
3217
+ componentRowThumbnail: "Vorschaubild in der Editorzeile anzeigen",
2913
3218
  initialState: "Anfangszustand der Akkordeons",
2914
3219
  "states.closed": "Alle geschlossen",
2915
3220
  "states.open": "Alle ge\xF6ffnet",
@@ -2917,10 +3222,10 @@ var de_default = {
2917
3222
  rememberHelp: "Nur die expliziten Schaltfl\xE4chen \u201Ealle \xF6ffnen/schlie\xDFen\u201C aktualisieren die Erinnerung, pro Benutzer und Browser. Das \xD6ffnen eines einzelnen Blocks \xE4ndert nichts.",
2918
3223
  previewUrl: "Basis-URL der Vorschauroute",
2919
3224
  previewUrlHelp: "Vollst\xE4ndige URL der Seitenvorschau-Route Ihres Frontends, z. B. https://site.test/block-preview/page. Leer lassen, um den Ursprung der nativen Strapi-Vorschau (wenn f\xFCr den Inhaltstyp konfiguriert) mit /block-preview/page zu verwenden. Die Route muss die Bridge implementieren (siehe README).",
2920
- previewUrlEmpty: "Keine Vorschau-URL gesetzt: Redakteure erhalten die Modi Felder + Seite und Visueller Editor nur bei Inhaltstypen, f\xFCr die Strapis native Vorschau konfiguriert ist. Sonst wird das Modusmen\xFC nicht angezeigt.",
3225
+ previewUrlEmpty: "Keine Vorschau-URL gesetzt: Redakteure erhalten die Modi Felder + Vorschau und Visueller Editor nur bei Inhaltstypen, f\xFCr die Strapis native Vorschau konfiguriert ist. Sonst wird das Modusmen\xFC nicht angezeigt.",
2921
3226
  previewMode: "Anf\xE4nglicher Vorschaumodus",
2922
- "modes.form": "Felder",
2923
- "modes.split": "Felder + Seite",
3227
+ "modes.form": "Nur Felder",
3228
+ "modes.split": "Felder + Vorschau",
2924
3229
  "modes.preview": "Visueller Editor",
2925
3230
  previewModeHelp: "Jede Bearbeitungsansicht \xF6ffnet in diesem Modus, au\xDFer ihr Inhaltstyp legt unten einen eigenen fest. Beim Bearbeiten l\xE4sst sich wechseln; der Wechsel wird nicht gespeichert.",
2926
3231
  lazyEdit: "Zum Bearbeiten klicken",
@@ -2928,8 +3233,8 @@ var de_default = {
2928
3233
  lazyFields: "Bei Bedarf geladene benutzerdefinierte Felder",
2929
3234
  lazyEditorsHelp: "Die aufgef\xFChrten benutzerdefinierten Felder zeigen eine schreibgesch\xFCtzte Vorschau, bis sie angeklickt oder fokussiert werden, damit gro\xDFe Seiten schnell \xF6ffnen. Uids durch Kommas trennen.",
2930
3235
  lazyFieldsInvalid: "Bis zu {max} Uids benutzerdefinierter Felder verwenden, z. B. plugin::ckeditor5.CKEditor oder global::mein-feld.",
2931
- modeForm: "Felder",
2932
- modeSplit: "Felder + Seite",
3236
+ modeForm: "Nur Felder",
3237
+ modeSplit: "Felder + Vorschau",
2933
3238
  modePreview: "Visueller Editor",
2934
3239
  previewPane: "Seitenvorschau",
2935
3240
  resize: "Vorschaubereich anpassen",
@@ -2956,6 +3261,7 @@ var de_default = {
2956
3261
  denied: "Zugriff verweigert.",
2957
3262
  loadFailed: "Einstellungen konnten nicht geladen werden. Neu laden, um es erneut zu versuchen.",
2958
3263
  invalidColor: "Farben m\xFCssen #RRGGBB verwenden.",
3264
+ invalidUrl: "Vorschau-URLs m\xFCssen vollst\xE4ndige HTTP- oder HTTPS-Adressen sein.",
2959
3265
  previewLabel: "Palettenvorschau",
2960
3266
  removeGroup: "Gruppe entfernen",
2961
3267
  diagTitle: "Blockgruppen m\xFCssen korrigiert werden; das Ver\xF6ffentlichen wird bis dahin abgelehnt:",
@@ -2990,6 +3296,7 @@ var de_default = {
2990
3296
  contentTypes: "Inhaltstypen",
2991
3297
  contentTypesHelp: "Galerie, Akkordeons und Seitenvorschau arbeiten auf diesen Inhaltstypen (denen mit einer Dynamic Zone). Schalte einen aus, um seine Bearbeitung nativ zu lassen. \u201E\xD6ffnet in\u201C bestimmt, wie jede Bearbeitungsansicht dieses Typs startet; beim Bearbeiten l\xE4sst sich weiter wechseln.",
2992
3298
  typeMode: "\xD6ffnet in",
3299
+ typeAdvanced: "Optionen des visuellen Editors",
2993
3300
  modeDefault: "Standard ({mode})",
2994
3301
  blockModalDone: "Fertig",
2995
3302
  crashed: "Blockscene wurde hier wegen eines Fehlers beendet. Der native Editor ist nicht betroffen. Passiert es erneut, schalte Blockscene unter Settings, Blockscene aus.",
@@ -3024,6 +3331,9 @@ var de_default = {
3024
3331
  unstar: "Aus Favoriten entfernen",
3025
3332
  quickInsert: "{label} einf\xFCgen",
3026
3333
  insert: "Einf\xFCgen",
3334
+ starterKits: "Mit einem Kit starten",
3335
+ starterKitsHelp: "W\xE4hlen Sie eine Ausgangsstruktur. Alles wird als ungespeicherter, bearbeitbarer Entwurf eingef\xFCgt.",
3336
+ startBlank: "Leer beginnen",
3027
3337
  closeDetail: "Details schlie\xDFen",
3028
3338
  typology: "Typologie",
3029
3339
  typologyAuto: "Automatisch ({name})",
@@ -3078,6 +3388,11 @@ var de_default = {
3078
3388
  confirmDeleteTitle: "Block l\xF6schen",
3079
3389
  confirmDelete: "Block {name} l\xF6schen?",
3080
3390
  confirmDeleteMarker: "Dies ist eine Gruppenmarkierung: Nur die Markierung wird entfernt, nicht die Bl\xF6cke der Gruppe, und die Gruppe bleibt unausgeglichen, bis sie korrigiert ist.",
3391
+ confirmDeleteGroupTitle: "Gruppe l\xF6schen",
3392
+ confirmDeleteGroup: "Gruppe {name} l\xF6schen?",
3393
+ confirmDeleteGroupHint: "Diese Gruppe enth\xE4lt {count, plural, one {# Block} other {# Bl\xF6cke}}. L\xF6schen Sie sie oder behalten Sie sie ohne die Gruppe auf der Seite.",
3394
+ keepGroupBlocks: "Gruppe entfernen, Bl\xF6cke behalten",
3395
+ deleteGroupAndBlocks: "{count, plural, =0 {Gruppe l\xF6schen} one {Gruppe und # Block l\xF6schen} other {Gruppe und # Bl\xF6cke l\xF6schen}}",
3081
3396
  delete: "L\xF6schen",
3082
3397
  selectBlocks: "Bl\xF6cke ausw\xE4hlen",
3083
3398
  selectAll: "Alle ausw\xE4hlen",
@@ -3272,6 +3587,7 @@ var de_default = {
3272
3587
  gridCellMenu: "Weitere Aktionen f\xFCr {label}",
3273
3588
  removeFromGroup: "Aus der Gruppe entfernen",
3274
3589
  gridAdd: "Block hinzuf\xFCgen",
3590
+ groupAdd: "Block in {label} hinzuf\xFCgen",
3275
3591
  gridShowList: "Gruppe {label} als Liste anzeigen",
3276
3592
  gridShowGrid: "Gruppe {label} als Raster anzeigen",
3277
3593
  layoutColumnsField: "Layout-Raster: Feld der Spalten",
@@ -3280,13 +3596,29 @@ var de_default = {
3280
3596
  layoutOff: "Kein Raster",
3281
3597
  layoutNoMobile: "Keines",
3282
3598
  layoutHelp: "Die Bl\xF6cke der Gruppe erscheinen im Formular als Raster, mit der Spaltenzahl dieses Blocks.",
3283
- layoutNoFields: "Dieser Block hat kein Feld, das eine Spaltenzahl enthalten kann."
3599
+ layoutNoFields: "Dieser Block hat kein Feld, das eine Spaltenzahl enthalten kann.",
3600
+ "toolbar.versions": "Versionsverlauf",
3601
+ versionsDenied: "Bitte einen Administrator um die Blockscene-Berechtigung zum Lesen des Versionsverlaufs.",
3602
+ versionsDisabled: "Der Verlauf ist f\xFCr diesen Inhaltstyp nicht aktiviert. Bitte einen Administrator, ihn unter Settings > Blockscene zu aktivieren (settings.history.enabled).",
3603
+ versionsNew: "Speichere diesen Eintrag zuerst, um seinen Verlauf zu beginnen.",
3604
+ versionsPerson: "Nach Person filtern",
3605
+ versionsEveryone: "Alle Personen",
3606
+ versionsCounts: "{total} Bl\xF6cke",
3607
+ versionsCountsMissing: "Blockanzahl nicht verf\xFCgbar (\xE4lteres oder nicht aufgezeichnetes Ereignis).",
3608
+ versionsPage: "Seite {page} von {count}",
3609
+ versionsPrevious: "Zur\xFCck",
3610
+ versionsNext: "Weiter",
3611
+ versionsViewing: "Version vom {date} von {person} (schreibgesch\xFCtzt).",
3612
+ versionsCurrent: "Zur\xFCck zum aktuellen Entwurf",
3613
+ versionsMissing: "Einige Bl\xF6cke, Felder, Medien oder Beziehungen sind in dieser Vorschau nicht mehr verf\xFCgbar.",
3614
+ versionsBridgeLegacy: "Diese Bridge unterst\xFCtzt keine schreibgesch\xFCtzte Navigation. Interaktion ist deaktiviert; aktualisiere die Bridge f\xFCr readOnly.",
3615
+ historyExpired: "Snapshot nicht mehr verf\xFCgbar"
3284
3616
  };
3285
3617
 
3286
3618
  // admin/translations/it.json
3287
3619
  var it_default = {
3288
3620
  title: "Blockscene",
3289
- settings: "Galleria",
3621
+ settings: "Generali",
3290
3622
  gallery: "Galleria dei blocchi",
3291
3623
  search: "Cerca blocchi",
3292
3624
  clear: "Cancella ricerca",
@@ -3302,6 +3634,17 @@ var it_default = {
3302
3634
  moreActions: "Altre azioni",
3303
3635
  settingsTitle: "Blockscene",
3304
3636
  settingsIntro: "Miniature della galleria, palette dei wireframe e preferenze dell'editor. Le modifiche valgono alla prossima apertura della galleria; non serve alcun rebuild.",
3637
+ settingsGeneral: "Generali",
3638
+ settingsGeneralIntro: "Configura il comportamento di Blockscene nell'editor e le azioni disponibili sulle righe.",
3639
+ settingsPreview: "Anteprima pagina",
3640
+ settingsPreviewIntro: "Collega l'anteprima del frontend e configura modalit\xE0, barra degli strumenti e larghezze responsive.",
3641
+ settingsContentTypes: "Tipi di contenuto",
3642
+ settingsContentTypesIntro: "Scegli dove attivare Blockscene e personalizza l'editor visivo per ogni tipo di contenuto.",
3643
+ settingsGallery: "Galleria dei blocchi",
3644
+ settingsGalleryIntro: "Configura miniature, colori dei wireframe, tipi e filtri della galleria.",
3645
+ settingsHistory: "Cronologia e cestino",
3646
+ settingsHistoryIntro: "Gestisci versioni, conservazione delle attivit\xE0 ed eliminazioni recuperabili.",
3647
+ historyUnavailable: "Le impostazioni di cronologia e cestino richiedono Strapi 5.",
3305
3648
  palette: "Palette dei wireframe",
3306
3649
  background: "Sfondo",
3307
3650
  surface: "Superfici",
@@ -3331,6 +3674,7 @@ var it_default = {
3331
3674
  showCloseAll: 'Mostra "Comprimi tutto"',
3332
3675
  toggleHelp: "La barra della zona mostra un solo pulsante: con entrambe le opzioni attive espande finch\xE9 c'\xE8 un blocco compresso, altrimenti li comprime tutti; con una sola, offre solo quell'azione.",
3333
3676
  showRowThumbnails: "Mostra le miniature dei blocchi nelle righe",
3677
+ componentRowThumbnail: "Mostra la miniatura nella riga dell'editor",
3334
3678
  initialState: "Stato iniziale delle fisarmoniche",
3335
3679
  "states.closed": "Tutte chiuse",
3336
3680
  "states.open": "Tutte aperte",
@@ -3338,10 +3682,10 @@ var it_default = {
3338
3682
  rememberHelp: "Solo i pulsanti espliciti apri tutti / chiudi tutti aggiornano la memoria, per utente e browser. Aprire un singolo blocco non la cambia.",
3339
3683
  previewUrl: "URL di base della route di anteprima",
3340
3684
  previewUrlHelp: "URL completo della route di anteprima pagina del tuo frontend, ad es. https://site.test/block-preview/page. Lascia vuoto per riutilizzare l'origine dell'Anteprima nativa di Strapi (se configurata per il tipo di contenuto) con /block-preview/page. La route deve implementare il bridge (vedi README).",
3341
- previewUrlEmpty: "Nessun URL di anteprima impostato: gli editor hanno le modalit\xE0 Campi + pagina ed Editor visivo solo sui tipi di contenuto con l'anteprima nativa di Strapi configurata. Altrove il menu delle modalit\xE0 non compare.",
3685
+ previewUrlEmpty: "Nessun URL di anteprima impostato: gli editor hanno le modalit\xE0 Campi + anteprima ed Editor visivo solo sui tipi di contenuto con l'anteprima nativa di Strapi configurata. Altrove il menu delle modalit\xE0 non compare.",
3342
3686
  previewMode: "Modalit\xE0 iniziale dell'anteprima",
3343
- "modes.form": "Campi",
3344
- "modes.split": "Campi + pagina",
3687
+ "modes.form": "Solo campi",
3688
+ "modes.split": "Campi + anteprima",
3345
3689
  "modes.preview": "Editor visivo",
3346
3690
  previewModeHelp: "Ogni vista di modifica si apre in questo modo, a meno che il suo tipo di contenuto ne imposti uno proprio qui sotto. Durante la modifica si pu\xF2 cambiare; la scelta non viene ricordata.",
3347
3691
  lazyEdit: "Fai clic per modificare",
@@ -3349,8 +3693,8 @@ var it_default = {
3349
3693
  lazyFields: "Campi personalizzati caricati su richiesta",
3350
3694
  lazyEditorsHelp: "I campi personalizzati elencati mostrano un'anteprima di sola lettura finch\xE9 non ricevono un clic o il focus, cos\xEC le pagine grandi si aprono in fretta. Separa gli uid con virgole.",
3351
3695
  lazyFieldsInvalid: "Usa fino a {max} uid di campi personalizzati, come plugin::ckeditor5.CKEditor o global::mio-campo.",
3352
- modeForm: "Campi",
3353
- modeSplit: "Campi + pagina",
3696
+ modeForm: "Solo campi",
3697
+ modeSplit: "Campi + anteprima",
3354
3698
  modePreview: "Editor visivo",
3355
3699
  previewPane: "Anteprima della pagina",
3356
3700
  resize: "Ridimensiona il pannello di anteprima",
@@ -3377,6 +3721,7 @@ var it_default = {
3377
3721
  denied: "Accesso negato.",
3378
3722
  loadFailed: "Impossibile caricare le impostazioni. Ricarica per riprovare.",
3379
3723
  invalidColor: "I colori devono usare #RRGGBB.",
3724
+ invalidUrl: "Gli URL di anteprima devono essere indirizzi HTTP o HTTPS completi.",
3380
3725
  previewLabel: "Anteprima della palette",
3381
3726
  removeGroup: "Rimuovi gruppo",
3382
3727
  diagTitle: "I gruppi di blocchi richiedono attenzione; la pubblicazione \xE8 rifiutata finch\xE9 non vengono corretti:",
@@ -3411,6 +3756,7 @@ var it_default = {
3411
3756
  contentTypes: "Tipi di contenuto",
3412
3757
  contentTypesHelp: "La galleria, le fisarmoniche e l'anteprima di pagina funzionano su questi tipi di contenuto (quelli con una Dynamic Zone). Disattivane uno per lasciarne la modifica nativa. \xABSi apre in\xBB \xE8 il modo in cui parte ogni vista di modifica di quel tipo; durante la modifica si pu\xF2 sempre cambiare.",
3413
3758
  typeMode: "Si apre in",
3759
+ typeAdvanced: "Opzioni dell'editor visivo",
3414
3760
  modeDefault: "Predefinito ({mode})",
3415
3761
  blockModalDone: "Fatto",
3416
3762
  crashed: "Blockscene si \xE8 fermato qui a causa di un errore. L'editor nativo non \xE8 toccato. Se succede di nuovo, disattiva Blockscene in Settings, Blockscene.",
@@ -3445,6 +3791,9 @@ var it_default = {
3445
3791
  unstar: "Rimuovi dai preferiti",
3446
3792
  quickInsert: "Inserisci {label}",
3447
3793
  insert: "Inserisci",
3794
+ starterKits: "Inizia con un kit",
3795
+ starterKitsHelp: "Scegli una struttura iniziale. Tutto viene inserito come bozza modificabile e non salvata.",
3796
+ startBlank: "Inizia da zero",
3448
3797
  closeDetail: "Chiudi dettagli",
3449
3798
  typology: "Tipologia",
3450
3799
  typologyAuto: "Automatica ({name})",
@@ -3499,6 +3848,11 @@ var it_default = {
3499
3848
  confirmDeleteTitle: "Elimina blocco",
3500
3849
  confirmDelete: "Eliminare il blocco {name}?",
3501
3850
  confirmDeleteMarker: "\xC8 un marcatore di gruppo: viene rimosso solo il marcatore, non i blocchi del gruppo, e il gruppo resta sbilanciato finch\xE9 non viene corretto.",
3851
+ confirmDeleteGroupTitle: "Elimina gruppo",
3852
+ confirmDeleteGroup: "Eliminare il gruppo {name}?",
3853
+ confirmDeleteGroupHint: "Questo gruppo contiene {count, plural, one {# blocco} other {# blocchi}}. Scegli se eliminarli o mantenerli nella pagina senza il gruppo.",
3854
+ keepGroupBlocks: "Rimuovi il gruppo, mantieni i blocchi",
3855
+ deleteGroupAndBlocks: "{count, plural, =0 {Elimina gruppo} one {Elimina gruppo e # blocco} other {Elimina gruppo e # blocchi}}",
3502
3856
  delete: "Elimina",
3503
3857
  selectBlocks: "Seleziona blocchi",
3504
3858
  selectAll: "Seleziona tutti",
@@ -3693,6 +4047,7 @@ var it_default = {
3693
4047
  gridCellMenu: "Altre azioni per {label}",
3694
4048
  removeFromGroup: "Rimuovi dal gruppo",
3695
4049
  gridAdd: "Aggiungi un blocco",
4050
+ groupAdd: "Aggiungi un blocco dentro {label}",
3696
4051
  gridShowList: "Mostra il gruppo {label} come elenco",
3697
4052
  gridShowGrid: "Mostra il gruppo {label} come griglia",
3698
4053
  layoutColumnsField: "Griglia di layout: campo delle colonne",
@@ -3701,13 +4056,29 @@ var it_default = {
3701
4056
  layoutOff: "Nessuna griglia",
3702
4057
  layoutNoMobile: "Nessuno",
3703
4058
  layoutHelp: "I blocchi del gruppo appaiono in griglia nel modulo, con il numero di colonne di questo blocco.",
3704
- layoutNoFields: "Questo blocco non ha un campo che possa contenere un numero di colonne."
4059
+ layoutNoFields: "Questo blocco non ha un campo che possa contenere un numero di colonne.",
4060
+ "toolbar.versions": "Cronologia delle versioni",
4061
+ versionsDenied: "Chiedi a un amministratore il permesso Leggere la cronologia delle versioni di Blockscene.",
4062
+ versionsDisabled: "La cronologia non \xE8 attiva per questo tipo di contenuto. Chiedi a un amministratore di attivarla in Settings > Blockscene (settings.history.enabled).",
4063
+ versionsNew: "Salva prima questo contenuto per avviare la cronologia.",
4064
+ versionsPerson: "Filtra per persona",
4065
+ versionsEveryone: "Tutte le persone",
4066
+ versionsCounts: "{total} blocchi",
4067
+ versionsCountsMissing: "Conteggio dei blocchi non disponibile (evento vecchio o non registrato).",
4068
+ versionsPage: "Pagina {page} di {count}",
4069
+ versionsPrevious: "Precedente",
4070
+ versionsNext: "Successiva",
4071
+ versionsViewing: "Versione del {date} di {person} (sola lettura).",
4072
+ versionsCurrent: "Torna alla bozza attuale",
4073
+ versionsMissing: "Alcuni blocchi, campi, media o relazioni non sono pi\xF9 disponibili in questa anteprima.",
4074
+ versionsBridgeLegacy: "Questa bridge non supporta la navigazione in sola lettura. Interazione disattivata; aggiorna la bridge per supportare readOnly.",
4075
+ historyExpired: "Snapshot non pi\xF9 disponibile"
3705
4076
  };
3706
4077
 
3707
4078
  // admin/translations/nl.json
3708
4079
  var nl_default = {
3709
4080
  title: "Blockscene",
3710
- settings: "Galerij",
4081
+ settings: "Algemeen",
3711
4082
  gallery: "Blokkengalerij",
3712
4083
  search: "Blokken zoeken",
3713
4084
  clear: "Zoekopdracht wissen",
@@ -3723,6 +4094,17 @@ var nl_default = {
3723
4094
  moreActions: "Meer acties",
3724
4095
  settingsTitle: "Blockscene",
3725
4096
  settingsIntro: "Galerijminiaturen, wireframe-palet en editorvoorkeuren. Wijzigingen gelden bij de volgende opening van de galerij; geen rebuild nodig.",
4097
+ settingsGeneral: "Algemeen",
4098
+ settingsGeneralIntro: "Bepaal hoe Blockscene in de editor werkt en welke rijacties beschikbaar zijn.",
4099
+ settingsPreview: "Paginavoorbeeld",
4100
+ settingsPreviewIntro: "Koppel het frontendvoorbeeld en configureer modi, werkbalk en responsieve breedtes.",
4101
+ settingsContentTypes: "Contenttypes",
4102
+ settingsContentTypesIntro: "Kies waar Blockscene actief is en pas de visuele editor per contenttype aan.",
4103
+ settingsGallery: "Blokkengalerij",
4104
+ settingsGalleryIntro: "Configureer miniaturen, wireframekleuren, bloktypen en filters.",
4105
+ settingsHistory: "Geschiedenis en prullenbak",
4106
+ settingsHistoryIntro: "Beheer versies, activiteitsbewaring en herstelbare verwijderingen.",
4107
+ historyUnavailable: "Instellingen voor geschiedenis en prullenbak vereisen Strapi 5.",
3726
4108
  palette: "Wireframe-palet",
3727
4109
  background: "Achtergrond",
3728
4110
  surface: "Vlakken",
@@ -3752,6 +4134,7 @@ var nl_default = {
3752
4134
  showCloseAll: '"Alles inklappen" tonen',
3753
4135
  toggleHelp: "De zonebalk toont \xE9\xE9n knop: staan beide opties aan, dan klapt hij uit zolang er een blok ingeklapt is en klapt hij anders alles in; staat er maar \xE9\xE9n aan, dan biedt hij alleen die actie.",
3754
4136
  showRowThumbnails: "Blokminiaturen in de rijen tonen",
4137
+ componentRowThumbnail: "Miniatuur in de editorrij tonen",
3755
4138
  initialState: "Beginstand van de accordeons",
3756
4139
  "states.closed": "Alle gesloten",
3757
4140
  "states.open": "Alle open",
@@ -3759,10 +4142,10 @@ var nl_default = {
3759
4142
  rememberHelp: "Alleen de expliciete knoppen alles openen / alles sluiten werken het geheugen bij, per gebruiker en browser. E\xE9n blok openen verandert niets.",
3760
4143
  previewUrl: "Basis-URL van de voorbeeldroute",
3761
4144
  previewUrlHelp: "Volledige URL van de paginavoorbeeldroute van uw frontend, bijv. https://site.test/block-preview/page. Laat leeg om de oorsprong van Strapi's native Preview (indien geconfigureerd voor het contenttype) met /block-preview/page te hergebruiken. De route moet de bridge implementeren (zie README).",
3762
- previewUrlEmpty: "Geen preview-URL ingesteld: redacteuren krijgen de modi Velden + pagina en Visuele editor alleen bij inhoudstypes waarvoor de native Preview van Strapi is ingesteld. Elders verschijnt het modusmenu niet.",
4145
+ previewUrlEmpty: "Geen preview-URL ingesteld: redacteuren krijgen de modi Velden + voorbeeld en Visuele editor alleen bij inhoudstypes waarvoor de native Preview van Strapi is ingesteld. Elders verschijnt het modusmenu niet.",
3763
4146
  previewMode: "Beginmodus van het voorbeeld",
3764
- "modes.form": "Velden",
3765
- "modes.split": "Velden + pagina",
4147
+ "modes.form": "Alleen velden",
4148
+ "modes.split": "Velden + voorbeeld",
3766
4149
  "modes.preview": "Visuele editor",
3767
4150
  previewModeHelp: "Elke bewerkweergave opent in deze modus, tenzij het contenttype hieronder een eigen modus instelt. Tijdens het bewerken kan je wisselen; die keuze wordt niet onthouden.",
3768
4151
  lazyEdit: "Klik om te bewerken",
@@ -3770,8 +4153,8 @@ var nl_default = {
3770
4153
  lazyFields: "Aangepaste velden die op aanvraag laden",
3771
4154
  lazyEditorsHelp: "De vermelde aangepaste velden tonen een alleen-lezen voorbeeld tot ze worden aangeklikt of focus krijgen, zodat grote pagina's snel openen. Scheid uids met komma's.",
3772
4155
  lazyFieldsInvalid: "Gebruik maximaal {max} uids van aangepaste velden, zoals plugin::ckeditor5.CKEditor of global::mijn-veld.",
3773
- modeForm: "Velden",
3774
- modeSplit: "Velden + pagina",
4156
+ modeForm: "Alleen velden",
4157
+ modeSplit: "Velden + voorbeeld",
3775
4158
  modePreview: "Visuele editor",
3776
4159
  previewPane: "Paginavoorbeeld",
3777
4160
  resize: "Voorbeeldpaneel aanpassen",
@@ -3798,6 +4181,7 @@ var nl_default = {
3798
4181
  denied: "Toegang geweigerd.",
3799
4182
  loadFailed: "Instellingen konden niet worden geladen. Herlaad om opnieuw te proberen.",
3800
4183
  invalidColor: "Kleuren moeten #RRGGBB gebruiken.",
4184
+ invalidUrl: "Voorbeeld-URL's moeten volledige HTTP- of HTTPS-adressen zijn.",
3801
4185
  previewLabel: "Paletvoorbeeld",
3802
4186
  removeGroup: "Groep verwijderen",
3803
4187
  diagTitle: "Blokgroepen vragen aandacht; publiceren wordt geweigerd tot ze hersteld zijn:",
@@ -3832,6 +4216,7 @@ var nl_default = {
3832
4216
  contentTypes: "Contenttypes",
3833
4217
  contentTypesHelp: 'De galerij, accordeons en paginavoorbeeld werken op deze contenttypes (die met een Dynamic Zone). Zet er een uit om de bewerking native te laten. "Opent in" bepaalt hoe elke bewerkweergave van dat type start; tijdens het bewerken kan je nog wisselen.',
3834
4218
  typeMode: "Opent in",
4219
+ typeAdvanced: "Opties voor de visuele editor",
3835
4220
  modeDefault: "Standaard ({mode})",
3836
4221
  blockModalDone: "Klaar",
3837
4222
  crashed: "Blockscene is hier gestopt door een fout. De native editor blijft werken. Gebeurt het opnieuw, zet Blockscene uit in Settings, Blockscene.",
@@ -3866,6 +4251,9 @@ var nl_default = {
3866
4251
  unstar: "Uit favorieten verwijderen",
3867
4252
  quickInsert: "{label} invoegen",
3868
4253
  insert: "Invoegen",
4254
+ starterKits: "Start met een kit",
4255
+ starterKitsHelp: "Kies een beginstructuur. Alles wordt ingevoegd als een onopgeslagen, bewerkbaar concept.",
4256
+ startBlank: "Leeg beginnen",
3869
4257
  closeDetail: "Details sluiten",
3870
4258
  typology: "Typologie",
3871
4259
  typologyAuto: "Automatisch ({name})",
@@ -3920,6 +4308,11 @@ var nl_default = {
3920
4308
  confirmDeleteTitle: "Blok verwijderen",
3921
4309
  confirmDelete: "Blok {name} verwijderen?",
3922
4310
  confirmDeleteMarker: "Dit is een groepsmarkering: alleen de markering wordt verwijderd, niet de blokken in de groep, en de groep blijft onevenwichtig tot hij hersteld is.",
4311
+ confirmDeleteGroupTitle: "Groep verwijderen",
4312
+ confirmDeleteGroup: "Groep {name} verwijderen?",
4313
+ confirmDeleteGroupHint: "Deze groep bevat {count, plural, one {# blok} other {# blokken}}. Verwijder ze of behoud ze op de pagina zonder de groep.",
4314
+ keepGroupBlocks: "Groep verwijderen, blokken behouden",
4315
+ deleteGroupAndBlocks: "{count, plural, =0 {Groep verwijderen} one {Groep en # blok verwijderen} other {Groep en # blokken verwijderen}}",
3923
4316
  delete: "Verwijderen",
3924
4317
  selectBlocks: "Blokken selecteren",
3925
4318
  selectAll: "Alles selecteren",
@@ -4114,6 +4507,7 @@ var nl_default = {
4114
4507
  gridCellMenu: "Meer acties voor {label}",
4115
4508
  removeFromGroup: "Uit de groep halen",
4116
4509
  gridAdd: "Blok toevoegen",
4510
+ groupAdd: "Blok toevoegen binnen {label}",
4117
4511
  gridShowList: "Groep {label} als lijst tonen",
4118
4512
  gridShowGrid: "Groep {label} als raster tonen",
4119
4513
  layoutColumnsField: "Layoutraster: veld met kolommen",
@@ -4122,7 +4516,23 @@ var nl_default = {
4122
4516
  layoutOff: "Geen raster",
4123
4517
  layoutNoMobile: "Geen",
4124
4518
  layoutHelp: "De blokken van de groep verschijnen als raster in het formulier, met het aantal kolommen van dit blok.",
4125
- layoutNoFields: "Dit blok heeft geen veld dat een aantal kolommen kan bevatten."
4519
+ layoutNoFields: "Dit blok heeft geen veld dat een aantal kolommen kan bevatten.",
4520
+ "toolbar.versions": "Versiegeschiedenis",
4521
+ versionsDenied: "Vraag een beheerder om de Blockscene-machtiging Versiegeschiedenis lezen.",
4522
+ versionsDisabled: "Geschiedenis is niet ingeschakeld voor dit inhoudstype. Vraag een beheerder dit in Settings > Blockscene in te schakelen (settings.history.enabled).",
4523
+ versionsNew: "Sla dit item eerst op om de geschiedenis te starten.",
4524
+ versionsPerson: "Filter op persoon",
4525
+ versionsEveryone: "Iedereen",
4526
+ versionsCounts: "{total} blokken",
4527
+ versionsCountsMissing: "Aantal blokken niet beschikbaar (oudere of niet vastgelegde gebeurtenis).",
4528
+ versionsPage: "Pagina {page} van {count}",
4529
+ versionsPrevious: "Vorige",
4530
+ versionsNext: "Volgende",
4531
+ versionsViewing: "Versie van {date} door {person} bekijken (alleen-lezen).",
4532
+ versionsCurrent: "Terug naar huidig concept",
4533
+ versionsMissing: "Sommige blokken, velden, media of relaties zijn niet meer beschikbaar in dit voorbeeld.",
4534
+ versionsBridgeLegacy: "Deze bridge ondersteunt geen alleen-lezen navigatie. Interactie is uitgeschakeld; werk de bridge bij voor readOnly.",
4535
+ historyExpired: "Snapshot niet meer beschikbaar"
4126
4536
  };
4127
4537
 
4128
4538
  // admin/messages.ts
@@ -4226,8 +4636,15 @@ function RowPreviews({ zones, components, catalog, Modal: Modal2 }) {
4226
4636
  const candidates = (uid) => candidatesFor(uid, catalog?.components?.[uid] || {}, catalog || {});
4227
4637
  const label = (uid) => catalog?.components?.[uid]?.label || components?.[uid]?.info?.displayName || uid;
4228
4638
  const srcOf = (uid) => candidates(uid)[resolved[uid] ?? -1] || "";
4639
+ const visible = anchors.filter(({ uid }) => showRowThumbnail(uid, catalog));
4229
4640
  React2.useEffect(() => {
4230
4641
  for (const { el, uid } of anchors) {
4642
+ if (!showRowThumbnail(uid, catalog)) {
4643
+ el.style.removeProperty("cursor");
4644
+ for (const name of ["role", "tabindex", "aria-label"])
4645
+ el.removeAttribute(name);
4646
+ continue;
4647
+ }
4231
4648
  if (srcOf(uid)) {
4232
4649
  el.setAttribute("role", "button");
4233
4650
  el.setAttribute("tabindex", "0");
@@ -4239,7 +4656,7 @@ function RowPreviews({ zones, components, catalog, Modal: Modal2 }) {
4239
4656
  }
4240
4657
  });
4241
4658
  return /* @__PURE__ */ jsxs(Fragment, { children: [
4242
- anchors.map(
4659
+ visible.map(
4243
4660
  (a) => createPortal(
4244
4661
  /* @__PURE__ */ jsx2(
4245
4662
  "span",
@@ -4419,7 +4836,15 @@ function movedRow(prev, next, actor) {
4419
4836
  }
4420
4837
  function keepGroupsTogether(prev, next, groups, actor) {
4421
4838
  if (!groups) return null;
4422
- const move = movedRow(prev, next, actor);
4839
+ let move = movedRow(prev, next, actor);
4840
+ if (!move && actor == null) {
4841
+ const candidates = prev.flatMap((row) => {
4842
+ if (!(0, import_groups2.isOpener)(row, groups)) return [];
4843
+ const candidate = movedRow(prev, next, (0, import_groups2.blockKey)(row));
4844
+ return candidate && (0, import_groups2.isOpener)(prev[candidate.from], groups) ? [candidate] : [];
4845
+ });
4846
+ if (candidates.length === 1) move = candidates[0];
4847
+ }
4423
4848
  if (!move || !(0, import_groups2.isOpener)(prev[move.from], groups)) return null;
4424
4849
  const start = move.from, end = groupOutline(prev, groups)[start].end;
4425
4850
  if (end == null) return null;
@@ -4772,6 +5197,7 @@ var DEPTH = "data-blockscene-depth";
4772
5197
  var KIND = "data-blockscene-group";
4773
5198
  var FOLD = "data-blockscene-fold";
4774
5199
  var COUNT = "data-blockscene-fold-count";
5200
+ var INSERT = "data-blockscene-group-insert";
4775
5201
  var GRID_BOX = "data-blockscene-grid";
4776
5202
  var STEP = "2.4rem";
4777
5203
  var folded = /* @__PURE__ */ new Set();
@@ -4793,6 +5219,14 @@ var Count = styled3.span`
4793
5219
  margin-right: 4px; padding: 1px 6px; border-radius: 3px; font-size: 11px; font-weight: 600; line-height: 16px; white-space: nowrap;
4794
5220
  color: ${({ theme }) => theme.colors.primary700}; background: ${({ theme }) => theme.colors.primary100};
4795
5221
  `;
5222
+ var GroupInsert = styled3.button`
5223
+ display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; min-height: 42px; padding: 8px 12px;
5224
+ border: 1px dashed ${({ theme }) => theme.colors.primary600}; border-radius: 4px; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600;
5225
+ color: ${({ theme }) => theme.colors.primary600}; background: ${({ theme }) => theme.colors.neutral0};
5226
+ &:hover:not(:disabled) { background: ${({ theme }) => theme.colors.primary100}; }
5227
+ &:disabled { opacity: 0.5; cursor: default; }
5228
+ &:focus-visible { outline: 2px solid ${({ theme }) => theme.colors.primary600}; outline-offset: 1px; }
5229
+ `;
4796
5230
  function GroupRows({ zones, form, groups, docKey, labelOf, layouts = null, components, catalog, openBlock, openInsert }) {
4797
5231
  const t = useMessages();
4798
5232
  const theme = useTheme();
@@ -4888,18 +5322,34 @@ function GroupRows({ zones, form, groups, docKey, labelOf, layouts = null, compo
4888
5322
  for (const index of unfold) for (const p of outline[index]?.parents || []) folded.delete(idOf(p));
4889
5323
  const isFolded = (i) => outline[i].end != null && folded.has(idOf(i));
4890
5324
  const grid = [];
5325
+ const anchorByOpen = /* @__PURE__ */ new Map();
4891
5326
  lis.forEach((li, i) => {
4892
5327
  const o = outline[i];
4893
5328
  seen.add(li);
4894
5329
  set(li, DEPTH, o.depth ? String(o.depth) : null);
4895
5330
  if (o.depth) li.style.setProperty("--bs-depth", String(o.depth));
4896
5331
  set(li, KIND, o.kind === "block" ? null : o.kind);
4897
- const inGrid = (o.kind === "close" ? o.parents.slice(0, -1) : o.parents).some((p) => grid[p]);
5332
+ const inGrid = o.parents.some((p) => grid[p]);
4898
5333
  const hidden = o.parents.some(isFolded) || inGrid;
4899
5334
  set(li, FOLDED, hidden ? "" : null);
4900
5335
  const layout = o.kind === "open" && o.end != null ? layouts2?.[rows[i].__component] || null : null;
4901
5336
  const toggle = li.querySelector("button[aria-expanded]");
4902
5337
  grid[i] = Boolean(layout && toggle?.parentElement) && !hidden && !isFolded(i) && !listed.has(idOf(i));
5338
+ if (o.kind === "close") {
5339
+ const open = o.parents[o.parents.length - 1];
5340
+ const anchor2 = anchorByOpen.get(open);
5341
+ if (anchor2 && !grid[open] && !hidden) {
5342
+ let insertEl = li.querySelector(`:scope > [${INSERT}]`);
5343
+ if (!insertEl) {
5344
+ insertEl = document.createElement("div");
5345
+ insertEl.setAttribute(INSERT, "");
5346
+ li.appendChild(insertEl);
5347
+ }
5348
+ anchor2.insertEl = insertEl;
5349
+ anchor2.after = blockKey(rows[Math.max(open, i - 1)]);
5350
+ }
5351
+ return;
5352
+ }
4903
5353
  if (o.kind !== "open" || o.end == null || !toggle?.parentElement) return;
4904
5354
  let gridEl = li.querySelector(`:scope > [${GRID_BOX}]`);
4905
5355
  if (grid[i] && !gridEl) {
@@ -4922,15 +5372,32 @@ function GroupRows({ zones, form, groups, docKey, labelOf, layouts = null, compo
4922
5372
  countEl.style.cssText = "display:inline-flex;align-items:center";
4923
5373
  actions.insertBefore(countEl, actions.firstChild);
4924
5374
  }
4925
- next.push({ el, countEl, zone: zone.name, index: i, id: idOf(i), count: o.count || 0, open: !isFolded(i), label: labelOf2(rows[i]), layout, gridEl });
5375
+ const anchor = {
5376
+ el,
5377
+ countEl,
5378
+ insertEl: null,
5379
+ after: null,
5380
+ full: Boolean(zone.full),
5381
+ zone: zone.name,
5382
+ index: i,
5383
+ id: idOf(i),
5384
+ count: o.count || 0,
5385
+ open: !isFolded(i),
5386
+ label: labelOf2(rows[i]),
5387
+ layout,
5388
+ gridEl
5389
+ };
5390
+ next.push(anchor);
5391
+ anchorByOpen.set(i, anchor);
4926
5392
  });
4927
5393
  }
4928
5394
  landed.current = null;
4929
5395
  for (const li of document.querySelectorAll(`li[${DEPTH}], li[${KIND}], li[${FOLDED}]`))
4930
5396
  if (!seen.has(li)) for (const name of [DEPTH, KIND, FOLDED]) li.removeAttribute(name);
4931
- for (const el of document.querySelectorAll(`[${FOLD}], [${COUNT}], [${GRID_BOX}]`)) if (!next.some((a) => a.el === el || a.countEl === el || a.gridEl === el)) el.remove();
5397
+ for (const el of document.querySelectorAll(`[${FOLD}], [${COUNT}], [${GRID_BOX}], [${INSERT}]`))
5398
+ if (!next.some((a) => a.el === el || a.countEl === el || a.gridEl === el || a.insertEl === el)) el.remove();
4932
5399
  setAnchors(
4933
- (prev) => prev.length === next.length && prev.every((a, i) => ["el", "countEl", "id", "index", "count", "open", "label", "layout", "gridEl"].every((k) => a[k] === next[i][k])) ? prev : next
5400
+ (prev) => prev.length === next.length && prev.every((a, i) => ["el", "countEl", "insertEl", "after", "full", "id", "index", "count", "open", "label", "layout", "gridEl"].every((k) => a[k] === next[i][k])) ? prev : next
4934
5401
  );
4935
5402
  };
4936
5403
  React4.useEffect(() => {
@@ -4948,7 +5415,7 @@ function GroupRows({ zones, form, groups, docKey, labelOf, layouts = null, compo
4948
5415
  return () => {
4949
5416
  observer.disconnect();
4950
5417
  cancelAnimationFrame(frame2);
4951
- for (const el of document.querySelectorAll(`[${FOLD}], [${COUNT}], [${GRID_BOX}]`)) el.remove();
5418
+ for (const el of document.querySelectorAll(`[${FOLD}], [${COUNT}], [${GRID_BOX}], [${INSERT}]`)) el.remove();
4952
5419
  for (const li of document.querySelectorAll(`li[${DEPTH}], li[${KIND}], li[${FOLDED}]`)) for (const name of [DEPTH, KIND, FOLDED]) li.removeAttribute(name);
4953
5420
  };
4954
5421
  }, []);
@@ -4965,10 +5432,8 @@ function GroupRows({ zones, form, groups, docKey, labelOf, layouts = null, compo
4965
5432
  ${list}[${DEPTH}] { padding-left: calc(var(--bs-depth) * ${STEP}); background: repeating-linear-gradient(to right, ${line} 0 2px, transparent 2px ${STEP}) 1.1rem 0 / calc(var(--bs-depth) * ${STEP}) 100% no-repeat; }
4966
5433
  ${list}[${FOLDED}]:not([data-bp-block-modal]) { display: none !important; }
4967
5434
  ${list}[data-bp-block-modal] { padding-left: 0 !important; background-image: none !important; }
4968
- ${list}[${KIND}="close"] [data-handler-id] { display: none !important; }
4969
- ${list}[${KIND}="close"] button[aria-expanded]:first-of-type { min-height: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important; opacity: 0.7; }
4970
- ${list}[${KIND}="close"] button[aria-expanded]:first-of-type + * { padding-top: 0 !important; padding-bottom: 0 !important; }
4971
- ${list}[${KIND}="close"] button[aria-expanded] [data-blockscene-row-thumb] { display: none; }` }),
5435
+ ${list}[${KIND}="close"] > *:not([${INSERT}]) { display: none !important; }
5436
+ ${list}[${KIND}="close"] [${INSERT}] { display: block; padding: 8px 12px; }` }),
4972
5437
  anchors.map(
4973
5438
  (a) => createPortal2(
4974
5439
  /* @__PURE__ */ jsx5(
@@ -5022,7 +5487,27 @@ ${list}[${KIND}="close"] button[aria-expanded] [data-blockscene-row-thumb] { dis
5022
5487
  a.gridEl,
5023
5488
  `grid:${a.zone}:${a.index}`
5024
5489
  ) : null;
5025
- })
5490
+ }),
5491
+ anchors.map(
5492
+ (a) => a.insertEl ? createPortal2(
5493
+ /* @__PURE__ */ jsxs3(
5494
+ GroupInsert,
5495
+ {
5496
+ type: "button",
5497
+ disabled: a.full,
5498
+ title: a.full ? t.zoneFull : void 0,
5499
+ "data-testid": `group-add-${a.zone}-${a.index}`,
5500
+ onClick: () => openInsert?.(a.zone, a.after),
5501
+ children: [
5502
+ /* @__PURE__ */ jsx5(Icon, { name: "plus", size: 14 }),
5503
+ t.f("groupAdd", { label: a.label })
5504
+ ]
5505
+ }
5506
+ ),
5507
+ a.insertEl,
5508
+ `insert:${a.zone}:${a.index}`
5509
+ ) : null
5510
+ )
5026
5511
  ] });
5027
5512
  }
5028
5513
  function ViewToggle({ grid, testid, label, onFlip }) {
@@ -5225,9 +5710,33 @@ function useRowActions({ zones, components, catalog, form }) {
5225
5710
  if (hiddenName) form.setRows(zoneName, setHidden(rows, index, groups, hiddenName, rows[index]?.[hiddenName] !== true));
5226
5711
  };
5227
5712
  const paste = (zoneName, at) => pasteInto(form, zoneOf(zoneName), clip, components, groups, t, at);
5713
+ const changeGroup = (zoneName, key, keepBlocks) => {
5714
+ const rows = form.rows(zoneName);
5715
+ const next = keepBlocks ? (0, import_groups2.unwrapGroup)(rows, key, groups) : (0, import_groups2.removeGroup)(rows, key, groups);
5716
+ if (next) form.setRows(zoneName, next);
5717
+ };
5228
5718
  const pastable = (zoneName) => !["empty", "notAllowed"].includes(pasteProblem(clip, zoneOf(zoneName), form.rows(zoneName), components, groups)?.code);
5229
5719
  const selectable = (zoneName) => form.rows(zoneName).filter((row) => canAct(row, groups)).map((row) => blockKey(row)).filter(Boolean);
5230
- return { t, editor, groups, hiddenName, clip, selection, setSelection, busy, form, labelOf, duplicate, copy: copy2, toggleHidden, paste, pastable, selectable, isMarker: (row) => isGroupMarker(row, groups) };
5720
+ return {
5721
+ t,
5722
+ editor,
5723
+ groups,
5724
+ hiddenName,
5725
+ clip,
5726
+ selection,
5727
+ setSelection,
5728
+ busy,
5729
+ form,
5730
+ labelOf,
5731
+ duplicate,
5732
+ copy: copy2,
5733
+ toggleHidden,
5734
+ paste,
5735
+ pastable,
5736
+ selectable,
5737
+ changeGroup,
5738
+ isMarker: (row) => isGroupMarker(row, groups)
5739
+ };
5231
5740
  }
5232
5741
  var RowButton = styled4.button`
5233
5742
  display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: 0;
@@ -5251,7 +5760,7 @@ function RowActions({ zones, actions, Modal: Modal2 }) {
5251
5760
  const latest = React5.useRef({ zones, a });
5252
5761
  latest.current = { zones, a };
5253
5762
  React5.useEffect(() => {
5254
- if (!a || e.confirmDelete === false) return;
5763
+ if (!a) return;
5255
5764
  const onClick = (event) => {
5256
5765
  const button = event.target?.closest?.("button");
5257
5766
  if (!button || bypass.current) return;
@@ -5261,10 +5770,23 @@ function RowActions({ zones, actions, Modal: Modal2 }) {
5261
5770
  const headers = toggles(list);
5262
5771
  const index = headers.findIndex((toggle) => trashOf(toggle) === button);
5263
5772
  if (index < 0) return;
5773
+ const row = latest.current.a?.form.rows(zone.name)[index];
5774
+ const marker2 = Boolean(latest.current.a?.isMarker(row));
5775
+ if (!marker2 && e.confirmDelete === false) return;
5264
5776
  event.preventDefault();
5265
5777
  event.stopPropagation();
5266
- const row = latest.current.a?.form.rows(zone.name)[index];
5267
- setConfirm({ button, label: headers[index].textContent?.trim() || latest.current.a?.labelOf(row), marker: Boolean(latest.current.a?.isMarker(row)) });
5778
+ if (marker2 && !canAct(row, latest.current.a?.groups)) return;
5779
+ const key = blockKey(row) || "";
5780
+ const rows = latest.current.a.form.rows(zone.name);
5781
+ const range = marker2 ? actionRange(rows, index, latest.current.a.groups) : [index, index];
5782
+ setConfirm({
5783
+ button,
5784
+ label: latest.current.a?.labelOf(row) || headers[index].textContent?.trim(),
5785
+ kind: marker2 ? "group" : "block",
5786
+ zone: zone.name,
5787
+ key,
5788
+ count: marker2 ? rows.slice(range[0] + 1, range[1]).filter((item) => canAct(item, latest.current.a.groups)).length : 0
5789
+ });
5268
5790
  return;
5269
5791
  }
5270
5792
  };
@@ -5292,6 +5814,11 @@ function RowActions({ zones, actions, Modal: Modal2 }) {
5292
5814
  bypass.current = false;
5293
5815
  }
5294
5816
  };
5817
+ const confirmGroup = (keepBlocks) => {
5818
+ const target = confirm;
5819
+ setConfirm(null);
5820
+ if (target?.kind === "group") a.changeGroup(target.zone, target.key, keepBlocks);
5821
+ };
5295
5822
  return /* @__PURE__ */ jsxs4(Fragment3, { children: [
5296
5823
  /* @__PURE__ */ jsx6("style", { children: `li[${HIDDEN_ATTR}] button[aria-expanded] { opacity: 0.5; }
5297
5824
  ol[aria-describedby] > li button[data-strapi-accordion-toggle] { overflow: hidden; }
@@ -5371,14 +5898,25 @@ ol[aria-describedby] > li button[data-strapi-accordion-toggle] > span:last-child
5371
5898
  `${zone}:${index}`
5372
5899
  );
5373
5900
  }),
5374
- confirm && /* @__PURE__ */ jsx6(Modal2, { open: true, width: "48rem", onOpenChange: (open) => !open && setConfirm(null), trigger: null, title: t.confirmDeleteTitle, children: /* @__PURE__ */ jsxs4(Flex, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "row-confirm-delete", children: [
5375
- /* @__PURE__ */ jsx6(Typography, { children: t.f("confirmDelete", { name: confirm.label }) }),
5376
- confirm.marker && /* @__PURE__ */ jsx6(Typography, { variant: "pi", textColor: "neutral600", children: t.confirmDeleteMarker }),
5377
- /* @__PURE__ */ jsxs4(Flex, { gap: 2, justifyContent: "flex-end", children: [
5378
- /* @__PURE__ */ jsx6(Button, { variant: "tertiary", onClick: () => setConfirm(null), "data-testid": "row-confirm-cancel", children: t.cancel }),
5379
- /* @__PURE__ */ jsx6(Button, { variant: "danger", onClick: confirmDelete, "data-testid": "row-confirm-ok", children: t.delete })
5380
- ] })
5381
- ] }) })
5901
+ confirm && /* @__PURE__ */ jsx6(
5902
+ Modal2,
5903
+ {
5904
+ open: true,
5905
+ width: "48rem",
5906
+ onOpenChange: (open) => !open && setConfirm(null),
5907
+ trigger: null,
5908
+ title: confirm.kind === "group" ? t.confirmDeleteGroupTitle : t.confirmDeleteTitle,
5909
+ children: /* @__PURE__ */ jsxs4(Flex, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "row-confirm-delete", children: [
5910
+ /* @__PURE__ */ jsx6(Typography, { children: t.f(confirm.kind === "group" ? "confirmDeleteGroup" : "confirmDelete", { name: confirm.label, count: confirm.count }) }),
5911
+ confirm.kind === "group" && confirm.count > 0 && /* @__PURE__ */ jsx6(Typography, { variant: "pi", textColor: "neutral600", children: t.f("confirmDeleteGroupHint", { count: confirm.count }) }),
5912
+ /* @__PURE__ */ jsxs4(Flex, { gap: 2, justifyContent: "flex-end", children: [
5913
+ /* @__PURE__ */ jsx6(Button, { variant: "tertiary", onClick: () => setConfirm(null), "data-testid": "row-confirm-cancel", children: t.cancel }),
5914
+ confirm.kind === "group" && confirm.count > 0 && /* @__PURE__ */ jsx6(Button, { variant: "secondary", onClick: () => confirmGroup(true), "data-testid": "row-confirm-unwrap", children: t.keepGroupBlocks }),
5915
+ /* @__PURE__ */ jsx6(Button, { variant: "danger", onClick: confirm.kind === "group" ? () => confirmGroup(false) : confirmDelete, "data-testid": "row-confirm-ok", children: confirm.kind === "group" ? t.f("deleteGroupAndBlocks", { count: confirm.count }) : t.delete })
5916
+ ] })
5917
+ ] })
5918
+ }
5919
+ )
5382
5920
  ] });
5383
5921
  }
5384
5922
  function zoneMenuItems(zone, a) {
@@ -5736,6 +6274,10 @@ var Round = styled5.button`
5736
6274
  border: 1px solid ${({ theme }) => theme.colors.neutral200};
5737
6275
  color: ${({ theme, $on }) => $on ? theme.colors.warning500 : theme.colors.neutral600};
5738
6276
  background: ${({ theme }) => theme.colors.neutral0};
6277
+ transition: transform 120ms ease-out;
6278
+ &:active {
6279
+ transform: scale(0.97);
6280
+ }
5739
6281
  &:focus-visible {
5740
6282
  outline: 2px solid ${({ theme }) => theme.colors.primary600};
5741
6283
  outline-offset: 1px;
@@ -6429,7 +6971,7 @@ function ZoneGallery({
6429
6971
  gap: 4,
6430
6972
  style: { overflowY: "auto", flex: 1, minHeight: 0, padding: "4px" },
6431
6973
  children: (view === "recent" ? [{ typology: "recent", entries }] : groupEntries(entries)).map(
6432
- ({ typology, entries: items2 }) => /* @__PURE__ */ jsxs5(Flex2, { direction: "column", alignItems: "stretch", gap: 2, children: [
6974
+ ({ typology, entries: items2 }) => /* @__PURE__ */ jsxs5(Flex2, { direction: "column", alignItems: "stretch", gap: 2, flex: "0 0 auto", children: [
6433
6975
  /* @__PURE__ */ jsx7(Typography2, { variant: "sigma", textColor: "neutral600", "data-testid": `block-group-${typology}`, children: `${typology === "recent" ? t.nav.recent : t.typologies[typology] || typology} (${items2.length})` }),
6434
6976
  /* @__PURE__ */ jsx7(Columns, { $columns: columns, children: items2.map((entry) => /* @__PURE__ */ jsx7("div", { children: /* @__PURE__ */ jsx7(
6435
6977
  Card,
@@ -6715,8 +7257,14 @@ import styled6, { useTheme as useTheme2 } from "styled-components";
6715
7257
  import { Box as Box4, Button as Button3, Flex as Flex3, MenuItem, SimpleMenu, Typography as Typography4 } from "@strapi/design-system";
6716
7258
 
6717
7259
  // admin/pane.mjs
6718
- var TOOLBAR = ["modes", "history", "devices", "status", "actions"];
7260
+ var TOOLBAR = ["modes", "history", "versions", "devices", "status", "actions"];
6719
7261
  var RIGHT = ["status", "actions"];
7262
+ function topNavigationInset(navs, viewportWidth) {
7263
+ return Math.round(Math.max(0, ...(Array.isArray(navs) ? navs : []).flatMap((nav) => {
7264
+ const rect = nav?.rect || {};
7265
+ return ["fixed", "sticky"].includes(nav?.position) && Math.abs(Number(rect.top) || 0) <= 1 && (Number(rect.left) || 0) <= 1 && Number(rect.right) >= viewportWidth - 1 && Number(rect.height) > 0 && Number(rect.height) <= 128 ? [Number(rect.bottom) || Number(rect.height)] : [];
7266
+ })));
7267
+ }
6720
7268
  function toolbarLayout(list) {
6721
7269
  const ids = Array.isArray(list) ? list.filter((id, i) => TOOLBAR.includes(id) && list.indexOf(id) === i) : TOOLBAR;
6722
7270
  const at = ids.findIndex((id) => RIGHT.includes(id));
@@ -6851,6 +7399,25 @@ function useMainRect() {
6851
7399
  }, []);
6852
7400
  return rect;
6853
7401
  }
7402
+ function useAdminTopInset() {
7403
+ const [inset, setInset] = React8.useState(0);
7404
+ React8.useLayoutEffect(() => {
7405
+ const navs = () => [...document.querySelectorAll("nav")];
7406
+ const measure = () => setInset(topNavigationInset(navs().map((nav) => ({
7407
+ position: getComputedStyle(nav).position,
7408
+ rect: nav.getBoundingClientRect()
7409
+ })), window.innerWidth));
7410
+ measure();
7411
+ const observer = "ResizeObserver" in window ? new ResizeObserver(measure) : null;
7412
+ navs().forEach((nav) => observer?.observe(nav));
7413
+ window.addEventListener("resize", measure);
7414
+ return () => {
7415
+ observer?.disconnect();
7416
+ window.removeEventListener("resize", measure);
7417
+ };
7418
+ }, []);
7419
+ return inset;
7420
+ }
6854
7421
  var Handle = styled6.div`
6855
7422
  position: absolute;
6856
7423
  top: 0;
@@ -6939,6 +7506,7 @@ body.bp-block-modal [data-bp-block-modal] { position: fixed !important; top: ${B
6939
7506
  background: ${background}; border-radius: 0 0 8px 8px; box-shadow: 0 8px 32px rgba(33, 33, 52, 0.3); }
6940
7507
  body.bp-block-modal [data-bp-block-modal]::before, body.bp-block-modal [data-bp-block-modal]::after { display: none !important; }
6941
7508
  body.bp-block-modal [data-bp-block-modal] > div { margin: 0 !important; padding-top: 0 !important; }
7509
+ body.bp-block-modal > div:has(> [role="listbox"]) { z-index: 1002 !important; }
6942
7510
  body.bp-block-modal [data-bp-modal-hide] { display: none !important; }`;
6943
7511
  var DRAWER_WIDTH = 640;
6944
7512
  var fieldsStyle = (background, drawer) => `
@@ -6947,6 +7515,7 @@ body.bp-fields [data-bp-show] { grid-column: 1 / -1 !important; }
6947
7515
  body.bp-fields [data-bp-flat] { border: 0 !important; box-shadow: none !important; padding: 0 !important; background: transparent !important; }
6948
7516
  body.bp-fields [data-bp-fields] { position: fixed !important; z-index: 1001; overflow: auto; margin: 0 !important;
6949
7517
  padding: 1.6rem 2.4rem; background: ${background}; box-shadow: 0 8px 32px rgba(33, 33, 52, 0.3); }
7518
+ body.bp-fields > div:has(> [role="listbox"]) { z-index: 1002 !important; }
6950
7519
  body.bp-fields [data-bp-fields="modal"] { top: ${BLOCK_TOP}; left: 50%; transform: translateX(-50%); width: min(96rem, 92vw);
6951
7520
  max-height: calc(88vh - 5.6rem); border-radius: 0 0 8px 8px; }
6952
7521
  ${drawer ? `body.bp-fields [data-bp-fields="drawer"] { top: ${drawer.top + 56}px; left: ${drawer.left}px; width: ${drawer.width}px; height: ${drawer.height - 56}px; }` : ""}`;
@@ -7138,7 +7707,8 @@ function PagePreview({
7138
7707
  hiddenAttribute = null,
7139
7708
  form = null,
7140
7709
  Modal: Modal2,
7141
- Toggle
7710
+ Toggle,
7711
+ versions
7142
7712
  }) {
7143
7713
  const t = useMessages();
7144
7714
  const { values, zone, zoneLabel: zoneLabel2, canEdit, latest, insertRows: insertRows2 } = usePreviewZone(host);
@@ -7158,12 +7728,15 @@ function PagePreview({
7158
7728
  return v > 0 && v < 1 ? v : 0.5;
7159
7729
  });
7160
7730
  const main = useMainRect();
7731
+ const topInset = useAdminTopInset();
7161
7732
  const vw = main.width;
7162
7733
  const [dragging, setDragging] = React8.useState(false);
7163
7734
  const [ready, setReady] = React8.useState(false);
7735
+ const [readOnlyBridge, setReadOnlyBridge] = React8.useState(false);
7164
7736
  const [failed, setFailed] = React8.useState(false);
7165
7737
  const [attempt, retry] = React8.useReducer((n) => n + 1, 0);
7166
7738
  const [picking, setPicking] = React8.useState(null);
7739
+ const [deletingGroup, setDeletingGroup] = React8.useState(null);
7167
7740
  const [hovered, setHovered] = React8.useState(null);
7168
7741
  const [edge, setEdge] = React8.useState(null);
7169
7742
  const hoverRow = React8.useRef(null);
@@ -7205,7 +7778,13 @@ function PagePreview({
7205
7778
  const iframe = React8.useRef(null);
7206
7779
  const loaded = React8.useRef(false);
7207
7780
  const anchor = React8.useRef(null);
7208
- const channel = React8.useMemo(() => crypto.randomUUID(), []);
7781
+ const version = versions?.view;
7782
+ const readOnly = Boolean(version);
7783
+ const viewRows = React8.useRef([]);
7784
+ viewRows.current = version ? version.values?.[zone] || [] : latest.current;
7785
+ const viewValues = React8.useRef({});
7786
+ viewValues.current = version ? version.values : values;
7787
+ const channel = React8.useMemo(() => crypto.randomUUID(), [host.model, host.documentId, host.locale, version?.scope, version?.event.id]);
7209
7788
  const { base, source } = state.preview;
7210
7789
  const url = base ? new URL(base) : null;
7211
7790
  url?.searchParams.set("channel", channel);
@@ -7224,7 +7803,8 @@ function PagePreview({
7224
7803
  setMode,
7225
7804
  onChange,
7226
7805
  clip,
7227
- clipCount
7806
+ clipCount,
7807
+ readOnly
7228
7808
  });
7229
7809
  live.current = {
7230
7810
  mode,
@@ -7234,7 +7814,8 @@ function PagePreview({
7234
7814
  setMode,
7235
7815
  onChange,
7236
7816
  clip,
7237
- clipCount
7817
+ clipCount,
7818
+ readOnly
7238
7819
  };
7239
7820
  const send = React8.useCallback(() => {
7240
7821
  iframe.current?.contentWindow?.postMessage(
@@ -7242,20 +7823,45 @@ function PagePreview({
7242
7823
  protocol: PROTOCOL,
7243
7824
  channel,
7244
7825
  type: "update-page",
7826
+ entry: projectEntry(
7827
+ viewValues.current,
7828
+ host.contentType,
7829
+ live.current.components,
7830
+ window.location.origin,
7831
+ host.readable
7832
+ ),
7833
+ contentType: {
7834
+ uid: host.model,
7835
+ kind: host.contentType?.kind,
7836
+ singularName: host.contentType?.info?.singularName,
7837
+ pluralName: host.contentType?.info?.pluralName,
7838
+ displayName: host.contentType?.info?.displayName
7839
+ },
7840
+ zone,
7245
7841
  blocks: projectPage(
7246
- latest.current,
7842
+ viewRows.current,
7247
7843
  live.current.components,
7248
7844
  window.location.origin,
7249
7845
  hiddenAttribute
7250
- ),
7846
+ ).map((block) => live.current.readOnly ? { ...block, fields: [], media: {} } : block),
7251
7847
  groups,
7252
7848
  locale: t.locale,
7253
7849
  mode: live.current.mode,
7254
- clipboard: live.current.clipCount
7850
+ clipboard: live.current.readOnly ? 0 : live.current.clipCount,
7851
+ readOnly: live.current.readOnly
7255
7852
  },
7256
7853
  origin
7257
7854
  );
7258
- }, [channel, origin, hiddenAttribute]);
7855
+ }, [channel, origin, hiddenAttribute, groups, host.contentType, host.model, host.readable, zone]);
7856
+ React8.useEffect(() => {
7857
+ if (readOnly) {
7858
+ setInserting(null);
7859
+ setBlockModal(null);
7860
+ setPicking(null);
7861
+ setFieldsPanel(null);
7862
+ setHovered(null);
7863
+ }
7864
+ }, [readOnly]);
7259
7865
  const indexOf = (key) => latest.current.findIndex((row) => blockKey(row) === key);
7260
7866
  const path = (key, field) => `${zone}.${indexOf(key)}.${field}`;
7261
7867
  React8.useEffect(() => {
@@ -7412,9 +8018,11 @@ function PagePreview({
7412
8018
  React8.useEffect(() => {
7413
8019
  if (!active) return;
7414
8020
  setReady(false);
8021
+ setReadOnlyBridge(false);
7415
8022
  setFailed(false);
7416
8023
  const timeout = setTimeout(() => setFailed(true), 15e3);
7417
8024
  const receive = (event) => {
8025
+ if (!previewMessageAllowed(event, origin, iframe.current?.contentWindow, channel, live.current.readOnly)) return;
7418
8026
  const is = (type) => isPreviewMessage(
7419
8027
  event,
7420
8028
  origin,
@@ -7427,6 +8035,7 @@ function PagePreview({
7427
8035
  clearTimeout(timeout);
7428
8036
  setReady(true);
7429
8037
  setFailed(false);
8038
+ setReadOnlyBridge(Array.isArray(event.data.capabilities) && event.data.capabilities.includes("readOnly"));
7430
8039
  send();
7431
8040
  return;
7432
8041
  }
@@ -7458,12 +8067,17 @@ function PagePreview({
7458
8067
  return;
7459
8068
  }
7460
8069
  if (is("delete-group") && canEdit2 && groups) {
7461
- const next = (0, import_groups.removeGroup)(
7462
- latest.current,
7463
- String(event.data.key),
7464
- groups
7465
- );
7466
- if (next) onChange2(zone, next);
8070
+ const key2 = String(event.data.key);
8071
+ const start = latest.current.findIndex((row) => blockKey(row) === key2);
8072
+ if (start < 0) return;
8073
+ const [, end] = (0, import_groups.groupRange)(latest.current, start, groups);
8074
+ if (end <= start || latest.current[end]?.__component !== groups[latest.current[start]?.__component]) return;
8075
+ const closes = new Set(Object.values(groups));
8076
+ setDeletingGroup({
8077
+ key: key2,
8078
+ label: components?.[latest.current[start]?.__component]?.info?.displayName || latest.current[start]?.__component || "",
8079
+ count: latest.current.slice(start + 1, end).filter((row) => !closes.has(row?.__component)).length
8080
+ });
7467
8081
  return;
7468
8082
  }
7469
8083
  if (is("insert-group") && canEdit2 && groups) {
@@ -7554,9 +8168,9 @@ function PagePreview({
7554
8168
  if (!ready || !active) return;
7555
8169
  const timer = setTimeout(send, 120);
7556
8170
  return () => clearTimeout(timer);
7557
- }, [values, host.components, ready, active, send, mode, clipCount]);
8171
+ }, [values, version, host.components, ready, active, send, mode, clipCount]);
7558
8172
  React8.useEffect(() => {
7559
- if (!active || !ready) return;
8173
+ if (!active || !ready || readOnly) return;
7560
8174
  let last = null;
7561
8175
  const post = (key) => {
7562
8176
  if (key === last) return;
@@ -7579,7 +8193,7 @@ function PagePreview({
7579
8193
  document.removeEventListener("pointerout", onOut);
7580
8194
  post(null);
7581
8195
  };
7582
- }, [active, ready, channel, origin]);
8196
+ }, [active, ready, channel, origin, readOnly]);
7583
8197
  React8.useEffect(() => {
7584
8198
  const item = hovered && active ? findZoneList(live.current.zoneLabel)?.querySelectorAll(":scope > li")[indexOf(hovered)] : void 0;
7585
8199
  hoverRow.current = item || null;
@@ -7633,7 +8247,7 @@ function PagePreview({
7633
8247
  }
7634
8248
  ) });
7635
8249
  const layout = toolbarLayout(editor?.previewToolbar);
7636
- const tools = { modes: switcher, history: historyTools, devices };
8250
+ const tools = { modes: switcher, history: !readOnly && historyTools, versions: versions?.button, devices };
7637
8251
  const toolbarShown = !ready || layout.before.length + layout.right.length + layout.after.length > 0;
7638
8252
  const onKey = (event) => {
7639
8253
  const map = {
@@ -7647,6 +8261,12 @@ function PagePreview({
7647
8261
  applyWidth(map[event.key], true);
7648
8262
  }
7649
8263
  };
8264
+ const confirmGroupDelete = (keepBlocks) => {
8265
+ if (!deletingGroup || !zone) return;
8266
+ const next = keepBlocks ? (0, import_groups.unwrapGroup)(latest.current, deletingGroup.key, groups) : (0, import_groups.removeGroup)(latest.current, deletingGroup.key, groups);
8267
+ setDeletingGroup(null);
8268
+ if (next) onChange(zone, next);
8269
+ };
7650
8270
  return (
7651
8271
  // Hidden anchor in the side panels column: split mode and the sidebar items find the edit view's grid from here.
7652
8272
  /* @__PURE__ */ jsxs6("div", { ref: anchor, children: [
@@ -7657,6 +8277,7 @@ function PagePreview({
7657
8277
  "data-testid": "page-preview-pane",
7658
8278
  "aria-label": t.previewPane,
7659
8279
  style: {
8280
+ top: topInset,
7660
8281
  left: mode === "preview" || narrow ? main.left : main.left + main.width - paneWidth,
7661
8282
  width: mode === "preview" || narrow ? main.width : paneWidth,
7662
8283
  userSelect: dragging ? "none" : void 0
@@ -7742,7 +8363,7 @@ ${/* Strapi 4's scrolled header is fixed to the viewport's right edge: beside th
7742
8363
  children: [
7743
8364
  !ready && /* @__PURE__ */ jsx9(Typography4, { variant: "pi", role: "status", textColor: "neutral600", children: failed ? t.previewFailed : t.previewLoading }),
7744
8365
  failed && /* @__PURE__ */ jsx9(Button3, { size: "S", variant: "secondary", onClick: retry, children: t.retry }),
7745
- layout.right.length > 0 && /* @__PURE__ */ jsx9(Actions, { parts: layout.right })
8366
+ !readOnly && layout.right.length > 0 && /* @__PURE__ */ jsx9(Actions, { parts: layout.right })
7746
8367
  ]
7747
8368
  }
7748
8369
  ),
@@ -7750,68 +8371,83 @@ ${/* Strapi 4's scrolled header is fixed to the viewport's right edge: beside th
7750
8371
  ]
7751
8372
  }
7752
8373
  ),
7753
- /* @__PURE__ */ jsxs6("div", { style: { flex: 1, minHeight: 0, display: "flex", flexDirection: sidebarPosition === "bottom" ? "column-reverse" : sidebarPosition === "right" ? "row-reverse" : "row" }, children: [
7754
- mode === "preview" && sidebar.length > 0 && /* @__PURE__ */ jsx9("div", { ref: setRailEl, style: { display: "flex" }, children: /* @__PURE__ */ jsx9(
7755
- Flex3,
7756
- {
7757
- "data-testid": "page-preview-sidebar",
7758
- "data-position": sidebarPosition,
7759
- role: "toolbar",
7760
- "aria-label": t.sidebarLabel,
7761
- direction: sidebarPosition === "bottom" ? "row" : "column",
7762
- gap: 1,
7763
- padding: 1,
7764
- background: "neutral100",
7765
- justifyContent: sidebarPosition === "bottom" ? "center" : "flex-start",
7766
- style: { [sidebarPosition === "bottom" ? "borderTop" : sidebarPosition === "right" ? "borderLeft" : "borderRight"]: `1px solid ${theme?.colors?.neutral200 || "#dcdce4"}`, overflow: "auto" },
7767
- children: sidebar.map((item, i) => /* @__PURE__ */ jsxs6(
7768
- RailButton,
7769
- {
7770
- type: "button",
7771
- $active: fieldsPanel === item,
7772
- "aria-pressed": fieldsPanel === item,
7773
- title: item.label,
7774
- "data-testid": item.custom ? `sidebar-panel-${item.id}` : `sidebar-item-${i}`,
7775
- onClick: () => setFieldsPanel(fieldsPanel === item ? null : item),
7776
- children: [
7777
- typeof item.icon === "string" ? item.icon && /* @__PURE__ */ jsx9(Icon, { name: item.icon }) : item.icon,
7778
- /* @__PURE__ */ jsx9("span", { children: item.label })
7779
- ]
7780
- },
7781
- `${item.label}-${i}`
7782
- ))
7783
- }
7784
- ) }),
7785
- /* @__PURE__ */ jsx9(
7786
- "div",
7787
- {
7788
- ref: setStage,
7789
- "data-testid": "page-preview-stage",
7790
- "data-device": device.id,
7791
- style: { position: "relative", flex: 1, overflow: "hidden", ...stageBackground(theme) },
7792
- children: /* @__PURE__ */ jsx9(
7793
- Frame2,
7794
- {
7795
- ref: iframe,
7796
- title: t.previewPane,
7797
- src: url.href,
7798
- sandbox: "allow-scripts allow-same-origin",
7799
- referrerPolicy: "no-referrer",
7800
- onLoad: () => {
7801
- loaded.current = true;
8374
+ versions?.banner,
8375
+ readOnly && ready && !readOnlyBridge && /* @__PURE__ */ jsx9(Box4, { padding: 2, background: "neutral100", children: /* @__PURE__ */ jsx9(Typography4, { variant: "pi", role: "status", children: t.versionsBridgeLegacy }) }),
8376
+ /* @__PURE__ */ jsxs6("div", { style: { flex: 1, minHeight: 0, display: "flex" }, children: [
8377
+ /* @__PURE__ */ jsxs6("div", { style: { flex: 1, minWidth: 0, minHeight: 0, display: "flex", flexDirection: sidebarPosition === "bottom" ? "column-reverse" : sidebarPosition === "right" ? "row-reverse" : "row" }, children: [
8378
+ !readOnly && mode === "preview" && sidebar.length > 0 && /* @__PURE__ */ jsx9("div", { ref: setRailEl, style: { display: "flex" }, children: /* @__PURE__ */ jsx9(
8379
+ Flex3,
8380
+ {
8381
+ "data-testid": "page-preview-sidebar",
8382
+ "data-position": sidebarPosition,
8383
+ role: "toolbar",
8384
+ "aria-label": t.sidebarLabel,
8385
+ direction: sidebarPosition === "bottom" ? "row" : "column",
8386
+ gap: 1,
8387
+ padding: 1,
8388
+ background: "neutral100",
8389
+ justifyContent: sidebarPosition === "bottom" ? "center" : "flex-start",
8390
+ style: { [sidebarPosition === "bottom" ? "borderTop" : sidebarPosition === "right" ? "borderLeft" : "borderRight"]: `1px solid ${theme?.colors?.neutral200 || "#dcdce4"}`, overflow: "auto" },
8391
+ children: sidebar.map((item, i) => /* @__PURE__ */ jsxs6(
8392
+ RailButton,
8393
+ {
8394
+ type: "button",
8395
+ $active: fieldsPanel === item,
8396
+ "aria-pressed": fieldsPanel === item,
8397
+ title: item.label,
8398
+ "data-testid": item.custom ? `sidebar-panel-${item.id}` : `sidebar-item-${i}`,
8399
+ onClick: () => setFieldsPanel(fieldsPanel === item ? null : item),
8400
+ children: [
8401
+ typeof item.icon === "string" ? item.icon && /* @__PURE__ */ jsx9(Icon, { name: item.icon }) : item.icon,
8402
+ /* @__PURE__ */ jsx9("span", { children: item.label })
8403
+ ]
7802
8404
  },
7803
- style: { ...frameStyle(device.width, stageSize), ...dragging ? { pointerEvents: "none" } : {} }
7804
- },
7805
- attempt
7806
- )
7807
- }
7808
- )
8405
+ `${item.label}-${i}`
8406
+ ))
8407
+ }
8408
+ ) }),
8409
+ /* @__PURE__ */ jsx9(
8410
+ "div",
8411
+ {
8412
+ ref: setStage,
8413
+ "data-testid": "page-preview-stage",
8414
+ "data-device": device.id,
8415
+ style: { position: "relative", flex: 1, overflow: "hidden", ...stageBackground(theme) },
8416
+ children: /* @__PURE__ */ jsx9(
8417
+ Frame2,
8418
+ {
8419
+ ref: iframe,
8420
+ title: t.previewPane,
8421
+ src: url.href,
8422
+ sandbox: "allow-scripts allow-same-origin",
8423
+ referrerPolicy: "no-referrer",
8424
+ ...readOnly && !readOnlyBridge ? { inert: "", tabIndex: -1 } : {},
8425
+ onLoad: () => {
8426
+ loaded.current = true;
8427
+ },
8428
+ style: { ...frameStyle(device.width, stageSize), ...dragging || readOnly && !readOnlyBridge ? { pointerEvents: "none" } : {} }
8429
+ },
8430
+ attempt
8431
+ )
8432
+ }
8433
+ )
8434
+ ] }),
8435
+ versions?.drawer
7809
8436
  ] })
7810
8437
  ]
7811
8438
  }
7812
8439
  ),
7813
8440
  document.body
7814
8441
  ),
8442
+ deletingGroup && /* @__PURE__ */ jsx9(Modal2, { open: true, width: "48rem", onOpenChange: (open) => !open && setDeletingGroup(null), trigger: null, title: t.confirmDeleteGroupTitle, children: /* @__PURE__ */ jsxs6(Flex3, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "preview-confirm-delete-group", children: [
8443
+ /* @__PURE__ */ jsx9(Typography4, { children: t.f("confirmDeleteGroup", { name: deletingGroup.label, count: deletingGroup.count }) }),
8444
+ deletingGroup.count > 0 && /* @__PURE__ */ jsx9(Typography4, { variant: "pi", textColor: "neutral600", children: t.f("confirmDeleteGroupHint", { count: deletingGroup.count }) }),
8445
+ /* @__PURE__ */ jsxs6(Flex3, { gap: 2, justifyContent: "flex-end", children: [
8446
+ /* @__PURE__ */ jsx9(Button3, { variant: "tertiary", onClick: () => setDeletingGroup(null), children: t.cancel }),
8447
+ deletingGroup.count > 0 && /* @__PURE__ */ jsx9(Button3, { variant: "secondary", onClick: () => confirmGroupDelete(true), children: t.keepGroupBlocks }),
8448
+ /* @__PURE__ */ jsx9(Button3, { variant: "danger", onClick: () => confirmGroupDelete(false), children: t.f("deleteGroupAndBlocks", { count: deletingGroup.count }) })
8449
+ ] })
8450
+ ] }) }),
7815
8451
  inserting && insertAttr && /* @__PURE__ */ jsx9(
7816
8452
  PickerModal,
7817
8453
  {
@@ -7832,6 +8468,7 @@ ${/* Strapi 4's scrolled header is fixed to the viewport's right edge: beside th
7832
8468
  if (!open) setInserting(null);
7833
8469
  },
7834
8470
  onSelect: (uid, values2) => {
8471
+ if (live.current.readOnly) return;
7835
8472
  const rows = inserting.zone === zone ? latest.current : Array.isArray(host.values?.[inserting.zone]) ? host.values[inserting.zone] : [];
7836
8473
  const index = insertIndex(rows, inserting.after);
7837
8474
  setInserting(null);
@@ -7956,6 +8593,7 @@ ${/* Strapi 4's scrolled header is fixed to the viewport's right edge: beside th
7956
8593
  multiple: picking.attr.multiple === true,
7957
8594
  onClose: () => setPicking(null),
7958
8595
  onSelectAssets: (assets) => {
8596
+ if (live.current.readOnly) return;
7959
8597
  const index = indexOf(picking.key);
7960
8598
  setPicking(null);
7961
8599
  if (index < 0 || !assets?.length) return;
@@ -7993,6 +8631,27 @@ var Card2 = styled7.div`
7993
8631
  display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: 4px;
7994
8632
  border: 1px solid ${({ theme }) => theme.colors.neutral200}; background: ${({ theme }) => theme.colors.neutral0};
7995
8633
  `;
8634
+ var ContentTypeGrid = styled7.div`
8635
+ display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr)); gap: 16px; align-items: start;
8636
+ `;
8637
+ var ContentTypeCard = styled7.div`
8638
+ display: flex; flex-direction: column; gap: 16px; padding: 20px; border-radius: 4px;
8639
+ border: 1px solid ${({ theme }) => theme.colors.neutral200}; background: ${({ theme }) => theme.colors.neutral0};
8640
+ `;
8641
+ var ContentTypeTop = styled7.div`
8642
+ display: grid; grid-template-columns: minmax(0, 1fr) minmax(190px, 240px); gap: 16px; align-items: end;
8643
+ @media (max-width: 520px) { grid-template-columns: 1fr; }
8644
+ `;
8645
+ var Advanced = styled7.details`
8646
+ border-top: 1px solid ${({ theme }) => theme.colors.neutral200}; padding-top: 12px;
8647
+ summary { cursor: pointer; color: ${({ theme }) => theme.colors.neutral800}; font-size: 13px; font-weight: 600; }
8648
+ summary::marker { color: ${({ theme }) => theme.colors.neutral500}; }
8649
+ &[open] summary { margin-bottom: 16px; }
8650
+ `;
8651
+ var ToolbarSection = styled7.div`
8652
+ display: flex; flex-direction: column; gap: 12px; margin-top: 16px; padding-top: 16px;
8653
+ border-top: 1px solid ${({ theme }) => theme.colors.neutral200};
8654
+ `;
7996
8655
  var Bar = styled7.div`
7997
8656
  position: fixed; top: 0; z-index: 4; padding: 12px 32px;
7998
8657
  background: ${({ theme }) => theme.colors.neutral100}; border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};
@@ -8037,13 +8696,33 @@ function ColorField({ name, label, value, onChange, disabled }) {
8037
8696
  ] });
8038
8697
  }
8039
8698
  function TagsField({ name, label, hint, value, onChange, disabled }) {
8040
- const [text, setText] = React9.useState(value.join(", "));
8699
+ const external = value.join(", ");
8700
+ const input = React9.useRef(null);
8701
+ const focused = React9.useRef(false);
8702
+ const parse = (next) => [...new Set(next.split(",").map((tag) => tag.replace(/[<>]/g, "").trim().slice(0, 24)).filter(Boolean))].slice(0, 10);
8703
+ React9.useEffect(() => {
8704
+ if (!focused.current && input.current && input.current.value !== external) input.current.value = external;
8705
+ }, [external]);
8041
8706
  return /* @__PURE__ */ jsxs7(Label, { children: [
8042
8707
  /* @__PURE__ */ jsx10(Typography5, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
8043
- /* @__PURE__ */ jsx10("input", { name, value: text, disabled, onChange: (e) => {
8044
- setText(e.target.value);
8045
- onChange([...new Set(e.target.value.split(",").map((tag) => tag.replace(/[<>]/g, "").trim().slice(0, 24)).filter(Boolean))].slice(0, 10));
8046
- }, style: { padding: "6px 8px", border: "1px solid #dcdce4", borderRadius: 4, fontSize: 13 } }),
8708
+ /* @__PURE__ */ jsx10(
8709
+ "input",
8710
+ {
8711
+ ref: input,
8712
+ name,
8713
+ defaultValue: external,
8714
+ disabled,
8715
+ spellCheck: false,
8716
+ onFocus: () => {
8717
+ focused.current = true;
8718
+ },
8719
+ onBlur: (e) => {
8720
+ focused.current = false;
8721
+ onChange(parse(e.currentTarget.value));
8722
+ },
8723
+ style: { padding: "6px 8px", border: "1px solid #dcdce4", borderRadius: 4, fontSize: 13 }
8724
+ }
8725
+ ),
8047
8726
  /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: hint })
8048
8727
  ] });
8049
8728
  }
@@ -8075,12 +8754,12 @@ var Checks = styled7.fieldset`
8075
8754
  legend { font-size: 12px; font-weight: 600; margin-bottom: 4px; }
8076
8755
  label { display: inline-flex; align-items: center; gap: 6px; }
8077
8756
  `;
8078
- var TOOLBAR2 = ["modes", "history", "devices", "status", "actions"];
8757
+ var TOOLBAR2 = ["modes", "history", "versions", "devices", "status", "actions"];
8079
8758
  var DEVICE_NAMES = ["fit", "mobile", "tablet", "desktop"];
8080
8759
  var DEVICE_LABEL = /^[^<>]{1,24}$/;
8081
8760
  var badDevices = (list = []) => list.length < 1 || list.length > 8 || list.some((item) => typeof item !== "string" && (!DEVICE_LABEL.test(String(item.label || "").trim()) || !(Number.isInteger(item.width) && item.width >= 240 && item.width <= 3840))) || new Set(list.map((item) => typeof item === "string" ? item : item.width)).size !== list.length;
8082
8761
  var Row = styled7.div` display: flex; align-items: center; gap: 8px; min-height: 36px; font-size: 13px; color: ${({ theme }) => theme.colors.neutral800}; `;
8083
- function PaneEditor({ id, toolbar, devices, set: set2, t, disabled, TextField: TextField2 }) {
8762
+ function PaneEditor({ id, toolbar, devices, set: set2, t, disabled, TextField: TextField2, versions }) {
8084
8763
  const move = (list, index, by) => {
8085
8764
  const next = [...list];
8086
8765
  [next[index], next[index + by]] = [next[index + by], next[index]];
@@ -8103,7 +8782,7 @@ function PaneEditor({ id, toolbar, devices, set: set2, t, disabled, TextField: T
8103
8782
  const width = (index, patch) => set2("previewDevices", devices.map((item, i) => i === index ? { ...item, ...patch } : item));
8104
8783
  return /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 3, "data-testid": `pane-editor-${id}`, children: [
8105
8784
  /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: t.paneHelp }),
8106
- /* @__PURE__ */ jsx10(Box5, { children: [...toolbar, ...TOOLBAR2.filter((item) => !toolbar.includes(item))].map((item) => /* @__PURE__ */ jsxs7(Row, { "data-testid": `${id}-toolbar-${item}`, children: [
8785
+ /* @__PURE__ */ jsx10(Box5, { children: [...toolbar, ...TOOLBAR2.filter((item) => !toolbar.includes(item))].filter((item) => item !== "versions" || versions).map((item) => /* @__PURE__ */ jsxs7(Row, { "data-testid": `${id}-toolbar-${item}`, children: [
8107
8786
  arrows(toolbar, toolbar.indexOf(item), "previewToolbar"),
8108
8787
  /* @__PURE__ */ jsxs7("label", { style: { display: "inline-flex", gap: 6, alignItems: "center" }, children: [
8109
8788
  check(toolbar, item, "previewToolbar"),
@@ -8204,10 +8883,9 @@ function SidebarEditor({ type, entry, set: set2, t, disabled, SelectField: Selec
8204
8883
  };
8205
8884
  const fields = (type.attributes || []).filter((attr) => !SYSTEM_FIELDS2.includes(attr.name));
8206
8885
  const id = (name, index) => `sidebar-${name}-${type.uid}${index === void 0 ? "" : `-${index}`}`;
8207
- return /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 3, paddingLeft: 4, "data-testid": `sidebar-editor-${type.uid}`, children: [
8208
- /* @__PURE__ */ jsx10(Typography5, { variant: "delta", tag: "h3", children: t.f("sidebarTitle", { name: type.displayName }) }),
8886
+ return /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 3, "data-testid": `sidebar-editor-${type.uid}`, children: [
8209
8887
  /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: t.sidebarHelp }),
8210
- /* @__PURE__ */ jsx10(Box5, { style: { maxWidth: 240 }, children: /* @__PURE__ */ jsx10(
8888
+ /* @__PURE__ */ jsx10(Box5, { children: /* @__PURE__ */ jsx10(
8211
8889
  SelectField2,
8212
8890
  {
8213
8891
  name: id("position"),
@@ -8283,7 +8961,7 @@ function SidebarEditor({ type, entry, set: set2, t, disabled, SelectField: Selec
8283
8961
  ] });
8284
8962
  }
8285
8963
  var permissions = { read: [{ action: "plugin::blockscene.settings.read", subject: null }], update: [{ action: "plugin::blockscene.settings.update", subject: null }] };
8286
- function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: MediaPicker2, ToggleField: ToggleField2, SelectField: SelectField2, TextField: TextField2, lazyEditors = false }) {
8964
+ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: MediaPicker2, ToggleField: ToggleField2, SelectField: SelectField2, TextField: TextField2, lazyEditors = false, section = "general" }) {
8287
8965
  const t = useMessages();
8288
8966
  const { get, put, del } = useClient();
8289
8967
  const { canRead, canUpdate, isLoading } = usePermissions2();
@@ -8301,7 +8979,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8301
8979
  React9.useEffect(() => {
8302
8980
  if (!canRead || isLoading) return;
8303
8981
  let active = true;
8304
- Promise.all([get("/blockscene/settings"), get("/blockscene/catalog")]).then(([s, c]) => {
8982
+ Promise.all([get("/blockscene/settings"), section === "gallery" ? get("/blockscene/catalog") : Promise.resolve({ data: {} })]).then(([s, c]) => {
8305
8983
  if (!active) return;
8306
8984
  setData(s.data);
8307
8985
  setSettings(s.data.settings);
@@ -8313,18 +8991,20 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8313
8991
  return () => {
8314
8992
  active = false;
8315
8993
  };
8316
- }, [get, canRead, isLoading]);
8994
+ }, [get, canRead, isLoading, section]);
8317
8995
  const update = (patch) => {
8318
8996
  setSettings((current) => patch(structuredClone(current)));
8319
8997
  setDirty(true);
8320
8998
  setStatus("");
8321
8999
  };
8322
- const badColor = settings && (Object.values(settings.palette).some((value) => !COLOR2.test(value)) || [settings.editor.previewUrl, settings.editor.blockPreviewUrl].some((url) => url && !/^https?:\/\/\S+$/.test(url)));
9000
+ const badPalette = settings && Object.values(settings.palette).some((value) => !COLOR2.test(value));
9001
+ const badPreviewUrl = settings && [settings.editor.previewUrl, settings.editor.blockPreviewUrl].some((url) => url && !/^https?:\/\/\S+$/.test(url));
8323
9002
  const badSidebar = settings && Object.values(settings.contentTypes || {}).some((entry) => (entry.sidebar || []).some(badItem));
8324
9003
  const badLazy = settings && badUids(settings.editor.lazyFields);
8325
9004
  const badHistory = settings && data?.historyTypes && badRetention(settings.history);
8326
- const badPane = settings && [settings.editor, ...Object.values(settings.contentTypes || {})].some((entry) => entry.previewDevices && badDevices(entry.previewDevices));
8327
- const invalid = badColor || badSidebar || badLazy || badHistory || badPane;
9005
+ const badEditorPane = settings && settings.editor.previewDevices && badDevices(settings.editor.previewDevices);
9006
+ const badTypePane = settings && Object.values(settings.contentTypes || {}).some((entry) => entry.previewDevices && badDevices(entry.previewDevices));
9007
+ const invalid = section === "general" ? badLazy : section === "preview" ? badPreviewUrl || badEditorPane : section === "content-types" ? badSidebar || badTypePane : section === "gallery" ? badPalette : badHistory;
8328
9008
  const save = async () => {
8329
9009
  if (!settings || invalid || !canUpdate) return;
8330
9010
  setSaving(true);
@@ -8376,6 +9056,8 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8376
9056
  return index === 0 && manual ? t.manual : t.automatic;
8377
9057
  };
8378
9058
  const ready = !isLoading && canRead && !failed && settings && catalog;
9059
+ const sectionTitle = t[`settings${section === "content-types" ? "ContentTypes" : section[0].toUpperCase() + section.slice(1)}`];
9060
+ const sectionIntro = t[`settings${section === "content-types" ? "ContentTypes" : section[0].toUpperCase() + section.slice(1)}Intro`];
8379
9061
  const header = React9.useRef(null);
8380
9062
  const [floating, setFloating] = React9.useState(false);
8381
9063
  const main = useMainRect2(header);
@@ -8388,22 +9070,22 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8388
9070
  }, [ready]);
8389
9071
  const controls = (suffix) => ready && /* @__PURE__ */ jsxs7(Flex4, { gap: 3, alignItems: "center", wrap: "wrap", children: [
8390
9072
  /* @__PURE__ */ jsx10(Typography5, { role: "status", "aria-live": "polite", textColor: dirty ? "warning700" : "neutral600", "data-testid": `${dirty ? "unsaved-indicator" : "save-status"}${suffix}`, children: dirty ? t.unsaved : status || t.noChanges }),
8391
- !suffix && /* @__PURE__ */ jsx10(Button4, { variant: "tertiary", onClick: restore, disabled: !canUpdate || saving, "data-testid": "restore-blockscene-settings", children: data.projectDefaults ? t.restoreProject : t.resetAll }),
9073
+ !suffix && section === "general" && /* @__PURE__ */ jsx10(Button4, { variant: "tertiary", onClick: restore, disabled: !canUpdate || saving, "data-testid": "restore-blockscene-settings", children: data.projectDefaults ? t.restoreProject : t.resetAll }),
8392
9074
  /* @__PURE__ */ jsx10(Button4, { onClick: save, disabled: !canUpdate || invalid || !dirty, loading: saving, "data-testid": `save-blockscene-settings${suffix}`, children: t.save })
8393
9075
  ] });
8394
9076
  return /* @__PURE__ */ jsx10(Box5, { padding: 8, background: "neutral100", children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 5, children: [
8395
9077
  /* @__PURE__ */ jsx10("div", { ref: header, children: /* @__PURE__ */ jsxs7(Flex4, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
8396
- /* @__PURE__ */ jsx10(Typography5, { variant: "alpha", tag: "h1", children: t.settingsTitle }),
9078
+ /* @__PURE__ */ jsx10(Typography5, { variant: "alpha", tag: "h1", children: sectionTitle }),
8397
9079
  controls("")
8398
9080
  ] }) }),
8399
9081
  floating && main.width > 0 && /* @__PURE__ */ jsx10(Bar, { style: { left: main.left, width: main.width }, "data-testid": "settings-floating-bar", children: /* @__PURE__ */ jsxs7(Flex4, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
8400
- /* @__PURE__ */ jsx10(Typography5, { variant: "beta", tag: "p", children: t.settingsTitle }),
9082
+ /* @__PURE__ */ jsx10(Typography5, { variant: "beta", tag: "p", children: sectionTitle }),
8401
9083
  controls("-floating")
8402
9084
  ] }) }),
8403
- /* @__PURE__ */ jsx10(Typography5, { textColor: "neutral600", children: t.settingsIntro }),
9085
+ /* @__PURE__ */ jsx10(Typography5, { textColor: "neutral600", children: sectionIntro }),
8404
9086
  isLoading ? /* @__PURE__ */ jsx10(Typography5, { children: "\u2026" }) : !canRead ? /* @__PURE__ */ jsx10(Typography5, { role: "alert", children: t.denied }) : failed ? /* @__PURE__ */ jsx10(Typography5, { role: "alert", children: t.loadFailed }) : !settings || !catalog ? /* @__PURE__ */ jsx10(Typography5, { children: t.loading }) : /* @__PURE__ */ jsxs7(Fragment8, { children: [
8405
9087
  data.disabled && /* @__PURE__ */ jsx10(Box5, { padding: 4, background: "warning100", hasRadius: true, children: /* @__PURE__ */ jsx10(Typography5, { role: "alert", textColor: "warning700", children: t.disabledByServer }) }),
8406
- /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
9088
+ section === "gallery" && /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
8407
9089
  /* @__PURE__ */ jsx10(Typography5, { variant: "beta", tag: "h2", children: t.palette }),
8408
9090
  /* @__PURE__ */ jsx10(Swatches, { children: Object.keys(DEFAULT_PALETTE).map((key) => /* @__PURE__ */ jsx10(
8409
9091
  ColorField,
@@ -8419,7 +9101,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8419
9101
  },
8420
9102
  key
8421
9103
  )) }),
8422
- badColor && /* @__PURE__ */ jsx10(Typography5, { role: "alert", textColor: "danger600", children: t.invalidColor }),
9104
+ badPalette && /* @__PURE__ */ jsx10(Typography5, { role: "alert", textColor: "danger600", children: t.invalidColor }),
8423
9105
  /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: t.previewLabel }),
8424
9106
  /* @__PURE__ */ jsx10(Swatches, { "data-testid": "palette-preview", children: TEMPLATES.map((template) => /* @__PURE__ */ jsxs7(Flex4, { direction: "column", gap: 1, children: [
8425
9107
  /* @__PURE__ */ jsx10(Box5, { style: { aspectRatio: "16 / 9", overflow: "hidden" }, hasRadius: true, children: /* @__PURE__ */ jsx10(Wireframe, { template, palette: settings.palette }) }),
@@ -8430,7 +9112,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8430
9112
  return s;
8431
9113
  }), children: t.resetPalette }) })
8432
9114
  ] }) }),
8433
- /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
9115
+ section === "general" && /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
8434
9116
  /* @__PURE__ */ jsx10(Typography5, { variant: "beta", tag: "h2", children: t.editor }),
8435
9117
  /* @__PURE__ */ jsx10(ToggleField2, { name: "editor-enabled", label: t.enabled, value: editor.enabled, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
8436
9118
  s.editor.enabled = v;
@@ -8470,6 +9152,30 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8470
9152
  }
8471
9153
  ),
8472
9154
  /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: t.rememberHelp }),
9155
+ lazyEditors && /* @__PURE__ */ jsxs7(Fragment8, { children: [
9156
+ /* @__PURE__ */ jsx10(ToggleField2, { name: "editor-lazyEditors", label: t.lazyEditors, value: editor.lazyEditors !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
9157
+ s.editor.lazyEditors = v;
9158
+ return s;
9159
+ }) }),
9160
+ /* @__PURE__ */ jsx10(
9161
+ UidListField,
9162
+ {
9163
+ TextField: TextField2,
9164
+ name: "editor-lazyFields",
9165
+ label: t.lazyFields,
9166
+ value: editor.lazyFields || [],
9167
+ disabled: !canUpdate || saving || editor.lazyEditors === false,
9168
+ placeholder: "plugin::ckeditor5.CKEditor",
9169
+ onChange: (uids) => update((s) => {
9170
+ s.editor.lazyFields = uids;
9171
+ return s;
9172
+ })
9173
+ }
9174
+ ),
9175
+ /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: badLazy ? "danger600" : "neutral600", role: badLazy ? "alert" : void 0, children: badLazy ? t.f("lazyFieldsInvalid", { max: LAZY_MAX }) : t.lazyEditorsHelp })
9176
+ ] })
9177
+ ] }) }),
9178
+ section === "preview" && /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
8473
9179
  /* @__PURE__ */ jsx10(
8474
9180
  TextField2,
8475
9181
  {
@@ -8521,6 +9227,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8521
9227
  PaneEditor,
8522
9228
  {
8523
9229
  id: "editor",
9230
+ versions: Boolean(data.historyTypes),
8524
9231
  toolbar: editor.previewToolbar || TOOLBAR2,
8525
9232
  devices: editor.previewDevices || DEVICE_NAMES,
8526
9233
  t,
@@ -8532,37 +9239,16 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8532
9239
  })
8533
9240
  }
8534
9241
  ),
8535
- lazyEditors && /* @__PURE__ */ jsxs7(Fragment8, { children: [
8536
- /* @__PURE__ */ jsx10(ToggleField2, { name: "editor-lazyEditors", label: t.lazyEditors, value: editor.lazyEditors !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
8537
- s.editor.lazyEditors = v;
9242
+ badPreviewUrl && /* @__PURE__ */ jsx10(Typography5, { role: "alert", textColor: "danger600", children: t.invalidUrl }),
9243
+ lazyEditors && data.blockPreviewAvailable && /* @__PURE__ */ jsxs7(Fragment8, { children: [
9244
+ /* @__PURE__ */ jsx10(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
9245
+ s.editor.blockPreviewInForm = v;
8538
9246
  return s;
8539
9247
  }) }),
8540
- /* @__PURE__ */ jsx10(
8541
- UidListField,
8542
- {
8543
- TextField: TextField2,
8544
- name: "editor-lazyFields",
8545
- label: t.lazyFields,
8546
- value: editor.lazyFields || [],
8547
- disabled: !canUpdate || saving || editor.lazyEditors === false,
8548
- placeholder: "plugin::ckeditor5.CKEditor",
8549
- onChange: (uids) => update((s) => {
8550
- s.editor.lazyFields = uids;
8551
- return s;
8552
- })
8553
- }
8554
- ),
8555
- /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: badLazy ? "danger600" : "neutral600", role: badLazy ? "alert" : void 0, children: badLazy ? t.f("lazyFieldsInvalid", { max: LAZY_MAX }) : t.lazyEditorsHelp }),
8556
- data.blockPreviewAvailable && /* @__PURE__ */ jsxs7(Fragment8, { children: [
8557
- /* @__PURE__ */ jsx10(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
8558
- s.editor.blockPreviewInForm = v;
8559
- return s;
8560
- }) }),
8561
- /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
8562
- ] })
9248
+ /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
8563
9249
  ] })
8564
9250
  ] }) }),
8565
- /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "row-actions-settings", children: [
9251
+ section === "general" && /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "row-actions-settings", children: [
8566
9252
  /* @__PURE__ */ jsx10(Typography5, { variant: "beta", tag: "h2", children: t.rowActionsTitle }),
8567
9253
  /* @__PURE__ */ jsx10(ToggleField2, { name: "editor-confirmDelete", label: t.confirmDeleteOption, value: editor.confirmDelete !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
8568
9254
  s.editor.confirmDelete = v;
@@ -8592,7 +9278,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8592
9278
  ),
8593
9279
  /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: data.hiddenAttribute ? t.hiddenBlocksHelp : t.hiddenAttributeOff })
8594
9280
  ] }) }),
8595
- data.historyTypes && settings.history && /* @__PURE__ */ jsx10(
9281
+ section === "history" && data.historyTypes && settings.history && /* @__PURE__ */ jsx10(
8596
9282
  HistorySettings,
8597
9283
  {
8598
9284
  types: data.historyTypes,
@@ -8607,10 +9293,10 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8607
9293
  })
8608
9294
  }
8609
9295
  ),
8610
- (data.contentTypes || []).length > 0 && /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "content-types", children: [
8611
- /* @__PURE__ */ jsx10(Typography5, { variant: "beta", tag: "h2", children: t.contentTypes }),
8612
- /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: t.contentTypesHelp }),
8613
- data.contentTypes.map((type) => {
9296
+ section === "history" && !data.historyTypes && /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsx10(Typography5, { textColor: "neutral600", children: t.historyUnavailable }) }),
9297
+ section === "content-types" && (data.contentTypes || []).length > 0 && /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "content-types", children: [
9298
+ /* @__PURE__ */ jsx10(Box5, { padding: 4, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: t.contentTypesHelp }) }),
9299
+ /* @__PURE__ */ jsx10(ContentTypeGrid, { children: data.contentTypes.map((type) => {
8614
9300
  const entry = settings.contentTypes?.[type.uid] || {};
8615
9301
  const set2 = (key, value, fallback) => update((s) => {
8616
9302
  const next = { ...s.contentTypes?.[type.uid] || {} };
@@ -8621,9 +9307,10 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8621
9307
  else delete s.contentTypes[type.uid];
8622
9308
  return s;
8623
9309
  });
8624
- return /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
8625
- /* @__PURE__ */ jsxs7(Flex4, { gap: 6, alignItems: "flex-end", wrap: "wrap", "data-testid": `content-type-${type.uid}`, children: [
8626
- /* @__PURE__ */ jsx10(Box5, { style: { minWidth: 220 }, children: /* @__PURE__ */ jsx10(
9310
+ const customized = Boolean(entry.sidebar?.length || entry.sidebarPosition || entry.previewToolbar || entry.previewDevices);
9311
+ return /* @__PURE__ */ jsxs7(ContentTypeCard, { "data-testid": `content-type-${type.uid}`, children: [
9312
+ /* @__PURE__ */ jsxs7(ContentTypeTop, { children: [
9313
+ /* @__PURE__ */ jsx10(Box5, { children: /* @__PURE__ */ jsx10(
8627
9314
  ToggleField2,
8628
9315
  {
8629
9316
  name: `type-enabled-${type.uid}`,
@@ -8633,7 +9320,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8633
9320
  onChange: (v) => set2("enabled", v, true)
8634
9321
  }
8635
9322
  ) }),
8636
- /* @__PURE__ */ jsx10(Box5, { style: { minWidth: 240 }, children: /* @__PURE__ */ jsx10(
9323
+ /* @__PURE__ */ jsx10(Box5, { children: /* @__PURE__ */ jsx10(
8637
9324
  SelectField2,
8638
9325
  {
8639
9326
  name: `type-mode-${type.uid}`,
@@ -8645,45 +9332,51 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8645
9332
  }
8646
9333
  ) })
8647
9334
  ] }),
8648
- entry.enabled !== false && /* @__PURE__ */ jsx10(SidebarEditor, { type, entry, set: set2, t, disabled: !canUpdate || saving, SelectField: SelectField2, TextField: TextField2 }),
8649
- entry.enabled !== false && /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 3, paddingLeft: 4, children: [
8650
- /* @__PURE__ */ jsx10(
8651
- ToggleField2,
8652
- {
8653
- name: `type-pane-${type.uid}`,
8654
- label: t.f("paneTypeOverride", { name: type.displayName }),
8655
- value: Boolean(entry.previewToolbar || entry.previewDevices),
8656
- disabled: !canUpdate || saving,
8657
- onChange: (v) => {
8658
- set2("previewToolbar", v ? [...editor.previewToolbar || TOOLBAR2] : void 0, void 0);
8659
- set2("previewDevices", v ? structuredClone(editor.previewDevices || DEVICE_NAMES) : void 0, void 0);
9335
+ entry.enabled !== false && /* @__PURE__ */ jsxs7(Advanced, { defaultOpen: customized, children: [
9336
+ /* @__PURE__ */ jsx10("summary", { children: t.typeAdvanced }),
9337
+ /* @__PURE__ */ jsx10(SidebarEditor, { type, entry, set: set2, t, disabled: !canUpdate || saving, SelectField: SelectField2, TextField: TextField2 }),
9338
+ /* @__PURE__ */ jsxs7(ToolbarSection, { children: [
9339
+ /* @__PURE__ */ jsx10(
9340
+ ToggleField2,
9341
+ {
9342
+ name: `type-pane-${type.uid}`,
9343
+ label: t.f("paneTypeOverride", { name: type.displayName }),
9344
+ value: Boolean(entry.previewToolbar || entry.previewDevices),
9345
+ disabled: !canUpdate || saving,
9346
+ onChange: (v) => {
9347
+ set2("previewToolbar", v ? [...editor.previewToolbar || TOOLBAR2] : void 0, void 0);
9348
+ set2("previewDevices", v ? structuredClone(editor.previewDevices || DEVICE_NAMES) : void 0, void 0);
9349
+ }
8660
9350
  }
8661
- }
8662
- ),
8663
- (entry.previewToolbar || entry.previewDevices) && /* @__PURE__ */ jsx10(
8664
- PaneEditor,
8665
- {
8666
- id: `type-${type.uid}`,
8667
- toolbar: entry.previewToolbar || editor.previewToolbar || TOOLBAR2,
8668
- devices: entry.previewDevices || editor.previewDevices || DEVICE_NAMES,
8669
- t,
8670
- disabled: !canUpdate || saving,
8671
- TextField: TextField2,
8672
- set: (key, value) => set2(key, value, void 0)
8673
- }
8674
- )
9351
+ ),
9352
+ (entry.previewToolbar || entry.previewDevices) && /* @__PURE__ */ jsx10(
9353
+ PaneEditor,
9354
+ {
9355
+ id: `type-${type.uid}`,
9356
+ versions: Boolean(data.historyTypes),
9357
+ toolbar: entry.previewToolbar || editor.previewToolbar || TOOLBAR2,
9358
+ devices: entry.previewDevices || editor.previewDevices || DEVICE_NAMES,
9359
+ t,
9360
+ disabled: !canUpdate || saving,
9361
+ TextField: TextField2,
9362
+ set: (key, value) => set2(key, value, void 0)
9363
+ }
9364
+ )
9365
+ ] })
8675
9366
  ] })
8676
9367
  ] }, type.uid);
8677
- }),
9368
+ }) }),
8678
9369
  badSidebar && /* @__PURE__ */ jsx10(Typography5, { role: "alert", textColor: "danger600", children: t.sidebarInvalidSave })
8679
- ] }) }),
8680
- /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
9370
+ ] }),
9371
+ section === "gallery" && /* @__PURE__ */ jsx10(Box5, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs7(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
8681
9372
  /* @__PURE__ */ jsx10(Typography5, { variant: "beta", tag: "h2", children: t.components }),
8682
9373
  /* @__PURE__ */ jsx10(Searchbar2, { name: "component-filter", value: filter, placeholder: t.filter, clearLabel: t.clear, onClear: () => setFilter(""), onChange: (e) => setFilter(e.target.value), children: t.filter }),
8683
9374
  /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", "data-testid": "components-count", children: t.f("countAll", { count: components.length }) }),
8684
9375
  /* @__PURE__ */ jsx10(Grid2, { "data-testid": "components-grid", children: components.map((component) => {
8685
9376
  const entry = settings.components[component.uid] || {};
8686
9377
  const meta = { ...catalog.components?.[component.uid] || {}, ...media[component.uid] || {} };
9378
+ const groupMarker = Boolean(catalog.groups?.[component.uid] || Object.values(catalog.groups || {}).includes(component.uid));
9379
+ const rowThumbnail = entry.showRowThumbnail ?? !groupMarker;
8687
9380
  const candidates = candidatesFor(component.uid, meta, catalog);
8688
9381
  return /* @__PURE__ */ jsxs7(Card2, { "data-testid": `settings-${component.uid}`, children: [
8689
9382
  /* @__PURE__ */ jsx10(
@@ -8762,6 +9455,16 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
8762
9455
  onChange: (tags) => setComponent(component.uid, "tags", tags.length ? tags : void 0)
8763
9456
  }
8764
9457
  ),
9458
+ /* @__PURE__ */ jsx10(
9459
+ ToggleField2,
9460
+ {
9461
+ name: `row-thumbnail-${component.uid}`,
9462
+ label: t.componentRowThumbnail,
9463
+ value: rowThumbnail,
9464
+ disabled: !canUpdate || saving,
9465
+ onChange: (v) => setComponent(component.uid, "showRowThumbnail", v)
9466
+ }
9467
+ ),
8765
9468
  meta.variants?.length > 0 && /* @__PURE__ */ jsxs7(Typography5, { variant: "pi", textColor: "neutral600", "data-testid": `variants-${component.uid}`, children: [
8766
9469
  t.variantsFromCode,
8767
9470
  ": ",
@@ -8837,18 +9540,29 @@ function LayoutFields({ component, layout, set: set2, t, disabled, SelectField:
8837
9540
  /* @__PURE__ */ jsx10(Typography5, { variant: "pi", textColor: "neutral600", children: fields.length ? t.layoutHelp : t.layoutNoFields })
8838
9541
  ] });
8839
9542
  }
9543
+ var SETTINGS_SECTIONS = [
9544
+ { id: "general", label: "General" },
9545
+ { id: "preview", label: "Page preview" },
9546
+ { id: "content-types", label: "Content types" },
9547
+ { id: "gallery", label: "Block gallery" },
9548
+ { id: "history", label: "History & trash" }
9549
+ ];
8840
9550
  function register(app, Component2, to) {
8841
9551
  app.createSettingSection(
8842
9552
  { id: "blockscene", intlLabel: { id: "blockscene.title", defaultMessage: "Blockscene" } },
8843
- [{
8844
- id: "blockscene-settings",
8845
- to,
8846
- intlLabel: { id: "blockscene.settings", defaultMessage: "Gallery" },
8847
- // Module shape: older Strapi 4 (e.g. 4.11) only reads `.default` from the loader result.
8848
- // Not an `async` function: Strapi 5 warns on AsyncFunction loaders.
8849
- Component: () => Promise.resolve({ default: Component2 }),
8850
- permissions: permissions.read
8851
- }]
9553
+ SETTINGS_SECTIONS.map(({ id, label }) => {
9554
+ const Page = () => React9.createElement(Component2, { section: id });
9555
+ const sectionPath = id === "general" ? to : to.startsWith("/") ? `${to}-${id}` : `${to}/${id}`;
9556
+ return {
9557
+ id: `blockscene-${id}`,
9558
+ to: sectionPath,
9559
+ intlLabel: { id: `blockscene.settings${id === "content-types" ? "ContentTypes" : id[0].toUpperCase() + id.slice(1)}`, defaultMessage: label },
9560
+ // Module shape: older Strapi 4 (e.g. 4.11) only reads `.default` from the loader result.
9561
+ // Not an `async` function: Strapi 5 warns on AsyncFunction loaders.
9562
+ Component: () => Promise.resolve({ default: Page }),
9563
+ permissions: permissions.read
9564
+ };
9565
+ })
8852
9566
  );
8853
9567
  }
8854
9568
 
@@ -8922,20 +9636,75 @@ var labelsHook = (get, relabel, drop) => (args) => {
8922
9636
  }
8923
9637
  };
8924
9638
 
9639
+ // admin/StarterKits.tsx
9640
+ import * as React12 from "react";
9641
+ import { Box as Box6, Button as Button5, Flex as Flex6, Typography as Typography6 } from "@strapi/design-system";
9642
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
9643
+ var marker = (docKey) => {
9644
+ try {
9645
+ const entry = window.history.state?.key ?? window.history.state?.idx ?? "route";
9646
+ return `blockscene:starter-kit:${entry}:${docKey}`;
9647
+ } catch {
9648
+ return `blockscene:starter-kit:${docKey}`;
9649
+ }
9650
+ };
9651
+ var wasHandled = (key) => {
9652
+ try {
9653
+ return window.sessionStorage.getItem(key) === "handled";
9654
+ } catch {
9655
+ return false;
9656
+ }
9657
+ };
9658
+ var remember2 = (key) => {
9659
+ try {
9660
+ window.sessionStorage.setItem(key, "handled");
9661
+ } catch {
9662
+ }
9663
+ };
9664
+ function StarterKits({ creating, kits, zones, components, form, Modal: Modal2, docKey }) {
9665
+ const t = useMessages();
9666
+ const key = marker(docKey);
9667
+ const handled = React12.useRef({ key, value: wasHandled(key) });
9668
+ if (handled.current.key !== key) handled.current = { key, value: wasHandled(key) };
9669
+ const usable = starterKitsForLocale(kits, form?.locale).filter((kit) => Object.keys(kit.zones || {}).every((name) => zones.some((zone) => zone.name === name)));
9670
+ const available = creating && form && !handled.current.value && usable.length > 0 && zones.length > 0 && zones.every((zone) => form.rows(zone.name).length === 0);
9671
+ const [open, setOpen] = React12.useState(available);
9672
+ React12.useEffect(() => {
9673
+ if (available) setOpen(true);
9674
+ }, [available, key]);
9675
+ if (!available) return null;
9676
+ const finish = () => {
9677
+ handled.current.value = true;
9678
+ remember2(key);
9679
+ setOpen(false);
9680
+ };
9681
+ const apply = (kit) => {
9682
+ const rows = starterKitRows(kit, zones, components, form);
9683
+ if (!rows) return;
9684
+ for (const [zone, value] of Object.entries(rows)) form.setRows(zone, value);
9685
+ finish();
9686
+ };
9687
+ return /* @__PURE__ */ jsx12(Modal2, { open, onOpenChange: (next) => next ? setOpen(true) : finish(), title: t.starterKits, width: "560px", children: /* @__PURE__ */ jsxs9(Flex6, { direction: "column", alignItems: "stretch", gap: 3, children: [
9688
+ /* @__PURE__ */ jsx12(Typography6, { textColor: "neutral600", children: t.starterKitsHelp }),
9689
+ usable.map((kit) => /* @__PURE__ */ jsx12(Button5, { variant: "secondary", fullWidth: true, onClick: () => apply(kit), "data-testid": `starter-kit-${kit.id}`, children: localized(kit.label, t.locale) }, kit.id)),
9690
+ /* @__PURE__ */ jsx12(Box6, { paddingTop: 1, children: /* @__PURE__ */ jsx12(Button5, { variant: "tertiary", onClick: finish, children: t.startBlank }) })
9691
+ ] }) });
9692
+ }
9693
+
8925
9694
  // admin/strapi4.tsx
8926
- import { Fragment as Fragment9, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
9695
+ import { Fragment as Fragment9, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
8927
9696
  function Modal({ open, onOpenChange, trigger, title, children, width = "80vw" }) {
8928
- const id = React12.useId();
8929
- return /* @__PURE__ */ jsxs9(Fragment9, { children: [
9697
+ const id = React13.useId();
9698
+ return /* @__PURE__ */ jsxs10(Fragment9, { children: [
8930
9699
  trigger,
8931
- open && /* @__PURE__ */ jsxs9(ModalLayout, { onClose: () => onOpenChange(false), labelledBy: id, width, children: [
8932
- /* @__PURE__ */ jsx12(ModalHeader, { children: /* @__PURE__ */ jsx12(Typography6, { id, variant: "beta", children: title }) }),
8933
- /* @__PURE__ */ jsx12(ModalBody, { children })
9700
+ open && /* @__PURE__ */ jsxs10(ModalLayout, { onClose: () => onOpenChange(false), labelledBy: id, width, children: [
9701
+ /* @__PURE__ */ jsx13(ModalHeader, { children: /* @__PURE__ */ jsx13(Typography7, { id, variant: "beta", children: title }) }),
9702
+ /* @__PURE__ */ jsx13(ModalBody, { children })
8934
9703
  ] })
8935
9704
  ] });
8936
9705
  }
8937
- var Menu2 = ({ label, testid, items: items2 }) => /* @__PURE__ */ jsx12("div", { "data-testid": testid, children: /* @__PURE__ */ jsx12(SimpleMenu2, { variant: "tertiary", size: "S", "aria-label": label, title: label, endIcon: null, label: /* @__PURE__ */ jsx12(Icon, { name: "more", size: 16 }), children: items2.map((item) => /* @__PURE__ */ jsx12(MenuItem2, { onClick: item.onSelect, "data-testid": item.testid, children: /* @__PURE__ */ jsxs9(Flex6, { as: "span", gap: 2, alignItems: "center", children: [
8938
- /* @__PURE__ */ jsx12(Icon, { name: item.icon, size: 16 }),
9706
+ var Menu2 = ({ label, testid, items: items2 }) => /* @__PURE__ */ jsx13("div", { "data-testid": testid, children: /* @__PURE__ */ jsx13(SimpleMenu2, { variant: "tertiary", size: "S", "aria-label": label, title: label, endIcon: null, label: /* @__PURE__ */ jsx13(Icon, { name: "more", size: 16 }), children: items2.map((item) => /* @__PURE__ */ jsx13(MenuItem2, { onClick: item.onSelect, "data-testid": item.testid, children: /* @__PURE__ */ jsxs10(Flex7, { as: "span", gap: 2, alignItems: "center", children: [
9707
+ /* @__PURE__ */ jsx13(Icon, { name: item.icon, size: 16 }),
8939
9708
  item.label
8940
9709
  ] }) }, item.testid)) }) });
8941
9710
  function overlayVariant(c, components, zone, at, uid, values) {
@@ -8944,7 +9713,7 @@ function overlayVariant(c, components, zone, at, uid, values) {
8944
9713
  }
8945
9714
  function useRowForm(c, components) {
8946
9715
  const toggleNotification = useNotification();
8947
- const latest = React12.useRef(c.modifiedData);
9716
+ const latest = React13.useRef(c.modifiedData);
8948
9717
  latest.current = c.modifiedData;
8949
9718
  if (typeof c.onChange !== "function") return null;
8950
9719
  return {
@@ -8995,7 +9764,7 @@ function Picker() {
8995
9764
  };
8996
9765
  if (!catalog?.editor?.enabled || catalog.contentTypes?.[c.slug]?.enabled === false) return null;
8997
9766
  const docKey = `${c.slug}:${c.isCreatingEntry ? "new" : c.initialData?.id}:${c.initialData?.locale || ""}`;
8998
- return /* @__PURE__ */ jsx12("div", { hidden: true, "data-blockscene-editor": "", children: /* @__PURE__ */ jsx12(Workspace, { c, schema, zones, components, add, catalog, docKey, form, get, put }) });
9767
+ return /* @__PURE__ */ jsx13("div", { hidden: true, "data-blockscene-editor": "", children: /* @__PURE__ */ jsx13(Workspace, { c, schema, zones, components, add, catalog, docKey, form, get, put }) });
8999
9768
  }
9000
9769
  function Workspace({ c, schema, zones, components, add, catalog, docKey, form, get, put }) {
9001
9770
  const typeSettings = catalog.contentTypes?.[c.slug] || {};
@@ -9009,8 +9778,9 @@ function Workspace({ c, schema, zones, components, add, catalog, docKey, form, g
9009
9778
  };
9010
9779
  const host = usePreviewHost4(c, schema, components, get, put);
9011
9780
  const state = useEditorState(editor, host);
9012
- return /* @__PURE__ */ jsxs9(Fragment9, { children: [
9013
- /* @__PURE__ */ jsx12(
9781
+ return /* @__PURE__ */ jsxs10(Fragment9, { children: [
9782
+ /* @__PURE__ */ jsx13(StarterKits, { creating: c.isCreatingEntry, kits: catalog.kits?.[c.slug], zones, components, form, Modal, docKey }),
9783
+ /* @__PURE__ */ jsx13(
9014
9784
  Gallery,
9015
9785
  {
9016
9786
  zones,
@@ -9027,12 +9797,12 @@ function Workspace({ c, schema, zones, components, add, catalog, docKey, form, g
9027
9797
  userId: auth.getUserInfo?.()?.id,
9028
9798
  form,
9029
9799
  Menu: Menu2,
9030
- zoneTools: state.preview.base ? /* @__PURE__ */ jsx12(ZoneBarTools, { state }) : null,
9800
+ zoneTools: state.preview.base ? /* @__PURE__ */ jsx13(ZoneBarTools, { state }) : null,
9031
9801
  openBlock: state.openBlock,
9032
9802
  openInsert: state.openInsert
9033
9803
  }
9034
9804
  ),
9035
- /* @__PURE__ */ jsx12(
9805
+ /* @__PURE__ */ jsx13(
9036
9806
  PagePreview,
9037
9807
  {
9038
9808
  editor,
@@ -9051,9 +9821,13 @@ function usePreviewHost4(c, schema, components, get, put) {
9051
9821
  const toggleNotification = useNotification();
9052
9822
  const { components: library } = useLibrary();
9053
9823
  const creating = Boolean(c.isCreatingEntry);
9054
- const readable = React12.useCallback(
9055
- (name) => creating || (c.readActionAllowedFields || []).includes(name),
9056
- [creating, c.readActionAllowedFields]
9824
+ const layoutFields = React13.useMemo(
9825
+ () => new Set((schema?.layouts?.edit?.flat(3) || []).map((field) => field?.name).filter(Boolean)),
9826
+ [schema?.layouts?.edit]
9827
+ );
9828
+ const readable = React13.useCallback(
9829
+ (name) => fieldReadable(name, c.readActionAllowedFields, creating) || layoutFields.has(name.split(".")[0]),
9830
+ [creating, c.readActionAllowedFields, layoutFields]
9057
9831
  );
9058
9832
  return {
9059
9833
  ds: 1,
@@ -9090,7 +9864,7 @@ function Actions4({ parts }) {
9090
9864
  const c = useCMEditViewDataManager();
9091
9865
  const t = useMessages();
9092
9866
  const { formatMessage } = useIntl2();
9093
- const dirty = React12.useMemo(
9867
+ const dirty = React13.useMemo(
9094
9868
  () => c.isCreatingEntry ? Object.keys(c.modifiedData || {}).length > 0 : JSON.stringify(c.initialData) !== JSON.stringify(c.modifiedData),
9095
9869
  [c.initialData, c.modifiedData, c.isCreatingEntry]
9096
9870
  );
@@ -9104,13 +9878,13 @@ function Actions4({ parts }) {
9104
9878
  { label: save, variant: "secondary", disabled: !dirty, loading: c.status === "submit-pending", reason: t.saveDisabledHint },
9105
9879
  ...c.hasDraftAndPublish && !c.isCreatingEntry ? [{ label: publish, variant: "default", disabled: dirty, loading: c.status === (published ? "unpublish-pending" : "publish-pending"), reason: t.publishDisabledHint }] : []
9106
9880
  ].filter((action) => native(action.label));
9107
- return /* @__PURE__ */ jsxs9(Flex6, { gap: 2, alignItems: "center", "data-testid": "page-preview-actions", children: [
9108
- parts.includes("status") && (status || dirty) && /* @__PURE__ */ jsxs9(Flex6, { gap: 2, alignItems: "center", style: { order: parts.indexOf("status") }, children: [
9109
- status && /* @__PURE__ */ jsx12(Status, { size: "S", showBullet: false, role: "status", "data-testid": "page-preview-status", variant: published ? "success" : "secondary", children: /* @__PURE__ */ jsx12(Typography6, { as: "span", variant: "omega", fontWeight: "bold", children: formatMessage({ id: `content-manager.containers.List.${status}`, defaultMessage: status === "published" ? "Published" : "Draft" }) }) }),
9110
- dirty && /* @__PURE__ */ jsx12(Typography6, { variant: "pi", textColor: "neutral600", children: t.unsaved })
9881
+ return /* @__PURE__ */ jsxs10(Flex7, { gap: 2, alignItems: "center", "data-testid": "page-preview-actions", children: [
9882
+ parts.includes("status") && (status || dirty) && /* @__PURE__ */ jsxs10(Flex7, { gap: 2, alignItems: "center", style: { order: parts.indexOf("status") }, children: [
9883
+ status && /* @__PURE__ */ jsx13(Status, { size: "S", showBullet: false, role: "status", "data-testid": "page-preview-status", variant: published ? "success" : "secondary", children: /* @__PURE__ */ jsx13(Typography7, { as: "span", variant: "omega", fontWeight: "bold", children: formatMessage({ id: `content-manager.containers.List.${status}`, defaultMessage: status === "published" ? "Published" : "Draft" }) }) }),
9884
+ dirty && /* @__PURE__ */ jsx13(Typography7, { variant: "pi", textColor: "neutral600", children: t.unsaved })
9111
9885
  ] }),
9112
- parts.includes("actions") && actions.map((action) => /* @__PURE__ */ jsx12("span", { title: action.disabled ? action.reason : void 0, style: { order: parts.indexOf("actions") }, children: /* @__PURE__ */ jsx12(
9113
- Button5,
9886
+ parts.includes("actions") && actions.map((action) => /* @__PURE__ */ jsx13("span", { title: action.disabled ? action.reason : void 0, style: { order: parts.indexOf("actions") }, children: /* @__PURE__ */ jsx13(
9887
+ Button6,
9114
9888
  {
9115
9889
  size: "S",
9116
9890
  variant: action.variant,
@@ -9123,8 +9897,8 @@ function Actions4({ parts }) {
9123
9897
  ) }, action.label))
9124
9898
  ] });
9125
9899
  }
9126
- var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ jsxs9(Flex6, { gap: 3, children: [
9127
- /* @__PURE__ */ jsx12(
9900
+ var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ jsxs10(Flex7, { gap: 3, children: [
9901
+ /* @__PURE__ */ jsx13(
9128
9902
  Switch,
9129
9903
  {
9130
9904
  name,
@@ -9134,9 +9908,9 @@ var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ *
9134
9908
  onChange: () => onChange(!value)
9135
9909
  }
9136
9910
  ),
9137
- /* @__PURE__ */ jsx12(Typography6, { children: label })
9911
+ /* @__PURE__ */ jsx13(Typography7, { children: label })
9138
9912
  ] });
9139
- var TextField = ({ name, label, value, onChange, disabled, placeholder }) => /* @__PURE__ */ jsx12(TextInput, { name, label, value, disabled, placeholder, onChange: (e) => onChange(e.target.value) });
9913
+ var TextField = ({ name, label, value, onChange, disabled, placeholder }) => /* @__PURE__ */ jsx13(TextInput, { name, label, value, disabled, placeholder, onChange: (e) => onChange(e.target.value) });
9140
9914
  var SelectField = ({
9141
9915
  name,
9142
9916
  label,
@@ -9144,7 +9918,7 @@ var SelectField = ({
9144
9918
  onChange,
9145
9919
  disabled,
9146
9920
  options
9147
- }) => /* @__PURE__ */ jsx12(
9921
+ }) => /* @__PURE__ */ jsx13(
9148
9922
  SingleSelect,
9149
9923
  {
9150
9924
  name,
@@ -9152,7 +9926,7 @@ var SelectField = ({
9152
9926
  value,
9153
9927
  disabled,
9154
9928
  onChange: (v) => onChange(String(v)),
9155
- children: options.map((o) => /* @__PURE__ */ jsx12(SingleSelectOption, { value: o.value, children: o.label }, o.value))
9929
+ children: options.map((o) => /* @__PURE__ */ jsx13(SingleSelectOption, { value: o.value, children: o.label }, o.value))
9156
9930
  }
9157
9931
  );
9158
9932
  function MediaPicker({ onClose, onSelect }) {
@@ -9162,7 +9936,7 @@ function MediaPicker({ onClose, onSelect }) {
9162
9936
  onClose();
9163
9937
  return null;
9164
9938
  }
9165
- return /* @__PURE__ */ jsx12(
9939
+ return /* @__PURE__ */ jsx13(
9166
9940
  Dialog,
9167
9941
  {
9168
9942
  onClose,
@@ -9179,7 +9953,7 @@ function usePermissions() {
9179
9953
  isLoading
9180
9954
  };
9181
9955
  }
9182
- var SettingsPage = () => /* @__PURE__ */ jsx12(Guard, { children: /* @__PURE__ */ jsx12(
9956
+ var SettingsPage = ({ section }) => /* @__PURE__ */ jsx13(Guard, { children: /* @__PURE__ */ jsx13(
9183
9957
  Settings,
9184
9958
  {
9185
9959
  useClient: useFetchClient,
@@ -9187,7 +9961,8 @@ var SettingsPage = () => /* @__PURE__ */ jsx12(Guard, { children: /* @__PURE__ *
9187
9961
  MediaPicker,
9188
9962
  ToggleField,
9189
9963
  SelectField,
9190
- TextField
9964
+ TextField,
9965
+ section
9191
9966
  }
9192
9967
  ) });
9193
9968
  var strapi4_default = {
@@ -9200,7 +9975,7 @@ var strapi4_default = {
9200
9975
  app.registerHook("Admin/CM/pages/EditView/mutate-edit-view-layout", labelsHook(() => getFetchClient().get, labelEditLayout4, dropField4));
9201
9976
  app.injectContentManagerComponent("editView", "right-links", {
9202
9977
  name: "blockscene",
9203
- Component: () => /* @__PURE__ */ jsx12(Guard, { children: /* @__PURE__ */ jsx12(Picker, {}) })
9978
+ Component: () => /* @__PURE__ */ jsx13(Guard, { children: /* @__PURE__ */ jsx13(Picker, {}) })
9204
9979
  });
9205
9980
  }
9206
9981
  };