@aduptive/strapi-blockscene 2.0.0-alpha.5 → 2.0.0-alpha.6

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.cjs CHANGED
@@ -137,15 +137,110 @@ var require_groups = __commonJS({
137
137
  }
138
138
  });
139
139
 
140
+ // server/diff.js
141
+ var require_diff = __commonJS({
142
+ "server/diff.js"(exports, module2) {
143
+ "use strict";
144
+ var IGNORED = ["id", "documentId", "locale", "localizations", "createdAt", "updatedAt", "publishedAt", "firstPublishedAt", "createdBy", "updatedBy", "strapi_stage", "strapi_assignee", "__temp_key__", "__pivot"];
145
+ var morph = (attr) => String(attr?.relation || "").toLowerCase().includes("morph");
146
+ var kept2 = (name, attr) => attr && !IGNORED.includes(name) && attr.type !== "password" && !(attr.type === "relation" && (morph(attr) || attr.visible === false));
147
+ var empty = (value) => value === null || value === void 0 || value === "";
148
+ function snapshotPopulate(uid, schemaOf, stack = []) {
149
+ const schema = schemaOf(uid);
150
+ if (!schema || stack.includes(uid)) return {};
151
+ const scalars = (component) => Object.entries(schemaOf(component)?.attributes || {}).filter(([name, attr]) => kept2(name, attr) && !["relation", "media", "component", "dynamiczone"].includes(attr.type)).map(([name]) => name);
152
+ const nested = (component) => ({ select: scalars(component).length ? scalars(component) : ["id"], populate: snapshotPopulate(component, schemaOf, [...stack, uid]) });
153
+ const out = {};
154
+ for (const [name, attr] of Object.entries(schema.attributes || {})) {
155
+ if (!kept2(name, attr)) continue;
156
+ if (attr.type === "relation") out[name] = { select: ["documentId", "locale"] };
157
+ else if (attr.type === "media") out[name] = { select: ["id"] };
158
+ else if (attr.type === "component") out[name] = nested(attr.component);
159
+ else if (attr.type === "dynamiczone") out[name] = { on: Object.fromEntries((attr.components || []).map((component) => [component, nested(component)])) };
160
+ }
161
+ return out;
162
+ }
163
+ function canonical2(data, schema, schemaOf, { relations = true } = {}, depth = 0) {
164
+ const out = {};
165
+ if (!data || typeof data !== "object" || depth > 20) return out;
166
+ const idOf = (file) => file && typeof file === "object" ? file.id : file;
167
+ const ref = (item) => item && typeof item === "object" && item.documentId ? { documentId: item.documentId, ...item.locale && { locale: item.locale } } : null;
168
+ for (const [name, attr] of Object.entries(schema?.attributes || {})) {
169
+ const value = data[name];
170
+ if (!kept2(name, attr) || empty(value)) continue;
171
+ if (attr.type === "relation") {
172
+ if (!relations) continue;
173
+ const refs = (Array.isArray(value) ? value : [value]).map(ref).filter(Boolean);
174
+ if (refs.length) out[name] = Array.isArray(value) ? refs : refs[0];
175
+ } else if (attr.type === "media") {
176
+ const ids = (Array.isArray(value) ? value : [value]).map(idOf).filter((id) => !empty(id));
177
+ if (ids.length) out[name] = attr.multiple ? ids : ids[0];
178
+ } else if (attr.type === "component") {
179
+ const child = schemaOf(attr.component);
180
+ if (attr.repeatable) {
181
+ if (Array.isArray(value) && value.length) out[name] = value.map((item) => canonical2(item, child, schemaOf, { relations }, depth + 1));
182
+ } else out[name] = canonical2(value, child, schemaOf, { relations }, depth + 1);
183
+ } else if (attr.type === "dynamiczone") {
184
+ if (Array.isArray(value) && value.length) out[name] = value.filter((row) => row && typeof row.__component === "string").map((row) => ({ __component: row.__component, ...canonical2(row, schemaOf(row.__component), schemaOf, { relations }, depth + 1) }));
185
+ } else out[name] = value;
186
+ }
187
+ return out;
188
+ }
189
+ var stable = (value) => JSON.stringify(value, (_, v) => v && typeof v === "object" && !Array.isArray(v) ? Object.fromEntries(Object.keys(v).sort().map((k) => [k, v[k]])) : v);
190
+ var same2 = (a, b) => stable(a ?? null) === stable(b ?? null);
191
+ function diffRows2(before = [], after = []) {
192
+ const a = before.map(stable), b = after.map(stable);
193
+ const n = a.length, m = b.length;
194
+ if (n * m > 25e4) return after.map((row, to) => ({ op: a[to] === b[to] ? "same" : "changed", from: to < n ? to : void 0, to, uid: row.__component }));
195
+ const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
196
+ for (let i2 = n - 1; i2 >= 0; i2--) for (let j2 = m - 1; j2 >= 0; j2--) lcs[i2][j2] = a[i2] === b[j2] ? lcs[i2 + 1][j2 + 1] + 1 : Math.max(lcs[i2 + 1][j2], lcs[i2][j2 + 1]);
197
+ const out = [];
198
+ const gap = (fromRows2, toRows2) => {
199
+ const removed = [...fromRows2];
200
+ for (const to of toRows2) {
201
+ const k = removed.findIndex((from) => before[from].__component === after[to].__component);
202
+ if (k === -1) out.push({ op: "added", to, uid: after[to].__component });
203
+ else out.push({ op: "changed", from: removed.splice(k, 1)[0], to, uid: after[to].__component });
204
+ }
205
+ for (const from of removed) out.push({ op: "removed", from, uid: before[from].__component });
206
+ };
207
+ let i = 0, j = 0, fromRows = [], toRows = [];
208
+ while (i < n || j < m) {
209
+ if (i < n && j < m && a[i] === b[j]) {
210
+ gap(fromRows, toRows);
211
+ fromRows = [];
212
+ toRows = [];
213
+ out.push({ op: "same", from: i, to: j, uid: after[j].__component });
214
+ i++;
215
+ j++;
216
+ } else if (j < m && (i >= n || lcs[i][j + 1] >= lcs[i + 1][j])) toRows.push(j++);
217
+ else fromRows.push(i++);
218
+ }
219
+ gap(fromRows, toRows);
220
+ return out;
221
+ }
222
+ function summarize(before, after, schema) {
223
+ const zones = Object.entries(schema?.attributes || {}).filter(([, attr]) => attr?.type === "dynamiczone").map(([name]) => name);
224
+ const blocks = { added: 0, removed: 0, changed: 0 };
225
+ if (!before) return { initial: true, fields: [], blocks };
226
+ const names = [.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after || {})])];
227
+ const fields = names.filter((name) => !zones.includes(name) && !same2(before[name], after?.[name])).sort();
228
+ for (const name of zones) for (const { op } of diffRows2(before[name], after?.[name])) if (op !== "same") blocks[op]++;
229
+ return { fields, blocks };
230
+ }
231
+ module2.exports = { IGNORED, kept: kept2, snapshotPopulate, canonical: canonical2, stable, same: same2, diffRows: diffRows2, summarize };
232
+ }
233
+ });
234
+
140
235
  // admin/strapi5.tsx
141
236
  var strapi5_exports = {};
142
237
  __export(strapi5_exports, {
143
238
  default: () => strapi5_default
144
239
  });
145
240
  module.exports = __toCommonJS(strapi5_exports);
146
- var React10 = __toESM(require("react"));
147
- var import_design_system7 = require("@strapi/design-system");
148
- var import_admin2 = require("@strapi/strapi/admin");
241
+ var React11 = __toESM(require("react"));
242
+ var import_design_system8 = require("@strapi/design-system");
243
+ var import_admin3 = require("@strapi/strapi/admin");
149
244
  var import_strapi_admin2 = require("@strapi/content-manager/strapi-admin");
150
245
 
151
246
  // admin/Gallery.tsx
@@ -317,6 +412,57 @@ function initialState(editor, remembered) {
317
412
  if (editor?.initialState === "remember") return remembered || "closed";
318
413
  return "closed";
319
414
  }
