@aduptive/strapi-blockscene 2.0.0-alpha.3 → 2.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/dist/admin.cjs +1295 -366
- package/dist/admin.mjs +1334 -368
- package/package.json +1 -1
package/dist/admin.mjs
CHANGED
|
@@ -131,30 +131,61 @@ var require_groups = __commonJS({
|
|
|
131
131
|
});
|
|
132
132
|
|
|
133
133
|
// admin/strapi5.tsx
|
|
134
|
-
import * as
|
|
135
|
-
import {
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
import * as React7 from "react";
|
|
135
|
+
import {
|
|
136
|
+
Modal as Dialog,
|
|
137
|
+
Switch,
|
|
138
|
+
Flex as Flex5,
|
|
139
|
+
Typography as Typography5,
|
|
140
|
+
Field,
|
|
141
|
+
SingleSelect as SingleSelect2,
|
|
142
|
+
SingleSelectOption as SingleSelectOption2,
|
|
143
|
+
TextInput
|
|
144
|
+
} from "@strapi/design-system";
|
|
145
|
+
import {
|
|
146
|
+
useFetchClient as useFetchClient2,
|
|
147
|
+
useRBAC,
|
|
148
|
+
useStrapiApp as useStrapiApp3,
|
|
149
|
+
useAuth,
|
|
150
|
+
useForm as useForm3
|
|
151
|
+
} from "@strapi/strapi/admin";
|
|
152
|
+
import {
|
|
153
|
+
unstable_useContentManagerContext as useContext2,
|
|
154
|
+
useDocumentRBAC as useDocumentRBAC2
|
|
155
|
+
} from "@strapi/content-manager/strapi-admin";
|
|
138
156
|
|
|
139
157
|
// admin/Gallery.tsx
|
|
140
|
-
import * as
|
|
158
|
+
import * as React2 from "react";
|
|
141
159
|
import { unstable_batchedUpdates } from "react-dom";
|
|
142
|
-
import {
|
|
160
|
+
import {
|
|
161
|
+
Box,
|
|
162
|
+
Button,
|
|
163
|
+
Flex,
|
|
164
|
+
Searchbar,
|
|
165
|
+
SingleSelect,
|
|
166
|
+
SingleSelectOption,
|
|
167
|
+
Typography
|
|
168
|
+
} from "@strapi/design-system";
|
|
143
169
|
import styled from "styled-components";
|
|
144
170
|
|
|
145
171
|
// admin/model.mjs
|
|
146
172
|
import { generateNKeysBetween } from "fractional-indexing";
|
|
147
173
|
function componentDefaults(schema, components, stack = []) {
|
|
148
|
-
if (!schema || stack.includes(schema))
|
|
174
|
+
if (!schema || stack.includes(schema))
|
|
175
|
+
throw new Error("Invalid recursive component defaults");
|
|
149
176
|
const row = {};
|
|
150
177
|
for (const [name, attr] of Object.entries(schema.attributes || {})) {
|
|
151
178
|
if (Object.hasOwn(attr, "default")) {
|
|
152
179
|
const value = structuredClone(attr.default);
|
|
153
180
|
if (attr.type === "password") row[name] = "";
|
|
154
|
-
else if (attr.type === "relation")
|
|
181
|
+
else if (attr.type === "relation")
|
|
182
|
+
row[name] = { connect: [], disconnect: [] };
|
|
155
183
|
else if (value !== null || attr.type === "boolean") row[name] = value;
|
|
156
184
|
} else if (attr.type === "component" && attr.required) {
|
|
157
|
-
const create = () => componentDefaults(components[attr.component], components, [
|
|
185
|
+
const create = () => componentDefaults(components[attr.component], components, [
|
|
186
|
+
...stack,
|
|
187
|
+
schema
|
|
188
|
+
]);
|
|
158
189
|
if (attr.repeatable) {
|
|
159
190
|
const keys = generateNKeysBetween(null, null, attr.min || 0);
|
|
160
191
|
row[name] = keys.map((key) => ({ ...create(), __temp_key__: key }));
|
|
@@ -165,27 +196,58 @@ function componentDefaults(schema, components, stack = []) {
|
|
|
165
196
|
}
|
|
166
197
|
function editableZones(schema, values, canEdit, disabled = false) {
|
|
167
198
|
if (disabled) return [];
|
|
168
|
-
return Object.entries(schema?.attributes || {}).filter(
|
|
169
|
-
|
|
170
|
-
|
|
199
|
+
return Object.entries(schema?.attributes || {}).filter(
|
|
200
|
+
([name, attr]) => attr.type === "dynamiczone" && !attr.conditions && canEdit(name)
|
|
201
|
+
).map(([name, attr]) => {
|
|
202
|
+
const rows = Array.isArray(values?.[name]) ? values[name] : [];
|
|
203
|
+
return {
|
|
204
|
+
name,
|
|
205
|
+
components: attr.components || [],
|
|
206
|
+
max: attr.max,
|
|
207
|
+
count: rows.length,
|
|
208
|
+
uids: rows.map(
|
|
209
|
+
(row) => row && typeof row.__component === "string" ? row.__component : ""
|
|
210
|
+
),
|
|
211
|
+
full: rows.length >= (attr.max ?? Infinity)
|
|
212
|
+
};
|
|
171
213
|
});
|
|
172
214
|
}
|
|
173
215
|
function canInsert(zone, uid, values, components, count = 1) {
|
|
174
|
-
return Boolean(
|
|
216
|
+
return Boolean(
|
|
217
|
+
zone?.components.includes(uid) && components[uid] && (Array.isArray(values?.[zone.name]) ? values[zone.name].length : 0) + count <= (zone.max ?? Infinity)
|
|
218
|
+
);
|
|
175
219
|
}
|
|
176
220
|
function candidatesFor(uid, meta = {}, config = {}) {
|
|
177
221
|
const version = config.previewVersion ? `?v=${encodeURIComponent(config.previewVersion)}` : "";
|
|
178
222
|
const base = (config.previewBaseUrl || "/block-previews").replace(/\/$/, "");
|
|
179
|
-
return [
|
|
223
|
+
return [
|
|
224
|
+
meta.manualImage,
|
|
225
|
+
meta.image,
|
|
226
|
+
`${base}/${encodeURIComponent(uid)}.webp${version}`
|
|
227
|
+
].filter(Boolean);
|
|
180
228
|
}
|
|
181
|
-
var SYSTEM_FIELDS = [
|
|
229
|
+
var SYSTEM_FIELDS = [
|
|
230
|
+
"id",
|
|
231
|
+
"documentId",
|
|
232
|
+
"createdAt",
|
|
233
|
+
"updatedAt",
|
|
234
|
+
"publishedAt",
|
|
235
|
+
"createdBy",
|
|
236
|
+
"updatedBy",
|
|
237
|
+
"locale",
|
|
238
|
+
"localizations"
|
|
239
|
+
];
|
|
182
240
|
var fieldType = (attr) => attr?.type === "customField" ? String(attr.customField || "").includes("CKEditor") ? "richtext" : "customField" : attr?.type || "unknown";
|
|
183
241
|
var fieldsOf = (schema) => Object.entries(schema?.attributes || {}).filter(([name]) => !SYSTEM_FIELDS.includes(name)).map(([name, attr]) => ({ name, type: fieldType(attr) }));
|
|
184
242
|
var categoryOf = (uid, schema, meta = {}) => meta.category || schema?.category || uid.split(".")[0];
|
|
185
243
|
var byCategory = (a, b) => (a === "admin" ? 1 : 0) - (b === "admin" ? 1 : 0) || a.localeCompare(b);
|
|
244
|
+
var pickable = (zone, config) => {
|
|
245
|
+
const closers = Object.values(config.groups || {});
|
|
246
|
+
return zone.components.filter((uid) => !closers.includes(uid));
|
|
247
|
+
};
|
|
186
248
|
function entriesFor(zone, components, config, query, category = "all") {
|
|
187
249
|
const needle = query.trim().toLocaleLowerCase();
|
|
188
|
-
return zone.
|
|
250
|
+
return pickable(zone, config).flatMap((uid) => {
|
|
189
251
|
const schema = components[uid];
|
|
190
252
|
if (!schema) return [];
|
|
191
253
|
const meta = config.components?.[uid] || {};
|
|
@@ -200,11 +262,13 @@ function entriesFor(zone, components, config, query, category = "all") {
|
|
|
200
262
|
};
|
|
201
263
|
if (category !== "all" && entry.category !== category) return [];
|
|
202
264
|
return `${entry.label} ${entry.description} ${entry.category} ${uid} ${meta.keywords || ""}`.toLocaleLowerCase().includes(needle) ? [entry] : [];
|
|
203
|
-
}).sort(
|
|
265
|
+
}).sort(
|
|
266
|
+
(a, b) => byCategory(a.category, b.category) || a.label.localeCompare(b.label)
|
|
267
|
+
);
|
|
204
268
|
}
|
|
205
269
|
function categoriesFor(zone, components, config) {
|
|
206
270
|
const counts = /* @__PURE__ */ new Map();
|
|
207
|
-
for (const uid of zone
|
|
271
|
+
for (const uid of pickable(zone, config)) {
|
|
208
272
|
const schema = components[uid];
|
|
209
273
|
if (!schema) continue;
|
|
210
274
|
const c = categoryOf(uid, schema, config.components?.[uid] || {});
|
|
@@ -214,8 +278,12 @@ function categoriesFor(zone, components, config) {
|
|
|
214
278
|
}
|
|
215
279
|
function groupEntries(entries) {
|
|
216
280
|
const map = /* @__PURE__ */ new Map();
|
|
217
|
-
for (const entry of entries)
|
|
218
|
-
|
|
281
|
+
for (const entry of entries)
|
|
282
|
+
map.set(entry.category, [...map.get(entry.category) || [], entry]);
|
|
283
|
+
return [...map.entries()].map(([category, items]) => ({
|
|
284
|
+
category,
|
|
285
|
+
entries: items
|
|
286
|
+
}));
|
|
219
287
|
}
|
|
220
288
|
function memoryKey({ base = "", userId, contentType, zone }) {
|
|
221
289
|
if (!userId || !contentType || !zone) return null;
|
|
@@ -231,7 +299,8 @@ function readMemory(storage2, key) {
|
|
|
231
299
|
}
|
|
232
300
|
function writeMemory(storage2, key, value) {
|
|
233
301
|
try {
|
|
234
|
-
if (key && (value === "open" || value === "closed"))
|
|
302
|
+
if (key && (value === "open" || value === "closed"))
|
|
303
|
+
storage2?.setItem(key, value);
|
|
235
304
|
} catch {
|
|
236
305
|
}
|
|
237
306
|
}
|
|
@@ -317,6 +386,10 @@ function Wireframe({ template, palette, className, noPreview }) {
|
|
|
317
386
|
);
|
|
318
387
|
}
|
|
319
388
|
|
|
389
|
+
// admin/RowPreviews.tsx
|
|
390
|
+
import * as React from "react";
|
|
391
|
+
import { createPortal } from "react-dom";
|
|
392
|
+
|
|
320
393
|
// admin/messages.ts
|
|
321
394
|
import { useIntl } from "react-intl";
|
|
322
395
|
|
|
@@ -431,7 +504,8 @@ var en_default = {
|
|
|
431
504
|
columns: "Columns",
|
|
432
505
|
noPreview: "no preview",
|
|
433
506
|
"templates.none": "No preview",
|
|
434
|
-
noChanges: "No unsaved changes"
|
|
507
|
+
noChanges: "No unsaved changes",
|
|
508
|
+
rowPreview: "Open the {label} preview"
|
|
435
509
|
};
|
|
436
510
|
|
|
437
511
|
// admin/translations/pt-BR.json
|
|
@@ -545,7 +619,8 @@ var pt_BR_default = {
|
|
|
545
619
|
columns: "Colunas",
|
|
546
620
|
noPreview: "sem preview",
|
|
547
621
|
"templates.none": "Sem preview",
|
|
548
|
-
noChanges: "Sem altera\xE7\xF5es pendentes"
|
|
622
|
+
noChanges: "Sem altera\xE7\xF5es pendentes",
|
|
623
|
+
rowPreview: "Abrir a pr\xE9via de {label}"
|
|
549
624
|
};
|
|
550
625
|
|
|
551
626
|
// admin/translations/pt.json
|
|
@@ -659,7 +734,8 @@ var pt_default = {
|
|
|
659
734
|
columns: "Colunas",
|
|
660
735
|
noPreview: "sem pr\xE9-visualiza\xE7\xE3o",
|
|
661
736
|
"templates.none": "Sem pr\xE9-visualiza\xE7\xE3o",
|
|
662
|
-
noChanges: "Sem altera\xE7\xF5es pendentes"
|
|
737
|
+
noChanges: "Sem altera\xE7\xF5es pendentes",
|
|
738
|
+
rowPreview: "Abrir a pr\xE9-visualiza\xE7\xE3o de {label}"
|
|
663
739
|
};
|
|
664
740
|
|
|
665
741
|
// admin/translations/fr.json
|
|
@@ -773,7 +849,8 @@ var fr_default = {
|
|
|
773
849
|
columns: "Colonnes",
|
|
774
850
|
noPreview: "pas d\u2019aper\xE7u",
|
|
775
851
|
"templates.none": "Pas d\u2019aper\xE7u",
|
|
776
|
-
noChanges: "Aucune modification en attente"
|
|
852
|
+
noChanges: "Aucune modification en attente",
|
|
853
|
+
rowPreview: "Ouvrir l\u2019aper\xE7u de {label}"
|
|
777
854
|
};
|
|
778
855
|
|
|
779
856
|
// admin/translations/es.json
|
|
@@ -887,7 +964,8 @@ var es_default = {
|
|
|
887
964
|
columns: "Columnas",
|
|
888
965
|
noPreview: "sin vista previa",
|
|
889
966
|
"templates.none": "Sin vista previa",
|
|
890
|
-
noChanges: "Sin cambios pendientes"
|
|
967
|
+
noChanges: "Sin cambios pendientes",
|
|
968
|
+
rowPreview: "Abrir la vista previa de {label}"
|
|
891
969
|
};
|
|
892
970
|
|
|
893
971
|
// admin/translations/de.json
|
|
@@ -1001,7 +1079,8 @@ var de_default = {
|
|
|
1001
1079
|
columns: "Spalten",
|
|
1002
1080
|
noPreview: "keine Vorschau",
|
|
1003
1081
|
"templates.none": "Keine Vorschau",
|
|
1004
|
-
noChanges: "Keine ungespeicherten \xC4nderungen"
|
|
1082
|
+
noChanges: "Keine ungespeicherten \xC4nderungen",
|
|
1083
|
+
rowPreview: "Vorschau von {label} \xF6ffnen"
|
|
1005
1084
|
};
|
|
1006
1085
|
|
|
1007
1086
|
// admin/translations/it.json
|
|
@@ -1115,7 +1194,8 @@ var it_default = {
|
|
|
1115
1194
|
columns: "Colonne",
|
|
1116
1195
|
noPreview: "nessuna anteprima",
|
|
1117
1196
|
"templates.none": "Nessuna anteprima",
|
|
1118
|
-
noChanges: "Nessuna modifica in sospeso"
|
|
1197
|
+
noChanges: "Nessuna modifica in sospeso",
|
|
1198
|
+
rowPreview: "Apri l\u2019anteprima di {label}"
|
|
1119
1199
|
};
|
|
1120
1200
|
|
|
1121
1201
|
// admin/translations/nl.json
|
|
@@ -1229,7 +1309,8 @@ var nl_default = {
|
|
|
1229
1309
|
columns: "Kolommen",
|
|
1230
1310
|
noPreview: "geen voorbeeld",
|
|
1231
1311
|
"templates.none": "Geen voorbeeld",
|
|
1232
|
-
noChanges: "Geen niet-opgeslagen wijzigingen"
|
|
1312
|
+
noChanges: "Geen niet-opgeslagen wijzigingen",
|
|
1313
|
+
rowPreview: "Voorbeeld van {label} openen"
|
|
1233
1314
|
};
|
|
1234
1315
|
|
|
1235
1316
|
// admin/messages.ts
|
|
@@ -1249,26 +1330,224 @@ function useMessages() {
|
|
|
1249
1330
|
return out;
|
|
1250
1331
|
}
|
|
1251
1332
|
|
|
1333
|
+
// admin/RowPreviews.tsx
|
|
1334
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
1335
|
+
var ATTR = "data-blockscene-row-thumb";
|
|
1336
|
+
function useAnchors(zones, onOpen) {
|
|
1337
|
+
const [anchors, setAnchors] = React.useState([]);
|
|
1338
|
+
const open = React.useRef(onOpen);
|
|
1339
|
+
open.current = onOpen;
|
|
1340
|
+
const latest = React.useRef(zones);
|
|
1341
|
+
latest.current = zones;
|
|
1342
|
+
const sync = React.useRef(() => {
|
|
1343
|
+
});
|
|
1344
|
+
sync.current = () => {
|
|
1345
|
+
const next = [];
|
|
1346
|
+
for (const zone of latest.current) {
|
|
1347
|
+
const list = zone.uids?.length ? findZoneList(zone.label) : null;
|
|
1348
|
+
if (!list) continue;
|
|
1349
|
+
toggles(list).forEach((button, index) => {
|
|
1350
|
+
const uid = zone.uids[index];
|
|
1351
|
+
if (!uid) return;
|
|
1352
|
+
let el = button.querySelector(
|
|
1353
|
+
`:scope > [${ATTR}]`
|
|
1354
|
+
);
|
|
1355
|
+
if (!el) {
|
|
1356
|
+
el = document.createElement("span");
|
|
1357
|
+
el.setAttribute(ATTR, "");
|
|
1358
|
+
el.style.cssText = "display:inline-flex;align-items:center";
|
|
1359
|
+
const activate = (event) => {
|
|
1360
|
+
if (!event.currentTarget.getAttribute("role"))
|
|
1361
|
+
return;
|
|
1362
|
+
event.preventDefault();
|
|
1363
|
+
event.stopPropagation();
|
|
1364
|
+
open.current(
|
|
1365
|
+
String(event.currentTarget.dataset.uid || "")
|
|
1366
|
+
);
|
|
1367
|
+
};
|
|
1368
|
+
el.addEventListener("click", activate, true);
|
|
1369
|
+
el.addEventListener(
|
|
1370
|
+
"keydown",
|
|
1371
|
+
(event) => {
|
|
1372
|
+
if (event.key === "Enter" || event.key === " ") activate(event);
|
|
1373
|
+
},
|
|
1374
|
+
true
|
|
1375
|
+
);
|
|
1376
|
+
button.insertBefore(el, button.firstChild);
|
|
1377
|
+
}
|
|
1378
|
+
el.dataset.uid = uid;
|
|
1379
|
+
next.push({ el, uid, zone: zone.name, index });
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
for (const el of document.querySelectorAll(`[${ATTR}]`))
|
|
1383
|
+
if (!next.some((a) => a.el === el)) el.remove();
|
|
1384
|
+
setAnchors(
|
|
1385
|
+
(prev) => prev.length === next.length && prev.every((a, i) => a.el === next[i].el && a.uid === next[i].uid) ? prev : next
|
|
1386
|
+
);
|
|
1387
|
+
};
|
|
1388
|
+
React.useEffect(() => {
|
|
1389
|
+
sync.current();
|
|
1390
|
+
});
|
|
1391
|
+
React.useEffect(() => {
|
|
1392
|
+
let frame = 0;
|
|
1393
|
+
const observer = new MutationObserver(() => {
|
|
1394
|
+
if (frame) return;
|
|
1395
|
+
frame = requestAnimationFrame(() => {
|
|
1396
|
+
frame = 0;
|
|
1397
|
+
sync.current();
|
|
1398
|
+
});
|
|
1399
|
+
});
|
|
1400
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
1401
|
+
return () => {
|
|
1402
|
+
observer.disconnect();
|
|
1403
|
+
cancelAnimationFrame(frame);
|
|
1404
|
+
for (const el of document.querySelectorAll(`[${ATTR}]`)) el.remove();
|
|
1405
|
+
};
|
|
1406
|
+
}, []);
|
|
1407
|
+
return anchors;
|
|
1408
|
+
}
|
|
1409
|
+
function RowPreviews({ zones, components, catalog, Modal: Modal3 }) {
|
|
1410
|
+
const t = useMessages();
|
|
1411
|
+
const [resolved, setResolved] = React.useState({});
|
|
1412
|
+
const [open, setOpen] = React.useState(null);
|
|
1413
|
+
const anchors = useAnchors(zones, (uid) => setOpen(uid));
|
|
1414
|
+
const candidates = (uid) => candidatesFor(uid, catalog?.components?.[uid] || {}, catalog || {});
|
|
1415
|
+
const label = (uid) => catalog?.components?.[uid]?.label || components?.[uid]?.info?.displayName || uid;
|
|
1416
|
+
const srcOf = (uid) => candidates(uid)[resolved[uid] ?? -1] || "";
|
|
1417
|
+
React.useEffect(() => {
|
|
1418
|
+
for (const { el, uid } of anchors) {
|
|
1419
|
+
if (srcOf(uid)) {
|
|
1420
|
+
el.setAttribute("role", "button");
|
|
1421
|
+
el.setAttribute("tabindex", "0");
|
|
1422
|
+
el.setAttribute("aria-label", t.f("rowPreview", { label: label(uid) }));
|
|
1423
|
+
el.style.cursor = "zoom-in";
|
|
1424
|
+
} else
|
|
1425
|
+
for (const name of ["role", "tabindex", "aria-label"])
|
|
1426
|
+
el.removeAttribute(name);
|
|
1427
|
+
}
|
|
1428
|
+
});
|
|
1429
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1430
|
+
anchors.map(
|
|
1431
|
+
(a) => createPortal(
|
|
1432
|
+
/* @__PURE__ */ jsx2(
|
|
1433
|
+
"span",
|
|
1434
|
+
{
|
|
1435
|
+
style: {
|
|
1436
|
+
display: "block",
|
|
1437
|
+
width: "6.4rem",
|
|
1438
|
+
marginRight: "8px",
|
|
1439
|
+
flex: "0 0 auto"
|
|
1440
|
+
},
|
|
1441
|
+
children: /* @__PURE__ */ jsx2(
|
|
1442
|
+
Thumb,
|
|
1443
|
+
{
|
|
1444
|
+
candidates: candidates(a.uid),
|
|
1445
|
+
blank: true,
|
|
1446
|
+
onResolved: (index) => setResolved(
|
|
1447
|
+
(prev) => prev[a.uid] === index ? prev : { ...prev, [a.uid]: index }
|
|
1448
|
+
)
|
|
1449
|
+
}
|
|
1450
|
+
)
|
|
1451
|
+
}
|
|
1452
|
+
),
|
|
1453
|
+
a.el,
|
|
1454
|
+
`${a.zone}:${a.index}`
|
|
1455
|
+
)
|
|
1456
|
+
),
|
|
1457
|
+
open && srcOf(open) && /* @__PURE__ */ jsx2(
|
|
1458
|
+
Modal3,
|
|
1459
|
+
{
|
|
1460
|
+
open: true,
|
|
1461
|
+
onOpenChange: (value) => {
|
|
1462
|
+
if (!value) setOpen(null);
|
|
1463
|
+
},
|
|
1464
|
+
trigger: null,
|
|
1465
|
+
title: label(open),
|
|
1466
|
+
children: /* @__PURE__ */ jsx2(
|
|
1467
|
+
"img",
|
|
1468
|
+
{
|
|
1469
|
+
src: srcOf(open),
|
|
1470
|
+
alt: "",
|
|
1471
|
+
style: {
|
|
1472
|
+
display: "block",
|
|
1473
|
+
margin: "0 auto",
|
|
1474
|
+
maxWidth: "100%",
|
|
1475
|
+
maxHeight: "75vh",
|
|
1476
|
+
objectFit: "contain"
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
)
|
|
1480
|
+
}
|
|
1481
|
+
)
|
|
1482
|
+
] });
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1252
1485
|
// admin/Gallery.tsx
|
|
1253
|
-
import { jsx as
|
|
1486
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1254
1487
|
var Columns = styled.div`
|
|
1255
|
-
column-count: ${({ $columns }) => $columns};
|
|
1256
|
-
|
|
1488
|
+
column-count: ${({ $columns }) => $columns};
|
|
1489
|
+
column-gap: 12px;
|
|
1490
|
+
> * {
|
|
1491
|
+
break-inside: avoid;
|
|
1492
|
+
-webkit-column-break-inside: avoid;
|
|
1493
|
+
margin-bottom: 12px;
|
|
1494
|
+
}
|
|
1257
1495
|
`;
|
|
1258
1496
|
var Tile = styled.button`
|
|
1259
|
-
display: flex;
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1497
|
+
display: flex;
|
|
1498
|
+
flex-direction: column;
|
|
1499
|
+
gap: 8px;
|
|
1500
|
+
text-align: left;
|
|
1501
|
+
width: 100%;
|
|
1502
|
+
padding: 8px;
|
|
1503
|
+
border: 1px solid ${({ theme }) => theme.colors.neutral200};
|
|
1504
|
+
border-radius: 4px;
|
|
1505
|
+
background: ${({ theme }) => theme.colors.neutral0};
|
|
1506
|
+
cursor: pointer;
|
|
1507
|
+
&:hover {
|
|
1508
|
+
border-color: ${({ theme }) => theme.colors.primary600};
|
|
1509
|
+
}
|
|
1510
|
+
&:focus-visible {
|
|
1511
|
+
outline: 2px solid ${({ theme }) => theme.colors.primary600};
|
|
1512
|
+
outline-offset: 2px;
|
|
1513
|
+
}
|
|
1514
|
+
`;
|
|
1515
|
+
var Clamp = styled(Typography)`
|
|
1516
|
+
display: -webkit-box;
|
|
1517
|
+
-webkit-line-clamp: 2;
|
|
1518
|
+
-webkit-box-orient: vertical;
|
|
1519
|
+
overflow: hidden;
|
|
1264
1520
|
`;
|
|
1265
|
-
var Clamp = styled(Typography)` display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; `;
|
|
1266
1521
|
var Slider = styled.input`
|
|
1267
|
-
appearance: none;
|
|
1522
|
+
appearance: none;
|
|
1523
|
+
-webkit-appearance: none;
|
|
1524
|
+
width: 8rem;
|
|
1525
|
+
height: 0.4rem;
|
|
1526
|
+
border-radius: 0.4rem;
|
|
1527
|
+
cursor: pointer;
|
|
1268
1528
|
background: ${({ theme, $percent }) => `linear-gradient(to right, ${theme.colors.primary600} ${$percent}%, ${theme.colors.neutral200} ${$percent}%)`};
|
|
1269
|
-
&::-webkit-slider-thumb {
|
|
1270
|
-
|
|
1271
|
-
|
|
1529
|
+
&::-webkit-slider-thumb {
|
|
1530
|
+
appearance: none;
|
|
1531
|
+
-webkit-appearance: none;
|
|
1532
|
+
width: 1.6rem;
|
|
1533
|
+
height: 1.6rem;
|
|
1534
|
+
border-radius: 50%;
|
|
1535
|
+
background: ${({ theme }) => theme.colors.neutral0};
|
|
1536
|
+
border: 0.2rem solid ${({ theme }) => theme.colors.primary600};
|
|
1537
|
+
cursor: pointer;
|
|
1538
|
+
}
|
|
1539
|
+
&::-moz-range-thumb {
|
|
1540
|
+
width: 1.6rem;
|
|
1541
|
+
height: 1.6rem;
|
|
1542
|
+
border-radius: 50%;
|
|
1543
|
+
background: ${({ theme }) => theme.colors.neutral0};
|
|
1544
|
+
border: 0.2rem solid ${({ theme }) => theme.colors.primary600};
|
|
1545
|
+
cursor: pointer;
|
|
1546
|
+
}
|
|
1547
|
+
&:focus-visible {
|
|
1548
|
+
outline: 0.2rem solid ${({ theme }) => theme.colors.primary600};
|
|
1549
|
+
outline-offset: 0.2rem;
|
|
1550
|
+
}
|
|
1272
1551
|
`;
|
|
1273
1552
|
var COLUMNS = { key: "blockscene:columns", min: 1, max: 5, initial: 3 };
|
|
1274
1553
|
var SHOW_FIELDS_KEY = "blockscene:show-fields";
|
|
@@ -1294,16 +1573,31 @@ var remember = (key, value) => {
|
|
|
1294
1573
|
}
|
|
1295
1574
|
};
|
|
1296
1575
|
var Frame = styled.div`
|
|
1297
|
-
width: 100%;
|
|
1576
|
+
width: 100%;
|
|
1577
|
+
overflow: hidden;
|
|
1578
|
+
border-radius: 4px;
|
|
1579
|
+
line-height: 0;
|
|
1298
1580
|
aspect-ratio: ${({ $fixed }) => $fixed ? "16 / 9" : "auto"};
|
|
1299
1581
|
background: ${({ theme }) => theme.colors.neutral100};
|
|
1300
|
-
img {
|
|
1582
|
+
img {
|
|
1583
|
+
width: 100%;
|
|
1584
|
+
height: auto;
|
|
1585
|
+
display: block;
|
|
1586
|
+
}
|
|
1301
1587
|
`;
|
|
1302
|
-
function Thumb({
|
|
1588
|
+
function Thumb({
|
|
1589
|
+
candidates,
|
|
1590
|
+
template,
|
|
1591
|
+
palette,
|
|
1592
|
+
onResolved,
|
|
1593
|
+
noPreview,
|
|
1594
|
+
eager,
|
|
1595
|
+
blank
|
|
1596
|
+
}) {
|
|
1303
1597
|
const key = candidates.join("|");
|
|
1304
|
-
const [state, setState] =
|
|
1598
|
+
const [state, setState] = React2.useState({ key, index: 0 });
|
|
1305
1599
|
const index = state.key === key ? state.index : 0;
|
|
1306
|
-
const resolved =
|
|
1600
|
+
const resolved = React2.useRef("");
|
|
1307
1601
|
const report = (value) => {
|
|
1308
1602
|
const tag = `${key}:${value}`;
|
|
1309
1603
|
if (resolved.current !== tag) {
|
|
@@ -1311,11 +1605,19 @@ function Thumb({ candidates, template, palette, onResolved, noPreview, eager })
|
|
|
1311
1605
|
onResolved?.(value);
|
|
1312
1606
|
}
|
|
1313
1607
|
};
|
|
1314
|
-
|
|
1608
|
+
React2.useEffect(() => {
|
|
1315
1609
|
if (index >= candidates.length) report(-1);
|
|
1316
1610
|
});
|
|
1317
|
-
if (index >= candidates.length)
|
|
1318
|
-
|
|
1611
|
+
if (index >= candidates.length)
|
|
1612
|
+
return blank ? null : /* @__PURE__ */ jsx3(Frame, { $fixed: true, "data-thumb": "wireframe", children: /* @__PURE__ */ jsx3(
|
|
1613
|
+
Wireframe,
|
|
1614
|
+
{
|
|
1615
|
+
template,
|
|
1616
|
+
palette,
|
|
1617
|
+
noPreview
|
|
1618
|
+
}
|
|
1619
|
+
) });
|
|
1620
|
+
return /* @__PURE__ */ jsx3(Frame, { "data-thumb": String(index), children: /* @__PURE__ */ jsx3(
|
|
1319
1621
|
"img",
|
|
1320
1622
|
{
|
|
1321
1623
|
src: candidates[index],
|
|
@@ -1329,28 +1631,90 @@ function Thumb({ candidates, template, palette, onResolved, noPreview, eager })
|
|
|
1329
1631
|
}
|
|
1330
1632
|
function Card({ entry, palette, showFields, onSelect }) {
|
|
1331
1633
|
const t = useMessages();
|
|
1332
|
-
return /* @__PURE__ */
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1634
|
+
return /* @__PURE__ */ jsxs2(
|
|
1635
|
+
Tile,
|
|
1636
|
+
{
|
|
1637
|
+
type: "button",
|
|
1638
|
+
onClick: onSelect,
|
|
1639
|
+
title: entry.uid,
|
|
1640
|
+
"data-testid": `blockscene-${entry.uid}`,
|
|
1641
|
+
children: [
|
|
1642
|
+
/* @__PURE__ */ jsx3(
|
|
1643
|
+
Thumb,
|
|
1644
|
+
{
|
|
1645
|
+
candidates: entry.candidates,
|
|
1646
|
+
template: entry.template,
|
|
1647
|
+
palette,
|
|
1648
|
+
noPreview: t.noPreview
|
|
1649
|
+
}
|
|
1650
|
+
),
|
|
1651
|
+
/* @__PURE__ */ jsx3(
|
|
1652
|
+
Typography,
|
|
1653
|
+
{
|
|
1654
|
+
variant: "pi",
|
|
1655
|
+
fontWeight: "bold",
|
|
1656
|
+
textColor: "neutral800",
|
|
1657
|
+
ellipsis: true,
|
|
1658
|
+
children: entry.label
|
|
1659
|
+
}
|
|
1660
|
+
),
|
|
1661
|
+
entry.description && /* @__PURE__ */ jsx3(Clamp, { variant: "pi", textColor: "neutral600", children: entry.description }),
|
|
1662
|
+
showFields && entry.fields.length > 0 && /* @__PURE__ */ jsx3(
|
|
1663
|
+
Typography,
|
|
1664
|
+
{
|
|
1665
|
+
variant: "pi",
|
|
1666
|
+
textColor: "neutral500",
|
|
1667
|
+
style: { fontStyle: "italic" },
|
|
1668
|
+
"data-testid": "block-fields",
|
|
1669
|
+
children: entry.fields.map((f) => `${f.name} (${f.type})`).join(", ")
|
|
1670
|
+
}
|
|
1671
|
+
)
|
|
1672
|
+
]
|
|
1673
|
+
}
|
|
1674
|
+
);
|
|
1338
1675
|
}
|
|
1339
|
-
function PickerModal({
|
|
1340
|
-
|
|
1676
|
+
function PickerModal({
|
|
1677
|
+
zone,
|
|
1678
|
+
components,
|
|
1679
|
+
open,
|
|
1680
|
+
onOpenChange,
|
|
1681
|
+
onSelect,
|
|
1682
|
+
Modal: Modal3,
|
|
1683
|
+
Toggle,
|
|
1684
|
+
get
|
|
1685
|
+
}) {
|
|
1686
|
+
return /* @__PURE__ */ jsx3(
|
|
1687
|
+
ZoneGallery,
|
|
1688
|
+
{
|
|
1689
|
+
zone,
|
|
1690
|
+
components,
|
|
1691
|
+
Modal: Modal3,
|
|
1692
|
+
Toggle,
|
|
1693
|
+
get,
|
|
1694
|
+
controlled: { open, onOpenChange, onSelect }
|
|
1695
|
+
}
|
|
1696
|
+
);
|
|
1341
1697
|
}
|
|
1342
|
-
function ZoneGallery({
|
|
1698
|
+
function ZoneGallery({
|
|
1699
|
+
zone,
|
|
1700
|
+
components,
|
|
1701
|
+
add,
|
|
1702
|
+
Modal: Modal3,
|
|
1703
|
+
Toggle,
|
|
1704
|
+
get,
|
|
1705
|
+
controlled
|
|
1706
|
+
}) {
|
|
1343
1707
|
const t = useMessages();
|
|
1344
|
-
const [ownOpen, setOwnOpen] =
|
|
1708
|
+
const [ownOpen, setOwnOpen] = React2.useState(false);
|
|
1345
1709
|
const open = controlled ? controlled.open : ownOpen;
|
|
1346
1710
|
const setOpen = controlled ? controlled.onOpenChange : setOwnOpen;
|
|
1347
|
-
const [query, setQuery] =
|
|
1348
|
-
const [category, setCategory] =
|
|
1349
|
-
const [showFields, setShowFields] =
|
|
1350
|
-
const [columns, setColumns] =
|
|
1351
|
-
const [config, setConfig] =
|
|
1352
|
-
const [error, setError] =
|
|
1353
|
-
|
|
1711
|
+
const [query, setQuery] = React2.useState("");
|
|
1712
|
+
const [category, setCategory] = React2.useState("all");
|
|
1713
|
+
const [showFields, setShowFields] = React2.useState(readShowFields);
|
|
1714
|
+
const [columns, setColumns] = React2.useState(readColumns);
|
|
1715
|
+
const [config, setConfig] = React2.useState(null);
|
|
1716
|
+
const [error, setError] = React2.useState("");
|
|
1717
|
+
React2.useEffect(() => {
|
|
1354
1718
|
if (controlled) return;
|
|
1355
1719
|
const onClick = (event) => {
|
|
1356
1720
|
const button = event.target?.closest?.("button");
|
|
@@ -1362,7 +1726,7 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
|
|
|
1362
1726
|
document.addEventListener("click", onClick, true);
|
|
1363
1727
|
return () => document.removeEventListener("click", onClick, true);
|
|
1364
1728
|
}, [controlled, zone.name, zone.label]);
|
|
1365
|
-
|
|
1729
|
+
React2.useEffect(() => {
|
|
1366
1730
|
if (!open) return;
|
|
1367
1731
|
let active = true;
|
|
1368
1732
|
setError("");
|
|
@@ -1378,7 +1742,10 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
|
|
|
1378
1742
|
}, [open, get, t.failed]);
|
|
1379
1743
|
const entries = config ? entriesFor(zone, components, config, query, category) : [];
|
|
1380
1744
|
const categories = config ? categoriesFor(zone, components, config) : [];
|
|
1381
|
-
const total = categories.reduce(
|
|
1745
|
+
const total = categories.reduce(
|
|
1746
|
+
(sum, [, count]) => sum + count,
|
|
1747
|
+
0
|
|
1748
|
+
);
|
|
1382
1749
|
const filtering = query.trim() !== "" || category !== "all";
|
|
1383
1750
|
const reset = () => {
|
|
1384
1751
|
setQuery("");
|
|
@@ -1402,21 +1769,41 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
|
|
|
1402
1769
|
setShowFields(value);
|
|
1403
1770
|
remember(SHOW_FIELDS_KEY, String(value));
|
|
1404
1771
|
};
|
|
1405
|
-
return /* @__PURE__ */
|
|
1772
|
+
return /* @__PURE__ */ jsx3(
|
|
1406
1773
|
Modal3,
|
|
1407
1774
|
{
|
|
1408
1775
|
open,
|
|
1409
1776
|
onOpenChange: setOpen,
|
|
1410
1777
|
title: t.gallery,
|
|
1411
|
-
trigger: controlled ? null : /* @__PURE__ */
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1778
|
+
trigger: controlled ? null : /* @__PURE__ */ jsxs2(
|
|
1779
|
+
Button,
|
|
1780
|
+
{
|
|
1781
|
+
variant: "secondary",
|
|
1782
|
+
fullWidth: true,
|
|
1783
|
+
onClick: () => setOpen(true),
|
|
1784
|
+
"data-testid": `open-gallery-${zone.name}`,
|
|
1785
|
+
children: [
|
|
1786
|
+
t.add,
|
|
1787
|
+
": ",
|
|
1788
|
+
zone.name
|
|
1789
|
+
]
|
|
1790
|
+
}
|
|
1791
|
+
),
|
|
1792
|
+
children: /* @__PURE__ */ jsxs2(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
|
|
1793
|
+
/* @__PURE__ */ jsxs2(Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
|
|
1794
|
+
/* @__PURE__ */ jsx3(
|
|
1795
|
+
Typography,
|
|
1796
|
+
{
|
|
1797
|
+
variant: "omega",
|
|
1798
|
+
fontWeight: "bold",
|
|
1799
|
+
textColor: "neutral800",
|
|
1800
|
+
style: { whiteSpace: "nowrap" },
|
|
1801
|
+
"data-testid": `block-count-${zone.name}`,
|
|
1802
|
+
"aria-live": "polite",
|
|
1803
|
+
children: filtering ? t.f("countFiltered", { shown: entries.length, total }) : t.f("countAll", { count: total })
|
|
1804
|
+
}
|
|
1805
|
+
),
|
|
1806
|
+
/* @__PURE__ */ jsx3(Box, { style: { flex: 1, minWidth: "12rem" }, children: /* @__PURE__ */ jsx3(
|
|
1420
1807
|
Searchbar,
|
|
1421
1808
|
{
|
|
1422
1809
|
name: `block-search-${zone.name}`,
|
|
@@ -1428,14 +1815,54 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
|
|
|
1428
1815
|
children: t.search
|
|
1429
1816
|
}
|
|
1430
1817
|
) }),
|
|
1431
|
-
categories.length > 1 && /* @__PURE__ */
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1818
|
+
categories.length > 1 && /* @__PURE__ */ jsx3(
|
|
1819
|
+
Box,
|
|
1820
|
+
{
|
|
1821
|
+
style: { width: "14rem" },
|
|
1822
|
+
"data-testid": `block-category-${zone.name}`,
|
|
1823
|
+
children: /* @__PURE__ */ jsxs2(
|
|
1824
|
+
SingleSelect,
|
|
1825
|
+
{
|
|
1826
|
+
"aria-label": t.filterCategory,
|
|
1827
|
+
size: "S",
|
|
1828
|
+
value: category,
|
|
1829
|
+
onChange: (value) => setCategory(String(value)),
|
|
1830
|
+
children: [
|
|
1831
|
+
/* @__PURE__ */ jsx3(SingleSelectOption, { value: "all", children: t.allCategories }),
|
|
1832
|
+
categories.map(([name, count]) => /* @__PURE__ */ jsx3(
|
|
1833
|
+
SingleSelectOption,
|
|
1834
|
+
{
|
|
1835
|
+
value: name,
|
|
1836
|
+
children: `${name} (${count})`
|
|
1837
|
+
},
|
|
1838
|
+
name
|
|
1839
|
+
))
|
|
1840
|
+
]
|
|
1841
|
+
}
|
|
1842
|
+
)
|
|
1843
|
+
}
|
|
1844
|
+
),
|
|
1845
|
+
Toggle && /* @__PURE__ */ jsx3(
|
|
1846
|
+
Toggle,
|
|
1847
|
+
{
|
|
1848
|
+
name: `block-fields-${zone.name}`,
|
|
1849
|
+
label: t.showFields,
|
|
1850
|
+
hint: t.showFieldsHint,
|
|
1851
|
+
value: showFields,
|
|
1852
|
+
onChange: changeShowFields
|
|
1853
|
+
}
|
|
1854
|
+
),
|
|
1855
|
+
/* @__PURE__ */ jsxs2(Flex, { gap: 2, alignItems: "center", children: [
|
|
1856
|
+
/* @__PURE__ */ jsx3(
|
|
1857
|
+
Typography,
|
|
1858
|
+
{
|
|
1859
|
+
variant: "pi",
|
|
1860
|
+
textColor: "neutral600",
|
|
1861
|
+
id: `block-columns-${zone.name}`,
|
|
1862
|
+
children: t.columns
|
|
1863
|
+
}
|
|
1864
|
+
),
|
|
1865
|
+
/* @__PURE__ */ jsx3(
|
|
1439
1866
|
Slider,
|
|
1440
1867
|
{
|
|
1441
1868
|
type: "range",
|
|
@@ -1448,16 +1875,52 @@ function ZoneGallery({ zone, components, add, Modal: Modal3, Toggle, get, contro
|
|
|
1448
1875
|
onChange: (e) => changeColumns(Number(e.target.value))
|
|
1449
1876
|
}
|
|
1450
1877
|
),
|
|
1451
|
-
/* @__PURE__ */
|
|
1878
|
+
/* @__PURE__ */ jsx3(Typography, { variant: "pi", fontWeight: "bold", children: columns })
|
|
1452
1879
|
] })
|
|
1453
1880
|
] }),
|
|
1454
|
-
/* @__PURE__ */
|
|
1455
|
-
error ? /* @__PURE__ */
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1881
|
+
/* @__PURE__ */ jsx3(Typography, { variant: "pi", textColor: "neutral600", children: t.example }),
|
|
1882
|
+
error ? /* @__PURE__ */ jsx3(Typography, { role: "alert", textColor: "danger600", children: error }) : !config ? /* @__PURE__ */ jsx3(Typography, { children: t.loading }) : entries.length ? /* @__PURE__ */ jsx3(
|
|
1883
|
+
Flex,
|
|
1884
|
+
{
|
|
1885
|
+
direction: "column",
|
|
1886
|
+
alignItems: "stretch",
|
|
1887
|
+
gap: 4,
|
|
1888
|
+
style: { overflowY: "auto", maxHeight: "60vh", padding: "4px" },
|
|
1889
|
+
children: groupEntries(entries).map(
|
|
1890
|
+
({ category: name, entries: items }) => /* @__PURE__ */ jsxs2(
|
|
1891
|
+
Flex,
|
|
1892
|
+
{
|
|
1893
|
+
direction: "column",
|
|
1894
|
+
alignItems: "stretch",
|
|
1895
|
+
gap: 2,
|
|
1896
|
+
children: [
|
|
1897
|
+
/* @__PURE__ */ jsx3(
|
|
1898
|
+
Typography,
|
|
1899
|
+
{
|
|
1900
|
+
variant: "sigma",
|
|
1901
|
+
textColor: "neutral600",
|
|
1902
|
+
"data-testid": `block-group-${name}`,
|
|
1903
|
+
children: `${name} (${items.length})`
|
|
1904
|
+
}
|
|
1905
|
+
),
|
|
1906
|
+
/* @__PURE__ */ jsx3(Columns, { $columns: columns, children: items.map((entry) => /* @__PURE__ */ jsx3("div", { children: /* @__PURE__ */ jsx3(
|
|
1907
|
+
Card,
|
|
1908
|
+
{
|
|
1909
|
+
entry,
|
|
1910
|
+
palette: config.palette,
|
|
1911
|
+
showFields,
|
|
1912
|
+
onSelect: () => select(entry.uid)
|
|
1913
|
+
}
|
|
1914
|
+
) }, entry.uid)) })
|
|
1915
|
+
]
|
|
1916
|
+
},
|
|
1917
|
+
name
|
|
1918
|
+
)
|
|
1919
|
+
)
|
|
1920
|
+
}
|
|
1921
|
+
) : /* @__PURE__ */ jsxs2(Flex, { gap: 3, alignItems: "center", children: [
|
|
1922
|
+
/* @__PURE__ */ jsx3(Typography, { children: t.empty }),
|
|
1923
|
+
filtering && /* @__PURE__ */ jsx3(Button, { variant: "tertiary", size: "S", onClick: reset, children: t.clear })
|
|
1461
1924
|
] })
|
|
1462
1925
|
] })
|
|
1463
1926
|
}
|
|
@@ -1471,13 +1934,19 @@ var storage = () => {
|
|
|
1471
1934
|
}
|
|
1472
1935
|
};
|
|
1473
1936
|
var memoryBase = () => `${window.location.origin}${window.location.pathname.split("/content-manager")[0]}`;
|
|
1474
|
-
function useInitialAccordions({
|
|
1475
|
-
|
|
1476
|
-
|
|
1937
|
+
function useInitialAccordions({
|
|
1938
|
+
zones,
|
|
1939
|
+
editor,
|
|
1940
|
+
docKey,
|
|
1941
|
+
contentType,
|
|
1942
|
+
userId
|
|
1943
|
+
}) {
|
|
1944
|
+
const applied = React2.useRef("");
|
|
1945
|
+
const user = React2.useRef(userId);
|
|
1477
1946
|
user.current = userId;
|
|
1478
|
-
const latest =
|
|
1947
|
+
const latest = React2.useRef(zones);
|
|
1479
1948
|
latest.current = zones;
|
|
1480
|
-
|
|
1949
|
+
React2.useEffect(() => {
|
|
1481
1950
|
if (!editor?.enabled || !docKey || applied.current === docKey) return;
|
|
1482
1951
|
if (applied.current.startsWith(`${contentType}:new`) && docKey.startsWith(`${contentType}:`)) {
|
|
1483
1952
|
applied.current = docKey;
|
|
@@ -1486,7 +1955,10 @@ function useInitialAccordions({ zones, editor, docKey, contentType, userId }) {
|
|
|
1486
1955
|
applied.current = docKey;
|
|
1487
1956
|
let tries = 0;
|
|
1488
1957
|
const cancel = (event) => {
|
|
1489
|
-
if (event.target?.closest?.(
|
|
1958
|
+
if (event.target?.closest?.(
|
|
1959
|
+
'button[aria-expanded], [data-testid^="block-accordion-controls-"]'
|
|
1960
|
+
))
|
|
1961
|
+
stop();
|
|
1490
1962
|
};
|
|
1491
1963
|
const stop = () => {
|
|
1492
1964
|
clearInterval(timer);
|
|
@@ -1504,8 +1976,17 @@ function useInitialAccordions({ zones, editor, docKey, contentType, userId }) {
|
|
|
1504
1976
|
for (const zone of pending) {
|
|
1505
1977
|
const list = findZoneList(zone.label);
|
|
1506
1978
|
if (!list) continue;
|
|
1507
|
-
const key = memoryKey({
|
|
1508
|
-
|
|
1979
|
+
const key = memoryKey({
|
|
1980
|
+
base: memoryBase(),
|
|
1981
|
+
userId: user.current,
|
|
1982
|
+
contentType,
|
|
1983
|
+
zone: zone.name
|
|
1984
|
+
});
|
|
1985
|
+
setAll(
|
|
1986
|
+
list,
|
|
1987
|
+
initialState(editor, readMemory(storage(), key)) === "open",
|
|
1988
|
+
unstable_batchedUpdates
|
|
1989
|
+
);
|
|
1509
1990
|
}
|
|
1510
1991
|
}, 200);
|
|
1511
1992
|
return stop;
|
|
@@ -1517,50 +1998,117 @@ function ZoneControls({ zone, editor, contentType, userId }) {
|
|
|
1517
1998
|
const apply = (open) => {
|
|
1518
1999
|
const list = findZoneList(zone.label);
|
|
1519
2000
|
if (list) setAll(list, open, unstable_batchedUpdates);
|
|
1520
|
-
writeMemory(
|
|
2001
|
+
writeMemory(
|
|
2002
|
+
storage(),
|
|
2003
|
+
memoryKey({ base: memoryBase(), userId, contentType, zone: zone.name }),
|
|
2004
|
+
open ? "open" : "closed"
|
|
2005
|
+
);
|
|
1521
2006
|
};
|
|
1522
|
-
return /* @__PURE__ */
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
2007
|
+
return /* @__PURE__ */ jsxs2(
|
|
2008
|
+
Flex,
|
|
2009
|
+
{
|
|
2010
|
+
gap: 2,
|
|
2011
|
+
wrap: "wrap",
|
|
2012
|
+
"data-testid": `block-accordion-controls-${zone.name}`,
|
|
2013
|
+
children: [
|
|
2014
|
+
editor.showOpenAll && /* @__PURE__ */ jsx3(
|
|
2015
|
+
Button,
|
|
2016
|
+
{
|
|
2017
|
+
type: "button",
|
|
2018
|
+
variant: "tertiary",
|
|
2019
|
+
size: "S",
|
|
2020
|
+
onClick: () => apply(true),
|
|
2021
|
+
children: t.openAll
|
|
2022
|
+
}
|
|
2023
|
+
),
|
|
2024
|
+
editor.showCloseAll && /* @__PURE__ */ jsx3(
|
|
2025
|
+
Button,
|
|
2026
|
+
{
|
|
2027
|
+
type: "button",
|
|
2028
|
+
variant: "tertiary",
|
|
2029
|
+
size: "S",
|
|
2030
|
+
onClick: () => apply(false),
|
|
2031
|
+
children: t.closeAll
|
|
2032
|
+
}
|
|
2033
|
+
)
|
|
2034
|
+
]
|
|
2035
|
+
}
|
|
2036
|
+
);
|
|
1526
2037
|
}
|
|
1527
|
-
function Gallery({
|
|
2038
|
+
function Gallery({
|
|
2039
|
+
zones,
|
|
2040
|
+
editor,
|
|
2041
|
+
docKey,
|
|
2042
|
+
contentType,
|
|
2043
|
+
userId,
|
|
2044
|
+
catalog,
|
|
2045
|
+
...props
|
|
2046
|
+
}) {
|
|
1528
2047
|
useInitialAccordions({ zones, editor, docKey, contentType, userId });
|
|
1529
|
-
return /* @__PURE__ */
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
2048
|
+
return /* @__PURE__ */ jsxs2(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
|
|
2049
|
+
/* @__PURE__ */ jsx3(
|
|
2050
|
+
RowPreviews,
|
|
2051
|
+
{
|
|
2052
|
+
zones,
|
|
2053
|
+
components: props.components,
|
|
2054
|
+
catalog,
|
|
2055
|
+
Modal: props.Modal
|
|
2056
|
+
}
|
|
2057
|
+
),
|
|
2058
|
+
zones.map((zone) => /* @__PURE__ */ jsxs2(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
|
2059
|
+
!zone.full && /* @__PURE__ */ jsx3(ZoneGallery, { zone, ...props }),
|
|
2060
|
+
/* @__PURE__ */ jsx3(
|
|
2061
|
+
ZoneControls,
|
|
2062
|
+
{
|
|
2063
|
+
zone,
|
|
2064
|
+
editor,
|
|
2065
|
+
contentType,
|
|
2066
|
+
userId
|
|
2067
|
+
}
|
|
2068
|
+
)
|
|
2069
|
+
] }, zone.name))
|
|
2070
|
+
] });
|
|
1533
2071
|
}
|
|
1534
2072
|
|
|
1535
2073
|
// admin/PagePreview.tsx
|
|
1536
|
-
import * as
|
|
1537
|
-
import { createPortal } from "react-dom";
|
|
2074
|
+
import * as React4 from "react";
|
|
2075
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
1538
2076
|
import styled2 from "styled-components";
|
|
1539
2077
|
import { Box as Box2, Button as Button3, Flex as Flex3, Typography as Typography3 } from "@strapi/design-system";
|
|
1540
|
-
import {
|
|
1541
|
-
|
|
1542
|
-
|
|
2078
|
+
import {
|
|
2079
|
+
DescriptionComponentRenderer,
|
|
2080
|
+
useFetchClient,
|
|
2081
|
+
useForm as useForm2,
|
|
2082
|
+
useNotification,
|
|
2083
|
+
useQueryParams,
|
|
2084
|
+
useStrapiApp as useStrapiApp2
|
|
2085
|
+
} from "@strapi/strapi/admin";
|
|
2086
|
+
import {
|
|
2087
|
+
unstable_useContentManagerContext as useContext,
|
|
2088
|
+
unstable_useDocument as useDocument,
|
|
2089
|
+
useDocumentRBAC
|
|
2090
|
+
} from "@strapi/content-manager/strapi-admin";
|
|
1543
2091
|
|
|
1544
2092
|
// admin/FieldEditorModal.tsx
|
|
1545
|
-
import * as
|
|
2093
|
+
import * as React3 from "react";
|
|
1546
2094
|
import { Form, InputRenderer, useForm, useStrapiApp } from "@strapi/strapi/admin";
|
|
1547
2095
|
import { Button as Button2, Flex as Flex2, Modal, Typography as Typography2 } from "@strapi/design-system";
|
|
1548
|
-
import { jsx as
|
|
2096
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1549
2097
|
var Actions = ({ onApply, onCancel }) => {
|
|
1550
2098
|
const t = useMessages();
|
|
1551
2099
|
const value = useForm("BlocksceneFieldEditor", (state) => state.values.value);
|
|
1552
|
-
return /* @__PURE__ */
|
|
1553
|
-
/* @__PURE__ */
|
|
1554
|
-
/* @__PURE__ */
|
|
2100
|
+
return /* @__PURE__ */ jsxs3(Flex2, { gap: 2, justifyContent: "flex-end", children: [
|
|
2101
|
+
/* @__PURE__ */ jsx4(Button2, { variant: "tertiary", onClick: onCancel, children: t.cancel }),
|
|
2102
|
+
/* @__PURE__ */ jsx4(Button2, { onClick: () => onApply(value ?? null), "data-testid": "field-editor-apply", children: t.apply })
|
|
1555
2103
|
] });
|
|
1556
2104
|
};
|
|
1557
2105
|
function FieldEditorModal({ label, attribute, value, onApply, onCancel }) {
|
|
1558
2106
|
const t = useMessages();
|
|
1559
2107
|
const customFields = useStrapiApp("BlocksceneFieldEditor", (state) => state.customFields);
|
|
1560
|
-
const [Input, setInput] =
|
|
2108
|
+
const [Input, setInput] = React3.useState(void 0);
|
|
1561
2109
|
const isCustom = Boolean(attribute?.customField);
|
|
1562
2110
|
const isText = attribute?.type === "string" || attribute?.type === "text";
|
|
1563
|
-
|
|
2111
|
+
React3.useEffect(() => {
|
|
1564
2112
|
let active = true;
|
|
1565
2113
|
if (!isCustom) {
|
|
1566
2114
|
setInput(null);
|
|
@@ -1581,24 +2129,24 @@ function FieldEditorModal({ label, attribute, value, onApply, onCancel }) {
|
|
|
1581
2129
|
};
|
|
1582
2130
|
}, [attribute, customFields, isCustom]);
|
|
1583
2131
|
const supported = isText || isCustom && Input;
|
|
1584
|
-
return /* @__PURE__ */
|
|
2132
|
+
return /* @__PURE__ */ jsx4(Modal.Root, { open: true, onOpenChange: (open) => {
|
|
1585
2133
|
if (!open) onCancel();
|
|
1586
|
-
}, children: /* @__PURE__ */
|
|
1587
|
-
/* @__PURE__ */
|
|
2134
|
+
}, children: /* @__PURE__ */ jsxs3(Modal.Content, { "aria-label": `${t.editText} ${label}`, children: [
|
|
2135
|
+
/* @__PURE__ */ jsx4(Modal.Header, { children: /* @__PURE__ */ jsxs3(Modal.Title, { children: [
|
|
1588
2136
|
t.editText,
|
|
1589
2137
|
" \xB7 ",
|
|
1590
2138
|
label
|
|
1591
2139
|
] }) }),
|
|
1592
|
-
/* @__PURE__ */
|
|
2140
|
+
/* @__PURE__ */ jsxs3(Form, { initialValues: { value: value ?? (isText ? "" : null) }, method: "PUT", onSubmit: () => {
|
|
1593
2141
|
}, children: [
|
|
1594
|
-
/* @__PURE__ */
|
|
1595
|
-
/* @__PURE__ */
|
|
1596
|
-
isCustom && Input === void 0 && /* @__PURE__ */
|
|
1597
|
-
isCustom && Input && /* @__PURE__ */
|
|
1598
|
-
isText && /* @__PURE__ */
|
|
1599
|
-
(isCustom && Input === null || !isCustom && !isText) && /* @__PURE__ */
|
|
2142
|
+
/* @__PURE__ */ jsx4(Modal.Body, { children: /* @__PURE__ */ jsxs3(Flex2, { direction: "column", alignItems: "stretch", gap: 4, "data-testid": "field-editor-modal", children: [
|
|
2143
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", children: t.editHelp }),
|
|
2144
|
+
isCustom && Input === void 0 && /* @__PURE__ */ jsx4(Typography2, { children: t.loading }),
|
|
2145
|
+
isCustom && Input && /* @__PURE__ */ jsx4(Input, { name: "value", attribute, label, type: attribute.type }),
|
|
2146
|
+
isText && /* @__PURE__ */ jsx4(InputRenderer, { type: attribute.type === "text" ? "text" : "string", name: "value", label }),
|
|
2147
|
+
(isCustom && Input === null || !isCustom && !isText) && /* @__PURE__ */ jsx4(Typography2, { role: "alert", textColor: "danger600", children: t.editUnsupported })
|
|
1600
2148
|
] }) }),
|
|
1601
|
-
/* @__PURE__ */
|
|
2149
|
+
/* @__PURE__ */ jsx4(Modal.Footer, { children: supported ? /* @__PURE__ */ jsx4(Actions, { onApply, onCancel }) : /* @__PURE__ */ jsx4(Button2, { variant: "tertiary", onClick: onCancel, children: t.close }) })
|
|
1602
2150
|
] })
|
|
1603
2151
|
] }) });
|
|
1604
2152
|
}
|
|
@@ -1709,6 +2257,7 @@ var mediaAttribute = (uid, field, components) => {
|
|
|
1709
2257
|
const attr = resolveField(uid, field, components);
|
|
1710
2258
|
return attr?.type === "media" ? attr : null;
|
|
1711
2259
|
};
|
|
2260
|
+
var getIn = (row, path) => String(path).split(".").reduce((value, key) => value == null ? void 0 : value[key], row);
|
|
1712
2261
|
function isPreviewMessage(event, origin, source, channel, type) {
|
|
1713
2262
|
return event.origin === origin && event.source === source && event.data?.protocol === PROTOCOL && event.data?.channel === channel && event.data?.type === type;
|
|
1714
2263
|
}
|
|
@@ -1719,7 +2268,7 @@ function insertIndex(rows, after) {
|
|
|
1719
2268
|
}
|
|
1720
2269
|
|
|
1721
2270
|
// admin/PagePreview.tsx
|
|
1722
|
-
import { jsx as
|
|
2271
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1723
2272
|
var MODE_KEY = "blockscene:page-mode";
|
|
1724
2273
|
var RATIO_KEY = "blockscene:page-split-ratio";
|
|
1725
2274
|
var MIN_PANE = 360;
|
|
@@ -1740,20 +2289,32 @@ var write = (key, value) => {
|
|
|
1740
2289
|
} catch {
|
|
1741
2290
|
}
|
|
1742
2291
|
};
|
|
1743
|
-
var clampWidth = (width, vw) => Math.round(
|
|
1744
|
-
|
|
2292
|
+
var clampWidth = (width, vw) => Math.round(
|
|
2293
|
+
Math.min(Math.max(width, MIN_PANE), Math.max(MIN_PANE, vw - MIN_FORM))
|
|
2294
|
+
);
|
|
1745
2295
|
var Pane = styled2.aside`
|
|
1746
|
-
position: fixed;
|
|
1747
|
-
|
|
2296
|
+
position: fixed;
|
|
2297
|
+
top: 0;
|
|
2298
|
+
bottom: 0;
|
|
2299
|
+
z-index: 2;
|
|
2300
|
+
display: flex;
|
|
2301
|
+
flex-direction: column;
|
|
2302
|
+
background: ${({ theme }) => theme.colors.neutral0};
|
|
2303
|
+
border-left: 1px solid ${({ theme }) => theme.colors.neutral200};
|
|
1748
2304
|
box-shadow: ${({ theme }) => theme.shadows.popupShadow};
|
|
1749
2305
|
`;
|
|
1750
2306
|
function useMainRect() {
|
|
1751
|
-
const [rect, setRect] =
|
|
1752
|
-
|
|
2307
|
+
const [rect, setRect] = React4.useState(() => ({
|
|
2308
|
+
left: 0,
|
|
2309
|
+
width: window.innerWidth
|
|
2310
|
+
}));
|
|
2311
|
+
React4.useEffect(() => {
|
|
1753
2312
|
const main = document.getElementById("main-content");
|
|
1754
2313
|
const measure = () => {
|
|
1755
2314
|
const r = main?.getBoundingClientRect();
|
|
1756
|
-
setRect(
|
|
2315
|
+
setRect(
|
|
2316
|
+
r && r.width > 0 ? { left: Math.round(r.left), width: Math.round(r.width) } : { left: 0, width: window.innerWidth }
|
|
2317
|
+
);
|
|
1757
2318
|
};
|
|
1758
2319
|
measure();
|
|
1759
2320
|
const observer = main && "ResizeObserver" in window ? new ResizeObserver(measure) : null;
|
|
@@ -1767,12 +2328,37 @@ function useMainRect() {
|
|
|
1767
2328
|
return rect;
|
|
1768
2329
|
}
|
|
1769
2330
|
var Handle = styled2.div`
|
|
1770
|
-
position: absolute;
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
2331
|
+
position: absolute;
|
|
2332
|
+
top: 0;
|
|
2333
|
+
bottom: 0;
|
|
2334
|
+
left: -5px;
|
|
2335
|
+
width: 10px;
|
|
2336
|
+
cursor: col-resize;
|
|
2337
|
+
z-index: 3;
|
|
2338
|
+
touch-action: none;
|
|
2339
|
+
&::after {
|
|
2340
|
+
content: "";
|
|
2341
|
+
position: absolute;
|
|
2342
|
+
top: 0;
|
|
2343
|
+
bottom: 0;
|
|
2344
|
+
left: 4px;
|
|
2345
|
+
width: 2px;
|
|
2346
|
+
}
|
|
2347
|
+
&:hover::after,
|
|
2348
|
+
&[data-dragging="true"]::after,
|
|
2349
|
+
&:focus-visible::after {
|
|
2350
|
+
background: ${({ theme }) => theme.colors.primary600};
|
|
2351
|
+
}
|
|
2352
|
+
&:focus-visible {
|
|
2353
|
+
outline: none;
|
|
2354
|
+
}
|
|
2355
|
+
`;
|
|
2356
|
+
var Frame2 = styled2.iframe`
|
|
2357
|
+
flex: 1;
|
|
2358
|
+
width: 100%;
|
|
2359
|
+
border: 0;
|
|
2360
|
+
background: white;
|
|
1774
2361
|
`;
|
|
1775
|
-
var Frame2 = styled2.iframe` flex: 1; width: 100%; border: 0; background: white; `;
|
|
1776
2362
|
var SPLIT_STYLE = `
|
|
1777
2363
|
body.bp-split #main-content { padding-right: calc(var(--bp-pane, 50vw) + 1.6rem) !important; }
|
|
1778
2364
|
body.bp-split [data-bp-grid] { display: flex !important; flex-direction: column-reverse; gap: 1.6rem; }
|
|
@@ -1781,20 +2367,26 @@ body.bp-split [data-bp-panels] > div { flex-direction: row; flex-wrap: wrap; ali
|
|
|
1781
2367
|
body.bp-split [data-bp-panels] > div > * { flex: 1 1 24rem; }`;
|
|
1782
2368
|
var markLayout = (anchor) => {
|
|
1783
2369
|
let item = anchor;
|
|
1784
|
-
while (item?.parentElement && getComputedStyle(item.parentElement).display !== "grid")
|
|
2370
|
+
while (item?.parentElement && getComputedStyle(item.parentElement).display !== "grid")
|
|
2371
|
+
item = item.parentElement;
|
|
1785
2372
|
if (!item?.parentElement) return;
|
|
1786
2373
|
item.dataset.bpPanels = "";
|
|
1787
2374
|
item.parentElement.dataset.bpGrid = "";
|
|
1788
2375
|
};
|
|
1789
2376
|
function usePreviewBase(override, model, documentId, locale) {
|
|
1790
2377
|
const { get } = useFetchClient();
|
|
1791
|
-
const [native, setNative] =
|
|
1792
|
-
|
|
2378
|
+
const [native, setNative] = React4.useState(null);
|
|
2379
|
+
React4.useEffect(() => {
|
|
1793
2380
|
if (override || !model) return;
|
|
1794
2381
|
let active = true;
|
|
1795
|
-
const query = new URLSearchParams({
|
|
2382
|
+
const query = new URLSearchParams({
|
|
2383
|
+
status: "draft",
|
|
2384
|
+
...documentId ? { documentId } : {},
|
|
2385
|
+
...locale ? { locale } : {}
|
|
2386
|
+
});
|
|
1796
2387
|
get(`/content-manager/preview/url/${model}?${query}`).then(({ data }) => {
|
|
1797
|
-
if (active && typeof data?.data?.url === "string")
|
|
2388
|
+
if (active && typeof data?.data?.url === "string")
|
|
2389
|
+
setNative(`${new URL(data.data.url).origin}/block-preview/page`);
|
|
1798
2390
|
}).catch(() => {
|
|
1799
2391
|
if (active) setNative(null);
|
|
1800
2392
|
});
|
|
@@ -1804,56 +2396,109 @@ function usePreviewBase(override, model, documentId, locale) {
|
|
|
1804
2396
|
}, [get, model, documentId, locale, override]);
|
|
1805
2397
|
return override ? { base: override, source: "custom" } : native ? { base: native, source: "native" } : { base: null, source: "none" };
|
|
1806
2398
|
}
|
|
1807
|
-
function PickerDialog({ open, onOpenChange, trigger, title, children }) {
|
|
1808
|
-
return /* @__PURE__ */ jsxs3(Dialog.Root, { open, onOpenChange, children: [
|
|
1809
|
-
trigger && /* @__PURE__ */ jsx4(Dialog.Trigger, { children: trigger }),
|
|
1810
|
-
/* @__PURE__ */ jsxs3(Dialog.Content, { children: [
|
|
1811
|
-
/* @__PURE__ */ jsx4(Dialog.Header, { children: /* @__PURE__ */ jsx4(Dialog.Title, { children: title }) }),
|
|
1812
|
-
/* @__PURE__ */ jsx4(Dialog.Body, { children })
|
|
1813
|
-
] })
|
|
1814
|
-
] });
|
|
1815
|
-
}
|
|
1816
2399
|
var ACTION_TYPES = ["update", "publish"];
|
|
1817
|
-
var nativeButtons = () => document.querySelectorAll(
|
|
2400
|
+
var nativeButtons = () => document.querySelectorAll(
|
|
2401
|
+
'#main-content button:not([data-testid="page-preview-pane"] button)'
|
|
2402
|
+
);
|
|
1818
2403
|
function ToolbarActions({ model, collectionType, documentId, locale }) {
|
|
1819
|
-
const plugins = useStrapiApp2(
|
|
2404
|
+
const plugins = useStrapiApp2(
|
|
2405
|
+
"BlocksceneToolbar",
|
|
2406
|
+
(state) => state.plugins
|
|
2407
|
+
);
|
|
1820
2408
|
const [{ query }] = useQueryParams();
|
|
1821
|
-
const { document: doc, meta } = useDocument(
|
|
2409
|
+
const { document: doc, meta } = useDocument(
|
|
2410
|
+
{ model, collectionType, documentId, params: { locale } },
|
|
2411
|
+
{ skip: !documentId }
|
|
2412
|
+
);
|
|
1822
2413
|
const { toggleNotification } = useNotification();
|
|
1823
2414
|
const t = useMessages();
|
|
1824
2415
|
const descriptions = (plugins["content-manager"]?.apis?.getDocumentActions?.("panel") || []).filter((d) => ACTION_TYPES.includes(d.type));
|
|
1825
|
-
const props = {
|
|
2416
|
+
const props = {
|
|
2417
|
+
activeTab: query.status || "draft",
|
|
2418
|
+
model,
|
|
2419
|
+
documentId,
|
|
2420
|
+
document: doc,
|
|
2421
|
+
meta,
|
|
2422
|
+
collectionType
|
|
2423
|
+
};
|
|
1826
2424
|
const run = async (action, event) => {
|
|
1827
|
-
const native = [...nativeButtons()].find(
|
|
2425
|
+
const native = [...nativeButtons()].find(
|
|
2426
|
+
(b) => b.textContent?.trim() === action.label
|
|
2427
|
+
);
|
|
1828
2428
|
if (native) {
|
|
1829
2429
|
native.click();
|
|
1830
2430
|
return;
|
|
1831
2431
|
}
|
|
1832
2432
|
const mute = await action.onClick?.(event);
|
|
1833
|
-
if (action.dialog && !mute && action.dialog.type === "notification")
|
|
2433
|
+
if (action.dialog && !mute && action.dialog.type === "notification")
|
|
2434
|
+
toggleNotification({
|
|
2435
|
+
title: action.dialog.title,
|
|
2436
|
+
message: action.dialog.content,
|
|
2437
|
+
type: action.dialog.status
|
|
2438
|
+
});
|
|
1834
2439
|
};
|
|
1835
|
-
const typeOf = (action) => action.type || descriptions.find(
|
|
1836
|
-
|
|
2440
|
+
const typeOf = (action) => action.type || descriptions.find(
|
|
2441
|
+
(d) => typeof action.id === "string" && action.id.startsWith(`${d.name || d.displayName}-`)
|
|
2442
|
+
)?.type;
|
|
2443
|
+
return /* @__PURE__ */ jsx5(DescriptionComponentRenderer, { props, descriptions, children: (actions) => /* @__PURE__ */ jsx5(Flex3, { gap: 1, "data-testid": "page-preview-actions", children: [...actions].sort(
|
|
2444
|
+
(a, b) => ACTION_TYPES.indexOf(typeOf(a)) - ACTION_TYPES.indexOf(typeOf(b))
|
|
2445
|
+
).map((action) => {
|
|
1837
2446
|
const reason = action.disabled ? typeOf(action) === "publish" ? t.publishDisabledHint : t.saveDisabledHint : void 0;
|
|
1838
|
-
return /* @__PURE__ */
|
|
2447
|
+
return /* @__PURE__ */ jsx5("span", { title: reason, children: /* @__PURE__ */ jsx5(
|
|
2448
|
+
Button3,
|
|
2449
|
+
{
|
|
2450
|
+
size: "S",
|
|
2451
|
+
variant: action.variant || "default",
|
|
2452
|
+
disabled: action.disabled,
|
|
2453
|
+
loading: action.loading,
|
|
2454
|
+
"aria-description": reason,
|
|
2455
|
+
onClick: (e) => run(action, e),
|
|
2456
|
+
children: action.label
|
|
2457
|
+
}
|
|
2458
|
+
) }, action.id);
|
|
1839
2459
|
}) }) });
|
|
1840
2460
|
}
|
|
1841
|
-
function PagePreview({
|
|
2461
|
+
function PagePreview({
|
|
2462
|
+
editor,
|
|
2463
|
+
groups = null,
|
|
2464
|
+
Modal: Modal3,
|
|
2465
|
+
Toggle
|
|
2466
|
+
}) {
|
|
1842
2467
|
const t = useMessages();
|
|
1843
2468
|
const c = useContext();
|
|
1844
|
-
const rbac = useDocumentRBAC(
|
|
2469
|
+
const rbac = useDocumentRBAC(
|
|
2470
|
+
"BlockscenePagePreview",
|
|
2471
|
+
(state) => state
|
|
2472
|
+
);
|
|
1845
2473
|
const values = useForm2("BlockscenePagePreview", (state) => state.values);
|
|
1846
|
-
const onChange = useForm2(
|
|
1847
|
-
|
|
2474
|
+
const onChange = useForm2(
|
|
2475
|
+
"BlockscenePagePreview",
|
|
2476
|
+
(state) => state.onChange
|
|
2477
|
+
);
|
|
2478
|
+
const components = useStrapiApp2(
|
|
2479
|
+
"BlockscenePagePreview",
|
|
2480
|
+
(state) => state.components
|
|
2481
|
+
);
|
|
1848
2482
|
const MediaLibraryDialog = components?.["media-library"];
|
|
1849
|
-
const addFieldRow = useForm2(
|
|
1850
|
-
|
|
2483
|
+
const addFieldRow = useForm2(
|
|
2484
|
+
"BlockscenePagePreview",
|
|
2485
|
+
(state) => state.addFieldRow
|
|
2486
|
+
);
|
|
2487
|
+
const moveFieldRow = useForm2(
|
|
2488
|
+
"BlockscenePagePreview",
|
|
2489
|
+
(state) => state.moveFieldRow
|
|
2490
|
+
);
|
|
1851
2491
|
const fields = c.layout?.edit?.layout?.flat(3) || [];
|
|
1852
2492
|
const readable = (name) => c.isCreatingEntry || (rbac.canReadFields || []).includes(name);
|
|
1853
|
-
const zone =
|
|
2493
|
+
const zone = React4.useMemo(
|
|
2494
|
+
() => editableZones(c.contentType, values, readable, c.isLoading)[0]?.name,
|
|
2495
|
+
[c.contentType, values, c.isLoading, rbac.canReadFields, c.isCreatingEntry]
|
|
2496
|
+
);
|
|
1854
2497
|
const zoneLabel = fields.find((field) => field.name === zone)?.label || zone || "";
|
|
1855
|
-
const canEdit = Boolean(
|
|
1856
|
-
|
|
2498
|
+
const canEdit = Boolean(
|
|
2499
|
+
zone && ((c.isCreatingEntry ? rbac.canCreateFields : rbac.canUpdateFields) || []).includes(zone) && fields.find((field) => field.name === zone)?.disabled !== true && !c.form?.disabled && typeof addFieldRow === "function"
|
|
2500
|
+
);
|
|
2501
|
+
const [mode, setModeState] = React4.useState(() => {
|
|
1857
2502
|
const v = read(MODE_KEY);
|
|
1858
2503
|
return v === "split" || v === "preview" ? v : editor?.previewMode || "form";
|
|
1859
2504
|
});
|
|
@@ -1861,32 +2506,37 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
1861
2506
|
setModeState(next);
|
|
1862
2507
|
write(MODE_KEY, next);
|
|
1863
2508
|
};
|
|
1864
|
-
const [ratio, setRatio] =
|
|
2509
|
+
const [ratio, setRatio] = React4.useState(() => {
|
|
1865
2510
|
const v = Number(read(RATIO_KEY));
|
|
1866
2511
|
return v > 0 && v < 1 ? v : 0.5;
|
|
1867
2512
|
});
|
|
1868
2513
|
const main = useMainRect();
|
|
1869
2514
|
const vw = main.width;
|
|
1870
|
-
const [dragging, setDragging] =
|
|
1871
|
-
const [ready, setReady] =
|
|
1872
|
-
const [failed, setFailed] =
|
|
1873
|
-
const [attempt, retry] =
|
|
1874
|
-
const [picking, setPicking] =
|
|
1875
|
-
|
|
2515
|
+
const [dragging, setDragging] = React4.useState(false);
|
|
2516
|
+
const [ready, setReady] = React4.useState(false);
|
|
2517
|
+
const [failed, setFailed] = React4.useState(false);
|
|
2518
|
+
const [attempt, retry] = React4.useReducer((n) => n + 1, 0);
|
|
2519
|
+
const [picking, setPicking] = React4.useState(null);
|
|
2520
|
+
React4.useEffect(() => {
|
|
1876
2521
|
setEditing(null);
|
|
1877
2522
|
setPicking(null);
|
|
1878
2523
|
setInserting(null);
|
|
1879
2524
|
}, [c.id, c.form?.initialValues?.locale]);
|
|
1880
|
-
const [editing, setEditing] =
|
|
1881
|
-
const [inserting, setInserting] =
|
|
2525
|
+
const [editing, setEditing] = React4.useState(null);
|
|
2526
|
+
const [inserting, setInserting] = React4.useState(null);
|
|
1882
2527
|
const { get } = useFetchClient();
|
|
1883
2528
|
const { toggleNotification } = useNotification();
|
|
1884
2529
|
const zoneAttr = zone ? c.contentType?.attributes?.[zone] : null;
|
|
1885
|
-
const iframe =
|
|
1886
|
-
const loaded =
|
|
1887
|
-
const anchor =
|
|
1888
|
-
const channel =
|
|
1889
|
-
const { base, source } = usePreviewBase(
|
|
2530
|
+
const iframe = React4.useRef(null);
|
|
2531
|
+
const loaded = React4.useRef(false);
|
|
2532
|
+
const anchor = React4.useRef(null);
|
|
2533
|
+
const channel = React4.useMemo(() => crypto.randomUUID(), []);
|
|
2534
|
+
const { base, source } = usePreviewBase(
|
|
2535
|
+
editor?.previewUrl || "",
|
|
2536
|
+
c.model,
|
|
2537
|
+
c.isCreatingEntry ? void 0 : c.id,
|
|
2538
|
+
c.form?.initialValues?.locale
|
|
2539
|
+
);
|
|
1890
2540
|
const url = base ? new URL(base) : null;
|
|
1891
2541
|
url?.searchParams.set("channel", channel);
|
|
1892
2542
|
const origin = url?.origin || "";
|
|
@@ -1895,21 +2545,50 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
1895
2545
|
const resizable = mode === "split" && !narrow;
|
|
1896
2546
|
const active = mode !== "form" && Boolean(url) && Boolean(zone);
|
|
1897
2547
|
const rows = zone && Array.isArray(values?.[zone]) ? values[zone] : [];
|
|
1898
|
-
const latest =
|
|
2548
|
+
const latest = React4.useRef(rows);
|
|
1899
2549
|
latest.current = rows;
|
|
1900
2550
|
const insertRows = (at, ...items) => items.forEach((item, i) => {
|
|
1901
2551
|
const from = latest.current.length + i;
|
|
1902
2552
|
addFieldRow(zone, item);
|
|
1903
2553
|
if (at + i < from) moveFieldRow(zone, from, at + i);
|
|
1904
2554
|
});
|
|
1905
|
-
const live =
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
2555
|
+
const live = React4.useRef({
|
|
2556
|
+
mode,
|
|
2557
|
+
canEdit,
|
|
2558
|
+
zoneLabel,
|
|
2559
|
+
components: c.components,
|
|
2560
|
+
setMode,
|
|
2561
|
+
onChange
|
|
2562
|
+
});
|
|
2563
|
+
live.current = {
|
|
2564
|
+
mode,
|
|
2565
|
+
canEdit,
|
|
2566
|
+
zoneLabel,
|
|
2567
|
+
components: c.components,
|
|
2568
|
+
setMode,
|
|
2569
|
+
onChange
|
|
2570
|
+
};
|
|
2571
|
+
const send = React4.useCallback(() => {
|
|
2572
|
+
iframe.current?.contentWindow?.postMessage(
|
|
2573
|
+
{
|
|
2574
|
+
protocol: PROTOCOL,
|
|
2575
|
+
channel,
|
|
2576
|
+
type: "update-page",
|
|
2577
|
+
blocks: projectPage(
|
|
2578
|
+
latest.current,
|
|
2579
|
+
live.current.components,
|
|
2580
|
+
window.location.origin
|
|
2581
|
+
),
|
|
2582
|
+
groups,
|
|
2583
|
+
locale: t.locale,
|
|
2584
|
+
mode: live.current.mode
|
|
2585
|
+
},
|
|
2586
|
+
origin
|
|
2587
|
+
);
|
|
1909
2588
|
}, [channel, origin]);
|
|
1910
2589
|
const indexOf = (key) => latest.current.findIndex((row) => blockKey(row) === key);
|
|
1911
2590
|
const path = (key, field) => `${zone}.${indexOf(key)}.${field}`;
|
|
1912
|
-
|
|
2591
|
+
React4.useEffect(() => {
|
|
1913
2592
|
if (resizable) markLayout(anchor.current);
|
|
1914
2593
|
document.body.classList.toggle("bp-split", resizable);
|
|
1915
2594
|
document.documentElement.style.setProperty("--bp-pane", `${paneWidth}px`);
|
|
@@ -1921,7 +2600,9 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
1921
2600
|
if (persist) write(RATIO_KEY, String(next));
|
|
1922
2601
|
};
|
|
1923
2602
|
const focusField = (index, field) => {
|
|
1924
|
-
const item = findZoneList(live.current.zoneLabel)?.querySelectorAll(
|
|
2603
|
+
const item = findZoneList(live.current.zoneLabel)?.querySelectorAll(
|
|
2604
|
+
":scope > li"
|
|
2605
|
+
)[index];
|
|
1925
2606
|
if (!item) return;
|
|
1926
2607
|
const header = toggles(item.parentElement)[index];
|
|
1927
2608
|
if (header?.getAttribute("aria-expanded") === "false") header.click();
|
|
@@ -1932,33 +2613,47 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
1932
2613
|
if (++tries > 40) return clearInterval(timer);
|
|
1933
2614
|
let scope = item;
|
|
1934
2615
|
for (let i = 0; i + 1 < parts.length; i += 2) {
|
|
1935
|
-
const nested = [
|
|
2616
|
+
const nested = [
|
|
2617
|
+
...scope.querySelectorAll(
|
|
2618
|
+
"button[aria-expanded][data-radix-collection-item]"
|
|
2619
|
+
)
|
|
2620
|
+
].filter((b) => b !== header);
|
|
1936
2621
|
const row = nested[Number(parts[i + 1])];
|
|
1937
2622
|
if (!row) return;
|
|
1938
2623
|
if (row.getAttribute("aria-expanded") === "false") row.click();
|
|
1939
2624
|
scope = row.closest("li, div") || scope;
|
|
1940
2625
|
}
|
|
1941
|
-
const target = document.querySelector(
|
|
2626
|
+
const target = document.querySelector(
|
|
2627
|
+
`[name="${escaped}"], label[for="${escaped}"]`
|
|
2628
|
+
);
|
|
1942
2629
|
if (!target) return;
|
|
1943
2630
|
const INPUT = '.ck-editor__editable, textarea, input:not([type="hidden"]), select';
|
|
1944
2631
|
let container = target.matches(INPUT) ? target : target.parentElement;
|
|
1945
|
-
for (let depth = 0; container && depth < 4 && !container.matches(INPUT) && !container.querySelector(INPUT); depth++)
|
|
2632
|
+
for (let depth = 0; container && depth < 4 && !container.matches(INPUT) && !container.querySelector(INPUT); depth++)
|
|
2633
|
+
container = container.parentElement;
|
|
1946
2634
|
const editable = container?.matches(INPUT) ? container : container?.querySelector(INPUT);
|
|
1947
2635
|
if (!editable) return;
|
|
1948
|
-
if (editable.classList.contains("ck-editor__editable") && !editable.isContentEditable)
|
|
2636
|
+
if (editable.classList.contains("ck-editor__editable") && !editable.isContentEditable)
|
|
2637
|
+
return;
|
|
1949
2638
|
editable.focus();
|
|
1950
2639
|
if (document.activeElement !== editable) return;
|
|
1951
2640
|
clearInterval(timer);
|
|
1952
2641
|
editable.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
1953
2642
|
}, 150);
|
|
1954
2643
|
};
|
|
1955
|
-
|
|
2644
|
+
React4.useEffect(() => {
|
|
1956
2645
|
if (!active) return;
|
|
1957
2646
|
setReady(false);
|
|
1958
2647
|
setFailed(false);
|
|
1959
2648
|
const timeout = setTimeout(() => setFailed(true), 15e3);
|
|
1960
2649
|
const receive = (event) => {
|
|
1961
|
-
const is = (type) => isPreviewMessage(
|
|
2650
|
+
const is = (type) => isPreviewMessage(
|
|
2651
|
+
event,
|
|
2652
|
+
origin,
|
|
2653
|
+
iframe.current?.contentWindow,
|
|
2654
|
+
channel,
|
|
2655
|
+
type
|
|
2656
|
+
);
|
|
1962
2657
|
const { mode: mode2, canEdit: canEdit2, zoneLabel: zoneLabel2, components: components2, setMode: setMode2, onChange: onChange2 } = live.current;
|
|
1963
2658
|
if (is("ready")) {
|
|
1964
2659
|
clearTimeout(timeout);
|
|
@@ -1978,12 +2673,21 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
1978
2673
|
return;
|
|
1979
2674
|
}
|
|
1980
2675
|
if (is("move-group") && canEdit2 && groups) {
|
|
1981
|
-
const next = (0, import_groups.moveGroup)(
|
|
2676
|
+
const next = (0, import_groups.moveGroup)(
|
|
2677
|
+
latest.current,
|
|
2678
|
+
String(event.data.key),
|
|
2679
|
+
event.data.direction === "up" ? "up" : "down",
|
|
2680
|
+
groups
|
|
2681
|
+
);
|
|
1982
2682
|
if (next) onChange2(zone, next);
|
|
1983
2683
|
return;
|
|
1984
2684
|
}
|
|
1985
2685
|
if (is("delete-group") && canEdit2 && groups) {
|
|
1986
|
-
const next = (0, import_groups.removeGroup)(
|
|
2686
|
+
const next = (0, import_groups.removeGroup)(
|
|
2687
|
+
latest.current,
|
|
2688
|
+
String(event.data.key),
|
|
2689
|
+
groups
|
|
2690
|
+
);
|
|
1987
2691
|
if (next) onChange2(zone, next);
|
|
1988
2692
|
return;
|
|
1989
2693
|
}
|
|
@@ -1993,12 +2697,20 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
1993
2697
|
const uid2 = String(event.data.uid || "");
|
|
1994
2698
|
const close = groups[uid2];
|
|
1995
2699
|
const allowed = zoneAttr?.components || [];
|
|
1996
|
-
if (index2 < 0 || !close || !allowed.includes(uid2) || !allowed.includes(close))
|
|
2700
|
+
if (index2 < 0 || !close || !allowed.includes(uid2) || !allowed.includes(close))
|
|
2701
|
+
return;
|
|
1997
2702
|
if (latest.current.length + 2 > (zoneAttr?.max ?? Infinity)) {
|
|
1998
2703
|
toggleNotification({ type: "info", message: t.zoneFull });
|
|
1999
2704
|
return;
|
|
2000
2705
|
}
|
|
2001
|
-
insertRows(
|
|
2706
|
+
insertRows(
|
|
2707
|
+
index2,
|
|
2708
|
+
{
|
|
2709
|
+
...componentDefaults(components2[uid2], components2),
|
|
2710
|
+
__component: uid2
|
|
2711
|
+
},
|
|
2712
|
+
{ __component: close }
|
|
2713
|
+
);
|
|
2002
2714
|
return;
|
|
2003
2715
|
}
|
|
2004
2716
|
const key = typeof event.data?.key === "string" ? event.data.key : "";
|
|
@@ -2018,11 +2730,21 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
2018
2730
|
}, 1500);
|
|
2019
2731
|
}
|
|
2020
2732
|
if (mode2 === "preview") setMode2("split");
|
|
2021
|
-
iframe.current?.contentWindow?.postMessage(
|
|
2733
|
+
iframe.current?.contentWindow?.postMessage(
|
|
2734
|
+
{ protocol: PROTOCOL, channel, type: "highlight", key },
|
|
2735
|
+
origin
|
|
2736
|
+
);
|
|
2022
2737
|
} else if (is("focus")) {
|
|
2023
2738
|
const attr = validateFocus(uid, event.data.field, components2);
|
|
2024
2739
|
if (!attr) return;
|
|
2025
|
-
if (mode2 === "preview" && canEdit2 && (attr.customField || MODAL_TYPES.includes(attr.type)))
|
|
2740
|
+
if (mode2 === "preview" && canEdit2 && (attr.customField || MODAL_TYPES.includes(attr.type)))
|
|
2741
|
+
setEditing({
|
|
2742
|
+
key,
|
|
2743
|
+
field: event.data.field,
|
|
2744
|
+
attr,
|
|
2745
|
+
label: `${components2[uid]?.info?.displayName || uid} \xB7 ${event.data.field}`,
|
|
2746
|
+
value: getIn(latest.current[index], event.data.field)
|
|
2747
|
+
});
|
|
2026
2748
|
else focusField(index, event.data.field);
|
|
2027
2749
|
} else if (is("media") && canEdit2) {
|
|
2028
2750
|
const attr = mediaAttribute(uid, event.data.field, components2);
|
|
@@ -2031,27 +2753,67 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
2031
2753
|
const attr = mediaAttribute(uid, event.data.field, components2);
|
|
2032
2754
|
if (attr && !attr.required) onChange2(path(key, event.data.field), null);
|
|
2033
2755
|
} else if (is("edit") && canEdit2) {
|
|
2034
|
-
const value = validateEdit(
|
|
2756
|
+
const value = validateEdit(
|
|
2757
|
+
uid,
|
|
2758
|
+
event.data.field,
|
|
2759
|
+
event.data.value,
|
|
2760
|
+
components2
|
|
2761
|
+
);
|
|
2035
2762
|
if (value !== null) onChange2(path(key, event.data.field), value);
|
|
2036
2763
|
}
|
|
2037
2764
|
};
|
|
2038
2765
|
window.addEventListener("message", receive);
|
|
2039
|
-
if (loaded.current)
|
|
2766
|
+
if (loaded.current)
|
|
2767
|
+
iframe.current?.contentWindow?.postMessage(
|
|
2768
|
+
{ protocol: PROTOCOL, channel, type: "ping" },
|
|
2769
|
+
origin
|
|
2770
|
+
);
|
|
2040
2771
|
return () => {
|
|
2041
2772
|
clearTimeout(timeout);
|
|
2042
2773
|
window.removeEventListener("message", receive);
|
|
2043
2774
|
};
|
|
2044
2775
|
}, [active, attempt, channel, origin, groups]);
|
|
2045
|
-
|
|
2776
|
+
React4.useEffect(() => {
|
|
2046
2777
|
if (!ready || !active) return;
|
|
2047
2778
|
const timer = setTimeout(send, 120);
|
|
2048
2779
|
return () => clearTimeout(timer);
|
|
2049
2780
|
}, [values, c.components, ready, active, send, mode]);
|
|
2050
2781
|
if (!zone) return null;
|
|
2051
|
-
const modes = [
|
|
2052
|
-
|
|
2782
|
+
const modes = [
|
|
2783
|
+
["form", t.modeForm],
|
|
2784
|
+
["split", t.modeSplit],
|
|
2785
|
+
["preview", t.modePreview]
|
|
2786
|
+
];
|
|
2787
|
+
const switcher = /* @__PURE__ */ jsx5(
|
|
2788
|
+
Flex3,
|
|
2789
|
+
{
|
|
2790
|
+
gap: 1,
|
|
2791
|
+
wrap: "wrap",
|
|
2792
|
+
"data-testid": "page-preview-modes",
|
|
2793
|
+
role: "group",
|
|
2794
|
+
"aria-label": t.modeGroup,
|
|
2795
|
+
children: modes.map(([value, label]) => /* @__PURE__ */ jsx5(
|
|
2796
|
+
Button3,
|
|
2797
|
+
{
|
|
2798
|
+
type: "button",
|
|
2799
|
+
size: "S",
|
|
2800
|
+
variant: mode === value ? "default" : "tertiary",
|
|
2801
|
+
"aria-pressed": mode === value,
|
|
2802
|
+
onClick: () => setMode(value),
|
|
2803
|
+
disabled: !url && value !== "form",
|
|
2804
|
+
children: label
|
|
2805
|
+
},
|
|
2806
|
+
value
|
|
2807
|
+
))
|
|
2808
|
+
}
|
|
2809
|
+
);
|
|
2053
2810
|
const onKey = (event) => {
|
|
2054
|
-
const map = {
|
|
2811
|
+
const map = {
|
|
2812
|
+
ArrowLeft: paneWidth + KEY_STEP,
|
|
2813
|
+
ArrowRight: paneWidth - KEY_STEP,
|
|
2814
|
+
Home: MIN_PANE,
|
|
2815
|
+
End: vw - MIN_FORM
|
|
2816
|
+
};
|
|
2055
2817
|
if (event.key in map) {
|
|
2056
2818
|
event.preventDefault();
|
|
2057
2819
|
applyWidth(map[event.key], true);
|
|
@@ -2062,28 +2824,69 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
2062
2824
|
const end = (0, import_groups.groupRange)(latest.current, error.index, groups)[1];
|
|
2063
2825
|
insertRows(end + 1, { __component: error.expected });
|
|
2064
2826
|
};
|
|
2065
|
-
const diagnostics = problems.length > 0 && /* @__PURE__ */
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2827
|
+
const diagnostics = problems.length > 0 && /* @__PURE__ */ jsx5(
|
|
2828
|
+
Box2,
|
|
2829
|
+
{
|
|
2830
|
+
role: "alert",
|
|
2831
|
+
"data-testid": "page-preview-diagnostics",
|
|
2832
|
+
padding: 2,
|
|
2833
|
+
background: "danger100",
|
|
2834
|
+
hasRadius: true,
|
|
2835
|
+
children: /* @__PURE__ */ jsxs4("details", { children: [
|
|
2836
|
+
/* @__PURE__ */ jsx5("summary", { style: { cursor: "pointer" }, children: /* @__PURE__ */ jsx5(Typography3, { variant: "pi", fontWeight: "bold", textColor: "danger700", children: t.f("diagSummary", { count: problems.length }) }) }),
|
|
2837
|
+
/* @__PURE__ */ jsx5("ul", { style: { margin: "6px 0 0 16px", padding: 0 }, children: problems.map((error) => /* @__PURE__ */ jsxs4(
|
|
2838
|
+
"li",
|
|
2839
|
+
{
|
|
2840
|
+
style: { marginBottom: 6 },
|
|
2841
|
+
children: [
|
|
2842
|
+
/* @__PURE__ */ jsx5(Typography3, { variant: "pi", textColor: "danger700", children: t.f(
|
|
2843
|
+
error.code === "closeBeforeOpen" ? "diagCloseBeforeOpen" : error.code === "mismatch" ? "diagMismatch" : "diagUnclosed",
|
|
2844
|
+
{
|
|
2845
|
+
n: error.index + 1,
|
|
2846
|
+
uid: error.uid,
|
|
2847
|
+
open: error.open || "",
|
|
2848
|
+
expected: error.expected || ""
|
|
2849
|
+
}
|
|
2850
|
+
) }),
|
|
2851
|
+
error.code === "unclosed" && canEdit && /* @__PURE__ */ jsx5(Box2, { paddingTop: 1, children: /* @__PURE__ */ jsx5(
|
|
2852
|
+
Button3,
|
|
2853
|
+
{
|
|
2854
|
+
size: "S",
|
|
2855
|
+
variant: "danger-light",
|
|
2856
|
+
"data-testid": `diag-insert-close-${error.index}`,
|
|
2857
|
+
onClick: () => insertClose(error),
|
|
2858
|
+
children: t.f("diagInsertClose", {
|
|
2859
|
+
n: error.index + 1,
|
|
2860
|
+
expected: error.expected
|
|
2861
|
+
})
|
|
2862
|
+
}
|
|
2863
|
+
) }),
|
|
2864
|
+
error.code === "closeBeforeOpen" && /* @__PURE__ */ jsx5(Typography3, { variant: "pi", textColor: "neutral600", children: t.diagStrayHint })
|
|
2865
|
+
]
|
|
2866
|
+
},
|
|
2867
|
+
`${error.code}-${error.index}`
|
|
2868
|
+
)) })
|
|
2869
|
+
] })
|
|
2870
|
+
}
|
|
2871
|
+
);
|
|
2872
|
+
return /* @__PURE__ */ jsxs4(Flex3, { direction: "column", alignItems: "stretch", gap: 2, ref: anchor, children: [
|
|
2074
2873
|
switcher,
|
|
2075
2874
|
diagnostics,
|
|
2076
|
-
/* @__PURE__ */
|
|
2077
|
-
active &&
|
|
2078
|
-
/* @__PURE__ */
|
|
2875
|
+
/* @__PURE__ */ jsx5(Typography3, { variant: "pi", textColor: "neutral600", children: url ? t.previewHelp : t.previewNoUrl }),
|
|
2876
|
+
active && createPortal2(
|
|
2877
|
+
/* @__PURE__ */ jsxs4(
|
|
2079
2878
|
Pane,
|
|
2080
2879
|
{
|
|
2081
2880
|
"data-testid": "page-preview-pane",
|
|
2082
2881
|
"aria-label": t.previewPane,
|
|
2083
|
-
style: {
|
|
2882
|
+
style: {
|
|
2883
|
+
left: mode === "preview" || narrow ? main.left : main.left + main.width - paneWidth,
|
|
2884
|
+
width: mode === "preview" || narrow ? main.width : paneWidth,
|
|
2885
|
+
userSelect: dragging ? "none" : void 0
|
|
2886
|
+
},
|
|
2084
2887
|
children: [
|
|
2085
|
-
/* @__PURE__ */
|
|
2086
|
-
resizable && /* @__PURE__ */
|
|
2888
|
+
/* @__PURE__ */ jsx5("style", { children: SPLIT_STYLE }),
|
|
2889
|
+
resizable && /* @__PURE__ */ jsx5(
|
|
2087
2890
|
Handle,
|
|
2088
2891
|
{
|
|
2089
2892
|
role: "separator",
|
|
@@ -2101,7 +2904,8 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
2101
2904
|
setDragging(true);
|
|
2102
2905
|
},
|
|
2103
2906
|
onPointerMove: (e) => {
|
|
2104
|
-
if (dragging)
|
|
2907
|
+
if (dragging)
|
|
2908
|
+
applyWidth(main.left + main.width - e.clientX, false);
|
|
2105
2909
|
},
|
|
2106
2910
|
onPointerUp: (e) => {
|
|
2107
2911
|
if (!dragging) return;
|
|
@@ -2113,15 +2917,44 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
2113
2917
|
onKeyDown: onKey
|
|
2114
2918
|
}
|
|
2115
2919
|
),
|
|
2116
|
-
/* @__PURE__ */
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2920
|
+
/* @__PURE__ */ jsxs4(
|
|
2921
|
+
Flex3,
|
|
2922
|
+
{
|
|
2923
|
+
padding: 2,
|
|
2924
|
+
gap: 2,
|
|
2925
|
+
justifyContent: "space-between",
|
|
2926
|
+
alignItems: "center",
|
|
2927
|
+
background: "neutral100",
|
|
2928
|
+
wrap: "wrap",
|
|
2929
|
+
style: { position: "sticky", top: 0, zIndex: 2 },
|
|
2930
|
+
children: [
|
|
2931
|
+
switcher,
|
|
2932
|
+
/* @__PURE__ */ jsxs4(
|
|
2933
|
+
Flex3,
|
|
2934
|
+
{
|
|
2935
|
+
gap: 2,
|
|
2936
|
+
alignItems: "center",
|
|
2937
|
+
wrap: "wrap",
|
|
2938
|
+
style: { marginLeft: "auto" },
|
|
2939
|
+
children: [
|
|
2940
|
+
/* @__PURE__ */ jsx5(Typography3, { variant: "pi", role: "status", textColor: "neutral600", children: failed ? t.previewFailed : ready ? t.previewReady : t.previewLoading }),
|
|
2941
|
+
failed && /* @__PURE__ */ jsx5(Button3, { size: "S", variant: "secondary", onClick: retry, children: t.retry }),
|
|
2942
|
+
/* @__PURE__ */ jsx5(
|
|
2943
|
+
ToolbarActions,
|
|
2944
|
+
{
|
|
2945
|
+
model: c.model,
|
|
2946
|
+
collectionType: c.collectionType,
|
|
2947
|
+
documentId: c.isCreatingEntry ? void 0 : c.id,
|
|
2948
|
+
locale: c.form?.initialValues?.locale
|
|
2949
|
+
}
|
|
2950
|
+
)
|
|
2951
|
+
]
|
|
2952
|
+
}
|
|
2953
|
+
)
|
|
2954
|
+
]
|
|
2955
|
+
}
|
|
2956
|
+
),
|
|
2957
|
+
/* @__PURE__ */ jsx5(
|
|
2125
2958
|
Frame2,
|
|
2126
2959
|
{
|
|
2127
2960
|
ref: iframe,
|
|
@@ -2141,12 +2974,16 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
2141
2974
|
),
|
|
2142
2975
|
document.body
|
|
2143
2976
|
),
|
|
2144
|
-
inserting && zoneAttr && /* @__PURE__ */
|
|
2977
|
+
inserting && zoneAttr && /* @__PURE__ */ jsx5(
|
|
2145
2978
|
PickerModal,
|
|
2146
2979
|
{
|
|
2147
|
-
zone: {
|
|
2980
|
+
zone: {
|
|
2981
|
+
name: zone,
|
|
2982
|
+
components: zoneAttr.components || [],
|
|
2983
|
+
max: zoneAttr.max
|
|
2984
|
+
},
|
|
2148
2985
|
components: c.components,
|
|
2149
|
-
Modal:
|
|
2986
|
+
Modal: Modal3,
|
|
2150
2987
|
Toggle,
|
|
2151
2988
|
get,
|
|
2152
2989
|
open: true,
|
|
@@ -2158,14 +2995,24 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
2158
2995
|
setInserting(null);
|
|
2159
2996
|
const close = groups?.[uid];
|
|
2160
2997
|
if (index < 0 || !(zoneAttr.components || []).includes(uid) || close && !(zoneAttr.components || []).includes(close) || latest.current.length + (close ? 2 : 1) > (zoneAttr.max ?? Infinity)) {
|
|
2161
|
-
toggleNotification({
|
|
2998
|
+
toggleNotification({
|
|
2999
|
+
type: "warning",
|
|
3000
|
+
message: close ? t.zoneFull : t.insertMoved
|
|
3001
|
+
});
|
|
2162
3002
|
return;
|
|
2163
3003
|
}
|
|
2164
|
-
insertRows(
|
|
3004
|
+
insertRows(
|
|
3005
|
+
index,
|
|
3006
|
+
{
|
|
3007
|
+
...componentDefaults(c.components[uid], c.components),
|
|
3008
|
+
__component: uid
|
|
3009
|
+
},
|
|
3010
|
+
...close ? [{ __component: close }] : []
|
|
3011
|
+
);
|
|
2165
3012
|
}
|
|
2166
3013
|
}
|
|
2167
3014
|
),
|
|
2168
|
-
editing && /* @__PURE__ */
|
|
3015
|
+
editing && /* @__PURE__ */ jsx5(
|
|
2169
3016
|
FieldEditorModal,
|
|
2170
3017
|
{
|
|
2171
3018
|
label: editing.label,
|
|
@@ -2175,11 +3022,12 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
2175
3022
|
onApply: (value) => {
|
|
2176
3023
|
const index = indexOf(editing.key);
|
|
2177
3024
|
setEditing(null);
|
|
2178
|
-
if (index >= 0)
|
|
3025
|
+
if (index >= 0)
|
|
3026
|
+
onChange(`${zone}.${index}.${editing.field}`, value);
|
|
2179
3027
|
}
|
|
2180
3028
|
}
|
|
2181
3029
|
),
|
|
2182
|
-
picking && MediaLibraryDialog && /* @__PURE__ */
|
|
3030
|
+
picking && MediaLibraryDialog && /* @__PURE__ */ jsx5(
|
|
2183
3031
|
MediaLibraryDialog,
|
|
2184
3032
|
{
|
|
2185
3033
|
allowedTypes: picking.attr.allowedTypes || ["images"],
|
|
@@ -2190,19 +3038,32 @@ function PagePreview({ editor, groups = null, Toggle }) {
|
|
|
2190
3038
|
setPicking(null);
|
|
2191
3039
|
if (index < 0 || !assets?.length) return;
|
|
2192
3040
|
const current = getIn(latest.current[index], picking.field);
|
|
2193
|
-
onChange(
|
|
3041
|
+
onChange(
|
|
3042
|
+
`${zone}.${index}.${picking.field}`,
|
|
3043
|
+
picking.attr.multiple ? [...Array.isArray(current) ? current : [], ...assets] : assets[0]
|
|
3044
|
+
);
|
|
2194
3045
|
}
|
|
2195
3046
|
}
|
|
2196
3047
|
),
|
|
2197
|
-
/* @__PURE__ */
|
|
3048
|
+
/* @__PURE__ */ jsx5(
|
|
3049
|
+
Box2,
|
|
3050
|
+
{
|
|
3051
|
+
hidden: true,
|
|
3052
|
+
"data-testid": "page-preview-state",
|
|
3053
|
+
"data-mode": mode,
|
|
3054
|
+
"data-ready": ready,
|
|
3055
|
+
"data-failed": failed,
|
|
3056
|
+
"data-preview-source": source
|
|
3057
|
+
}
|
|
3058
|
+
)
|
|
2198
3059
|
] });
|
|
2199
3060
|
}
|
|
2200
3061
|
|
|
2201
3062
|
// admin/Settings.tsx
|
|
2202
|
-
import * as
|
|
3063
|
+
import * as React5 from "react";
|
|
2203
3064
|
import { Box as Box3, Button as Button4, Flex as Flex4, Searchbar as Searchbar2, Typography as Typography4 } from "@strapi/design-system";
|
|
2204
3065
|
import styled3 from "styled-components";
|
|
2205
|
-
import { Fragment, jsx as
|
|
3066
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2206
3067
|
var COLOR2 = /^#[0-9A-Fa-f]{6}$/;
|
|
2207
3068
|
var Grid = styled3.div` display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: 16px; `;
|
|
2208
3069
|
var Card2 = styled3.div`
|
|
@@ -2215,8 +3076,8 @@ var Bar = styled3.div`
|
|
|
2215
3076
|
box-shadow: 0 1px 4px rgba(33, 33, 52, 0.1);
|
|
2216
3077
|
`;
|
|
2217
3078
|
function useMainRect2(anchor) {
|
|
2218
|
-
const [rect, setRect] =
|
|
2219
|
-
|
|
3079
|
+
const [rect, setRect] = React5.useState({ left: 0, width: 0 });
|
|
3080
|
+
React5.useEffect(() => {
|
|
2220
3081
|
const read2 = () => {
|
|
2221
3082
|
let host = document.getElementById("main-content");
|
|
2222
3083
|
for (let el = anchor.current?.parentElement; !host && el; el = el.parentElement) if (["auto", "scroll"].includes(getComputedStyle(el).overflowY) && el.scrollHeight > el.clientHeight) host = el;
|
|
@@ -2233,11 +3094,11 @@ var Swatches = styled3.div` display: grid; grid-template-columns: repeat(auto-fi
|
|
|
2233
3094
|
var Label = styled3.label` display: flex; flex-direction: column; gap: 4px; font-size: 12px; `;
|
|
2234
3095
|
function ColorField({ name, label, value, onChange, disabled }) {
|
|
2235
3096
|
const valid = COLOR2.test(value);
|
|
2236
|
-
return /* @__PURE__ */
|
|
2237
|
-
/* @__PURE__ */
|
|
2238
|
-
/* @__PURE__ */
|
|
2239
|
-
/* @__PURE__ */
|
|
2240
|
-
/* @__PURE__ */
|
|
3097
|
+
return /* @__PURE__ */ jsxs5(Label, { children: [
|
|
3098
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
|
|
3099
|
+
/* @__PURE__ */ jsxs5(Flex4, { gap: 2, children: [
|
|
3100
|
+
/* @__PURE__ */ jsx6("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" } }),
|
|
3101
|
+
/* @__PURE__ */ jsx6(
|
|
2241
3102
|
"input",
|
|
2242
3103
|
{
|
|
2243
3104
|
name,
|
|
@@ -2257,18 +3118,18 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
2257
3118
|
const t = useMessages();
|
|
2258
3119
|
const { get, put } = useClient();
|
|
2259
3120
|
const { canRead, canUpdate, isLoading } = usePermissions2();
|
|
2260
|
-
const [data, setData] =
|
|
2261
|
-
const [catalog, setCatalog] =
|
|
2262
|
-
const [settings, setSettings] =
|
|
2263
|
-
const [media, setMedia] =
|
|
2264
|
-
const [sources, setSources] =
|
|
2265
|
-
const [dirty, setDirty] =
|
|
2266
|
-
const [saving, setSaving] =
|
|
2267
|
-
const [status, setStatus] =
|
|
2268
|
-
const [failed, setFailed] =
|
|
2269
|
-
const [filter, setFilter] =
|
|
2270
|
-
const [picking, setPicking] =
|
|
2271
|
-
|
|
3121
|
+
const [data, setData] = React5.useState(null);
|
|
3122
|
+
const [catalog, setCatalog] = React5.useState(null);
|
|
3123
|
+
const [settings, setSettings] = React5.useState(null);
|
|
3124
|
+
const [media, setMedia] = React5.useState({});
|
|
3125
|
+
const [sources, setSources] = React5.useState({});
|
|
3126
|
+
const [dirty, setDirty] = React5.useState(false);
|
|
3127
|
+
const [saving, setSaving] = React5.useState(false);
|
|
3128
|
+
const [status, setStatus] = React5.useState("");
|
|
3129
|
+
const [failed, setFailed] = React5.useState(false);
|
|
3130
|
+
const [filter, setFilter] = React5.useState("");
|
|
3131
|
+
const [picking, setPicking] = React5.useState(null);
|
|
3132
|
+
React5.useEffect(() => {
|
|
2272
3133
|
if (!canRead || isLoading) return;
|
|
2273
3134
|
let active = true;
|
|
2274
3135
|
Promise.all([get("/blockscene/settings"), get("/blockscene/catalog")]).then(([s, c]) => {
|
|
@@ -2316,35 +3177,35 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
2316
3177
|
return index === 0 && manual ? t.manual : t.automatic;
|
|
2317
3178
|
};
|
|
2318
3179
|
const ready = !isLoading && canRead && !failed && settings && catalog;
|
|
2319
|
-
const header =
|
|
2320
|
-
const [floating, setFloating] =
|
|
3180
|
+
const header = React5.useRef(null);
|
|
3181
|
+
const [floating, setFloating] = React5.useState(false);
|
|
2321
3182
|
const main = useMainRect2(header);
|
|
2322
|
-
|
|
3183
|
+
React5.useEffect(() => {
|
|
2323
3184
|
const el = header.current;
|
|
2324
3185
|
if (!el || typeof IntersectionObserver === "undefined") return;
|
|
2325
3186
|
const observer = new IntersectionObserver(([entry]) => setFloating(!entry.isIntersecting && entry.boundingClientRect.top < 0));
|
|
2326
3187
|
observer.observe(el);
|
|
2327
3188
|
return () => observer.disconnect();
|
|
2328
3189
|
}, [ready]);
|
|
2329
|
-
const controls = (suffix) => ready && /* @__PURE__ */
|
|
2330
|
-
/* @__PURE__ */
|
|
2331
|
-
/* @__PURE__ */
|
|
3190
|
+
const controls = (suffix) => ready && /* @__PURE__ */ jsxs5(Flex4, { gap: 3, alignItems: "center", wrap: "wrap", children: [
|
|
3191
|
+
/* @__PURE__ */ jsx6(Typography4, { role: "status", "aria-live": "polite", textColor: dirty ? "warning700" : "neutral600", "data-testid": `${dirty ? "unsaved-indicator" : "save-status"}${suffix}`, children: dirty ? t.unsaved : status || t.noChanges }),
|
|
3192
|
+
/* @__PURE__ */ jsx6(Button4, { onClick: save, disabled: !canUpdate || invalid || !dirty, loading: saving, "data-testid": `save-blockscene-settings${suffix}`, children: t.save })
|
|
2332
3193
|
] });
|
|
2333
|
-
return /* @__PURE__ */
|
|
2334
|
-
/* @__PURE__ */
|
|
2335
|
-
/* @__PURE__ */
|
|
3194
|
+
return /* @__PURE__ */ jsx6(Box3, { padding: 8, background: "neutral100", children: /* @__PURE__ */ jsxs5(Flex4, { direction: "column", alignItems: "stretch", gap: 5, children: [
|
|
3195
|
+
/* @__PURE__ */ jsx6("div", { ref: header, children: /* @__PURE__ */ jsxs5(Flex4, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
|
|
3196
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "alpha", tag: "h1", children: t.settingsTitle }),
|
|
2336
3197
|
controls("")
|
|
2337
3198
|
] }) }),
|
|
2338
|
-
floating && main.width > 0 && /* @__PURE__ */
|
|
2339
|
-
/* @__PURE__ */
|
|
3199
|
+
floating && main.width > 0 && /* @__PURE__ */ jsx6(Bar, { style: { left: main.left, width: main.width }, "data-testid": "settings-floating-bar", children: /* @__PURE__ */ jsxs5(Flex4, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
|
|
3200
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "beta", tag: "p", children: t.settingsTitle }),
|
|
2340
3201
|
controls("-floating")
|
|
2341
3202
|
] }) }),
|
|
2342
|
-
/* @__PURE__ */
|
|
2343
|
-
isLoading ? /* @__PURE__ */
|
|
2344
|
-
data.disabled && /* @__PURE__ */
|
|
2345
|
-
/* @__PURE__ */
|
|
2346
|
-
/* @__PURE__ */
|
|
2347
|
-
/* @__PURE__ */
|
|
3203
|
+
/* @__PURE__ */ jsx6(Typography4, { textColor: "neutral600", children: t.settingsIntro }),
|
|
3204
|
+
isLoading ? /* @__PURE__ */ jsx6(Typography4, { children: "\u2026" }) : !canRead ? /* @__PURE__ */ jsx6(Typography4, { role: "alert", children: t.denied }) : failed ? /* @__PURE__ */ jsx6(Typography4, { role: "alert", children: t.loadFailed }) : !settings || !catalog ? /* @__PURE__ */ jsx6(Typography4, { children: t.loading }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
3205
|
+
data.disabled && /* @__PURE__ */ jsx6(Box3, { padding: 4, background: "warning100", hasRadius: true, children: /* @__PURE__ */ jsx6(Typography4, { role: "alert", textColor: "warning700", children: t.disabledByServer }) }),
|
|
3206
|
+
/* @__PURE__ */ jsx6(Box3, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs5(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
3207
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "beta", tag: "h2", children: t.palette }),
|
|
3208
|
+
/* @__PURE__ */ jsx6(Swatches, { children: Object.keys(DEFAULT_PALETTE).map((key) => /* @__PURE__ */ jsx6(
|
|
2348
3209
|
ColorField,
|
|
2349
3210
|
{
|
|
2350
3211
|
name: `palette-${key}`,
|
|
@@ -2358,33 +3219,33 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
2358
3219
|
},
|
|
2359
3220
|
key
|
|
2360
3221
|
)) }),
|
|
2361
|
-
invalid && /* @__PURE__ */
|
|
2362
|
-
/* @__PURE__ */
|
|
2363
|
-
/* @__PURE__ */
|
|
2364
|
-
/* @__PURE__ */
|
|
2365
|
-
/* @__PURE__ */
|
|
3222
|
+
invalid && /* @__PURE__ */ jsx6(Typography4, { role: "alert", textColor: "danger600", children: t.invalidColor }),
|
|
3223
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "pi", textColor: "neutral600", children: t.previewLabel }),
|
|
3224
|
+
/* @__PURE__ */ jsx6(Swatches, { "data-testid": "palette-preview", children: TEMPLATES.map((template) => /* @__PURE__ */ jsxs5(Flex4, { direction: "column", gap: 1, children: [
|
|
3225
|
+
/* @__PURE__ */ jsx6(Box3, { style: { aspectRatio: "16 / 9", overflow: "hidden" }, hasRadius: true, children: /* @__PURE__ */ jsx6(Wireframe, { template, palette: settings.palette }) }),
|
|
3226
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "pi", textColor: "neutral600", children: t.templates[template] })
|
|
2366
3227
|
] }, template)) }),
|
|
2367
|
-
/* @__PURE__ */
|
|
3228
|
+
/* @__PURE__ */ jsx6(Flex4, { children: /* @__PURE__ */ jsx6(Button4, { variant: "tertiary", size: "S", disabled: !canUpdate, onClick: () => update((s) => {
|
|
2368
3229
|
s.palette = { ...DEFAULT_PALETTE };
|
|
2369
3230
|
return s;
|
|
2370
3231
|
}), children: t.resetPalette }) })
|
|
2371
3232
|
] }) }),
|
|
2372
|
-
/* @__PURE__ */
|
|
2373
|
-
/* @__PURE__ */
|
|
2374
|
-
/* @__PURE__ */
|
|
3233
|
+
/* @__PURE__ */ jsx6(Box3, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs5(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
3234
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "beta", tag: "h2", children: t.editor }),
|
|
3235
|
+
/* @__PURE__ */ jsx6(ToggleField2, { name: "editor-enabled", label: t.enabled, value: editor.enabled, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
|
|
2375
3236
|
s.editor.enabled = v;
|
|
2376
3237
|
return s;
|
|
2377
3238
|
}) }),
|
|
2378
|
-
/* @__PURE__ */
|
|
2379
|
-
/* @__PURE__ */
|
|
3239
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "pi", textColor: "neutral600", children: t.enabledHelp }),
|
|
3240
|
+
/* @__PURE__ */ jsx6(ToggleField2, { name: "editor-showOpenAll", label: t.showOpenAll, value: editor.showOpenAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
|
|
2380
3241
|
s.editor.showOpenAll = v;
|
|
2381
3242
|
return s;
|
|
2382
3243
|
}) }),
|
|
2383
|
-
/* @__PURE__ */
|
|
3244
|
+
/* @__PURE__ */ jsx6(ToggleField2, { name: "editor-showCloseAll", label: t.showCloseAll, value: editor.showCloseAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
|
|
2384
3245
|
s.editor.showCloseAll = v;
|
|
2385
3246
|
return s;
|
|
2386
3247
|
}) }),
|
|
2387
|
-
/* @__PURE__ */
|
|
3248
|
+
/* @__PURE__ */ jsx6(
|
|
2388
3249
|
SelectField2,
|
|
2389
3250
|
{
|
|
2390
3251
|
name: "editor-initialState",
|
|
@@ -2398,9 +3259,9 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
2398
3259
|
})
|
|
2399
3260
|
}
|
|
2400
3261
|
),
|
|
2401
|
-
/* @__PURE__ */
|
|
2402
|
-
previewSupported ? /* @__PURE__ */
|
|
2403
|
-
/* @__PURE__ */
|
|
3262
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "pi", textColor: "neutral600", children: t.rememberHelp }),
|
|
3263
|
+
previewSupported ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
3264
|
+
/* @__PURE__ */ jsx6(
|
|
2404
3265
|
TextField2,
|
|
2405
3266
|
{
|
|
2406
3267
|
name: "editor-previewUrl",
|
|
@@ -2414,8 +3275,8 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
2414
3275
|
})
|
|
2415
3276
|
}
|
|
2416
3277
|
),
|
|
2417
|
-
/* @__PURE__ */
|
|
2418
|
-
/* @__PURE__ */
|
|
3278
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "pi", textColor: "neutral600", children: t.previewUrlHelp }),
|
|
3279
|
+
/* @__PURE__ */ jsx6(
|
|
2419
3280
|
SelectField2,
|
|
2420
3281
|
{
|
|
2421
3282
|
name: "editor-previewMode",
|
|
@@ -2429,26 +3290,26 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
2429
3290
|
})
|
|
2430
3291
|
}
|
|
2431
3292
|
),
|
|
2432
|
-
/* @__PURE__ */
|
|
2433
|
-
data.blockPreviewAvailable && /* @__PURE__ */
|
|
2434
|
-
/* @__PURE__ */
|
|
3293
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "pi", textColor: "neutral600", children: t.previewModeHelp }),
|
|
3294
|
+
data.blockPreviewAvailable && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
3295
|
+
/* @__PURE__ */ jsx6(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
|
|
2435
3296
|
s.editor.blockPreviewInForm = v;
|
|
2436
3297
|
return s;
|
|
2437
3298
|
}) }),
|
|
2438
|
-
/* @__PURE__ */
|
|
3299
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
|
|
2439
3300
|
] })
|
|
2440
|
-
] }) : /* @__PURE__ */
|
|
3301
|
+
] }) : /* @__PURE__ */ jsx6(Typography4, { variant: "pi", textColor: "neutral600", children: t.previewV4 })
|
|
2441
3302
|
] }) }),
|
|
2442
|
-
/* @__PURE__ */
|
|
2443
|
-
/* @__PURE__ */
|
|
2444
|
-
/* @__PURE__ */
|
|
2445
|
-
/* @__PURE__ */
|
|
2446
|
-
/* @__PURE__ */
|
|
3303
|
+
/* @__PURE__ */ jsx6(Box3, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs5(Flex4, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
3304
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "beta", tag: "h2", children: t.components }),
|
|
3305
|
+
/* @__PURE__ */ jsx6(Searchbar2, { name: "component-filter", value: filter, placeholder: t.filter, clearLabel: t.clear, onClear: () => setFilter(""), onChange: (e) => setFilter(e.target.value), children: t.filter }),
|
|
3306
|
+
/* @__PURE__ */ jsx6(Typography4, { variant: "pi", textColor: "neutral600", "data-testid": "components-count", children: t.f("countAll", { count: components.length }) }),
|
|
3307
|
+
/* @__PURE__ */ jsx6(Grid, { "data-testid": "components-grid", children: components.map((component) => {
|
|
2447
3308
|
const entry = settings.components[component.uid] || {};
|
|
2448
3309
|
const meta = { ...catalog.components?.[component.uid] || {}, ...media[component.uid] || {} };
|
|
2449
3310
|
const candidates = candidatesFor(component.uid, meta, catalog);
|
|
2450
|
-
return /* @__PURE__ */
|
|
2451
|
-
/* @__PURE__ */
|
|
3311
|
+
return /* @__PURE__ */ jsxs5(Card2, { "data-testid": `settings-${component.uid}`, children: [
|
|
3312
|
+
/* @__PURE__ */ jsx6(
|
|
2452
3313
|
Thumb,
|
|
2453
3314
|
{
|
|
2454
3315
|
candidates,
|
|
@@ -2459,23 +3320,23 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
2459
3320
|
onResolved: (index) => setSources((current) => current[component.uid] === index ? current : { ...current, [component.uid]: index })
|
|
2460
3321
|
}
|
|
2461
3322
|
),
|
|
2462
|
-
/* @__PURE__ */
|
|
2463
|
-
/* @__PURE__ */
|
|
2464
|
-
/* @__PURE__ */
|
|
3323
|
+
/* @__PURE__ */ jsxs5(Flex4, { direction: "column", alignItems: "flex-start", gap: 2, children: [
|
|
3324
|
+
/* @__PURE__ */ jsx6(Typography4, { fontWeight: "bold", textColor: "neutral800", children: component.displayName }),
|
|
3325
|
+
/* @__PURE__ */ jsxs5(Typography4, { variant: "pi", textColor: "neutral600", children: [
|
|
2465
3326
|
component.uid,
|
|
2466
3327
|
" \xB7 ",
|
|
2467
3328
|
component.category
|
|
2468
3329
|
] }),
|
|
2469
|
-
/* @__PURE__ */
|
|
3330
|
+
/* @__PURE__ */ jsxs5(Typography4, { variant: "pi", "data-testid": `source-${component.uid}`, children: [
|
|
2470
3331
|
t.source,
|
|
2471
3332
|
": ",
|
|
2472
3333
|
sourceOf(component.uid, Boolean(meta.manualImage)),
|
|
2473
3334
|
meta.manualName ? ` (${meta.manualName})` : ""
|
|
2474
3335
|
] }),
|
|
2475
|
-
meta.manualMissing && /* @__PURE__ */
|
|
2476
|
-
/* @__PURE__ */
|
|
2477
|
-
/* @__PURE__ */
|
|
2478
|
-
entry.mediaId && /* @__PURE__ */
|
|
3336
|
+
meta.manualMissing && /* @__PURE__ */ jsx6(Typography4, { variant: "pi", role: "alert", textColor: "danger600", children: t.brokenMedia }),
|
|
3337
|
+
/* @__PURE__ */ jsxs5(Flex4, { gap: 2, wrap: "wrap", children: [
|
|
3338
|
+
/* @__PURE__ */ jsx6(Button4, { variant: "secondary", size: "S", disabled: !canUpdate || saving, onClick: () => setPicking(component.uid), children: entry.mediaId ? t.replace : t.choose }),
|
|
3339
|
+
entry.mediaId && /* @__PURE__ */ jsx6(Button4, { variant: "tertiary", size: "S", disabled: !canUpdate || saving, onClick: () => {
|
|
2479
3340
|
update((s) => {
|
|
2480
3341
|
delete s.components[component.uid]?.mediaId;
|
|
2481
3342
|
if (!Object.keys(s.components[component.uid] || {}).length) delete s.components[component.uid];
|
|
@@ -2488,7 +3349,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
2488
3349
|
});
|
|
2489
3350
|
}, children: t.useAutomatic })
|
|
2490
3351
|
] }),
|
|
2491
|
-
/* @__PURE__ */
|
|
3352
|
+
/* @__PURE__ */ jsx6(
|
|
2492
3353
|
SelectField2,
|
|
2493
3354
|
{
|
|
2494
3355
|
name: `template-${component.uid}`,
|
|
@@ -2506,7 +3367,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
2506
3367
|
] }, component.uid);
|
|
2507
3368
|
}) })
|
|
2508
3369
|
] }) }),
|
|
2509
|
-
picking && /* @__PURE__ */
|
|
3370
|
+
picking && /* @__PURE__ */ jsx6(MediaPicker2, { onClose: () => setPicking(null), onSelect: (asset) => {
|
|
2510
3371
|
const uid = picking;
|
|
2511
3372
|
setPicking(null);
|
|
2512
3373
|
if (!asset?.id) return;
|
|
@@ -2535,10 +3396,10 @@ function register(app, Component, to) {
|
|
|
2535
3396
|
}
|
|
2536
3397
|
|
|
2537
3398
|
// admin/catalog.ts
|
|
2538
|
-
import * as
|
|
3399
|
+
import * as React6 from "react";
|
|
2539
3400
|
function useCatalog(get) {
|
|
2540
|
-
const [catalog, setCatalog] =
|
|
2541
|
-
|
|
3401
|
+
const [catalog, setCatalog] = React6.useState(null);
|
|
3402
|
+
React6.useEffect(() => {
|
|
2542
3403
|
let active = true;
|
|
2543
3404
|
get("/blockscene/catalog").then(({ data }) => {
|
|
2544
3405
|
if (active) setCatalog(data);
|
|
@@ -2553,13 +3414,13 @@ function useCatalog(get) {
|
|
|
2553
3414
|
}
|
|
2554
3415
|
|
|
2555
3416
|
// admin/strapi5.tsx
|
|
2556
|
-
import { jsx as
|
|
3417
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2557
3418
|
function Modal2({ open, onOpenChange, trigger, title, children }) {
|
|
2558
|
-
return /* @__PURE__ */
|
|
2559
|
-
/* @__PURE__ */
|
|
2560
|
-
/* @__PURE__ */
|
|
2561
|
-
/* @__PURE__ */
|
|
2562
|
-
/* @__PURE__ */
|
|
3419
|
+
return /* @__PURE__ */ jsxs6(Dialog.Root, { open, onOpenChange, children: [
|
|
3420
|
+
trigger && /* @__PURE__ */ jsx7(Dialog.Trigger, { children: trigger }),
|
|
3421
|
+
/* @__PURE__ */ jsxs6(Dialog.Content, { style: { width: "80vw", maxWidth: "80vw" }, children: [
|
|
3422
|
+
/* @__PURE__ */ jsx7(Dialog.Header, { children: /* @__PURE__ */ jsx7(Dialog.Title, { children: title }) }),
|
|
3423
|
+
/* @__PURE__ */ jsx7(Dialog.Body, { children })
|
|
2563
3424
|
] })
|
|
2564
3425
|
] });
|
|
2565
3426
|
}
|
|
@@ -2579,49 +3440,154 @@ function Panel() {
|
|
|
2579
3440
|
formValues ?? c.form?.values,
|
|
2580
3441
|
(name) => allowed.includes(name) && (creating || (rbac.canReadFields || []).includes(name)) && fields.find((field) => field.name === name)?.disabled !== true,
|
|
2581
3442
|
c.isLoading || c.form?.disabled || !c.form?.addFieldRow
|
|
2582
|
-
).map((zone) => ({
|
|
3443
|
+
).map((zone) => ({
|
|
3444
|
+
...zone,
|
|
3445
|
+
label: fields.find((field) => field.name === zone.name)?.label || zone.name
|
|
3446
|
+
}));
|
|
2583
3447
|
const add = (zone, uid) => {
|
|
2584
3448
|
const values = formValues ?? c.form.values;
|
|
2585
3449
|
const close = catalog?.groups?.[uid];
|
|
2586
|
-
if (c.form.disabled || !canInsert(zone, uid, values, c.components, close ? 2 : 1) || close && !zone.components.includes(close))
|
|
3450
|
+
if (c.form.disabled || !canInsert(zone, uid, values, c.components, close ? 2 : 1) || close && !zone.components.includes(close))
|
|
3451
|
+
return false;
|
|
2587
3452
|
const at = Array.isArray(values?.[zone.name]) ? values[zone.name].length : 0;
|
|
2588
|
-
c.form.addFieldRow(
|
|
3453
|
+
c.form.addFieldRow(
|
|
3454
|
+
zone.name,
|
|
3455
|
+
{
|
|
3456
|
+
...componentDefaults(c.components[uid], c.components),
|
|
3457
|
+
__component: uid
|
|
3458
|
+
},
|
|
3459
|
+
at
|
|
3460
|
+
);
|
|
2589
3461
|
if (close) c.form.addFieldRow(zone.name, { __component: close }, at + 1);
|
|
2590
3462
|
return true;
|
|
2591
3463
|
};
|
|
2592
3464
|
if (!zones.length || !catalog?.editor?.enabled) return null;
|
|
2593
3465
|
const docKey = `${c.model}:${creating ? "new" : c.id}:${c.form?.initialValues?.locale || ""}`;
|
|
2594
|
-
return {
|
|
2595
|
-
|
|
2596
|
-
/* @__PURE__ */
|
|
2597
|
-
|
|
3466
|
+
return {
|
|
3467
|
+
title: t.gallery,
|
|
3468
|
+
content: /* @__PURE__ */ jsxs6(Flex5, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
3469
|
+
/* @__PURE__ */ jsx7(
|
|
3470
|
+
Gallery,
|
|
3471
|
+
{
|
|
3472
|
+
zones,
|
|
3473
|
+
components: c.components,
|
|
3474
|
+
add,
|
|
3475
|
+
Modal: Modal2,
|
|
3476
|
+
Toggle: ToggleField,
|
|
3477
|
+
get,
|
|
3478
|
+
editor: catalog.editor,
|
|
3479
|
+
catalog,
|
|
3480
|
+
docKey,
|
|
3481
|
+
contentType: c.model,
|
|
3482
|
+
userId: user?.id
|
|
3483
|
+
}
|
|
3484
|
+
),
|
|
3485
|
+
/* @__PURE__ */ jsx7(
|
|
3486
|
+
PagePreview,
|
|
3487
|
+
{
|
|
3488
|
+
editor: catalog.editor,
|
|
3489
|
+
groups: catalog.groups || null,
|
|
3490
|
+
Modal: Modal2,
|
|
3491
|
+
Toggle: ToggleField
|
|
3492
|
+
}
|
|
3493
|
+
)
|
|
3494
|
+
] })
|
|
3495
|
+
};
|
|
2598
3496
|
}
|
|
2599
|
-
var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */
|
|
2600
|
-
/* @__PURE__ */
|
|
2601
|
-
|
|
3497
|
+
var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ jsxs6(Flex5, { gap: 3, children: [
|
|
3498
|
+
/* @__PURE__ */ jsx7(
|
|
3499
|
+
Switch,
|
|
3500
|
+
{
|
|
3501
|
+
name,
|
|
3502
|
+
"aria-label": label,
|
|
3503
|
+
checked: Boolean(value),
|
|
3504
|
+
disabled,
|
|
3505
|
+
onCheckedChange: onChange
|
|
3506
|
+
}
|
|
3507
|
+
),
|
|
3508
|
+
/* @__PURE__ */ jsx7(Typography5, { children: label })
|
|
2602
3509
|
] });
|
|
2603
|
-
var TextField = ({
|
|
2604
|
-
|
|
2605
|
-
|
|
3510
|
+
var TextField = ({
|
|
3511
|
+
name,
|
|
3512
|
+
label,
|
|
3513
|
+
value,
|
|
3514
|
+
onChange,
|
|
3515
|
+
disabled,
|
|
3516
|
+
placeholder
|
|
3517
|
+
}) => /* @__PURE__ */ jsxs6(Field.Root, { name, children: [
|
|
3518
|
+
/* @__PURE__ */ jsx7(Field.Label, { children: label }),
|
|
3519
|
+
/* @__PURE__ */ jsx7(
|
|
3520
|
+
TextInput,
|
|
3521
|
+
{
|
|
3522
|
+
name,
|
|
3523
|
+
value,
|
|
3524
|
+
disabled,
|
|
3525
|
+
placeholder,
|
|
3526
|
+
onChange: (e) => onChange(e.target.value)
|
|
3527
|
+
}
|
|
3528
|
+
)
|
|
2606
3529
|
] });
|
|
2607
|
-
var SelectField = ({
|
|
2608
|
-
|
|
2609
|
-
|
|
3530
|
+
var SelectField = ({
|
|
3531
|
+
name,
|
|
3532
|
+
label,
|
|
3533
|
+
value,
|
|
3534
|
+
onChange,
|
|
3535
|
+
disabled,
|
|
3536
|
+
options
|
|
3537
|
+
}) => /* @__PURE__ */ jsxs6(Field.Root, { name, children: [
|
|
3538
|
+
/* @__PURE__ */ jsx7(Field.Label, { children: label }),
|
|
3539
|
+
/* @__PURE__ */ jsx7(
|
|
3540
|
+
SingleSelect2,
|
|
3541
|
+
{
|
|
3542
|
+
value,
|
|
3543
|
+
disabled,
|
|
3544
|
+
onChange: (v) => onChange(String(v)),
|
|
3545
|
+
children: options.map((o) => /* @__PURE__ */ jsx7(SingleSelectOption2, { value: o.value, children: o.label }, o.value))
|
|
3546
|
+
}
|
|
3547
|
+
)
|
|
2610
3548
|
] });
|
|
2611
3549
|
function MediaPicker({ onClose, onSelect }) {
|
|
2612
|
-
const components = useStrapiApp3(
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
3550
|
+
const components = useStrapiApp3(
|
|
3551
|
+
"Blockscene",
|
|
3552
|
+
(state) => state.components
|
|
3553
|
+
);
|
|
3554
|
+
const Dialog2 = components?.["media-library"];
|
|
3555
|
+
React7.useEffect(() => {
|
|
3556
|
+
if (!Dialog2) onClose();
|
|
3557
|
+
}, [Dialog2, onClose]);
|
|
3558
|
+
if (!Dialog2) return null;
|
|
3559
|
+
return /* @__PURE__ */ jsx7(
|
|
3560
|
+
Dialog2,
|
|
3561
|
+
{
|
|
3562
|
+
onClose,
|
|
3563
|
+
allowedTypes: ["images"],
|
|
3564
|
+
multiple: false,
|
|
3565
|
+
onSelectAssets: (assets) => onSelect(assets?.[0])
|
|
3566
|
+
}
|
|
3567
|
+
);
|
|
2619
3568
|
}
|
|
2620
3569
|
function usePermissions() {
|
|
2621
|
-
const { allowedActions, isLoading } = useRBAC(
|
|
2622
|
-
|
|
3570
|
+
const { allowedActions, isLoading } = useRBAC(
|
|
3571
|
+
Object.values(permissions).flat()
|
|
3572
|
+
);
|
|
3573
|
+
return {
|
|
3574
|
+
canRead: allowedActions.canRead,
|
|
3575
|
+
canUpdate: allowedActions.canUpdate,
|
|
3576
|
+
isLoading
|
|
3577
|
+
};
|
|
2623
3578
|
}
|
|
2624
|
-
var SettingsPage = () => /* @__PURE__ */
|
|
3579
|
+
var SettingsPage = () => /* @__PURE__ */ jsx7(
|
|
3580
|
+
Settings,
|
|
3581
|
+
{
|
|
3582
|
+
useClient: useFetchClient2,
|
|
3583
|
+
usePermissions,
|
|
3584
|
+
MediaPicker,
|
|
3585
|
+
ToggleField,
|
|
3586
|
+
SelectField,
|
|
3587
|
+
TextField,
|
|
3588
|
+
previewSupported: true
|
|
3589
|
+
}
|
|
3590
|
+
);
|
|
2625
3591
|
var strapi5_default = {
|
|
2626
3592
|
register(app) {
|
|
2627
3593
|
register(app, SettingsPage, "blockscene");
|