415
+ var withoutField = (rows, name) => rows.map((row) => row.filter((field) => field?.name !== name)).filter((row) => row.length);
416
+ function dropField(layout, name) {
417
+ if (!name || !layout?.components) return layout;
418
+ return { ...layout, components: Object.fromEntries(Object.entries(layout.components).map(([uid, component]) => [uid, Array.isArray(component?.layout) ? { ...component, layout: withoutField(component.layout, name) } : component])) };
419
+ }
420
+ function humanize(name) {
421
+ const text = String(name || "").replace(/[_\-\s]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").trim().split(" ").filter(Boolean).map((word) => /^[A-Z0-9]{2,}$/.test(word) && /[A-Z]/.test(word) ? word : word.toLowerCase()).join(" ");
422
+ return text.charAt(0).toUpperCase() + text.slice(1);
423
+ }
424
+ function localized(value, locale = "en") {
425
+ if (typeof value === "string") return value;
426
+ if (!value || typeof value !== "object") return void 0;
427
+ const keys = Object.keys(value);
428
+ const lang = (key2) => key2.toLowerCase().split("-")[0];
429
+ const lower = String(locale || "en").toLowerCase();
430
+ const key = keys.find((k) => k.toLowerCase() === lower) ?? keys.find((k) => k.toLowerCase() === lang(lower)) ?? keys.find((k) => lang(k) === lang(lower)) ?? keys.find((k) => lang(k) === "en") ?? keys[0];
431
+ return key === void 0 ? void 0 : value[key];
432
+ }
433
+ function fieldText(fields, owner, name, label, locale, on) {
434
+ const entry = owner && fields?.[owner]?.[name] || {};
435
+ const out = {};
436
+ const text = localized(entry.label, locale) ?? (on && label === name ? humanize(name) : void 0);
437
+ if (text !== void 0) out.label = text;
438
+ for (const key of ["description", "placeholder"]) {
439
+ const value = localized(entry[key], locale);
440
+ if (value !== void 0) out[key] = value;
441
+ }
442
+ return Object.keys(out).length ? out : null;
443
+ }
444
+ function layoutType(layout, types = {}) {
445
+ const names = (layout?.layout || []).flat(2).map((field) => field?.name);
446
+ const found = Object.entries(types || {}).filter(([, [displayName, ...attributes]]) => displayName === layout?.settings?.displayName && names.every((name) => attributes.includes(name)));
447
+ return found.length === 1 ? found[0][0] : found.length ? false : null;
448
+ }
449
+ var labelsOff = (catalog) => !catalog?.editor?.enabled || !catalog.editor.friendlyLabels && !Object.keys(catalog.fields || {}).length;
450
+ function labelEditLayout(layout, catalog, locale) {
451
+ if (labelsOff(catalog) || !Array.isArray(layout?.layout) || !layout.layout.length) return layout;
452
+ const uid = layoutType(layout, catalog.types);
453
+ if (uid === false || uid && catalog.contentTypes?.[uid]?.enabled === false) return layout;
454
+ const fix = (owner) => (field) => {
455
+ const text = field && fieldText(catalog.fields, owner, field.name, field.label, locale, catalog.editor.friendlyLabels);
456
+ if (!text) return field;
457
+ const { description, ...rest } = text;
458
+ return { ...field, ...rest, ...description !== void 0 && { hint: description } };
459
+ };
460
+ return {
461
+ ...layout,
462
+ layout: layout.layout.map((panel) => panel.map((row) => row.map(fix(uid)))),
463
+ components: Object.fromEntries(Object.entries(layout.components || {}).map(([cuid, component]) => [cuid, Array.isArray(component?.layout) ? { ...component, layout: component.layout.map((row) => row.map(fix(cuid))) } : component]))
464
+ };
465
+ }
320
466
 
321
467
  // admin/preview.mjs
322
468
  var import_groups = __toESM(require_groups(), 1);
@@ -468,15 +614,15 @@ var stageBackground = (theme) => {
468
614
 
469
615
  // admin/accordions.mjs
470
616
  function zoneLists(root = document) {
471
- return [...root.querySelectorAll("ol[aria-describedby]")].filter((list) => list.querySelector(":scope > li button[aria-expanded]"));
617
+ return [...root.querySelectorAll("ol[aria-describedby]")].filter((list2) => list2.querySelector(":scope > li button[aria-expanded]"));
472
618
  }
473
619
  function findZoneList(label, root = document) {
474
620
  const lists = zoneLists(root);
475
- const text = (list) => (list.parentElement?.textContent || "").trim().toLocaleLowerCase();
476
- return lists.find((list) => text(list).startsWith(String(label).toLocaleLowerCase())) || (lists.length === 1 ? lists[0] : null);
621
+ const text = (list2) => (list2.parentElement?.textContent || "").trim().toLocaleLowerCase();
622
+ return lists.find((list2) => text(list2).startsWith(String(label).toLocaleLowerCase())) || (lists.length === 1 ? lists[0] : null);
477
623
  }
478
- function toggles(list) {
479
- return [...list.querySelectorAll(":scope > li")].map((item) => item.querySelector("button[aria-expanded]")).filter(Boolean);
624
+ function toggles(list2) {
625
+ return [...list2.querySelectorAll(":scope > li")].map((item) => item.querySelector("button[aria-expanded]")).filter(Boolean);
480
626
  }
481
627
  function planRows(rects, view, margin = 0) {
482
628
  const now = [], later = [];
@@ -500,9 +646,9 @@ function stopAll() {
500
646
  var PER_FRAME = 3;
501
647
  var idle = (run) => typeof requestIdleCallback === "function" ? requestIdleCallback(run, { timeout: 300 }) : setTimeout(() => run({ timeRemaining: () => 8 }), 16);
502
648
  var frame = (run) => typeof requestAnimationFrame === "function" ? requestAnimationFrame(run) : setTimeout(run, 16);
503
- function setAll(list, open, batch = (run) => run()) {
504
- jobs.get(list)?.();
505
- jobs.delete(list);
649
+ function setAll(list2, open, batch = (run) => run()) {
650
+ jobs.get(list2)?.();
651
+ jobs.delete(list2);
506
652
  const header = (li) => li.querySelector("button[aria-expanded]");
507
653
  const differs = (li) => {
508
654
  const b = li.isConnected && header(li);
@@ -515,9 +661,9 @@ function setAll(list, open, batch = (run) => run()) {
515
661
  });
516
662
  return buttons.length;
517
663
  };
518
- const rows = [...list.querySelectorAll(":scope > li")].filter(differs);
664
+ const rows = [...list2.querySelectorAll(":scope > li")].filter(differs);
519
665
  if (!rows.length) return 0;
520
- const root = scroller(list);
666
+ const root = scroller(list2);
521
667
  const view = () => root ? root.getBoundingClientRect() : { top: 0, bottom: window.innerHeight };
522
668
  const height = view().bottom - view().top;
523
669
  const { now, later } = planRows(rows.map((li) => li.getBoundingClientRect()), view(), open ? height : 0);
@@ -548,7 +694,7 @@ function setAll(list, open, batch = (run) => run()) {
548
694
  if (queue.size && !handle && !stopped) handle = frame(flush);
549
695
  }, { root, rootMargin: `${Math.round(height)}px 0px` });
550
696
  later.forEach((i) => observer.observe(rows[i]));
551
- jobs.set(list, () => {
697
+ jobs.set(list2, () => {
552
698
  stopped = true;
553
699
  observer.disconnect();
554
700
  });
@@ -557,15 +703,15 @@ function setAll(list, open, batch = (run) => run()) {
557
703
  }
558
704
  const changed = click(now.map((i) => rows[i]));
559
705
  if (!later.length) return changed;
560
- const pending = later.map((i) => rows[i]);
706
+ const pending2 = later.map((i) => rows[i]);
561
707
  const slice = (deadline) => {
562
708
  if (stopped) return;
563
- click(pending.splice(0, deadline.timeRemaining() > 10 ? PER_FRAME : 1));
564
- if (pending.length) idle(slice);
565
- else jobs.delete(list);
709
+ click(pending2.splice(0, deadline.timeRemaining() > 10 ? PER_FRAME : 1));
710
+ if (pending2.length) idle(slice);
711
+ else jobs.delete(list2);
566
712
  };
567
713
  idle(slice);
568
- jobs.set(list, () => {
714
+ jobs.set(list2, () => {
569
715
  stopped = true;
570
716
  });
571
717
  return changed;
@@ -573,7 +719,9 @@ function setAll(list, open, batch = (run) => run()) {
573
719
  function isNativeAddButton(button, zone) {
574
720
  if (!button || button.getAttribute("aria-expanded") || button.closest('ol[aria-describedby] > li, [role="dialog"], [data-testid^="open-gallery-"], [data-testid^="block-"], [data-testid^="page-preview"], [data-testid^="bp-"], [data-testid^="zone-"], [data-blockscene-row-actions]')) return false;
575
721
  const text = (button.textContent || "").trim();
576
- return Boolean(text) && new RegExp(`(^|\\s)${String(zone.name).replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`).test(text);
722
+ const escape = (value) => String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
723
+ const names = [...new Set([zone.name, zone.label].filter(Boolean))].map(escape).join("|");
724
+ return Boolean(text) && new RegExp(`(^|\\s)(${names})$`).test(text);
577
725
  }
578
726
 
579
727
  // admin/wireframes.tsx
@@ -696,7 +844,6 @@ var en_default = {
696
844
  previewHelp: "Unsaved changes appear in the preview. Click a block to open its form, an image to open the Media Library, a text to edit it.",
697
845
  previewNoUrl: "No preview URL: set it in Settings, Blockscene, or configure Strapi's native Preview for this content type.",
698
846
  previewFailed: "The preview did not answer within 15 s. If the frontend is still loading it will appear by itself; the form stays usable.",
699
- previewReady: "Page preview \xB7 unsaved changes",
700
847
  previewLoading: "Loading preview\u2026",
701
848
  retry: "Try again",
702
849
  editText: "Edit text",
@@ -854,12 +1001,57 @@ var en_default = {
854
1001
  confirmDeleteOption: "Confirm before deleting a block",
855
1002
  duplicateOption: 'Show "Duplicate" on each block',
856
1003
  clipboardOption: 'Show "Copy" and "Paste" (across pages)',
1004
+ friendlyLabels: "Friendly field labels",
1005
+ friendlyLabelsHelp: `Fields whose label is still the attribute name read as words ("mobileColumnsCount" becomes "Mobile columns count"). Labels set in "Configure the view" and texts from the project's "fields" config are kept.`,
857
1006
  hiddenBlocks: "Blocks hidden on the site",
858
1007
  "hiddenModes.strip": "Removed from the content API",
859
1008
  "hiddenModes.flag": "Sent with the flag (the frontend decides)",
860
1009
  "hiddenModes.off": "Off (no hide button)",
861
1010
  hiddenBlocksHelp: "The eye on each block marks it hidden on the site. Removed: content API reads (REST, GraphQL) leave it out, the admin always shows it. Flag: it is sent with the attribute so the frontend can decide.",
862
- hiddenAttributeOff: "The plugin config sets hiddenAttribute to false: blocks cannot be hidden."
1011
+ hiddenAttributeOff: "The plugin config sets hiddenAttribute to false: blocks cannot be hidden.",
1012
+ historyTitle: "History",
1013
+ historyEmpty: "No versions yet. Saves, publishes and deletes are recorded from now on.",
1014
+ historyLoading: "Loading history\u2026",
1015
+ historyFailed: "The history could not be loaded.",
1016
+ historyRefresh: "Refresh history",
1017
+ historySystem: "System",
1018
+ "historyActions.create": "Created",
1019
+ "historyActions.update": "Saved",
1020
+ "historyActions.publish": "Published",
1021
+ "historyActions.unpublish": "Unpublished",
1022
+ "historyActions.discard": "Draft discarded",
1023
+ "historyActions.delete": "Deleted",
1024
+ "historyActions.restore": "Restored",
1025
+ historyInitial: "First version",
1026
+ historyNoChange: "No content change",
1027
+ historyMissing: "Not recorded (the capture failed)",
1028
+ historyBlocksSummary: "Blocks: {added} added, {removed} removed, {changed} changed",
1029
+ historyFieldsSummary: "Fields: {fields}",
1030
+ historyNotKept: "This version is no longer kept.",
1031
+ historyCompare: "Compared with the form",
1032
+ historySame: "Same content as the form.",
1033
+ "diffOps.added": "Added",
1034
+ "diffOps.removed": "Removed",
1035
+ "diffOps.changed": "Changed",
1036
+ historyDiffFields: "Fields that differ: {fields}",
1037
+ historyDiffNote: "Relations are not compared.",
1038
+ historyLoad: "Load this version",
1039
+ historyLoaded: "Version loaded into the form. Nothing is saved until you save.",
1040
+ historyLeft: "Left as they are: {fields}",
1041
+ historyRemovedFields: "No longer in the schema, not loaded: {fields}",
1042
+ historyMissingItems: "No longer exist, left out: {media} media files, {relations} related entries, {blocks} blocks",
1043
+ historyLoadFailed: "This version could not be loaded.",
1044
+ historyShowMore: "Show more",
1045
+ historySettings: "Version history",
1046
+ historySettingsHelp: "Records every create, save, publish, unpublish, discard and delete made through Strapi's document service (the admin, the REST and GraphQL APIs, other plugins), with a snapshot of the content. Editors see the versions in the edit view and can load one into the form. This is content activity, not a security audit log: direct database writes are not seen.",
1047
+ historyEnabled: "Record versions",
1048
+ historyAll: "All content types",
1049
+ historyTypes: "Content types",
1050
+ historyRetention: "Keep snapshots (days)",
1051
+ historyMax: "Snapshots per document (maximum)",
1052
+ historyEventDays: "Keep the activity (days)",
1053
+ historyRetentionHelp: "A nightly job empties snapshots older than this or beyond the per-document maximum (the newest are kept) and deletes activity older than its limit. It never deletes media files.",
1054
+ historyInvalid: "Whole numbers: 1 to 3650 days (the activity kept at least as long as the snapshots) and 1 to 1000 snapshots."
863
1055
  };
864
1056
 
865
1057
  // admin/translations/pt-BR.json
@@ -937,7 +1129,6 @@ var pt_BR_default = {
937
1129
  previewHelp: "Altera\xE7\xF5es n\xE3o salvas aparecem na preview. Clique em um bloco para abrir seu formul\xE1rio, em uma imagem para abrir a Media Library, em um texto para edit\xE1-lo.",
938
1130
  previewNoUrl: "Sem URL de preview: defina em Configura\xE7\xF5es, Blockscene, ou configure a Preview nativa do Strapi para este tipo de conte\xFAdo.",
939
1131
  previewFailed: "A preview n\xE3o respondeu em 15 s. Se o frontend ainda estiver carregando, ela aparece sozinha; o formul\xE1rio continua utiliz\xE1vel.",
940
- previewReady: "Preview da p\xE1gina \xB7 altera\xE7\xF5es n\xE3o salvas",
941
1132
  previewLoading: "Carregando preview\u2026",
942
1133
  retry: "Tentar novamente",
943
1134
  editText: "Editar texto",
@@ -1095,12 +1286,57 @@ var pt_BR_default = {
1095
1286
  confirmDeleteOption: "Confirmar antes de excluir um bloco",
1096
1287
  duplicateOption: 'Mostrar "Duplicar" em cada bloco',
1097
1288
  clipboardOption: 'Mostrar "Copiar" e "Colar" (entre p\xE1ginas)',
1289
+ friendlyLabels: "R\xF3tulos de campo amig\xE1veis",
1290
+ friendlyLabelsHelp: 'Campos cujo r\xF3tulo ainda \xE9 o nome do atributo aparecem como palavras ("mobileColumnsCount" vira "Mobile columns count"). R\xF3tulos definidos em "Configurar a visualiza\xE7\xE3o" e textos da configura\xE7\xE3o "fields" do projeto s\xE3o mantidos.',
1098
1291
  hiddenBlocks: "Blocos ocultos no site",
1099
1292
  "hiddenModes.strip": "Removidos da API de conte\xFAdo",
1100
1293
  "hiddenModes.flag": "Enviados com a marca\xE7\xE3o (o frontend decide)",
1101
1294
  "hiddenModes.off": "Desligado (sem bot\xE3o de ocultar)",
1102
1295
  hiddenBlocksHelp: "O olho em cada bloco o marca como oculto no site. Removidos: as leituras da API de conte\xFAdo (REST, GraphQL) o deixam de fora; o admin sempre o mostra. Marca\xE7\xE3o: ele \xE9 enviado com o atributo para o frontend decidir.",
1103
- hiddenAttributeOff: "A config do plugin define hiddenAttribute como false: n\xE3o \xE9 poss\xEDvel ocultar blocos."
1296
+ hiddenAttributeOff: "A config do plugin define hiddenAttribute como false: n\xE3o \xE9 poss\xEDvel ocultar blocos.",
1297
+ historyTitle: "Hist\xF3rico",
1298
+ historyEmpty: "Nenhuma vers\xE3o ainda. Salvamentos, publica\xE7\xF5es e exclus\xF5es passam a ser registrados a partir de agora.",
1299
+ historyLoading: "Carregando hist\xF3rico\u2026",
1300
+ historyFailed: "N\xE3o foi poss\xEDvel carregar o hist\xF3rico.",
1301
+ historyRefresh: "Atualizar hist\xF3rico",
1302
+ historySystem: "Sistema",
1303
+ "historyActions.create": "Criado",
1304
+ "historyActions.update": "Salvo",
1305
+ "historyActions.publish": "Publicado",
1306
+ "historyActions.unpublish": "Despublicado",
1307
+ "historyActions.discard": "Rascunho descartado",
1308
+ "historyActions.delete": "Exclu\xEDdo",
1309
+ "historyActions.restore": "Restaurado",
1310
+ historyInitial: "Primeira vers\xE3o",
1311
+ historyNoChange: "Sem mudan\xE7a de conte\xFAdo",
1312
+ historyMissing: "N\xE3o registrado (a captura falhou)",
1313
+ historyBlocksSummary: "Blocos: {added} adicionados, {removed} removidos, {changed} alterados",
1314
+ historyFieldsSummary: "Campos: {fields}",
1315
+ historyNotKept: "Esta vers\xE3o n\xE3o \xE9 mais mantida.",
1316
+ historyCompare: "Comparado com o formul\xE1rio",
1317
+ historySame: "Mesmo conte\xFAdo do formul\xE1rio.",
1318
+ "diffOps.added": "Adicionado",
1319
+ "diffOps.removed": "Removido",
1320
+ "diffOps.changed": "Alterado",
1321
+ historyDiffFields: "Campos diferentes: {fields}",
1322
+ historyDiffNote: "Rela\xE7\xF5es n\xE3o s\xE3o comparadas.",
1323
+ historyLoad: "Carregar esta vers\xE3o",
1324
+ historyLoaded: "Vers\xE3o carregada no formul\xE1rio. Nada \xE9 salvo at\xE9 voc\xEA salvar.",
1325
+ historyLeft: "Mantidos como est\xE3o: {fields}",
1326
+ historyRemovedFields: "N\xE3o existem mais no schema, n\xE3o carregados: {fields}",
1327
+ historyMissingItems: "N\xE3o existem mais, deixados de fora: {media} arquivos de m\xEDdia, {relations} entradas relacionadas, {blocks} blocos",
1328
+ historyLoadFailed: "N\xE3o foi poss\xEDvel carregar esta vers\xE3o.",
1329
+ historyShowMore: "Mostrar mais",
1330
+ historySettings: "Hist\xF3rico de vers\xF5es",
1331
+ historySettingsHelp: "Registra cada cria\xE7\xE3o, salvamento, publica\xE7\xE3o, despublica\xE7\xE3o, descarte e exclus\xE3o feitos pelo document service do Strapi (o admin, as APIs REST e GraphQL, outros plugins), com um snapshot do conte\xFAdo. Editores veem as vers\xF5es na tela de edi\xE7\xE3o e podem carregar uma no formul\xE1rio. \xC9 atividade de conte\xFAdo, n\xE3o um log de auditoria de seguran\xE7a: grava\xE7\xF5es diretas no banco n\xE3o s\xE3o vistas.",
1332
+ historyEnabled: "Registrar vers\xF5es",
1333
+ historyAll: "Todos os tipos de conte\xFAdo",
1334
+ historyTypes: "Tipos de conte\xFAdo",
1335
+ historyRetention: "Manter snapshots (dias)",
1336
+ historyMax: "Snapshots por documento (m\xE1ximo)",
1337
+ historyEventDays: "Manter a atividade (dias)",
1338
+ historyRetentionHelp: "Uma rotina noturna esvazia snapshots mais antigos que isso ou al\xE9m do m\xE1ximo por documento (os mais novos s\xE3o mantidos) e exclui a atividade mais antiga que o limite. Nunca exclui arquivos de m\xEDdia.",
1339
+ historyInvalid: "N\xFAmeros inteiros: 1 a 3650 dias (a atividade mantida pelo menos tanto quanto os snapshots) e 1 a 1000 snapshots."
1104
1340
  };
1105
1341
 
1106
1342
  // admin/translations/pt.json
@@ -1178,7 +1414,6 @@ var pt_default = {
1178
1414
  previewHelp: "As altera\xE7\xF5es por guardar aparecem na pr\xE9-visualiza\xE7\xE3o. Clique num bloco para abrir o seu formul\xE1rio, numa imagem para abrir a Media Library, num texto para o editar.",
1179
1415
  previewNoUrl: "Sem URL de pr\xE9-visualiza\xE7\xE3o: defina em Defini\xE7\xF5es, Blockscene, ou configure a Preview nativa do Strapi para este tipo de conte\xFAdo.",
1180
1416
  previewFailed: "A pr\xE9-visualiza\xE7\xE3o n\xE3o respondeu em 15 s. Se o frontend ainda estiver a carregar, ela aparece sozinha; o formul\xE1rio continua utiliz\xE1vel.",
1181
- previewReady: "Pr\xE9-visualiza\xE7\xE3o da p\xE1gina \xB7 altera\xE7\xF5es por guardar",
1182
1417
  previewLoading: "A carregar pr\xE9-visualiza\xE7\xE3o\u2026",
1183
1418
  retry: "Tentar novamente",
1184
1419
  editText: "Editar texto",
@@ -1336,12 +1571,57 @@ var pt_default = {
1336
1571
  confirmDeleteOption: "Confirmar antes de eliminar um bloco",
1337
1572
  duplicateOption: 'Mostrar "Duplicar" em cada bloco',
1338
1573
  clipboardOption: 'Mostrar "Copiar" e "Colar" (entre p\xE1ginas)',
1574
+ friendlyLabels: "Etiquetas de campo leg\xEDveis",
1575
+ friendlyLabelsHelp: 'Os campos cuja etiqueta ainda \xE9 o nome do atributo aparecem como palavras ("mobileColumnsCount" passa a "Mobile columns count"). As etiquetas definidas em "Configurar a vista" e os textos da configura\xE7\xE3o "fields" do projeto mant\xEAm-se.',
1339
1576
  hiddenBlocks: "Blocos ocultos no site",
1340
1577
  "hiddenModes.strip": "Removidos da API de conte\xFAdo",
1341
1578
  "hiddenModes.flag": "Enviados com a marca\xE7\xE3o (o frontend decide)",
1342
1579
  "hiddenModes.off": "Desligado (sem bot\xE3o de ocultar)",
1343
1580
  hiddenBlocksHelp: "O olho em cada bloco marca-o como oculto no site. Removidos: as leituras da API de conte\xFAdo (REST, GraphQL) deixam-no de fora; o admin mostra-o sempre. Marca\xE7\xE3o: \xE9 enviado com o atributo para o frontend decidir.",
1344
- hiddenAttributeOff: "A configura\xE7\xE3o do plugin define hiddenAttribute como false: n\xE3o \xE9 poss\xEDvel ocultar blocos."
1581
+ hiddenAttributeOff: "A configura\xE7\xE3o do plugin define hiddenAttribute como false: n\xE3o \xE9 poss\xEDvel ocultar blocos.",
1582
+ historyTitle: "Hist\xF3rico",
1583
+ historyEmpty: "Ainda n\xE3o h\xE1 vers\xF5es. Grava\xE7\xF5es, publica\xE7\xF5es e elimina\xE7\xF5es passam a ser registadas a partir de agora.",
1584
+ historyLoading: "A carregar o hist\xF3rico\u2026",
1585
+ historyFailed: "N\xE3o foi poss\xEDvel carregar o hist\xF3rico.",
1586
+ historyRefresh: "Atualizar hist\xF3rico",
1587
+ historySystem: "Sistema",
1588
+ "historyActions.create": "Criado",
1589
+ "historyActions.update": "Guardado",
1590
+ "historyActions.publish": "Publicado",
1591
+ "historyActions.unpublish": "Despublicado",
1592
+ "historyActions.discard": "Rascunho descartado",
1593
+ "historyActions.delete": "Eliminado",
1594
+ "historyActions.restore": "Restaurado",
1595
+ historyInitial: "Primeira vers\xE3o",
1596
+ historyNoChange: "Sem altera\xE7\xE3o de conte\xFAdo",
1597
+ historyMissing: "N\xE3o registado (a captura falhou)",
1598
+ historyBlocksSummary: "Blocos: {added} adicionados, {removed} removidos, {changed} alterados",
1599
+ historyFieldsSummary: "Campos: {fields}",
1600
+ historyNotKept: "Esta vers\xE3o j\xE1 n\xE3o \xE9 mantida.",
1601
+ historyCompare: "Comparado com o formul\xE1rio",
1602
+ historySame: "Mesmo conte\xFAdo do formul\xE1rio.",
1603
+ "diffOps.added": "Adicionado",
1604
+ "diffOps.removed": "Removido",
1605
+ "diffOps.changed": "Alterado",
1606
+ historyDiffFields: "Campos diferentes: {fields}",
1607
+ historyDiffNote: "As rela\xE7\xF5es n\xE3o s\xE3o comparadas.",
1608
+ historyLoad: "Carregar esta vers\xE3o",
1609
+ historyLoaded: "Vers\xE3o carregada no formul\xE1rio. Nada \xE9 guardado at\xE9 guardar.",
1610
+ historyLeft: "Mantidos como est\xE3o: {fields}",
1611
+ historyRemovedFields: "J\xE1 n\xE3o existem no esquema, n\xE3o carregados: {fields}",
1612
+ historyMissingItems: "J\xE1 n\xE3o existem, deixados de fora: {media} ficheiros multim\xE9dia, {relations} entradas relacionadas, {blocks} blocos",
1613
+ historyLoadFailed: "N\xE3o foi poss\xEDvel carregar esta vers\xE3o.",
1614
+ historyShowMore: "Mostrar mais",
1615
+ historySettings: "Hist\xF3rico de vers\xF5es",
1616
+ historySettingsHelp: "Regista cada cria\xE7\xE3o, grava\xE7\xE3o, publica\xE7\xE3o, despublica\xE7\xE3o, descarte e elimina\xE7\xE3o feitos pelo document service do Strapi (o admin, as APIs REST e GraphQL, outros plugins), com um snapshot do conte\xFAdo. Os editores veem as vers\xF5es no ecr\xE3 de edi\xE7\xE3o e podem carregar uma no formul\xE1rio. \xC9 atividade de conte\xFAdo, n\xE3o um registo de auditoria de seguran\xE7a: escritas diretas na base de dados n\xE3o s\xE3o vistas.",
1617
+ historyEnabled: "Registar vers\xF5es",
1618
+ historyAll: "Todos os tipos de conte\xFAdo",
1619
+ historyTypes: "Tipos de conte\xFAdo",
1620
+ historyRetention: "Manter snapshots (dias)",
1621
+ historyMax: "Snapshots por documento (m\xE1ximo)",
1622
+ historyEventDays: "Manter a atividade (dias)",
1623
+ historyRetentionHelp: "Uma tarefa noturna esvazia os snapshots mais antigos do que isto ou al\xE9m do m\xE1ximo por documento (os mais recentes s\xE3o mantidos) e elimina a atividade mais antiga do que o limite. Nunca elimina ficheiros multim\xE9dia.",
1624
+ historyInvalid: "N\xFAmeros inteiros: 1 a 3650 dias (a atividade mantida pelo menos tanto quanto os snapshots) e 1 a 1000 snapshots."
1345
1625
  };
1346
1626
 
1347
1627
  // admin/translations/fr.json
@@ -1419,7 +1699,6 @@ var fr_default = {
1419
1699
  previewHelp: "Les modifications non enregistr\xE9es apparaissent dans l'aper\xE7u. Cliquez sur un bloc pour ouvrir son formulaire, sur une image pour ouvrir la M\xE9diath\xE8que, sur un texte pour le modifier.",
1420
1700
  previewNoUrl: "Aucune URL d'aper\xE7u : d\xE9finissez-la dans Param\xE8tres, Blockscene, ou configurez l'aper\xE7u natif de Strapi pour ce type de contenu.",
1421
1701
  previewFailed: "L'aper\xE7u n'a pas r\xE9pondu en 15 s. Si le frontend est encore en train de charger, il appara\xEEtra de lui-m\xEAme ; le formulaire reste utilisable.",
1422
- previewReady: "Aper\xE7u de la page \xB7 modifications non enregistr\xE9es",
1423
1702
  previewLoading: "Chargement de l'aper\xE7u\u2026",
1424
1703
  retry: "R\xE9essayer",
1425
1704
  editText: "Modifier le texte",
@@ -1577,12 +1856,57 @@ var fr_default = {
1577
1856
  confirmDeleteOption: "Confirmer avant de supprimer un bloc",
1578
1857
  duplicateOption: "Afficher \xAB Dupliquer \xBB sur chaque bloc",
1579
1858
  clipboardOption: "Afficher \xAB Copier \xBB et \xAB Coller \xBB (entre pages)",
1859
+ friendlyLabels: "Libell\xE9s de champ lisibles",
1860
+ friendlyLabelsHelp: `Les champs dont le libell\xE9 est encore le nom de l'attribut s'affichent en mots ("mobileColumnsCount" devient "Mobile columns count"). Les libell\xE9s d\xE9finis dans \xAB Configurer la vue \xBB et les textes de la configuration \xAB fields \xBB du projet sont conserv\xE9s.`,
1580
1861
  hiddenBlocks: "Blocs masqu\xE9s sur le site",
1581
1862
  "hiddenModes.strip": "Retir\xE9s de l'API de contenu",
1582
1863
  "hiddenModes.flag": "Envoy\xE9s avec l'indicateur (le frontend d\xE9cide)",
1583
1864
  "hiddenModes.off": "D\xE9sactiv\xE9 (pas de bouton masquer)",
1584
1865
  hiddenBlocksHelp: "L'\u0153il de chaque bloc le marque comme masqu\xE9 sur le site. Retir\xE9s : les lectures de l'API de contenu (REST, GraphQL) l'omettent, l'admin l'affiche toujours. Indicateur : il est envoy\xE9 avec l'attribut et le frontend d\xE9cide.",
1585
- hiddenAttributeOff: "La configuration du plugin fixe hiddenAttribute \xE0 false : les blocs ne peuvent pas \xEAtre masqu\xE9s."
1866
+ hiddenAttributeOff: "La configuration du plugin fixe hiddenAttribute \xE0 false : les blocs ne peuvent pas \xEAtre masqu\xE9s.",
1867
+ historyTitle: "Historique",
1868
+ historyEmpty: "Aucune version pour l'instant. Les enregistrements, publications et suppressions sont d\xE9sormais consign\xE9s.",
1869
+ historyLoading: "Chargement de l'historique\u2026",
1870
+ historyFailed: "Impossible de charger l'historique.",
1871
+ historyRefresh: "Actualiser l'historique",
1872
+ historySystem: "Syst\xE8me",
1873
+ "historyActions.create": "Cr\xE9\xE9",
1874
+ "historyActions.update": "Enregistr\xE9",
1875
+ "historyActions.publish": "Publi\xE9",
1876
+ "historyActions.unpublish": "D\xE9publi\xE9",
1877
+ "historyActions.discard": "Brouillon abandonn\xE9",
1878
+ "historyActions.delete": "Supprim\xE9",
1879
+ "historyActions.restore": "Restaur\xE9",
1880
+ historyInitial: "Premi\xE8re version",
1881
+ historyNoChange: "Aucun changement de contenu",
1882
+ historyMissing: "Non consign\xE9 (la capture a \xE9chou\xE9)",
1883
+ historyBlocksSummary: "Blocs : {added} ajout\xE9s, {removed} supprim\xE9s, {changed} modifi\xE9s",
1884
+ historyFieldsSummary: "Champs : {fields}",
1885
+ historyNotKept: "Cette version n'est plus conserv\xE9e.",
1886
+ historyCompare: "Compar\xE9 au formulaire",
1887
+ historySame: "M\xEAme contenu que le formulaire.",
1888
+ "diffOps.added": "Ajout\xE9",
1889
+ "diffOps.removed": "Supprim\xE9",
1890
+ "diffOps.changed": "Modifi\xE9",
1891
+ historyDiffFields: "Champs diff\xE9rents : {fields}",
1892
+ historyDiffNote: "Les relations ne sont pas compar\xE9es.",
1893
+ historyLoad: "Charger cette version",
1894
+ historyLoaded: "Version charg\xE9e dans le formulaire. Rien n'est enregistr\xE9 tant que vous n'enregistrez pas.",
1895
+ historyLeft: "Laiss\xE9s tels quels : {fields}",
1896
+ historyRemovedFields: "N'existent plus dans le sch\xE9ma, non charg\xE9s : {fields}",
1897
+ historyMissingItems: "N'existent plus, laiss\xE9s de c\xF4t\xE9 : {media} fichiers m\xE9dia, {relations} entr\xE9es li\xE9es, {blocks} blocs",
1898
+ historyLoadFailed: "Impossible de charger cette version.",
1899
+ historyShowMore: "Afficher plus",
1900
+ historySettings: "Historique des versions",
1901
+ historySettingsHelp: "Consigne chaque cr\xE9ation, enregistrement, publication, d\xE9publication, abandon de brouillon et suppression passant par le document service de Strapi (l'admin, les API REST et GraphQL, d'autres plugins), avec un instantan\xE9 du contenu. Les \xE9diteurs voient les versions dans la vue d'\xE9dition et peuvent en charger une dans le formulaire. Il s'agit d'activit\xE9 de contenu, pas d'un journal d'audit de s\xE9curit\xE9 : les \xE9critures directes en base ne sont pas vues.",
1902
+ historyEnabled: "Consigner les versions",
1903
+ historyAll: "Tous les types de contenu",
1904
+ historyTypes: "Types de contenu",
1905
+ historyRetention: "Conserver les instantan\xE9s (jours)",
1906
+ historyMax: "Instantan\xE9s par document (maximum)",
1907
+ historyEventDays: "Conserver l'activit\xE9 (jours)",
1908
+ historyRetentionHelp: "Une t\xE2che nocturne vide les instantan\xE9s plus anciens que cela ou au-del\xE0 du maximum par document (les plus r\xE9cents sont gard\xE9s) et supprime l'activit\xE9 plus ancienne que sa limite. Elle ne supprime jamais de fichiers m\xE9dia.",
1909
+ historyInvalid: "Nombres entiers : 1 \xE0 3650 jours (l'activit\xE9 conserv\xE9e au moins aussi longtemps que les instantan\xE9s) et 1 \xE0 1000 instantan\xE9s."
1586
1910
  };
1587
1911
 
1588
1912
  // admin/translations/es.json
@@ -1660,7 +1984,6 @@ var es_default = {
1660
1984
  previewHelp: "Los cambios sin guardar aparecen en la vista previa. Haga clic en un bloque para abrir su formulario, en una imagen para abrir la Biblioteca multimedia, en un texto para editarlo.",
1661
1985
  previewNoUrl: "Sin URL de vista previa: def\xEDnala en Ajustes, Blockscene, o configure la Vista previa nativa de Strapi para este tipo de contenido.",
1662
1986
  previewFailed: "La vista previa no respondi\xF3 en 15 s. Si el frontend a\xFAn est\xE1 cargando, aparecer\xE1 sola; el formulario sigue utilizable.",
1663
- previewReady: "Vista previa de la p\xE1gina \xB7 cambios sin guardar",
1664
1987
  previewLoading: "Cargando vista previa\u2026",
1665
1988
  retry: "Reintentar",
1666
1989
  editText: "Editar texto",
@@ -1818,12 +2141,57 @@ var es_default = {
1818
2141
  confirmDeleteOption: "Confirmar antes de eliminar un bloque",
1819
2142
  duplicateOption: "Mostrar \xABDuplicar\xBB en cada bloque",
1820
2143
  clipboardOption: "Mostrar \xABCopiar\xBB y \xABPegar\xBB (entre p\xE1ginas)",
2144
+ friendlyLabels: "Etiquetas de campo legibles",
2145
+ friendlyLabelsHelp: 'Los campos cuya etiqueta sigue siendo el nombre del atributo se muestran como palabras ("mobileColumnsCount" pasa a "Mobile columns count"). Se conservan las etiquetas definidas en \xABConfigurar la vista\xBB y los textos de la configuraci\xF3n \xABfields\xBB del proyecto.',
1821
2146
  hiddenBlocks: "Bloques ocultos en el sitio",
1822
2147
  "hiddenModes.strip": "Eliminados de la API de contenido",
1823
2148
  "hiddenModes.flag": "Enviados con la marca (el frontend decide)",
1824
2149
  "hiddenModes.off": "Desactivado (sin bot\xF3n de ocultar)",
1825
2150
  hiddenBlocksHelp: "El ojo de cada bloque lo marca como oculto en el sitio. Eliminados: las lecturas de la API de contenido (REST, GraphQL) lo omiten; el admin siempre lo muestra. Marca: se env\xEDa con el atributo y el frontend decide.",
1826
- hiddenAttributeOff: "La configuraci\xF3n del plugin fija hiddenAttribute en false: no se pueden ocultar bloques."
2151
+ hiddenAttributeOff: "La configuraci\xF3n del plugin fija hiddenAttribute en false: no se pueden ocultar bloques.",
2152
+ historyTitle: "Historial",
2153
+ historyEmpty: "A\xFAn no hay versiones. Desde ahora se registran los guardados, las publicaciones y las eliminaciones.",
2154
+ historyLoading: "Cargando historial\u2026",
2155
+ historyFailed: "No se pudo cargar el historial.",
2156
+ historyRefresh: "Actualizar historial",
2157
+ historySystem: "Sistema",
2158
+ "historyActions.create": "Creado",
2159
+ "historyActions.update": "Guardado",
2160
+ "historyActions.publish": "Publicado",
2161
+ "historyActions.unpublish": "Despublicado",
2162
+ "historyActions.discard": "Borrador descartado",
2163
+ "historyActions.delete": "Eliminado",
2164
+ "historyActions.restore": "Restaurado",
2165
+ historyInitial: "Primera versi\xF3n",
2166
+ historyNoChange: "Sin cambios de contenido",
2167
+ historyMissing: "No registrado (la captura fall\xF3)",
2168
+ historyBlocksSummary: "Bloques: {added} a\xF1adidos, {removed} eliminados, {changed} modificados",
2169
+ historyFieldsSummary: "Campos: {fields}",
2170
+ historyNotKept: "Esta versi\xF3n ya no se conserva.",
2171
+ historyCompare: "Comparado con el formulario",
2172
+ historySame: "Mismo contenido que el formulario.",
2173
+ "diffOps.added": "A\xF1adido",
2174
+ "diffOps.removed": "Eliminado",
2175
+ "diffOps.changed": "Modificado",
2176
+ historyDiffFields: "Campos distintos: {fields}",
2177
+ historyDiffNote: "Las relaciones no se comparan.",
2178
+ historyLoad: "Cargar esta versi\xF3n",
2179
+ historyLoaded: "Versi\xF3n cargada en el formulario. No se guarda nada hasta que guardes.",
2180
+ historyLeft: "Se dejan como est\xE1n: {fields}",
2181
+ historyRemovedFields: "Ya no est\xE1n en el esquema, no se cargan: {fields}",
2182
+ historyMissingItems: "Ya no existen, se omiten: {media} archivos multimedia, {relations} entradas relacionadas, {blocks} bloques",
2183
+ historyLoadFailed: "No se pudo cargar esta versi\xF3n.",
2184
+ historyShowMore: "Mostrar m\xE1s",
2185
+ historySettings: "Historial de versiones",
2186
+ historySettingsHelp: "Registra cada creaci\xF3n, guardado, publicaci\xF3n, despublicaci\xF3n, descarte y eliminaci\xF3n hechos a trav\xE9s del document service de Strapi (el admin, las API REST y GraphQL, otros plugins), con una instant\xE1nea del contenido. Los editores ven las versiones en la vista de edici\xF3n y pueden cargar una en el formulario. Es actividad de contenido, no un registro de auditor\xEDa de seguridad: las escrituras directas en la base de datos no se ven.",
2187
+ historyEnabled: "Registrar versiones",
2188
+ historyAll: "Todos los tipos de contenido",
2189
+ historyTypes: "Tipos de contenido",
2190
+ historyRetention: "Conservar instant\xE1neas (d\xEDas)",
2191
+ historyMax: "Instant\xE1neas por documento (m\xE1ximo)",
2192
+ historyEventDays: "Conservar la actividad (d\xEDas)",
2193
+ historyRetentionHelp: "Una tarea nocturna vac\xEDa las instant\xE1neas m\xE1s antiguas que esto o por encima del m\xE1ximo por documento (se conservan las m\xE1s recientes) y elimina la actividad m\xE1s antigua que su l\xEDmite. Nunca elimina archivos multimedia.",
2194
+ historyInvalid: "N\xFAmeros enteros: de 1 a 3650 d\xEDas (la actividad se conserva al menos tanto como las instant\xE1neas) y de 1 a 1000 instant\xE1neas."
1827
2195
  };
1828
2196
 
1829
2197
  // admin/translations/de.json
@@ -1901,7 +2269,6 @@ var de_default = {
1901
2269
  previewHelp: "Ungespeicherte \xC4nderungen erscheinen in der Vorschau. Klicken Sie auf einen Block, um sein Formular zu \xF6ffnen, auf ein Bild f\xFCr die Medienbibliothek, auf einen Text, um ihn zu bearbeiten.",
1902
2270
  previewNoUrl: "Keine Vorschau-URL: in Einstellungen, Blockscene festlegen oder die native Strapi-Vorschau f\xFCr diesen Inhaltstyp konfigurieren.",
1903
2271
  previewFailed: "Die Vorschau hat innerhalb von 15 s nicht geantwortet. L\xE4dt das Frontend noch, erscheint sie von selbst; das Formular bleibt benutzbar.",
1904
- previewReady: "Seitenvorschau \xB7 ungespeicherte \xC4nderungen",
1905
2272
  previewLoading: "Vorschau wird geladen\u2026",
1906
2273
  retry: "Erneut versuchen",
1907
2274
  editText: "Text bearbeiten",
@@ -2059,12 +2426,57 @@ var de_default = {
2059
2426
  confirmDeleteOption: "Vor dem L\xF6schen eines Blocks nachfragen",
2060
2427
  duplicateOption: "\u201EDuplizieren\u201C an jedem Block anzeigen",
2061
2428
  clipboardOption: "\u201EKopieren\u201C und \u201EEinf\xFCgen\u201C anzeigen (seiten\xFCbergreifend)",
2429
+ friendlyLabels: "Lesbare Feldbezeichnungen",
2430
+ friendlyLabelsHelp: "Felder, deren Bezeichnung noch der Attributname ist, erscheinen als W\xF6rter (\u201EmobileColumnsCount\u201C wird zu \u201EMobile columns count\u201C). In \u201EAnsicht konfigurieren\u201C gesetzte Bezeichnungen und Texte aus der \u201Efields\u201C-Konfiguration des Projekts bleiben erhalten.",
2062
2431
  hiddenBlocks: "Auf der Website ausgeblendete Bl\xF6cke",
2063
2432
  "hiddenModes.strip": "Aus der Content-API entfernt",
2064
2433
  "hiddenModes.flag": "Mit Markierung gesendet (das Frontend entscheidet)",
2065
2434
  "hiddenModes.off": "Aus (kein Ausblenden-Knopf)",
2066
2435
  hiddenBlocksHelp: "Das Auge an jedem Block blendet ihn auf der Website aus. Entfernt: Lesezugriffe der Content-API (REST, GraphQL) lassen ihn weg, der Admin zeigt ihn immer. Markierung: Er wird mit dem Attribut gesendet und das Frontend entscheidet.",
2067
- hiddenAttributeOff: "Die Plugin-Konfiguration setzt hiddenAttribute auf false: Bl\xF6cke k\xF6nnen nicht ausgeblendet werden."
2436
+ hiddenAttributeOff: "Die Plugin-Konfiguration setzt hiddenAttribute auf false: Bl\xF6cke k\xF6nnen nicht ausgeblendet werden.",
2437
+ historyTitle: "Verlauf",
2438
+ historyEmpty: "Noch keine Versionen. Speichern, Ver\xF6ffentlichen und L\xF6schen werden ab jetzt aufgezeichnet.",
2439
+ historyLoading: "Verlauf wird geladen\u2026",
2440
+ historyFailed: "Der Verlauf konnte nicht geladen werden.",
2441
+ historyRefresh: "Verlauf aktualisieren",
2442
+ historySystem: "System",
2443
+ "historyActions.create": "Erstellt",
2444
+ "historyActions.update": "Gespeichert",
2445
+ "historyActions.publish": "Ver\xF6ffentlicht",
2446
+ "historyActions.unpublish": "Ver\xF6ffentlichung zur\xFCckgezogen",
2447
+ "historyActions.discard": "Entwurf verworfen",
2448
+ "historyActions.delete": "Gel\xF6scht",
2449
+ "historyActions.restore": "Wiederhergestellt",
2450
+ historyInitial: "Erste Version",
2451
+ historyNoChange: "Keine inhaltliche \xC4nderung",
2452
+ historyMissing: "Nicht aufgezeichnet (Erfassung fehlgeschlagen)",
2453
+ historyBlocksSummary: "Bl\xF6cke: {added} hinzugef\xFCgt, {removed} entfernt, {changed} ge\xE4ndert",
2454
+ historyFieldsSummary: "Felder: {fields}",
2455
+ historyNotKept: "Diese Version wird nicht mehr aufbewahrt.",
2456
+ historyCompare: "Verglichen mit dem Formular",
2457
+ historySame: "Gleicher Inhalt wie im Formular.",
2458
+ "diffOps.added": "Hinzugef\xFCgt",
2459
+ "diffOps.removed": "Entfernt",
2460
+ "diffOps.changed": "Ge\xE4ndert",
2461
+ historyDiffFields: "Abweichende Felder: {fields}",
2462
+ historyDiffNote: "Relationen werden nicht verglichen.",
2463
+ historyLoad: "Diese Version laden",
2464
+ historyLoaded: "Version ins Formular geladen. Nichts wird gespeichert, bis Sie speichern.",
2465
+ historyLeft: "Unver\xE4ndert gelassen: {fields}",
2466
+ historyRemovedFields: "Nicht mehr im Schema, nicht geladen: {fields}",
2467
+ historyMissingItems: "Existieren nicht mehr, ausgelassen: {media} Mediendateien, {relations} verkn\xFCpfte Eintr\xE4ge, {blocks} Bl\xF6cke",
2468
+ historyLoadFailed: "Diese Version konnte nicht geladen werden.",
2469
+ historyShowMore: "Mehr anzeigen",
2470
+ historySettings: "Versionsverlauf",
2471
+ historySettingsHelp: "Zeichnet jedes Erstellen, Speichern, Ver\xF6ffentlichen, Zur\xFCckziehen, Verwerfen und L\xF6schen \xFCber den Document Service von Strapi auf (Admin, REST- und GraphQL-API, andere Plugins), mit einem Snapshot des Inhalts. Redakteure sehen die Versionen in der Bearbeitungsansicht und k\xF6nnen eine ins Formular laden. Das ist Inhaltsaktivit\xE4t, kein Sicherheits-Audit-Log: direkte Datenbankschreibvorg\xE4nge werden nicht erfasst.",
2472
+ historyEnabled: "Versionen aufzeichnen",
2473
+ historyAll: "Alle Inhaltstypen",
2474
+ historyTypes: "Inhaltstypen",
2475
+ historyRetention: "Snapshots aufbewahren (Tage)",
2476
+ historyMax: "Snapshots pro Dokument (Maximum)",
2477
+ historyEventDays: "Aktivit\xE4t aufbewahren (Tage)",
2478
+ historyRetentionHelp: "Ein n\xE4chtlicher Job leert Snapshots, die \xE4lter sind oder das Maximum pro Dokument \xFCberschreiten (die neuesten bleiben), und l\xF6scht Aktivit\xE4t, die \xE4lter als ihr Limit ist. Mediendateien l\xF6scht er nie.",
2479
+ historyInvalid: "Ganze Zahlen: 1 bis 3650 Tage (die Aktivit\xE4t mindestens so lange wie die Snapshots) und 1 bis 1000 Snapshots."
2068
2480
  };
2069
2481
 
2070
2482
  // admin/translations/it.json
@@ -2142,7 +2554,6 @@ var it_default = {
2142
2554
  previewHelp: "Le modifiche non salvate compaiono nell'anteprima. Clicca un blocco per aprire il suo modulo, un'immagine per aprire la Libreria media, un testo per modificarlo.",
2143
2555
  previewNoUrl: "Nessun URL di anteprima: impostalo in Impostazioni, Blockscene, oppure configura l'Anteprima nativa di Strapi per questo tipo di contenuto.",
2144
2556
  previewFailed: "L'anteprima non ha risposto entro 15 s. Se il frontend sta ancora caricando, comparir\xE0 da sola; il modulo resta utilizzabile.",
2145
- previewReady: "Anteprima della pagina \xB7 modifiche non salvate",
2146
2557
  previewLoading: "Caricamento dell'anteprima\u2026",
2147
2558
  retry: "Riprova",
2148
2559
  editText: "Modifica testo",
@@ -2300,12 +2711,57 @@ var it_default = {
2300
2711
  confirmDeleteOption: "Chiedi conferma prima di eliminare un blocco",
2301
2712
  duplicateOption: 'Mostra "Duplica" su ogni blocco',
2302
2713
  clipboardOption: 'Mostra "Copia" e "Incolla" (tra pagine)',
2714
+ friendlyLabels: "Etichette dei campi leggibili",
2715
+ friendlyLabelsHelp: `I campi la cui etichetta \xE8 ancora il nome dell'attributo appaiono come parole ("mobileColumnsCount" diventa "Mobile columns count"). Le etichette impostate in "Configura la vista" e i testi della configurazione "fields" del progetto restano invariati.`,
2303
2716
  hiddenBlocks: "Blocchi nascosti sul sito",
2304
2717
  "hiddenModes.strip": "Rimossi dall'API dei contenuti",
2305
2718
  "hiddenModes.flag": "Inviati con il flag (decide il frontend)",
2306
2719
  "hiddenModes.off": "Disattivato (nessun pulsante nascondi)",
2307
2720
  hiddenBlocksHelp: "L'occhio su ogni blocco lo segna come nascosto sul sito. Rimossi: le letture dell'API dei contenuti (REST, GraphQL) lo omettono, l'admin lo mostra sempre. Flag: viene inviato con l'attributo e decide il frontend.",
2308
- hiddenAttributeOff: "La configurazione del plugin imposta hiddenAttribute a false: i blocchi non possono essere nascosti."
2721
+ hiddenAttributeOff: "La configurazione del plugin imposta hiddenAttribute a false: i blocchi non possono essere nascosti.",
2722
+ historyTitle: "Cronologia",
2723
+ historyEmpty: "Ancora nessuna versione. Da ora vengono registrati salvataggi, pubblicazioni ed eliminazioni.",
2724
+ historyLoading: "Caricamento della cronologia\u2026",
2725
+ historyFailed: "Impossibile caricare la cronologia.",
2726
+ historyRefresh: "Aggiorna cronologia",
2727
+ historySystem: "Sistema",
2728
+ "historyActions.create": "Creato",
2729
+ "historyActions.update": "Salvato",
2730
+ "historyActions.publish": "Pubblicato",
2731
+ "historyActions.unpublish": "Pubblicazione annullata",
2732
+ "historyActions.discard": "Bozza scartata",
2733
+ "historyActions.delete": "Eliminato",
2734
+ "historyActions.restore": "Ripristinato",
2735
+ historyInitial: "Prima versione",
2736
+ historyNoChange: "Nessuna modifica al contenuto",
2737
+ historyMissing: "Non registrato (acquisizione non riuscita)",
2738
+ historyBlocksSummary: "Blocchi: {added} aggiunti, {removed} rimossi, {changed} modificati",
2739
+ historyFieldsSummary: "Campi: {fields}",
2740
+ historyNotKept: "Questa versione non \xE8 pi\xF9 conservata.",
2741
+ historyCompare: "Confrontato con il modulo",
2742
+ historySame: "Stesso contenuto del modulo.",
2743
+ "diffOps.added": "Aggiunto",
2744
+ "diffOps.removed": "Rimosso",
2745
+ "diffOps.changed": "Modificato",
2746
+ historyDiffFields: "Campi diversi: {fields}",
2747
+ historyDiffNote: "Le relazioni non vengono confrontate.",
2748
+ historyLoad: "Carica questa versione",
2749
+ historyLoaded: "Versione caricata nel modulo. Nulla viene salvato finch\xE9 non salvi.",
2750
+ historyLeft: "Lasciati come sono: {fields}",
2751
+ historyRemovedFields: "Non pi\xF9 nello schema, non caricati: {fields}",
2752
+ historyMissingItems: "Non esistono pi\xF9, esclusi: {media} file multimediali, {relations} voci collegate, {blocks} blocchi",
2753
+ historyLoadFailed: "Impossibile caricare questa versione.",
2754
+ historyShowMore: "Mostra altro",
2755
+ historySettings: "Cronologia delle versioni",
2756
+ historySettingsHelp: "Registra ogni creazione, salvataggio, pubblicazione, annullamento della pubblicazione, scarto e eliminazione fatti tramite il document service di Strapi (l'admin, le API REST e GraphQL, altri plugin), con un'istantanea del contenuto. Gli editor vedono le versioni nella vista di modifica e possono caricarne una nel modulo. \xC8 attivit\xE0 sui contenuti, non un registro di audit di sicurezza: le scritture dirette nel database non vengono viste.",
2757
+ historyEnabled: "Registra le versioni",
2758
+ historyAll: "Tutti i tipi di contenuto",
2759
+ historyTypes: "Tipi di contenuto",
2760
+ historyRetention: "Conserva le istantanee (giorni)",
2761
+ historyMax: "Istantanee per documento (massimo)",
2762
+ historyEventDays: "Conserva l'attivit\xE0 (giorni)",
2763
+ historyRetentionHelp: "Un'attivit\xE0 notturna svuota le istantanee pi\xF9 vecchie di cos\xEC o oltre il massimo per documento (le pi\xF9 recenti restano) ed elimina l'attivit\xE0 pi\xF9 vecchia del suo limite. Non elimina mai file multimediali.",
2764
+ historyInvalid: "Numeri interi: da 1 a 3650 giorni (l'attivit\xE0 conservata almeno quanto le istantanee) e da 1 a 1000 istantanee."
2309
2765
  };
2310
2766
 
2311
2767
  // admin/translations/nl.json
@@ -2383,7 +2839,6 @@ var nl_default = {
2383
2839
  previewHelp: "Niet-opgeslagen wijzigingen verschijnen in het voorbeeld. Klik op een blok om het formulier te openen, op een afbeelding voor de Mediabibliotheek, op een tekst om die te bewerken.",
2384
2840
  previewNoUrl: "Geen voorbeeld-URL: stel die in bij Instellingen, Blockscene, of configureer Strapi's native Preview voor dit contenttype.",
2385
2841
  previewFailed: "Het voorbeeld antwoordde niet binnen 15 s. Als de frontend nog laadt, verschijnt het vanzelf; het formulier blijft bruikbaar.",
2386
- previewReady: "Paginavoorbeeld \xB7 niet-opgeslagen wijzigingen",
2387
2842
  previewLoading: "Voorbeeld laden\u2026",
2388
2843
  retry: "Opnieuw proberen",
2389
2844
  editText: "Tekst bewerken",
@@ -2541,12 +2996,57 @@ var nl_default = {
2541
2996
  confirmDeleteOption: "Bevestigen voordat een blok wordt verwijderd",
2542
2997
  duplicateOption: '"Dupliceren" op elk blok tonen',
2543
2998
  clipboardOption: `"Kopi\xEBren" en "Plakken" tonen (tussen pagina's)`,
2999
+ friendlyLabels: "Leesbare veldlabels",
3000
+ friendlyLabelsHelp: 'Velden waarvan het label nog de attribuutnaam is, verschijnen als woorden ("mobileColumnsCount" wordt "Mobile columns count"). Labels uit "Weergave configureren" en teksten uit de "fields"-configuratie van het project blijven behouden.',
2544
3001
  hiddenBlocks: "Op de site verborgen blokken",
2545
3002
  "hiddenModes.strip": "Verwijderd uit de content-API",
2546
3003
  "hiddenModes.flag": "Verzonden met de markering (de frontend beslist)",
2547
3004
  "hiddenModes.off": "Uit (geen verbergknop)",
2548
3005
  hiddenBlocksHelp: "Het oog op elk blok markeert het als verborgen op de site. Verwijderd: leesverzoeken van de content-API (REST, GraphQL) laten het weg, de admin toont het altijd. Markering: het wordt met het attribuut verzonden en de frontend beslist.",
2549
- hiddenAttributeOff: "De pluginconfiguratie zet hiddenAttribute op false: blokken kunnen niet verborgen worden."
3006
+ hiddenAttributeOff: "De pluginconfiguratie zet hiddenAttribute op false: blokken kunnen niet verborgen worden.",
3007
+ historyTitle: "Geschiedenis",
3008
+ historyEmpty: "Nog geen versies. Opslaan, publiceren en verwijderen worden vanaf nu vastgelegd.",
3009
+ historyLoading: "Geschiedenis laden\u2026",
3010
+ historyFailed: "De geschiedenis kon niet worden geladen.",
3011
+ historyRefresh: "Geschiedenis vernieuwen",
3012
+ historySystem: "Systeem",
3013
+ "historyActions.create": "Aangemaakt",
3014
+ "historyActions.update": "Opgeslagen",
3015
+ "historyActions.publish": "Gepubliceerd",
3016
+ "historyActions.unpublish": "Publicatie ingetrokken",
3017
+ "historyActions.discard": "Concept verworpen",
3018
+ "historyActions.delete": "Verwijderd",
3019
+ "historyActions.restore": "Hersteld",
3020
+ historyInitial: "Eerste versie",
3021
+ historyNoChange: "Geen inhoudelijke wijziging",
3022
+ historyMissing: "Niet vastgelegd (vastleggen mislukt)",
3023
+ historyBlocksSummary: "Blokken: {added} toegevoegd, {removed} verwijderd, {changed} gewijzigd",
3024
+ historyFieldsSummary: "Velden: {fields}",
3025
+ historyNotKept: "Deze versie wordt niet meer bewaard.",
3026
+ historyCompare: "Vergeleken met het formulier",
3027
+ historySame: "Zelfde inhoud als het formulier.",
3028
+ "diffOps.added": "Toegevoegd",
3029
+ "diffOps.removed": "Verwijderd",
3030
+ "diffOps.changed": "Gewijzigd",
3031
+ historyDiffFields: "Afwijkende velden: {fields}",
3032
+ historyDiffNote: "Relaties worden niet vergeleken.",
3033
+ historyLoad: "Deze versie laden",
3034
+ historyLoaded: "Versie in het formulier geladen. Er wordt niets opgeslagen totdat je opslaat.",
3035
+ historyLeft: "Gelaten zoals ze zijn: {fields}",
3036
+ historyRemovedFields: "Niet meer in het schema, niet geladen: {fields}",
3037
+ historyMissingItems: "Bestaan niet meer, weggelaten: {media} mediabestanden, {relations} gekoppelde items, {blocks} blokken",
3038
+ historyLoadFailed: "Deze versie kon niet worden geladen.",
3039
+ historyShowMore: "Meer tonen",
3040
+ historySettings: "Versiegeschiedenis",
3041
+ historySettingsHelp: "Legt elke aanmaak, opslag, publicatie, intrekking, verwerping en verwijdering via de document service van Strapi vast (de admin, de REST- en GraphQL-API's, andere plugins), met een momentopname van de inhoud. Redacteuren zien de versies in de bewerkweergave en kunnen er een in het formulier laden. Dit is inhoudsactiviteit, geen beveiligingsauditlog: rechtstreekse schrijfacties in de database worden niet gezien.",
3042
+ historyEnabled: "Versies vastleggen",
3043
+ historyAll: "Alle inhoudstypen",
3044
+ historyTypes: "Inhoudstypen",
3045
+ historyRetention: "Momentopnamen bewaren (dagen)",
3046
+ historyMax: "Momentopnamen per document (maximum)",
3047
+ historyEventDays: "Activiteit bewaren (dagen)",
3048
+ historyRetentionHelp: "Een nachtelijke taak leegt momentopnamen die ouder zijn of boven het maximum per document uitkomen (de nieuwste blijven) en verwijdert activiteit die ouder is dan de limiet. Mediabestanden worden nooit verwijderd.",
3049
+ historyInvalid: "Gehele getallen: 1 tot 3650 dagen (de activiteit minstens zo lang bewaard als de momentopnamen) en 1 tot 1000 momentopnamen."
2550
3050
  };
2551
3051
 
2552
3052
  // admin/messages.ts
@@ -2580,9 +3080,9 @@ function useAnchors(zones, onOpen) {
2580
3080
  sync.current = () => {
2581
3081
  const next = [];
2582
3082
  for (const zone of latest.current) {
2583
- const list = zone.uids?.length ? findZoneList(zone.label) : null;
2584
- if (!list) continue;
2585
- toggles(list).forEach((button, index) => {
3083
+ const list2 = zone.uids?.length ? findZoneList(zone.label) : null;
3084
+ if (!list2) continue;
3085
+ toggles(list2).forEach((button, index) => {
2586
3086
  const uid = zone.uids[index];
2587
3087
  if (!uid) return;
2588
3088
  let el = button.querySelector(
@@ -2793,7 +3293,7 @@ function toConnect(relations, target) {
2793
3293
  id: r.id,
2794
3294
  apiData: { id: r.id, documentId: r.documentId, locale: r.locale, isTemporary: true },
2795
3295
  status: r.status,
2796
- label: r.documentId,
3296
+ label: r.label ?? r.documentId,
2797
3297
  href: `../collection-types/${target}/${r.documentId}${r.locale ? `?plugins[i18n][locale]=${r.locale}` : ""}`,
2798
3298
  __temp_key__: keys[i]
2799
3299
  })),
@@ -2968,9 +3468,9 @@ function useAnchors2(zones, enabled) {
2968
3468
  const next = [];
2969
3469
  if (enabled)
2970
3470
  for (const zone of latest.current) {
2971
- const list = zone.count ? findZoneList(zone.label) : null;
2972
- if (!list) continue;
2973
- toggles(list).forEach((toggle, index) => {
3471
+ const list2 = zone.count ? findZoneList(zone.label) : null;
3472
+ if (!list2) continue;
3473
+ toggles(list2).forEach((toggle, index) => {
2974
3474
  const trash = trashOf(toggle);
2975
3475
  if (!trash || index >= zone.count) return;
2976
3476
  const holder = trash.parentElement !== actionsOf(toggle) && trash.parentElement?.children.length === 1 ? trash.parentElement : trash;
@@ -3088,9 +3588,9 @@ function RowActions({ zones, actions, Modal: Modal2 }) {
3088
3588
  const button = event.target?.closest?.("button");
3089
3589
  if (!button || bypass.current) return;
3090
3590
  for (const zone of latest.current.zones) {
3091
- const list = findZoneList(zone.label);
3092
- if (!list?.contains(button)) continue;
3093
- const headers = toggles(list);
3591
+ const list2 = findZoneList(zone.label);
3592
+ if (!list2?.contains(button)) continue;
3593
+ const headers = toggles(list2);
3094
3594
  const index = headers.findIndex((toggle) => trashOf(toggle) === button);
3095
3595
  if (index < 0) return;
3096
3596
  event.preventDefault();
@@ -3552,7 +4052,7 @@ var readCollapsed = () => {
3552
4052
  };
3553
4053
  var TYPE_ICONS = { hero: "hero", text: "text", media: "image", listing: "list", cards: "cards", cta: "link", form: "form", layout: "layout" };
3554
4054
  var FILTER_MENUS = ["tags", "media", "content"];
3555
- var toggled = (list, value) => list.includes(value) ? list.filter((item) => item !== value) : [...list, value];
4055
+ var toggled = (list2, value) => list2.includes(value) ? list2.filter((item) => item !== value) : [...list2, value];
3556
4056
  function FilterMenu({ name, label, options, picked, onChange, labelOf }) {
3557
4057
  const [open, setOpen] = React4.useState(false);
3558
4058
  const ref = React4.useRef(null);
@@ -4033,7 +4533,7 @@ function ZoneGallery({
4033
4533
  };
4034
4534
  const star = (uid) => savePrefs({ ...prefs, starred: toggled(prefs.starred, uid) });
4035
4535
  const options = config2 ? optionsFor(zone, components, config2) : null;
4036
- const inZone = (list) => options ? list.filter((uid) => options.uids.includes(uid)) : [];
4536
+ const inZone = (list2) => options ? list2.filter((uid) => options.uids.includes(uid)) : [];
4037
4537
  const filter = {
4038
4538
  ...picked,
4039
4539
  typology: TYPOLOGIES.includes(view) ? view : void 0,
@@ -4310,16 +4810,16 @@ function useInitialAccordions({
4310
4810
  };
4311
4811
  document.addEventListener("click", cancel, true);
4312
4812
  const timer = setInterval(() => {
4313
- const pending = latest.current.filter((zone) => zone.count > 0);
4314
- const ready = pending.length > 0 && pending.every((zone) => {
4315
- const list = findZoneList(zone.label);
4316
- return list && toggles(list).length >= zone.count;
4813
+ const pending2 = latest.current.filter((zone) => zone.count > 0);
4814
+ const ready = pending2.length > 0 && pending2.every((zone) => {
4815
+ const list2 = findZoneList(zone.label);
4816
+ return list2 && toggles(list2).length >= zone.count;
4317
4817
  }) && (editor.initialState !== "remember" || user.current);
4318
4818
  if (!ready && ++tries < 25) return;
4319
4819
  stop();
4320
- for (const zone of pending) {
4321
- const list = findZoneList(zone.label);
4322
- if (!list) continue;
4820
+ for (const zone of pending2) {
4821
+ const list2 = findZoneList(zone.label);
4822
+ if (!list2) continue;
4323
4823
  const key = memoryKey({
4324
4824
  base: memoryBase(),
4325
4825
  userId: user.current,
@@ -4327,7 +4827,7 @@ function useInitialAccordions({
4327
4827
  zone: zone.name
4328
4828
  });
4329
4829
  setAll(
4330
- list,
4830
+ list2,
4331
4831
  initialState(editor, readMemory(storage2(), key)) === "open",
4332
4832
  import_react_dom3.unstable_batchedUpdates
4333
4833
  );
@@ -4343,8 +4843,8 @@ function useLabelAnchor(zone, enabled) {
4343
4843
  if (!enabled) return;
4344
4844
  let frame2 = 0;
4345
4845
  const sync = () => {
4346
- const list = findZoneList(zone.label);
4347
- const row = list && [...list.parentElement?.children || []].find((child) => child !== list && child.textContent?.trim());
4846
+ const list2 = findZoneList(zone.label);
4847
+ const row = list2 && [...list2.parentElement?.children || []].find((child) => child !== list2 && child.textContent?.trim());
4348
4848
  let anchor = document.querySelector(`[${ZONE_ATTR}="${CSS.escape(zone.name)}"]`);
4349
4849
  if (anchor && anchor.parentElement !== row) {
4350
4850
  anchor.remove();
@@ -4381,8 +4881,8 @@ function ZoneControls({ zone, editor, contentType, userId, tools }) {
4381
4881
  const anchor = useLabelAnchor(zone, shown);
4382
4882
  if (!shown || !anchor) return null;
4383
4883
  const apply = (open) => {
4384
- const list = findZoneList(zone.label);
4385
- if (list) setAll(list, open, import_react_dom3.unstable_batchedUpdates);
4884
+ const list2 = findZoneList(zone.label);
4885
+ if (list2) setAll(list2, open, import_react_dom3.unstable_batchedUpdates);
4386
4886
  writeMemory(
4387
4887
  storage2(),
4388
4888
  memoryKey({ base: memoryBase(), userId, contentType, zone: zone.name }),
@@ -4444,6 +4944,7 @@ var React5 = __toESM(require("react"));
4444
4944
  var import_react_dom4 = require("react-dom");
4445
4945
  var import_styled_components4 = __toESM(require("styled-components"));
4446
4946
  var import_design_system3 = require("@strapi/design-system");
4947
+ var import_react_intl2 = require("react-intl");
4447
4948
  var import_admin = require("@strapi/strapi/admin");
4448
4949
  var import_strapi_admin = require("@strapi/content-manager/strapi-admin");
4449
4950
 
@@ -4677,6 +5178,9 @@ function ToolbarActions({ model, collectionType, documentId, locale }) {
4677
5178
  );
4678
5179
  const { toggleNotification } = (0, import_admin.useNotification)();
4679
5180
  const t = useMessages();
5181
+ const { formatMessage } = (0, import_react_intl2.useIntl)();
5182
+ const modified = (0, import_admin.useForm)("BlocksceneToolbar", (state) => state.modified);
5183
+ const status = documentId ? doc?.status : void 0;
4680
5184
  const descriptions = (plugins["content-manager"]?.apis?.getDocumentActions?.("panel") || []).filter((d) => ACTION_TYPES.includes(d.type));
4681
5185
  const props = {
4682
5186
  activeTab: query.status || "draft",
@@ -4705,23 +5209,36 @@ function ToolbarActions({ model, collectionType, documentId, locale }) {
4705
5209
  const typeOf = (action) => action.type || descriptions.find(
4706
5210
  (d) => typeof action.id === "string" && action.id.startsWith(`${d.name || d.displayName}-`)
4707
5211
  )?.type;
4708
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_admin.DescriptionComponentRenderer, { props, descriptions, children: (actions) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system3.Flex, { gap: 1, "data-testid": "page-preview-actions", children: [...actions].sort(
4709
- (a, b) => ACTION_TYPES.indexOf(typeOf(a)) - ACTION_TYPES.indexOf(typeOf(b))
4710
- ).map((action) => {
4711
- const reason = action.disabled ? typeOf(action) === "publish" ? t.publishDisabledHint : t.saveDisabledHint : void 0;
4712
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { title: reason, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4713
- import_design_system3.Button,
5212
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_admin.DescriptionComponentRenderer, { props, descriptions, children: (actions) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system3.Flex, { gap: 2, alignItems: "center", "data-testid": "page-preview-actions", children: [
5213
+ status && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5214
+ import_design_system3.Status,
4714
5215
  {
4715
5216
  size: "S",
4716
- variant: action.variant || "default",
4717
- disabled: action.disabled,
4718
- loading: action.loading,
4719
- "aria-description": reason,
4720
- onClick: (e) => run(action, e),
4721
- children: action.label
5217
+ role: "status",
5218
+ "data-testid": "page-preview-status",
5219
+ variant: status === "draft" ? "secondary" : status === "published" ? "success" : "alternative",
5220
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system3.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({ id: `content-manager.containers.List.${status}`, defaultMessage: status.charAt(0).toUpperCase() + status.slice(1) }) })
4722
5221
  }
4723
- ) }, action.id);
4724
- }) }) });
5222
+ ),
5223
+ modified && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system3.Typography, { variant: "pi", textColor: "neutral600", children: t.unsaved }),
5224
+ [...actions].sort(
5225
+ (a, b) => ACTION_TYPES.indexOf(typeOf(a)) - ACTION_TYPES.indexOf(typeOf(b))
5226
+ ).map((action) => {
5227
+ const reason = action.disabled ? typeOf(action) === "publish" ? t.publishDisabledHint : t.saveDisabledHint : void 0;
5228
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { title: reason, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5229
+ import_design_system3.Button,
5230
+ {
5231
+ size: "S",
5232
+ variant: typeOf(action) === "publish" ? "default" : "secondary",
5233
+ disabled: action.disabled,
5234
+ loading: action.loading,
5235
+ "aria-description": reason,
5236
+ onClick: (e) => run(action, e),
5237
+ children: action.label
5238
+ }
5239
+ ) }, action.id);
5240
+ })
5241
+ ] }) });
4725
5242
  }
4726
5243
  var COALESCE_MS = 400;
4727
5244
  var clone = (value) => {
@@ -5197,9 +5714,9 @@ function PagePreview({
5197
5714
  const uid = index >= 0 ? latest.current[index]?.__component : "";
5198
5715
  if (index < 0) return;
5199
5716
  if (is("select")) {
5200
- const list = findZoneList(zoneLabel2);
5201
- const item = list?.querySelectorAll(":scope > li")[index];
5202
- const header = list ? toggles(list)[index] : null;
5717
+ const list2 = findZoneList(zoneLabel2);
5718
+ const item = list2?.querySelectorAll(":scope > li")[index];
5719
+ const header = list2 ? toggles(list2)[index] : null;
5203
5720
  if (header?.getAttribute("aria-expanded") === "false") header.click();
5204
5721
  item?.scrollIntoView({ block: "center", behavior: "smooth" });
5205
5722
  if (item) {
@@ -5260,9 +5777,9 @@ function PagePreview({
5260
5777
  iframe.current?.contentWindow?.postMessage({ protocol: PROTOCOL, channel, type: "hover", key }, origin);
5261
5778
  };
5262
5779
  const onOver = (event) => {
5263
- const list = findZoneList(live.current.zoneLabel);
5780
+ const list2 = findZoneList(live.current.zoneLabel);
5264
5781
  const target = event.target;
5265
- const index = list?.contains(target) ? [...list.querySelectorAll(":scope > li")].findIndex((li) => li.contains(target)) : -1;
5782
+ const index = list2?.contains(target) ? [...list2.querySelectorAll(":scope > li")].findIndex((li) => li.contains(target)) : -1;
5266
5783
  post(index >= 0 ? blockKey(latest.current[index]) : null);
5267
5784
  };
5268
5785
  const onOut = (event) => {
@@ -5319,16 +5836,23 @@ function PagePreview({
5319
5836
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Tool, { icon: "undo", label: `${t.undo} (${MAC ? "\u2318Z" : "Ctrl+Z"})`, disabled: !history.canUndo, onClick: history.undo }),
5320
5837
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Tool, { icon: "redo", label: `${t.redo} (${MAC ? "\u21E7\u2318Z" : "Ctrl+Y"})`, disabled: !history.canRedo, onClick: history.redo })
5321
5838
  ] });
5322
- const devices = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system3.Flex, { gap: 1, wrap: "wrap", "data-testid": "page-preview-devices", role: "group", "aria-label": t.deviceGroup, children: Object.keys(DEVICES).map((value) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5323
- Tool,
5839
+ const deviceLabel = (value) => DEVICES[value] ? `${t.device[value]} \xB7 ${DEVICES[value]} px` : t.device[value];
5840
+ const devices = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system3.Box, { "data-testid": "page-preview-devices", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5841
+ import_design_system3.SimpleMenu,
5324
5842
  {
5325
- icon: value,
5326
- label: DEVICES[value] ? `${t.device[value]} \xB7 ${DEVICES[value]} px` : t.device[value],
5327
- active: device === value,
5328
- onClick: () => setDevice(value)
5329
- },
5330
- value
5331
- )) });
5843
+ variant: "tertiary",
5844
+ size: "S",
5845
+ "aria-label": `${t.deviceGroup}: ${deviceLabel(device)}`,
5846
+ label: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system3.Flex, { gap: 2, alignItems: "center", children: [
5847
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { name: device, size: 16 }),
5848
+ t.device[device]
5849
+ ] }),
5850
+ children: Object.keys(DEVICES).map((value) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system3.MenuItem, { onSelect: () => setDevice(value), "aria-checked": device === value, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system3.Flex, { gap: 2, alignItems: "center", children: [
5851
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { name: value, size: 16 }),
5852
+ deviceLabel(value)
5853
+ ] }) }, value))
5854
+ }
5855
+ ) });
5332
5856
  const onKey = (event) => {
5333
5857
  const map = {
5334
5858
  ArrowLeft: paneWidth + KEY_STEP,
@@ -5488,7 +6012,7 @@ function PagePreview({
5488
6012
  wrap: "wrap",
5489
6013
  style: { marginLeft: "auto" },
5490
6014
  children: [
5491
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system3.Typography, { variant: "pi", role: "status", textColor: "neutral600", children: failed ? t.previewFailed : ready ? t.previewReady : t.previewLoading }),
6015
+ !ready && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system3.Typography, { variant: "pi", role: "status", textColor: "neutral600", children: failed ? t.previewFailed : t.previewLoading }),
5492
6016
  failed && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_design_system3.Button, { size: "S", variant: "secondary", onClick: retry, children: t.retry }),
5493
6017
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5494
6018
  ToolbarActions,
@@ -5730,11 +6254,254 @@ function PagePreview({
5730
6254
  ] });
5731
6255
  }
5732
6256
 
5733
- // admin/Settings.tsx
6257
+ // admin/History.tsx
5734
6258
  var React6 = __toESM(require("react"));
5735
6259
  var import_design_system4 = require("@strapi/design-system");
5736
- var import_styled_components5 = __toESM(require("styled-components"));
6260
+ var import_admin2 = require("@strapi/strapi/admin");
6261
+
6262
+ // admin/versions.mjs
6263
+ var import_fractional_indexing3 = require("fractional-indexing");
6264
+ var import_diff = __toESM(require_diff(), 1);
6265
+ var targetOf = (attr) => attr.targetModel || attr.target;
6266
+ var list = (value) => Array.isArray(value) ? value : value == null ? [] : [value];
6267
+ var withKeys = (rows) => {
6268
+ const keys = rows.length ? (0, import_fractional_indexing3.generateNKeysBetween)(null, null, rows.length) : [];
6269
+ return rows.map((row, i) => ({ ...row, __temp_key__: keys[i] }));
6270
+ };
6271
+ function formDiff(snapshot, formValues, schema, components) {
6272
+ const schemaOf = (uid) => components?.[uid];
6273
+ const version = (0, import_diff.canonical)(snapshot, schema, schemaOf, { relations: false });
6274
+ const form = (0, import_diff.canonical)(formValues, schema, schemaOf, { relations: false });
6275
+ const zones = [];
6276
+ const fields = [];
6277
+ for (const [name, attr] of Object.entries(schema?.attributes || {})) {
6278
+ if (!(0, import_diff.kept)(name, attr) || attr.type === "relation") continue;
6279
+ if (attr.type === "dynamiczone") {
6280
+ const ops = (0, import_diff.diffRows)(form[name] || [], version[name] || []).filter((op) => op.op !== "same");
6281
+ if (ops.length) zones.push({ name, ops });
6282
+ } else if (!(0, import_diff.same)(form[name], version[name])) fields.push(name);
6283
+ }
6284
+ return { fields, zones };
6285
+ }
6286
+ function loadVersion(snapshot, { schema, components, current = {}, media = {}, relations = {}, server = {}, editable = () => true }) {
6287
+ const schemaOf = (uid) => components?.[uid];
6288
+ const report = { left: [], removed: [], blocks: 0, media: 0, relations: 0 };
6289
+ const file = (id) => media[id] || (report.media++, null);
6290
+ const resolve = (attr, refs) => {
6291
+ const targets = relations[targetOf(attr)] || [];
6292
+ const found = [];
6293
+ for (const ref of refs) {
6294
+ const hit = targets.find((r) => r.documentId === ref.documentId && (r.locale || null) === (ref.locale || null)) || targets.find((r) => r.documentId === ref.documentId);
6295
+ if (hit) found.push(hit);
6296
+ else report.relations++;
6297
+ }
6298
+ return found;
6299
+ };
6300
+ const build = (data, schema2) => {
6301
+ const out = {};
6302
+ for (const [name, attr] of Object.entries(schema2?.attributes || {})) {
6303
+ const value = data?.[name];
6304
+ if (!(0, import_diff.kept)(name, attr)) continue;
6305
+ if (attr.type === "relation") out[name] = toConnect(resolve(attr, list(value)), targetOf(attr));
6306
+ else if (value === void 0 || value === null) continue;
6307
+ else if (attr.type === "media") {
6308
+ if (attr.multiple) out[name] = list(value).map(file).filter(Boolean);
6309
+ else out[name] = file(value);
6310
+ } else if (attr.type === "component") {
6311
+ const child = schemaOf(attr.component);
6312
+ out[name] = attr.repeatable ? withKeys(list(value).map((item) => build(item, child))) : build(value, child);
6313
+ } else if (attr.type === "dynamiczone") out[name] = zone(attr, value);
6314
+ else out[name] = structuredClone(value);
6315
+ }
6316
+ return out;
6317
+ };
6318
+ const zone = (attr, rows) => withKeys(list(rows).filter((row) => {
6319
+ const ok = row && attr.components?.includes(row.__component) && schemaOf(row.__component);
6320
+ if (!ok) report.blocks++;
6321
+ return ok;
6322
+ }).map((row) => ({ ...build(row, schemaOf(row.__component)), __component: row.__component })));
6323
+ const values = { ...current };
6324
+ for (const name of Object.keys(snapshot || {})) if (!schema?.attributes?.[name]) report.removed.push(name);
6325
+ for (const [name, attr] of Object.entries(schema?.attributes || {})) {
6326
+ if (!(0, import_diff.kept)(name, attr)) continue;
6327
+ const value = snapshot?.[name];
6328
+ const empty = value === void 0 || value === null;
6329
+ if (!editable(name)) {
6330
+ if (!empty || current[name] != null) report.left.push(name);
6331
+ continue;
6332
+ }
6333
+ if (attr.type === "relation") {
6334
+ if (!Array.isArray(server[name])) {
6335
+ report.left.push(name);
6336
+ continue;
6337
+ }
6338
+ const wanted = resolve(attr, list(value));
6339
+ const has = new Set(server[name].map((r) => r.documentId));
6340
+ const keep = new Set(wanted.map((r) => r.documentId));
6341
+ values[name] = {
6342
+ connect: toConnect(wanted.filter((r) => !has.has(r.documentId)), targetOf(attr)).connect,
6343
+ disconnect: server[name].filter((r) => !keep.has(r.documentId)).map((r) => ({ id: r.id, status: r.status, apiData: { id: r.id, documentId: r.documentId, locale: r.locale } }))
6344
+ };
6345
+ } else if (attr.type === "component" || attr.type === "dynamiczone") {
6346
+ if (attr.type === "dynamiczone") values[name] = zone(attr, value);
6347
+ else if (attr.repeatable) values[name] = withKeys(list(value).map((item) => build(item, schemaOf(attr.component))));
6348
+ else values[name] = empty ? null : build(value, schemaOf(attr.component));
6349
+ } else if (attr.type === "media") {
6350
+ values[name] = attr.multiple ? list(value).map(file).filter(Boolean) : empty ? null : file(value);
6351
+ } else if (!empty) values[name] = structuredClone(value);
6352
+ else if (current[name] != null && current[name] !== "") values[name] = null;
6353
+ }
6354
+ return { values, report };
6355
+ }
6356
+
6357
+ // admin/History.tsx
5737
6358
  var import_jsx_runtime7 = require("react/jsx-runtime");
6359
+ var READ = [{ action: "plugin::blockscene.history.read", subject: null }];
6360
+ var PAGE = 10;
6361
+ function History({ model, documentId, schema, components, editable, disabled, get, relationsOf: relationsOf2 }) {
6362
+ const t = useMessages();
6363
+ const { allowedActions, isLoading } = (0, import_admin2.useRBAC)(READ);
6364
+ const [{ query }] = (0, import_admin2.useQueryParams)();
6365
+ const locale = typeof query?.plugins?.i18n?.locale === "string" ? query.plugins.i18n.locale : "";
6366
+ const values = (0, import_admin2.useForm)("BlocksceneVersions", (state) => state.values);
6367
+ const initialValues = (0, import_admin2.useForm)("BlocksceneVersions", (state) => state.initialValues);
6368
+ const setValues = (0, import_admin2.useForm)("BlocksceneVersions", (state) => state.setValues);
6369
+ const [events, setEvents] = React6.useState(null);
6370
+ const [failed, setFailed] = React6.useState(false);
6371
+ const [shown, setShown] = React6.useState(PAGE);
6372
+ const [open, setOpen] = React6.useState(null);
6373
+ const [report, setReport] = React6.useState(null);
6374
+ const [loading, setLoading] = React6.useState(false);
6375
+ const [refresh, reload] = React6.useReducer((n) => n + 1, 0);
6376
+ const allowed = Boolean(allowedActions?.canRead);
6377
+ React6.useEffect(() => {
6378
+ if (!allowed || !documentId) return;
6379
+ let active = true;
6380
+ setFailed(false);
6381
+ get(`/blockscene/history/${encodeURIComponent(model)}/${encodeURIComponent(documentId)}${locale ? `?locale=${encodeURIComponent(locale)}` : ""}`).then(({ data }) => active && setEvents(Array.isArray(data?.results) ? data.results : [])).catch(() => active && setFailed(true));
6382
+ return () => {
6383
+ active = false;
6384
+ };
6385
+ }, [allowed, get, model, documentId, locale, initialValues, refresh]);
6386
+ React6.useEffect(() => {
6387
+ setOpen(null);
6388
+ setReport(null);
6389
+ setShown(PAGE);
6390
+ }, [model, documentId, locale]);
6391
+ if (isLoading || !allowed || !documentId) return null;
6392
+ const name = (uid) => components?.[uid]?.info?.displayName || uid;
6393
+ const when = (at) => {
6394
+ try {
6395
+ return new Date(at).toLocaleString(t.locale, { dateStyle: "medium", timeStyle: "short" });
6396
+ } catch {
6397
+ return at;
6398
+ }
6399
+ };
6400
+ const summary = (s) => {
6401
+ if (!s) return "";
6402
+ if (s.missing) return t.historyMissing;
6403
+ if (s.initial) return t.historyInitial;
6404
+ const parts = [];
6405
+ const b = s.blocks || {};
6406
+ if (b.added || b.removed || b.changed) parts.push(t.f("historyBlocksSummary", { added: b.added || 0, removed: b.removed || 0, changed: b.changed || 0 }));
6407
+ if (s.fields?.length) parts.push(t.f("historyFieldsSummary", { fields: s.fields.join(", ") }));
6408
+ return parts.join(" \xB7 ") || t.historyNoChange;
6409
+ };
6410
+ const select = async (event) => {
6411
+ setReport(null);
6412
+ if (open?.event?.id === event.id) return setOpen(null);
6413
+ setOpen({ event, loading: true });
6414
+ try {
6415
+ const { data } = await get(`/blockscene/history-events/${event.id}`);
6416
+ setOpen({ event, ...data });
6417
+ } catch {
6418
+ setOpen({ event, failed: true });
6419
+ }
6420
+ };
6421
+ const load2 = async () => {
6422
+ if (!open?.snapshot || typeof setValues !== "function" || disabled) return;
6423
+ setLoading(true);
6424
+ setReport(null);
6425
+ try {
6426
+ const server = {};
6427
+ for (const [field, attr] of Object.entries(schema?.attributes || {}))
6428
+ if (attr?.type === "relation" && editable(field)) server[field] = await relationsOf2(get, { uid: model, id: documentId, field }, locale).catch(() => void 0);
6429
+ const { values: next, report: report2 } = loadVersion(open.snapshot, { schema, components, current: values, media: open.media, relations: open.relations, server, editable });
6430
+ setValues(next);
6431
+ setReport(report2);
6432
+ } catch {
6433
+ setReport({ failed: true });
6434
+ } finally {
6435
+ setLoading(false);
6436
+ }
6437
+ };
6438
+ const diff = open?.snapshot ? formDiff(open.snapshot, values, schema, components) : null;
6439
+ const same2 = diff && !diff.fields.length && !diff.zones.length;
6440
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 2, "data-testid": "blockscene-versions", children: [
6441
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { justifyContent: "space-between", alignItems: "center", children: [
6442
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "sigma", tag: "h3", textColor: "neutral600", children: t.historyTitle }),
6443
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Button, { variant: "tertiary", size: "S", onClick: reload, children: t.historyRefresh })
6444
+ ] }),
6445
+ failed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", role: "alert", textColor: "danger600", children: t.historyFailed }) : !events ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.historyLoading }) : !events.length ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.historyEmpty }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { tag: "ol", direction: "column", alignItems: "stretch", gap: 1, style: { listStyle: "none", margin: 0, padding: 0 }, children: [
6446
+ events.slice(0, shown).map((event) => {
6447
+ const active = open?.event?.id === event.id;
6448
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("li", { "data-testid": `history-event-${event.id}`, children: [
6449
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6450
+ import_design_system4.Box,
6451
+ {
6452
+ tag: "button",
6453
+ type: "button",
6454
+ onClick: () => select(event),
6455
+ "aria-expanded": active,
6456
+ padding: 2,
6457
+ hasRadius: true,
6458
+ width: "100%",
6459
+ background: active ? "primary100" : "neutral0",
6460
+ borderColor: active ? "primary200" : "neutral150",
6461
+ style: { textAlign: "left", cursor: "pointer", borderStyle: "solid", borderWidth: 1 },
6462
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
6463
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "omega", fontWeight: "bold", children: t.historyActions[event.action] || event.action }),
6464
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: [
6465
+ event.actorName || (event.actor === "system" ? t.historySystem : event.actor),
6466
+ " \xB7 ",
6467
+ when(event.at)
6468
+ ] }),
6469
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: event.summary?.missing ? "warning700" : "neutral700", children: summary(event.summary) })
6470
+ ] })
6471
+ }
6472
+ ),
6473
+ active && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { padding: 3, background: "neutral100", hasRadius: true, marginTop: 1, children: open.loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", children: t.historyLoading }) : open.failed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", role: "alert", textColor: "danger600", children: t.historyLoadFailed }) : !open.snapshot ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.historyNotKept }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
6474
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", fontWeight: "bold", children: t.historyCompare }),
6475
+ same2 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.historySame }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
6476
+ diff.fields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", children: t.f("historyDiffFields", { fields: diff.fields.join(", ") }) }),
6477
+ diff.zones.map((zone) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Flex, { tag: "ul", direction: "column", alignItems: "stretch", gap: 1, style: { margin: 0, paddingLeft: 16 }, "data-testid": `history-diff-${zone.name}`, children: zone.ops.map((op, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Typography, { variant: "pi", textColor: op.op === "added" ? "success700" : op.op === "removed" ? "danger700" : "warning700", children: [
6478
+ t.diffOps[op.op],
6479
+ ": ",
6480
+ name(op.uid),
6481
+ op.to !== void 0 ? ` (#${op.to + 1})` : op.from !== void 0 ? ` (#${op.from + 1})` : ""
6482
+ ] }) }, i)) }, zone.name))
6483
+ ] }),
6484
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.historyDiffNote }),
6485
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Flex, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Button, { size: "S", onClick: load2, loading, disabled: disabled || loading, "data-testid": "history-load", children: t.historyLoad }) }),
6486
+ report && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { role: "status", padding: 2, background: report.failed ? "danger100" : "success100", hasRadius: true, children: report.failed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "danger700", children: t.historyLoadFailed }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "flex-start", gap: 1, children: [
6487
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "success700", children: t.historyLoaded }),
6488
+ report.left.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "warning700", "data-testid": "history-left", children: t.f("historyLeft", { fields: report.left.join(", ") }) }),
6489
+ report.removed.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "warning700", children: t.f("historyRemovedFields", { fields: report.removed.join(", ") }) }),
6490
+ (report.media || report.relations || report.blocks) > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "warning700", children: t.f("historyMissingItems", { media: report.media, relations: report.relations, blocks: report.blocks }) })
6491
+ ] }) })
6492
+ ] }) })
6493
+ ] }, event.id);
6494
+ }),
6495
+ events.length > shown && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Flex, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Button, { variant: "tertiary", size: "S", onClick: () => setShown(shown + PAGE), children: t.historyShowMore }) })
6496
+ ] })
6497
+ ] });
6498
+ }
6499
+
6500
+ // admin/Settings.tsx
6501
+ var React7 = __toESM(require("react"));
6502
+ var import_design_system5 = require("@strapi/design-system");
6503
+ var import_styled_components5 = __toESM(require("styled-components"));
6504
+ var import_jsx_runtime8 = require("react/jsx-runtime");
5738
6505
  var COLOR2 = /^#[0-9A-Fa-f]{6}$/;
5739
6506
  var Grid = import_styled_components5.default.div` display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: 16px; `;
5740
6507
  var Card2 = import_styled_components5.default.div`
@@ -5747,8 +6514,8 @@ var Bar = import_styled_components5.default.div`
5747
6514
  box-shadow: 0 1px 4px rgba(33, 33, 52, 0.1);
5748
6515
  `;
5749
6516
  function useMainRect2(anchor) {
5750
- const [rect, setRect] = React6.useState({ left: 0, width: 0 });
5751
- React6.useEffect(() => {
6517
+ const [rect, setRect] = React7.useState({ left: 0, width: 0 });
6518
+ React7.useEffect(() => {
5752
6519
  const read3 = () => {
5753
6520
  let host = document.getElementById("main-content");
5754
6521
  for (let el = anchor.current?.parentElement; !host && el; el = el.parentElement) if (["auto", "scroll"].includes(getComputedStyle(el).overflowY) && el.scrollHeight > el.clientHeight) host = el;
@@ -5765,11 +6532,11 @@ var Swatches = import_styled_components5.default.div` display: grid; grid-templa
5765
6532
  var Label = import_styled_components5.default.label` display: flex; flex-direction: column; gap: 4px; font-size: 12px; `;
5766
6533
  function ColorField({ name, label, value, onChange, disabled }) {
5767
6534
  const valid = COLOR2.test(value);
5768
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Label, { children: [
5769
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
5770
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { gap: 2, children: [
5771
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "color", "aria-label": label, value: valid ? value : "#000000", disabled, onChange: (e) => onChange(e.target.value.toUpperCase()), style: { width: 40, height: 32, padding: 0, border: 0, background: "none" } }),
5772
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6535
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Label, { children: [
6536
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
6537
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 2, children: [
6538
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "color", "aria-label": label, value: valid ? value : "#000000", disabled, onChange: (e) => onChange(e.target.value.toUpperCase()), style: { width: 40, height: 32, padding: 0, border: 0, background: "none" } }),
6539
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5773
6540
  "input",
5774
6541
  {
5775
6542
  name,
@@ -5785,14 +6552,14 @@ function ColorField({ name, label, value, onChange, disabled }) {
5785
6552
  ] });
5786
6553
  }
5787
6554
  function TagsField({ name, label, hint, value, onChange, disabled }) {
5788
- const [text, setText] = React6.useState(value.join(", "));
5789
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Label, { children: [
5790
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
5791
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { name, value: text, disabled, onChange: (e) => {
6555
+ const [text, setText] = React7.useState(value.join(", "));
6556
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Label, { children: [
6557
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
6558
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { name, value: text, disabled, onChange: (e) => {
5792
6559
  setText(e.target.value);
5793
6560
  onChange([...new Set(e.target.value.split(",").map((tag) => tag.replace(/[<>]/g, "").trim().slice(0, 24)).filter(Boolean))].slice(0, 10));
5794
6561
  }, style: { padding: "6px 8px", border: "1px solid #dcdce4", borderRadius: 4, fontSize: 13 } }),
5795
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: hint })
6562
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: hint })
5796
6563
  ] });
5797
6564
  }
5798
6565
  var FIELD_UID = /^(plugin|global)::[\w.-]+$/;
@@ -5800,11 +6567,11 @@ var LAZY_MAX = 20;
5800
6567
  var parseUids = (text) => [...new Set(text.split(/[\s,]+/).filter(Boolean))];
5801
6568
  var badUids = (uids = []) => uids.length > LAZY_MAX || uids.some((uid) => !FIELD_UID.test(uid));
5802
6569
  function UidListField({ TextField: TextField2, value, onChange, ...props }) {
5803
- const [text, setText] = React6.useState(value.join(", "));
5804
- React6.useEffect(() => {
6570
+ const [text, setText] = React7.useState(value.join(", "));
6571
+ React7.useEffect(() => {
5805
6572
  if (parseUids(text).join() !== value.join()) setText(value.join(", "));
5806
6573
  }, [value.join()]);
5807
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TextField2, { ...props, value: text, onChange: (v) => {
6574
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TextField2, { ...props, value: text, onChange: (v) => {
5808
6575
  setText(v);
5809
6576
  onChange(parseUids(v));
5810
6577
  } });
@@ -5823,6 +6590,49 @@ var Checks = import_styled_components5.default.fieldset`
5823
6590
  legend { font-size: 12px; font-weight: 600; margin-bottom: 4px; }
5824
6591
  label { display: inline-flex; align-items: center; gap: 6px; }
5825
6592
  `;
6593
+ var DAYS = (n) => Number.isInteger(n) && n >= 1 && n <= 3650;
6594
+ var badRetention = (h) => !h || !DAYS(h.retentionDays) || !DAYS(h.eventDays) || h.eventDays < h.retentionDays || !(Number.isInteger(h.maxSnapshots) && h.maxSnapshots >= 1 && h.maxSnapshots <= 1e3);
6595
+ function HistorySettings({ types, history, set, t, disabled, ToggleField: ToggleField2, TextField: TextField2 }) {
6596
+ const all = history.contentTypes === "all";
6597
+ const list2 = all ? [] : history.contentTypes;
6598
+ const number = (key) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { style: { minWidth: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6599
+ TextField2,
6600
+ {
6601
+ name: `history-${key}`,
6602
+ label: t[{ retentionDays: "historyRetention", maxSnapshots: "historyMax", eventDays: "historyEventDays" }[key]],
6603
+ value: Number.isFinite(history[key]) ? String(history[key]) : "",
6604
+ disabled,
6605
+ onChange: (v) => set(key, /^\d{1,5}$/.test(v.trim()) ? Number(v.trim()) : NaN)
6606
+ }
6607
+ ) });
6608
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "history-settings", children: [
6609
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.historySettings }),
6610
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.historySettingsHelp }),
6611
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "history-enabled", label: t.historyEnabled, value: history.enabled, disabled, onChange: (v) => set("enabled", v) }),
6612
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "history-all", label: t.historyAll, value: all, disabled: disabled || !history.enabled, onChange: (v) => set("contentTypes", v ? "all" : types.map((type) => type.uid)) }),
6613
+ !all && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Checks, { disabled: disabled || !history.enabled, children: [
6614
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("legend", { children: t.historyTypes }),
6615
+ types.map((type) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { children: [
6616
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6617
+ "input",
6618
+ {
6619
+ type: "checkbox",
6620
+ name: `history-type-${type.uid}`,
6621
+ checked: list2.includes(type.uid),
6622
+ onChange: (e) => set("contentTypes", e.target.checked ? [...list2, type.uid] : list2.filter((uid) => uid !== type.uid))
6623
+ }
6624
+ ),
6625
+ type.displayName
6626
+ ] }, type.uid))
6627
+ ] }),
6628
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 4, wrap: "wrap", alignItems: "flex-end", children: [
6629
+ number("retentionDays"),
6630
+ number("maxSnapshots"),
6631
+ number("eventDays")
6632
+ ] }),
6633
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: badRetention(history) ? "danger600" : "neutral600", role: badRetention(history) ? "alert" : void 0, children: badRetention(history) ? t.historyInvalid : t.historyRetentionHelp })
6634
+ ] }) });
6635
+ }
5826
6636
  function SidebarEditor({ type, entry, set, t, disabled, SelectField: SelectField2, TextField: TextField2 }) {
5827
6637
  const items = entry.sidebar || [];
5828
6638
  const save = (next) => set("sidebar", next.length ? next : void 0, void 0);
@@ -5834,10 +6644,10 @@ function SidebarEditor({ type, entry, set, t, disabled, SelectField: SelectField
5834
6644
  };
5835
6645
  const fields = (type.attributes || []).filter((attr) => !SYSTEM_FIELDS2.includes(attr.name));
5836
6646
  const id = (name, index) => `sidebar-${name}-${type.uid}${index === void 0 ? "" : `-${index}`}`;
5837
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 3, paddingLeft: 4, "data-testid": `sidebar-editor-${type.uid}`, children: [
5838
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "delta", tag: "h3", children: t.f("sidebarTitle", { name: type.displayName }) }),
5839
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.sidebarHelp }),
5840
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { style: { maxWidth: 240 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6647
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 3, paddingLeft: 4, "data-testid": `sidebar-editor-${type.uid}`, children: [
6648
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "delta", tag: "h3", children: t.f("sidebarTitle", { name: type.displayName }) }),
6649
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.sidebarHelp }),
6650
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { style: { maxWidth: 240 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5841
6651
  SelectField2,
5842
6652
  {
5843
6653
  name: id("position"),
@@ -5848,21 +6658,21 @@ function SidebarEditor({ type, entry, set, t, disabled, SelectField: SelectField
5848
6658
  onChange: (v) => set("sidebarPosition", v, "left")
5849
6659
  }
5850
6660
  ) }),
5851
- items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Item, { "data-testid": id("item", index), children: [
5852
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { gap: 4, alignItems: "flex-end", wrap: "wrap", children: [
5853
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { style: { flex: "1 1 200px" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TextField2, { name: id("label", index), label: t.sidebarItemLabel, value: item.label, disabled, onChange: (v) => edit(index, { label: v }) }) }),
5854
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { style: { minWidth: 180 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6661
+ items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Item, { "data-testid": id("item", index), children: [
6662
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 4, alignItems: "flex-end", wrap: "wrap", children: [
6663
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { style: { flex: "1 1 200px" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TextField2, { name: id("label", index), label: t.sidebarItemLabel, value: item.label, disabled, onChange: (v) => edit(index, { label: v }) }) }),
6664
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { style: { minWidth: 180 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5855
6665
  SelectField2,
5856
6666
  {
5857
6667
  name: id("icon", index),
5858
6668
  label: t.sidebarIcon,
5859
6669
  value: item.icon || "none",
5860
6670
  disabled,
5861
- options: [{ value: "none", label: t.noIcon }, ...SIDEBAR_ICONS.map((value) => ({ value, label: t.icons[value], icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { name: value, size: 16 }) }))],
6671
+ options: [{ value: "none", label: t.noIcon }, ...SIDEBAR_ICONS.map((value) => ({ value, label: t.icons[value], icon: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Icon, { name: value, size: 16 }) }))],
5862
6672
  onChange: (v) => edit(index, { icon: v === "none" ? void 0 : v })
5863
6673
  }
5864
6674
  ) }),
5865
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { style: { minWidth: 160 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6675
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { style: { minWidth: 160 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5866
6676
  SelectField2,
5867
6677
  {
5868
6678
  name: id("open", index),
@@ -5873,16 +6683,16 @@ function SidebarEditor({ type, entry, set, t, disabled, SelectField: SelectField
5873
6683
  onChange: (v) => edit(index, { open: v })
5874
6684
  }
5875
6685
  ) }),
5876
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { gap: 1, paddingBottom: 1, children: [
5877
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Tool, { icon: "up", label: t.moveUp, disabled: disabled || index === 0, onClick: () => move(index, -1) }),
5878
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Tool, { icon: "down", label: t.moveDown, disabled: disabled || index === items.length - 1, onClick: () => move(index, 1) }),
5879
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Tool, { icon: "close", label: t.sidebarRemove, disabled, onClick: () => save(items.filter((_, i) => i !== index)) })
6686
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 1, paddingBottom: 1, children: [
6687
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Tool, { icon: "up", label: t.moveUp, disabled: disabled || index === 0, onClick: () => move(index, -1) }),
6688
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Tool, { icon: "down", label: t.moveDown, disabled: disabled || index === items.length - 1, onClick: () => move(index, 1) }),
6689
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Tool, { icon: "close", label: t.sidebarRemove, disabled, onClick: () => save(items.filter((_, i) => i !== index)) })
5880
6690
  ] })
5881
6691
  ] }),
5882
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Checks, { disabled, children: [
5883
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { children: t.sidebarFields }),
5884
- fields.map((attr) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { children: [
5885
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6692
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Checks, { disabled, children: [
6693
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("legend", { children: t.sidebarFields }),
6694
+ fields.map((attr) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { children: [
6695
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
5886
6696
  "input",
5887
6697
  {
5888
6698
  type: "checkbox",
@@ -5894,11 +6704,11 @@ function SidebarEditor({ type, entry, set, t, disabled, SelectField: SelectField
5894
6704
  attr.name
5895
6705
  ] }, attr.name))
5896
6706
  ] }),
5897
- badItem(item) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { role: "alert", variant: "pi", textColor: "danger600", children: t.sidebarInvalid })
6707
+ badItem(item) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { role: "alert", variant: "pi", textColor: "danger600", children: t.sidebarInvalid })
5898
6708
  ] }, index)),
5899
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { gap: 2, alignItems: "center", children: [
5900
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5901
- import_design_system4.Button,
6709
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 2, alignItems: "center", children: [
6710
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6711
+ import_design_system5.Button,
5902
6712
  {
5903
6713
  variant: "secondary",
5904
6714
  size: "S",
@@ -5908,7 +6718,7 @@ function SidebarEditor({ type, entry, set, t, disabled, SelectField: SelectField
5908
6718
  children: t.sidebarAdd
5909
6719
  }
5910
6720
  ),
5911
- items.length >= SIDEBAR_MAX && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.f("sidebarLimit", { max: SIDEBAR_MAX }) })
6721
+ items.length >= SIDEBAR_MAX && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.f("sidebarLimit", { max: SIDEBAR_MAX }) })
5912
6722
  ] })
5913
6723
  ] });
5914
6724
  }
@@ -5917,18 +6727,18 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
5917
6727
  const t = useMessages();
5918
6728
  const { get, put, del } = useClient();
5919
6729
  const { canRead, canUpdate, isLoading } = usePermissions2();
5920
- const [data, setData] = React6.useState(null);
5921
- const [catalog, setCatalog] = React6.useState(null);
5922
- const [settings, setSettings] = React6.useState(null);
5923
- const [media, setMedia] = React6.useState({});
5924
- const [sources, setSources] = React6.useState({});
5925
- const [dirty, setDirty] = React6.useState(false);
5926
- const [saving, setSaving] = React6.useState(false);
5927
- const [status, setStatus] = React6.useState("");
5928
- const [failed, setFailed] = React6.useState(false);
5929
- const [filter, setFilter] = React6.useState("");
5930
- const [picking, setPicking] = React6.useState(null);
5931
- React6.useEffect(() => {
6730
+ const [data, setData] = React7.useState(null);
6731
+ const [catalog, setCatalog] = React7.useState(null);
6732
+ const [settings, setSettings] = React7.useState(null);
6733
+ const [media, setMedia] = React7.useState({});
6734
+ const [sources, setSources] = React7.useState({});
6735
+ const [dirty, setDirty] = React7.useState(false);
6736
+ const [saving, setSaving] = React7.useState(false);
6737
+ const [status, setStatus] = React7.useState("");
6738
+ const [failed, setFailed] = React7.useState(false);
6739
+ const [filter, setFilter] = React7.useState("");
6740
+ const [picking, setPicking] = React7.useState(null);
6741
+ React7.useEffect(() => {
5932
6742
  if (!canRead || isLoading) return;
5933
6743
  let active = true;
5934
6744
  Promise.all([get("/blockscene/settings"), get("/blockscene/catalog")]).then(([s, c]) => {
@@ -5952,7 +6762,8 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
5952
6762
  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)));
5953
6763
  const badSidebar = settings && Object.values(settings.contentTypes || {}).some((entry) => (entry.sidebar || []).some(badItem));
5954
6764
  const badLazy = settings && badUids(settings.editor.lazyFields);
5955
- const invalid = badColor || badSidebar || badLazy;
6765
+ const badHistory = settings && data?.historyTypes && badRetention(settings.history);
6766
+ const invalid = badColor || badSidebar || badLazy || badHistory;
5956
6767
  const save = async () => {
5957
6768
  if (!settings || invalid || !canUpdate) return;
5958
6769
  setSaving(true);
@@ -6004,36 +6815,36 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6004
6815
  return index === 0 && manual ? t.manual : t.automatic;
6005
6816
  };
6006
6817
  const ready = !isLoading && canRead && !failed && settings && catalog;
6007
- const header = React6.useRef(null);
6008
- const [floating, setFloating] = React6.useState(false);
6818
+ const header = React7.useRef(null);
6819
+ const [floating, setFloating] = React7.useState(false);
6009
6820
  const main = useMainRect2(header);
6010
- React6.useEffect(() => {
6821
+ React7.useEffect(() => {
6011
6822
  const el = header.current;
6012
6823
  if (!el || typeof IntersectionObserver === "undefined") return;
6013
6824
  const observer = new IntersectionObserver(([entry]) => setFloating(!entry.isIntersecting && entry.boundingClientRect.top < 0));
6014
6825
  observer.observe(el);
6015
6826
  return () => observer.disconnect();
6016
6827
  }, [ready]);
6017
- const controls = (suffix) => ready && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
6018
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { role: "status", "aria-live": "polite", textColor: dirty ? "warning700" : "neutral600", "data-testid": `${dirty ? "unsaved-indicator" : "save-status"}${suffix}`, children: dirty ? t.unsaved : status || t.noChanges }),
6019
- !suffix && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Button, { variant: "tertiary", onClick: restore, disabled: !canUpdate || saving, "data-testid": "restore-blockscene-settings", children: data.projectDefaults ? t.restoreProject : t.resetAll }),
6020
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Button, { onClick: save, disabled: !canUpdate || invalid || !dirty, loading: saving, "data-testid": `save-blockscene-settings${suffix}`, children: t.save })
6828
+ const controls = (suffix) => ready && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
6829
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { role: "status", "aria-live": "polite", textColor: dirty ? "warning700" : "neutral600", "data-testid": `${dirty ? "unsaved-indicator" : "save-status"}${suffix}`, children: dirty ? t.unsaved : status || t.noChanges }),
6830
+ !suffix && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Button, { variant: "tertiary", onClick: restore, disabled: !canUpdate || saving, "data-testid": "restore-blockscene-settings", children: data.projectDefaults ? t.restoreProject : t.resetAll }),
6831
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Button, { onClick: save, disabled: !canUpdate || invalid || !dirty, loading: saving, "data-testid": `save-blockscene-settings${suffix}`, children: t.save })
6021
6832
  ] });
6022
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { padding: 8, background: "neutral100", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 5, children: [
6023
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref: header, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
6024
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "alpha", tag: "h1", children: t.settingsTitle }),
6833
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { padding: 8, background: "neutral100", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 5, children: [
6834
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: header, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
6835
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "alpha", tag: "h1", children: t.settingsTitle }),
6025
6836
  controls("")
6026
6837
  ] }) }),
6027
- floating && main.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Bar, { style: { left: main.left, width: main.width }, "data-testid": "settings-floating-bar", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
6028
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "beta", tag: "p", children: t.settingsTitle }),
6838
+ floating && main.width > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Bar, { style: { left: main.left, width: main.width }, "data-testid": "settings-floating-bar", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
6839
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "beta", tag: "p", children: t.settingsTitle }),
6029
6840
  controls("-floating")
6030
6841
  ] }) }),
6031
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { textColor: "neutral600", children: t.settingsIntro }),
6032
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { children: "\u2026" }) : !canRead ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { role: "alert", children: t.denied }) : failed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { role: "alert", children: t.loadFailed }) : !settings || !catalog ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
6033
- data.disabled && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { padding: 4, background: "warning100", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { role: "alert", textColor: "warning700", children: t.disabledByServer }) }),
6034
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
6035
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "beta", tag: "h2", children: t.palette }),
6036
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Swatches, { children: Object.keys(DEFAULT_PALETTE).map((key) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6842
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { textColor: "neutral600", children: t.settingsIntro }),
6843
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { children: "\u2026" }) : !canRead ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { role: "alert", children: t.denied }) : failed ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { role: "alert", children: t.loadFailed }) : !settings || !catalog ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { children: t.loading }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6844
+ data.disabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { padding: 4, background: "warning100", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { role: "alert", textColor: "warning700", children: t.disabledByServer }) }),
6845
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
6846
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.palette }),
6847
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Swatches, { children: Object.keys(DEFAULT_PALETTE).map((key) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6037
6848
  ColorField,
6038
6849
  {
6039
6850
  name: `palette-${key}`,
@@ -6047,37 +6858,42 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6047
6858
  },
6048
6859
  key
6049
6860
  )) }),
6050
- badColor && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { role: "alert", textColor: "danger600", children: t.invalidColor }),
6051
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.previewLabel }),
6052
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Swatches, { "data-testid": "palette-preview", children: TEMPLATES.map((template) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", gap: 1, children: [
6053
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { style: { aspectRatio: "16 / 9", overflow: "hidden" }, hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Wireframe, { template, palette: settings.palette }) }),
6054
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.templates[template] })
6861
+ badColor && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { role: "alert", textColor: "danger600", children: t.invalidColor }),
6862
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewLabel }),
6863
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Swatches, { "data-testid": "palette-preview", children: TEMPLATES.map((template) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", gap: 1, children: [
6864
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { style: { aspectRatio: "16 / 9", overflow: "hidden" }, hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Wireframe, { template, palette: settings.palette }) }),
6865
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.templates[template] })
6055
6866
  ] }, template)) }),
6056
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Flex, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Button, { variant: "tertiary", size: "S", disabled: !canUpdate, onClick: () => update((s) => {
6867
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Flex, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Button, { variant: "tertiary", size: "S", disabled: !canUpdate, onClick: () => update((s) => {
6057
6868
  s.palette = { ...DEFAULT_PALETTE };
6058
6869
  return s;
6059
6870
  }), children: t.resetPalette }) })
6060
6871
  ] }) }),
6061
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
6062
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "beta", tag: "h2", children: t.editor }),
6063
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToggleField2, { name: "editor-enabled", label: t.enabled, value: editor.enabled, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6872
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
6873
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.editor }),
6874
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-enabled", label: t.enabled, value: editor.enabled, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6064
6875
  s.editor.enabled = v;
6065
6876
  return s;
6066
6877
  }) }),
6067
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.enabledHelp }),
6068
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToggleField2, { name: "editor-showOpenAll", label: t.showOpenAll, value: editor.showOpenAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6878
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.enabledHelp }),
6879
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-showOpenAll", label: t.showOpenAll, value: editor.showOpenAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6069
6880
  s.editor.showOpenAll = v;
6070
6881
  return s;
6071
6882
  }) }),
6072
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToggleField2, { name: "editor-showCloseAll", label: t.showCloseAll, value: editor.showCloseAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6883
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-showCloseAll", label: t.showCloseAll, value: editor.showCloseAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6073
6884
  s.editor.showCloseAll = v;
6074
6885
  return s;
6075
6886
  }) }),
6076
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToggleField2, { name: "editor-showRowThumbnails", label: t.showRowThumbnails, value: editor.showRowThumbnails !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6887
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-showRowThumbnails", label: t.showRowThumbnails, value: editor.showRowThumbnails !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6077
6888
  s.editor.showRowThumbnails = v;
6078
6889
  return s;
6079
6890
  }) }),
6080
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6891
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-friendlyLabels", label: t.friendlyLabels, value: editor.friendlyLabels !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6892
+ s.editor.friendlyLabels = v;
6893
+ return s;
6894
+ }) }),
6895
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.friendlyLabelsHelp }),
6896
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6081
6897
  SelectField2,
6082
6898
  {
6083
6899
  name: "editor-initialState",
@@ -6091,8 +6907,8 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6091
6907
  })
6092
6908
  }
6093
6909
  ),
6094
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.rememberHelp }),
6095
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6910
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.rememberHelp }),
6911
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6096
6912
  TextField2,
6097
6913
  {
6098
6914
  name: "editor-blockPreviewUrl",
@@ -6106,9 +6922,9 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6106
6922
  })
6107
6923
  }
6108
6924
  ),
6109
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.blockPreviewUrlHelp }),
6110
- previewSupported ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
6111
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6925
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.blockPreviewUrlHelp }),
6926
+ previewSupported ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6927
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6112
6928
  TextField2,
6113
6929
  {
6114
6930
  name: "editor-previewUrl",
@@ -6122,8 +6938,8 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6122
6938
  })
6123
6939
  }
6124
6940
  ),
6125
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.previewUrlHelp }),
6126
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6941
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewUrlHelp }),
6942
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6127
6943
  SelectField2,
6128
6944
  {
6129
6945
  name: "editor-previewMode",
@@ -6137,12 +6953,12 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6137
6953
  })
6138
6954
  }
6139
6955
  ),
6140
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.previewModeHelp }),
6141
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToggleField2, { name: "editor-lazyEditors", label: t.lazyEditors, value: editor.lazyEditors !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6956
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewModeHelp }),
6957
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-lazyEditors", label: t.lazyEditors, value: editor.lazyEditors !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6142
6958
  s.editor.lazyEditors = v;
6143
6959
  return s;
6144
6960
  }) }),
6145
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
6961
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6146
6962
  UidListField,
6147
6963
  {
6148
6964
  TextField: TextField2,
@@ -6157,31 +6973,31 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6157
6973
  })
6158
6974
  }
6159
6975
  ),
6160
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: badLazy ? "danger600" : "neutral600", role: badLazy ? "alert" : void 0, children: badLazy ? t.f("lazyFieldsInvalid", { max: LAZY_MAX }) : t.lazyEditorsHelp }),
6161
- data.blockPreviewAvailable && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
6162
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6976
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: badLazy ? "danger600" : "neutral600", role: badLazy ? "alert" : void 0, children: badLazy ? t.f("lazyFieldsInvalid", { max: LAZY_MAX }) : t.lazyEditorsHelp }),
6977
+ data.blockPreviewAvailable && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
6978
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6163
6979
  s.editor.blockPreviewInForm = v;
6164
6980
  return s;
6165
6981
  }) }),
6166
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
6982
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
6167
6983
  ] })
6168
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.previewV4 })
6984
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.previewV4 })
6169
6985
  ] }) }),
6170
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "row-actions-settings", children: [
6171
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "beta", tag: "h2", children: t.rowActionsTitle }),
6172
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToggleField2, { name: "editor-confirmDelete", label: t.confirmDeleteOption, value: editor.confirmDelete !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6986
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "row-actions-settings", children: [
6987
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.rowActionsTitle }),
6988
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-confirmDelete", label: t.confirmDeleteOption, value: editor.confirmDelete !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6173
6989
  s.editor.confirmDelete = v;
6174
6990
  return s;
6175
6991
  }) }),
6176
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToggleField2, { name: "editor-duplicate", label: t.duplicateOption, value: editor.duplicate !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6992
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-duplicate", label: t.duplicateOption, value: editor.duplicate !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6177
6993
  s.editor.duplicate = v;
6178
6994
  return s;
6179
6995
  }) }),
6180
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToggleField2, { name: "editor-clipboard", label: t.clipboardOption, value: editor.clipboard !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6996
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ToggleField2, { name: "editor-clipboard", label: t.clipboardOption, value: editor.clipboard !== false, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
6181
6997
  s.editor.clipboard = v;
6182
6998
  return s;
6183
6999
  }) }),
6184
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
7000
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6185
7001
  SelectField2,
6186
7002
  {
6187
7003
  name: "editor-hiddenBlocks",
@@ -6195,11 +7011,26 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6195
7011
  })
6196
7012
  }
6197
7013
  ),
6198
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: data.hiddenAttribute ? t.hiddenBlocksHelp : t.hiddenAttributeOff })
7014
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: data.hiddenAttribute ? t.hiddenBlocksHelp : t.hiddenAttributeOff })
6199
7015
  ] }) }),
6200
- (data.contentTypes || []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "content-types", children: [
6201
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "beta", tag: "h2", children: t.contentTypes }),
6202
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: t.contentTypesHelp }),
7016
+ data.historyTypes && settings.history && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
7017
+ HistorySettings,
7018
+ {
7019
+ types: data.historyTypes,
7020
+ history: settings.history,
7021
+ t,
7022
+ disabled: !canUpdate || saving,
7023
+ ToggleField: ToggleField2,
7024
+ TextField: TextField2,
7025
+ set: (key, value) => update((s) => {
7026
+ s.history = { ...s.history, [key]: value };
7027
+ return s;
7028
+ })
7029
+ }
7030
+ ),
7031
+ (data.contentTypes || []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "content-types", children: [
7032
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.contentTypes }),
7033
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: t.contentTypesHelp }),
6203
7034
  data.contentTypes.map((type) => {
6204
7035
  const entry = settings.contentTypes?.[type.uid] || {};
6205
7036
  const set = (key, value, fallback) => update((s) => {
@@ -6211,9 +7042,9 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6211
7042
  else delete s.contentTypes[type.uid];
6212
7043
  return s;
6213
7044
  });
6214
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
6215
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { gap: 6, alignItems: "flex-end", wrap: "wrap", "data-testid": `content-type-${type.uid}`, children: [
6216
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { style: { minWidth: 220 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
7045
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
7046
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 6, alignItems: "flex-end", wrap: "wrap", "data-testid": `content-type-${type.uid}`, children: [
7047
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { style: { minWidth: 220 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6217
7048
  ToggleField2,
6218
7049
  {
6219
7050
  name: `type-enabled-${type.uid}`,
@@ -6223,7 +7054,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6223
7054
  onChange: (v) => set("enabled", v, true)
6224
7055
  }
6225
7056
  ) }),
6226
- previewSupported && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { style: { minWidth: 240 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
7057
+ previewSupported && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { style: { minWidth: 240 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6227
7058
  SelectField2,
6228
7059
  {
6229
7060
  name: `type-mode-${type.uid}`,
@@ -6235,21 +7066,21 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6235
7066
  }
6236
7067
  ) })
6237
7068
  ] }),
6238
- previewSupported && entry.enabled !== false && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SidebarEditor, { type, entry, set, t, disabled: !canUpdate || saving, SelectField: SelectField2, TextField: TextField2 })
7069
+ previewSupported && entry.enabled !== false && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SidebarEditor, { type, entry, set, t, disabled: !canUpdate || saving, SelectField: SelectField2, TextField: TextField2 })
6239
7070
  ] }, type.uid);
6240
7071
  }),
6241
- badSidebar && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { role: "alert", textColor: "danger600", children: t.sidebarInvalidSave })
7072
+ badSidebar && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { role: "alert", textColor: "danger600", children: t.sidebarInvalidSave })
6242
7073
  ] }) }),
6243
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
6244
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "beta", tag: "h2", children: t.components }),
6245
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Searchbar, { name: "component-filter", value: filter, placeholder: t.filter, clearLabel: t.clear, onClear: () => setFilter(""), onChange: (e) => setFilter(e.target.value), children: t.filter }),
6246
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", "data-testid": "components-count", children: t.f("countAll", { count: components.length }) }),
6247
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Grid, { "data-testid": "components-grid", children: components.map((component) => {
7074
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
7075
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "beta", tag: "h2", children: t.components }),
7076
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Searchbar, { name: "component-filter", value: filter, placeholder: t.filter, clearLabel: t.clear, onClear: () => setFilter(""), onChange: (e) => setFilter(e.target.value), children: t.filter }),
7077
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", "data-testid": "components-count", children: t.f("countAll", { count: components.length }) }),
7078
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Grid, { "data-testid": "components-grid", children: components.map((component) => {
6248
7079
  const entry = settings.components[component.uid] || {};
6249
7080
  const meta = { ...catalog.components?.[component.uid] || {}, ...media[component.uid] || {} };
6250
7081
  const candidates = candidatesFor(component.uid, meta, catalog);
6251
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Card2, { "data-testid": `settings-${component.uid}`, children: [
6252
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
7082
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Card2, { "data-testid": `settings-${component.uid}`, children: [
7083
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6253
7084
  Thumb,
6254
7085
  {
6255
7086
  candidates,
@@ -6260,23 +7091,23 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6260
7091
  onResolved: (index) => setSources((current) => current[component.uid] === index ? current : { ...current, [component.uid]: index })
6261
7092
  }
6262
7093
  ),
6263
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
6264
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { fontWeight: "bold", textColor: "neutral800", children: component.displayName }),
6265
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Typography, { variant: "pi", textColor: "neutral600", children: [
7094
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
7095
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { fontWeight: "bold", textColor: "neutral800", children: component.displayName }),
7096
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Typography, { variant: "pi", textColor: "neutral600", children: [
6266
7097
  component.uid,
6267
7098
  " \xB7 ",
6268
7099
  component.category
6269
7100
  ] }),
6270
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Typography, { variant: "pi", "data-testid": `source-${component.uid}`, children: [
7101
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Typography, { variant: "pi", "data-testid": `source-${component.uid}`, children: [
6271
7102
  t.source,
6272
7103
  ": ",
6273
7104
  sourceOf(component.uid, Boolean(meta.manualImage)),
6274
7105
  meta.manualName ? ` (${meta.manualName})` : ""
6275
7106
  ] }),
6276
- meta.manualMissing && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Typography, { variant: "pi", role: "alert", textColor: "danger600", children: t.brokenMedia }),
6277
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_design_system4.Flex, { gap: 2, wrap: "wrap", children: [
6278
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Button, { variant: "secondary", size: "S", disabled: !canUpdate || saving, onClick: () => setPicking(component.uid), children: entry.mediaId ? t.replace : t.choose }),
6279
- entry.mediaId && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_design_system4.Button, { variant: "tertiary", size: "S", disabled: !canUpdate || saving, onClick: () => {
7107
+ meta.manualMissing && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", role: "alert", textColor: "danger600", children: t.brokenMedia }),
7108
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_design_system5.Flex, { gap: 2, wrap: "wrap", children: [
7109
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Button, { variant: "secondary", size: "S", disabled: !canUpdate || saving, onClick: () => setPicking(component.uid), children: entry.mediaId ? t.replace : t.choose }),
7110
+ entry.mediaId && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Button, { variant: "tertiary", size: "S", disabled: !canUpdate || saving, onClick: () => {
6280
7111
  update((s) => {
6281
7112
  delete s.components[component.uid]?.mediaId;
6282
7113
  if (!Object.keys(s.components[component.uid] || {}).length) delete s.components[component.uid];
@@ -6289,7 +7120,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6289
7120
  });
6290
7121
  }, children: t.useAutomatic })
6291
7122
  ] }),
6292
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
7123
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6293
7124
  SelectField2,
6294
7125
  {
6295
7126
  name: `template-${component.uid}`,
@@ -6303,7 +7134,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6303
7134
  })
6304
7135
  }
6305
7136
  ),
6306
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
7137
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6307
7138
  SelectField2,
6308
7139
  {
6309
7140
  name: `typology-${component.uid}`,
@@ -6314,7 +7145,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6314
7145
  onChange: (v) => setComponent(component.uid, "typology", v === "auto" ? void 0 : v)
6315
7146
  }
6316
7147
  ),
6317
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
7148
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
6318
7149
  TagsField,
6319
7150
  {
6320
7151
  name: `tags-${component.uid}`,
@@ -6329,7 +7160,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
6329
7160
  ] }, component.uid);
6330
7161
  }) })
6331
7162
  ] }) }),
6332
- picking && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MediaPicker2, { onClose: () => setPicking(null), onSelect: (asset) => {
7163
+ picking && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MediaPicker2, { onClose: () => setPicking(null), onSelect: (asset) => {
6333
7164
  const uid = picking;
6334
7165
  setPicking(null);
6335
7166
  if (!asset?.id) return;
@@ -6358,14 +7189,14 @@ function register(app, Component2, to) {
6358
7189
  }
6359
7190
 
6360
7191
  // admin/Guard.tsx
6361
- var React7 = __toESM(require("react"));
6362
- var import_design_system5 = require("@strapi/design-system");
6363
- var import_jsx_runtime8 = require("react/jsx-runtime");
7192
+ var React8 = __toESM(require("react"));
7193
+ var import_design_system6 = require("@strapi/design-system");
7194
+ var import_jsx_runtime9 = require("react/jsx-runtime");
6364
7195
  var Notice = () => {
6365
7196
  const t = useMessages();
6366
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Box, { padding: 3, background: "warning100", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_design_system5.Typography, { variant: "pi", textColor: "warning700", role: "alert", children: t.crashed }) });
7197
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_design_system6.Box, { padding: 3, background: "warning100", hasRadius: true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_design_system6.Typography, { variant: "pi", textColor: "warning700", role: "alert", children: t.crashed }) });
6367
7198
  };
6368
- var Guard = class extends React7.Component {
7199
+ var Guard = class extends React8.Component {
6369
7200
  constructor() {
6370
7201
  super(...arguments);
6371
7202
  __publicField(this, "state", { failed: false });
@@ -6377,17 +7208,23 @@ var Guard = class extends React7.Component {
6377
7208
  console.error("[blockscene] disabled for this view after an error:", error);
6378
7209
  }
6379
7210
  render() {
6380
- return this.state.failed ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Notice, {}) : this.props.children;
7211
+ return this.state.failed ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Notice, {}) : this.props.children;
6381
7212
  }
6382
7213
  };
6383
7214
 
6384
7215
  // admin/catalog.ts
6385
- var React8 = __toESM(require("react"));
7216
+ var React9 = __toESM(require("react"));
7217
+ var cached = null;
7218
+ var pending = null;
7219
+ var load = (get) => get("/blockscene/catalog").then(({ data }) => {
7220
+ cached = data;
7221
+ return data;
7222
+ });
6386
7223
  function useCatalog(get) {
6387
- const [catalog, setCatalog] = React8.useState(null);
6388
- React8.useEffect(() => {
7224
+ const [catalog, setCatalog] = React9.useState(null);
7225
+ React9.useEffect(() => {
6389
7226
  let active = true;
6390
- get("/blockscene/catalog").then(({ data }) => {
7227
+ load(get).then((data) => {
6391
7228
  if (active) setCatalog(data);
6392
7229
  }).catch(() => {
6393
7230
  if (active) setCatalog(null);
@@ -6398,10 +7235,31 @@ function useCatalog(get) {
6398
7235
  }, [get]);
6399
7236
  return catalog;
6400
7237
  }
7238
+ var adminLocale = () => {
7239
+ try {
7240
+ return localStorage.getItem("strapi-admin-language") || document.documentElement.lang || "en";
7241
+ } catch {
7242
+ return "en";
7243
+ }
7244
+ };
7245
+ var labelsHook = (get, relabel, drop) => (args) => {
7246
+ try {
7247
+ if (!cached) pending || (pending = load(get()).catch(() => {
7248
+ }).finally(() => {
7249
+ pending = null;
7250
+ }));
7251
+ const trimmed = drop(args.layout, cached ? cached.hiddenAttribute : "bsHidden");
7252
+ const layout = cached ? relabel(trimmed, cached, adminLocale()) : trimmed;
7253
+ return layout === args.layout ? args : { ...args, layout };
7254
+ } catch (error) {
7255
+ console.error("[blockscene] field labels skipped after an error:", error);
7256
+ return args;
7257
+ }
7258
+ };
6401
7259
 
6402
7260
  // admin/LazyInput.tsx
6403
- var React9 = __toESM(require("react"));
6404
- var import_design_system6 = require("@strapi/design-system");
7261
+ var React10 = __toESM(require("react"));
7262
+ var import_design_system7 = require("@strapi/design-system");
6405
7263
  var import_styled_components6 = __toESM(require("styled-components"));
6406
7264
 
6407
7265
  // admin/sanitize.mjs
@@ -6441,8 +7299,8 @@ function cleanTree(root) {
6441
7299
  for (const { name, value } of [...el.attributes]) {
6442
7300
  const key = name.toLowerCase();
6443
7301
  if (key === "style") {
6444
- const kept = safeStyle(value);
6445
- if (kept) el.setAttribute(name, kept);
7302
+ const kept2 = safeStyle(value);
7303
+ if (kept2) el.setAttribute(name, kept2);
6446
7304
  else el.removeAttribute(name);
6447
7305
  } else if (key.startsWith("on") || key === "srcdoc" || URL_ATTRS.has(key) && unsafeUrl(value)) el.removeAttribute(name);
6448
7306
  }
@@ -6456,7 +7314,7 @@ function sanitizeHtml(html) {
6456
7314
  }
6457
7315
 
6458
7316
  // admin/LazyInput.tsx
6459
- var import_jsx_runtime9 = require("react/jsx-runtime");
7317
+ var import_jsx_runtime10 = require("react/jsx-runtime");
6460
7318
  var config = { on: false, fields: [] };
6461
7319
  var listeners = /* @__PURE__ */ new Set();
6462
7320
  function setLazyConfig(next) {
@@ -6491,14 +7349,14 @@ var Preview = import_styled_components6.default.div`
6491
7349
  `;
6492
7350
  function Placeholder({ name, label, hint, error, required, labelAction, placeholder, value, disabled, onActivate }) {
6493
7351
  const t = useMessages();
6494
- const html = React9.useMemo(() => typeof value === "string" ? sanitizeHtml(value) : value == null ? "" : null, [value]);
7352
+ const html = React10.useMemo(() => typeof value === "string" ? sanitizeHtml(value) : value == null ? "" : null, [value]);
6495
7353
  const activate = disabled ? void 0 : (event) => {
6496
7354
  event.preventDefault();
6497
7355
  onActivate();
6498
7356
  };
6499
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_design_system6.Field.Root, { id: name, name, error, hint, required, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_design_system6.Flex, { direction: "column", alignItems: "stretch", gap: 1, children: [
6500
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_design_system6.Field.Label, { action: labelAction, children: label }),
6501
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
7357
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Field.Root, { id: name, name, error, hint, required, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_design_system7.Flex, { direction: "column", alignItems: "stretch", gap: 1, children: [
7358
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Field.Label, { action: labelAction, children: label }),
7359
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
6502
7360
  Preview,
6503
7361
  {
6504
7362
  id: name,
@@ -6514,22 +7372,22 @@ function Placeholder({ name, label, hint, error, required, labelAction, placehol
6514
7372
  if (e.key === "Enter" || e.key === " ") activate?.(e);
6515
7373
  },
6516
7374
  children: [
6517
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-bar": true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_design_system6.Typography, { variant: "pi", textColor: "neutral500", children: disabled ? "" : t.lazyEdit }) }),
6518
- html === null ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-body": true, children: JSON.stringify(value) }) : html ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-body": true, dangerouslySetInnerHTML: { __html: html } }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { "data-body": true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_design_system6.Typography, { textColor: "neutral500", children: placeholder || "" }) })
7375
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-bar": true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Typography, { variant: "pi", textColor: "neutral500", children: disabled ? "" : t.lazyEdit }) }),
7376
+ html === null ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-body": true, children: JSON.stringify(value) }) : html ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-body": true, dangerouslySetInnerHTML: { __html: html } }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-body": true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Typography, { textColor: "neutral500", children: placeholder || "" }) })
6519
7377
  ]
6520
7378
  }
6521
7379
  ),
6522
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_design_system6.Field.Hint, {}),
6523
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_design_system6.Field.Error, {})
7380
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Field.Hint, {}),
7381
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Field.Error, {})
6524
7382
  ] }) });
6525
7383
  }
6526
7384
  function lazyInput(uid, Real) {
6527
- const Lazy = React9.forwardRef((props, ref) => {
6528
- React9.useSyncExternalStore(subscribe, read2);
6529
- const [active, setActive] = React9.useState(() => !lazyFor(uid));
6530
- const box = React9.useRef(null);
6531
- const focus = React9.useRef(false);
6532
- React9.useEffect(() => {
7385
+ const Lazy = React10.forwardRef((props, ref) => {
7386
+ React10.useSyncExternalStore(subscribe, read2);
7387
+ const [active, setActive] = React10.useState(() => !lazyFor(uid));
7388
+ const box = React10.useRef(null);
7389
+ const focus = React10.useRef(false);
7390
+ React10.useEffect(() => {
6533
7391
  if (!active || !focus.current) return;
6534
7392
  focus.current = false;
6535
7393
  let frame2 = 0;
@@ -6542,7 +7400,7 @@ function lazyInput(uid, Real) {
6542
7400
  poll();
6543
7401
  return () => cancelAnimationFrame(frame2);
6544
7402
  }, [active]);
6545
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { ref: box, style: { display: "contents" }, children: active || !lazyFor(uid) ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Real, { ...props, ref }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Placeholder, { ...props, onActivate: () => {
7403
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { ref: box, style: { display: "contents" }, children: active || !lazyFor(uid) ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Real, { ...props, ref }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Placeholder, { ...props, onActivate: () => {
6546
7404
  focus.current = true;
6547
7405
  setActive(true);
6548
7406
  } }) });
@@ -6553,22 +7411,22 @@ function lazyInput(uid, Real) {
6553
7411
  function wrapCustomFields(app) {
6554
7412
  const all = app?.customFields?.getAll?.() || {};
6555
7413
  for (const [uid, field] of Object.entries(all)) {
6556
- const load = field?.components?.Input;
6557
- if (typeof load !== "function" || load.blockscene) continue;
6558
- const wrapped = () => Promise.resolve(load()).then((mod) => ({ ...mod, default: lazyInput(uid, mod?.default ?? mod) }));
7414
+ const load2 = field?.components?.Input;
7415
+ if (typeof load2 !== "function" || load2.blockscene) continue;
7416
+ const wrapped = () => Promise.resolve(load2()).then((mod) => ({ ...mod, default: lazyInput(uid, mod?.default ?? mod) }));
6559
7417
  wrapped.blockscene = true;
6560
7418
  field.components.Input = wrapped;
6561
7419
  }
6562
7420
  }
6563
7421
 
6564
7422
  // admin/strapi5.tsx
6565
- var import_jsx_runtime10 = require("react/jsx-runtime");
7423
+ var import_jsx_runtime11 = require("react/jsx-runtime");
6566
7424
  function Modal({ open, onOpenChange, trigger, title, children, width = "80vw" }) {
6567
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_design_system7.Modal.Root, { open, onOpenChange, children: [
6568
- trigger && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Modal.Trigger, { children: trigger }),
6569
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_design_system7.Modal.Content, { style: { width, maxWidth: "92vw" }, children: [
6570
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Modal.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Modal.Title, { children: title }) }),
6571
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Modal.Body, { children })
7425
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_design_system8.Modal.Root, { open, onOpenChange, children: [
7426
+ trigger && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_design_system8.Modal.Trigger, { children: trigger }),
7427
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_design_system8.Modal.Content, { style: { width, maxWidth: "92vw" }, children: [
7428
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_design_system8.Modal.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_design_system8.Modal.Title, { children: title }) }),
7429
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_design_system8.Modal.Body, { children })
6572
7430
  ] })
6573
7431
  ] });
6574
7432
  }
@@ -6583,9 +7441,9 @@ async function relationsOf(get, { uid, id, field }, locale) {
6583
7441
  return out.reverse();
6584
7442
  }
6585
7443
  function useRowForm(c, values, get) {
6586
- const onChange = (0, import_admin2.useForm)("Blockscene", (state) => state.onChange);
6587
- const { toggleNotification } = (0, import_admin2.useNotification)();
6588
- const latest = React10.useRef(values);
7444
+ const onChange = (0, import_admin3.useForm)("Blockscene", (state) => state.onChange);
7445
+ const { toggleNotification } = (0, import_admin3.useNotification)();
7446
+ const latest = React11.useRef(values);
6589
7447
  latest.current = values;
6590
7448
  const locale = c.form?.initialValues?.locale || void 0;
6591
7449
  if (typeof onChange !== "function") return null;
@@ -6608,9 +7466,9 @@ function useRowForm(c, values, get) {
6608
7466
  function Panel2() {
6609
7467
  const c = (0, import_strapi_admin2.unstable_useContentManagerContext)();
6610
7468
  const rbac = (0, import_strapi_admin2.useDocumentRBAC)("Blockscene", (state) => state);
6611
- const { get, put } = (0, import_admin2.useFetchClient)();
6612
- const user = (0, import_admin2.useAuth)("Blockscene", (state) => state.user);
6613
- const formValues = (0, import_admin2.useForm)("Blockscene", (state) => state.values);
7469
+ const { get, put } = (0, import_admin3.useFetchClient)();
7470
+ const user = (0, import_admin3.useAuth)("Blockscene", (state) => state.user);
7471
+ const formValues = (0, import_admin3.useForm)("Blockscene", (state) => state.values);
6614
7472
  const catalog = useCatalog(get);
6615
7473
  const form = useRowForm(c, formValues ?? c.form?.values, get);
6616
7474
  const creating = !c.id && !c.form?.initialValues?.id && !c.form?.initialValues?.documentId;
@@ -6645,55 +7503,72 @@ function Panel2() {
6645
7503
  const typeSettings = catalog?.contentTypes?.[c.model] || {};
6646
7504
  const lazy = Boolean(catalog?.editor?.enabled && catalog.editor.lazyEditors !== false && typeSettings.enabled !== false);
6647
7505
  const lazyFields = (catalog?.editor?.lazyFields || []).join(",");
6648
- React10.useEffect(() => {
7506
+ React11.useEffect(() => {
6649
7507
  if (catalog) setLazyConfig({ on: lazy, fields: lazyFields ? lazyFields.split(",") : [] });
6650
7508
  }, [catalog, lazy, lazyFields]);
6651
- if (!zones.length || !catalog?.editor?.enabled || typeSettings.enabled === false) return null;
7509
+ const gallery = zones.length > 0 && catalog?.editor?.enabled && typeSettings.enabled !== false;
7510
+ const history = !creating && Boolean(c.id) && Boolean(catalog?.history?.contentTypes?.includes(c.model));
7511
+ if (!gallery && !history) return null;
6652
7512
  const docKey = `${c.model}:${creating ? "new" : c.id}:${c.form?.initialValues?.locale || ""}`;
6653
7513
  return {
6654
7514
  // The panel is the plugin (gallery, accordions, preview modes), so it carries the plugin's name; the dialog stays "Block gallery".
6655
7515
  title: "Blockscene",
6656
- content: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Guard, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_design_system7.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
6657
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
6658
- Gallery,
7516
+ content: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Guard, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_design_system8.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
7517
+ gallery && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
7518
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7519
+ Gallery,
7520
+ {
7521
+ zones,
7522
+ components: c.components,
7523
+ add,
7524
+ Modal,
7525
+ Toggle: ToggleField,
7526
+ get,
7527
+ put,
7528
+ editor: catalog.editor,
7529
+ catalog,
7530
+ docKey,
7531
+ contentType: c.model,
7532
+ userId: user?.id,
7533
+ form
7534
+ }
7535
+ ),
7536
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7537
+ PagePreview,
7538
+ {
7539
+ editor: {
7540
+ ...catalog.editor,
7541
+ previewMode: typeSettings.previewMode || catalog.editor.previewMode,
7542
+ sidebar: typeSettings.sidebar || [],
7543
+ sidebarPosition: typeSettings.sidebarPosition || "left"
7544
+ },
7545
+ groups: catalog.groups || null,
7546
+ hiddenAttribute: catalog.editor.hiddenBlocks !== "off" ? catalog.hiddenAttribute : null,
7547
+ form,
7548
+ Modal,
7549
+ Toggle: ToggleField
7550
+ }
7551
+ )
7552
+ ] }),
7553
+ history && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7554
+ History,
6659
7555
  {
6660
- zones,
7556
+ model: c.model,
7557
+ documentId: c.id,
7558
+ schema: c.contentType,
6661
7559
  components: c.components,
6662
- add,
6663
- Modal,
6664
- Toggle: ToggleField,
7560
+ editable: (name) => (rbac.canUpdateFields || []).some((field) => field === name || field.startsWith(`${name}.`)),
7561
+ disabled: Boolean(c.form?.disabled),
6665
7562
  get,
6666
- put,
6667
- editor: catalog.editor,
6668
- catalog,
6669
- docKey,
6670
- contentType: c.model,
6671
- userId: user?.id,
6672
- form
6673
- }
6674
- ),
6675
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
6676
- PagePreview,
6677
- {
6678
- editor: {
6679
- ...catalog.editor,
6680
- previewMode: typeSettings.previewMode || catalog.editor.previewMode,
6681
- sidebar: typeSettings.sidebar || [],
6682
- sidebarPosition: typeSettings.sidebarPosition || "left"
6683
- },
6684
- groups: catalog.groups || null,
6685
- hiddenAttribute: catalog.editor.hiddenBlocks !== "off" ? catalog.hiddenAttribute : null,
6686
- form,
6687
- Modal,
6688
- Toggle: ToggleField
7563
+ relationsOf
6689
7564
  }
6690
7565
  )
6691
7566
  ] }) })
6692
7567
  };
6693
7568
  }
6694
- var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_design_system7.Flex, { gap: 3, children: [
6695
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
6696
- import_design_system7.Switch,
7569
+ var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_design_system8.Flex, { gap: 3, children: [
7570
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7571
+ import_design_system8.Switch,
6697
7572
  {
6698
7573
  name,
6699
7574
  "aria-label": label,
@@ -6702,7 +7577,7 @@ var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ *
6702
7577
  onCheckedChange: onChange
6703
7578
  }
6704
7579
  ),
6705
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Typography, { children: label })
7580
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_design_system8.Typography, { children: label })
6706
7581
  ] });
6707
7582
  var TextField = ({
6708
7583
  name,
@@ -6711,10 +7586,10 @@ var TextField = ({
6711
7586
  onChange,
6712
7587
  disabled,
6713
7588
  placeholder
6714
- }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_design_system7.Field.Root, { name, children: [
6715
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Field.Label, { children: label }),
6716
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
6717
- import_design_system7.TextInput,
7589
+ }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_design_system8.Field.Root, { name, children: [
7590
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_design_system8.Field.Label, { children: label }),
7591
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7592
+ import_design_system8.TextInput,
6718
7593
  {
6719
7594
  name,
6720
7595
  value,
@@ -6731,30 +7606,30 @@ var SelectField = ({
6731
7606
  onChange,
6732
7607
  disabled,
6733
7608
  options
6734
- }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_design_system7.Field.Root, { name, children: [
6735
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.Field.Label, { children: label }),
6736
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
6737
- import_design_system7.SingleSelect,
7609
+ }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_design_system8.Field.Root, { name, children: [
7610
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_design_system8.Field.Label, { children: label }),
7611
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7612
+ import_design_system8.SingleSelect,
6738
7613
  {
6739
7614
  value,
6740
7615
  disabled,
6741
7616
  startIcon: options.find((o) => o.value === value)?.icon,
6742
7617
  onChange: (v) => onChange(String(v)),
6743
- children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_design_system7.SingleSelectOption, { value: o.value, startIcon: o.icon, children: o.label }, o.value))
7618
+ children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_design_system8.SingleSelectOption, { value: o.value, startIcon: o.icon, children: o.label }, o.value))
6744
7619
  }
6745
7620
  )
6746
7621
  ] });
6747
7622
  function MediaPicker({ onClose, onSelect }) {
6748
- const components = (0, import_admin2.useStrapiApp)(
7623
+ const components = (0, import_admin3.useStrapiApp)(
6749
7624
  "Blockscene",
6750
7625
  (state) => state.components
6751
7626
  );
6752
7627
  const Dialog2 = components?.["media-library"];
6753
- React10.useEffect(() => {
7628
+ React11.useEffect(() => {
6754
7629
  if (!Dialog2) onClose();
6755
7630
  }, [Dialog2, onClose]);
6756
7631
  if (!Dialog2) return null;
6757
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7632
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6758
7633
  Dialog2,
6759
7634
  {
6760
7635
  onClose,
@@ -6765,7 +7640,7 @@ function MediaPicker({ onClose, onSelect }) {
6765
7640
  );
6766
7641
  }
6767
7642
  function usePermissions() {
6768
- const { allowedActions, isLoading } = (0, import_admin2.useRBAC)(
7643
+ const { allowedActions, isLoading } = (0, import_admin3.useRBAC)(
6769
7644
  Object.values(permissions).flat()
6770
7645
  );
6771
7646
  return {
@@ -6774,10 +7649,10 @@ function usePermissions() {
6774
7649
  isLoading
6775
7650
  };
6776
7651
  }
6777
- var SettingsPage = () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Guard, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
7652
+ var SettingsPage = () => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Guard, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6778
7653
  Settings,
6779
7654
  {
6780
- useClient: import_admin2.useFetchClient,
7655
+ useClient: import_admin3.useFetchClient,
6781
7656
  usePermissions,
6782
7657
  MediaPicker,
6783
7658
  ToggleField,
@@ -6796,6 +7671,7 @@ var strapi5_default = {
6796
7671
  registerTrads,
6797
7672
  bootstrap(app) {
6798
7673
  app.getPlugin("content-manager").apis.addEditViewSidePanel([Panel2]);
7674
+ app.registerHook("Admin/CM/pages/EditView/mutate-edit-view-layout", labelsHook(() => (0, import_admin3.getFetchClient)().get, labelEditLayout, dropField));
6799
7675
  wrapCustomFields(strapiApp);
6800
7676
  }
6801
7677
  };