@aduptive/strapi-blockscene 1.0.0-alpha.3 → 1.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 +765 -206
- package/dist/admin.mjs +789 -207
- package/package.json +1 -1
package/dist/admin.mjs
CHANGED
|
@@ -1,39 +1,93 @@
|
|
|
1
1
|
// admin/strapi4.tsx
|
|
2
|
-
import * as
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import * as React5 from "react";
|
|
3
|
+
import {
|
|
4
|
+
ModalLayout,
|
|
5
|
+
ModalHeader,
|
|
6
|
+
ModalBody,
|
|
7
|
+
Typography as Typography3,
|
|
8
|
+
Switch,
|
|
9
|
+
Flex as Flex3,
|
|
10
|
+
SingleSelect as SingleSelect2,
|
|
11
|
+
SingleSelectOption as SingleSelectOption2
|
|
12
|
+
} from "@strapi/design-system";
|
|
13
|
+
import {
|
|
14
|
+
useCMEditViewDataManager,
|
|
15
|
+
useFetchClient,
|
|
16
|
+
useLibrary,
|
|
17
|
+
useRBAC,
|
|
18
|
+
auth
|
|
19
|
+
} from "@strapi/helper-plugin";
|
|
5
20
|
|
|
6
21
|
// admin/Gallery.tsx
|
|
7
|
-
import * as
|
|
22
|
+
import * as React2 from "react";
|
|
8
23
|
import { unstable_batchedUpdates } from "react-dom";
|
|
9
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
Box,
|
|
26
|
+
Button,
|
|
27
|
+
Flex,
|
|
28
|
+
Searchbar,
|
|
29
|
+
SingleSelect,
|
|
30
|
+
SingleSelectOption,
|
|
31
|
+
Typography
|
|
32
|
+
} from "@strapi/design-system";
|
|
10
33
|
import styled from "styled-components";
|
|
11
34
|
|
|
12
35
|
// admin/model.mjs
|
|
13
36
|
import { generateNKeysBetween } from "fractional-indexing";
|
|
14
37
|
function editableZones(schema, values, canEdit, disabled = false) {
|
|
15
38
|
if (disabled) return [];
|
|
16
|
-
return Object.entries(schema?.attributes || {}).filter(
|
|
17
|
-
|
|
18
|
-
|
|
39
|
+
return Object.entries(schema?.attributes || {}).filter(
|
|
40
|
+
([name, attr]) => attr.type === "dynamiczone" && !attr.conditions && canEdit(name)
|
|
41
|
+
).map(([name, attr]) => {
|
|
42
|
+
const rows = Array.isArray(values?.[name]) ? values[name] : [];
|
|
43
|
+
return {
|
|
44
|
+
name,
|
|
45
|
+
components: attr.components || [],
|
|
46
|
+
max: attr.max,
|
|
47
|
+
count: rows.length,
|
|
48
|
+
uids: rows.map(
|
|
49
|
+
(row) => row && typeof row.__component === "string" ? row.__component : ""
|
|
50
|
+
),
|
|
51
|
+
full: rows.length >= (attr.max ?? Infinity)
|
|
52
|
+
};
|
|
19
53
|
});
|
|
20
54
|
}
|
|
21
55
|
function canInsert(zone, uid, values, components, count = 1) {
|
|
22
|
-
return Boolean(
|
|
56
|
+
return Boolean(
|
|
57
|
+
zone?.components.includes(uid) && components[uid] && (Array.isArray(values?.[zone.name]) ? values[zone.name].length : 0) + count <= (zone.max ?? Infinity)
|
|
58
|
+
);
|
|
23
59
|
}
|
|
24
60
|
function candidatesFor(uid, meta = {}, config = {}) {
|
|
25
61
|
const version = config.previewVersion ? `?v=${encodeURIComponent(config.previewVersion)}` : "";
|
|
26
62
|
const base = (config.previewBaseUrl || "/block-previews").replace(/\/$/, "");
|
|
27
|
-
return [
|
|
63
|
+
return [
|
|
64
|
+
meta.manualImage,
|
|
65
|
+
meta.image,
|
|
66
|
+
`${base}/${encodeURIComponent(uid)}.webp${version}`
|
|
67
|
+
].filter(Boolean);
|
|
28
68
|
}
|
|
29
|
-
var SYSTEM_FIELDS = [
|
|
69
|
+
var SYSTEM_FIELDS = [
|
|
70
|
+
"id",
|
|
71
|
+
"documentId",
|
|
72
|
+
"createdAt",
|
|
73
|
+
"updatedAt",
|
|
74
|
+
"publishedAt",
|
|
75
|
+
"createdBy",
|
|
76
|
+
"updatedBy",
|
|
77
|
+
"locale",
|
|
78
|
+
"localizations"
|
|
79
|
+
];
|
|
30
80
|
var fieldType = (attr) => attr?.type === "customField" ? String(attr.customField || "").includes("CKEditor") ? "richtext" : "customField" : attr?.type || "unknown";
|
|
31
81
|
var fieldsOf = (schema) => Object.entries(schema?.attributes || {}).filter(([name]) => !SYSTEM_FIELDS.includes(name)).map(([name, attr]) => ({ name, type: fieldType(attr) }));
|
|
32
82
|
var categoryOf = (uid, schema, meta = {}) => meta.category || schema?.category || uid.split(".")[0];
|
|
33
83
|
var byCategory = (a, b) => (a === "admin" ? 1 : 0) - (b === "admin" ? 1 : 0) || a.localeCompare(b);
|
|
84
|
+
var pickable = (zone, config) => {
|
|
85
|
+
const closers = Object.values(config.groups || {});
|
|
86
|
+
return zone.components.filter((uid) => !closers.includes(uid));
|
|
87
|
+
};
|
|
34
88
|
function entriesFor(zone, components, config, query, category = "all") {
|
|
35
89
|
const needle = query.trim().toLocaleLowerCase();
|
|
36
|
-
return zone.
|
|
90
|
+
return pickable(zone, config).flatMap((uid) => {
|
|
37
91
|
const schema = components[uid];
|
|
38
92
|
if (!schema) return [];
|
|
39
93
|
const meta = config.components?.[uid] || {};
|
|
@@ -48,11 +102,13 @@ function entriesFor(zone, components, config, query, category = "all") {
|
|
|
48
102
|
};
|
|
49
103
|
if (category !== "all" && entry.category !== category) return [];
|
|
50
104
|
return `${entry.label} ${entry.description} ${entry.category} ${uid} ${meta.keywords || ""}`.toLocaleLowerCase().includes(needle) ? [entry] : [];
|
|
51
|
-
}).sort(
|
|
105
|
+
}).sort(
|
|
106
|
+
(a, b) => byCategory(a.category, b.category) || a.label.localeCompare(b.label)
|
|
107
|
+
);
|
|
52
108
|
}
|
|
53
109
|
function categoriesFor(zone, components, config) {
|
|
54
110
|
const counts = /* @__PURE__ */ new Map();
|
|
55
|
-
for (const uid of zone
|
|
111
|
+
for (const uid of pickable(zone, config)) {
|
|
56
112
|
const schema = components[uid];
|
|
57
113
|
if (!schema) continue;
|
|
58
114
|
const c = categoryOf(uid, schema, config.components?.[uid] || {});
|
|
@@ -62,8 +118,12 @@ function categoriesFor(zone, components, config) {
|
|
|
62
118
|
}
|
|
63
119
|
function groupEntries(entries) {
|
|
64
120
|
const map = /* @__PURE__ */ new Map();
|
|
65
|
-
for (const entry of entries)
|
|
66
|
-
|
|
121
|
+
for (const entry of entries)
|
|
122
|
+
map.set(entry.category, [...map.get(entry.category) || [], entry]);
|
|
123
|
+
return [...map.entries()].map(([category, items]) => ({
|
|
124
|
+
category,
|
|
125
|
+
entries: items
|
|
126
|
+
}));
|
|
67
127
|
}
|
|
68
128
|
function memoryKey({ base = "", userId, contentType, zone }) {
|
|
69
129
|
if (!userId || !contentType || !zone) return null;
|
|
@@ -79,7 +139,8 @@ function readMemory(storage2, key) {
|
|
|
79
139
|
}
|
|
80
140
|
function writeMemory(storage2, key, value) {
|
|
81
141
|
try {
|
|
82
|
-
if (key && (value === "open" || value === "closed"))
|
|
142
|
+
if (key && (value === "open" || value === "closed"))
|
|
143
|
+
storage2?.setItem(key, value);
|
|
83
144
|
} catch {
|
|
84
145
|
}
|
|
85
146
|
}
|
|
@@ -165,6 +226,10 @@ function Wireframe({ template, palette, className, noPreview }) {
|
|
|
165
226
|
);
|
|
166
227
|
}
|
|
167
228
|
|
|
229
|
+
// admin/RowPreviews.tsx
|
|
230
|
+
import * as React from "react";
|
|
231
|
+
import { createPortal } from "react-dom";
|
|
232
|
+
|
|
168
233
|
// admin/messages.ts
|
|
169
234
|
import { useIntl } from "react-intl";
|
|
170
235
|
|
|
@@ -279,7 +344,8 @@ var en_default = {
|
|
|
279
344
|
columns: "Columns",
|
|
280
345
|
noPreview: "no preview",
|
|
281
346
|
"templates.none": "No preview",
|
|
282
|
-
noChanges: "No unsaved changes"
|
|
347
|
+
noChanges: "No unsaved changes",
|
|
348
|
+
rowPreview: "Open the {label} preview"
|
|
283
349
|
};
|
|
284
350
|
|
|
285
351
|
// admin/translations/pt-BR.json
|
|
@@ -393,7 +459,8 @@ var pt_BR_default = {
|
|
|
393
459
|
columns: "Colunas",
|
|
394
460
|
noPreview: "sem preview",
|
|
395
461
|
"templates.none": "Sem preview",
|
|
396
|
-
noChanges: "Sem altera\xE7\xF5es pendentes"
|
|
462
|
+
noChanges: "Sem altera\xE7\xF5es pendentes",
|
|
463
|
+
rowPreview: "Abrir a pr\xE9via de {label}"
|
|
397
464
|
};
|
|
398
465
|
|
|
399
466
|
// admin/translations/pt.json
|
|
@@ -507,7 +574,8 @@ var pt_default = {
|
|
|
507
574
|
columns: "Colunas",
|
|
508
575
|
noPreview: "sem pr\xE9-visualiza\xE7\xE3o",
|
|
509
576
|
"templates.none": "Sem pr\xE9-visualiza\xE7\xE3o",
|
|
510
|
-
noChanges: "Sem altera\xE7\xF5es pendentes"
|
|
577
|
+
noChanges: "Sem altera\xE7\xF5es pendentes",
|
|
578
|
+
rowPreview: "Abrir a pr\xE9-visualiza\xE7\xE3o de {label}"
|
|
511
579
|
};
|
|
512
580
|
|
|
513
581
|
// admin/translations/fr.json
|
|
@@ -621,7 +689,8 @@ var fr_default = {
|
|
|
621
689
|
columns: "Colonnes",
|
|
622
690
|
noPreview: "pas d\u2019aper\xE7u",
|
|
623
691
|
"templates.none": "Pas d\u2019aper\xE7u",
|
|
624
|
-
noChanges: "Aucune modification en attente"
|
|
692
|
+
noChanges: "Aucune modification en attente",
|
|
693
|
+
rowPreview: "Ouvrir l\u2019aper\xE7u de {label}"
|
|
625
694
|
};
|
|
626
695
|
|
|
627
696
|
// admin/translations/es.json
|
|
@@ -735,7 +804,8 @@ var es_default = {
|
|
|
735
804
|
columns: "Columnas",
|
|
736
805
|
noPreview: "sin vista previa",
|
|
737
806
|
"templates.none": "Sin vista previa",
|
|
738
|
-
noChanges: "Sin cambios pendientes"
|
|
807
|
+
noChanges: "Sin cambios pendientes",
|
|
808
|
+
rowPreview: "Abrir la vista previa de {label}"
|
|
739
809
|
};
|
|
740
810
|
|
|
741
811
|
// admin/translations/de.json
|
|
@@ -849,7 +919,8 @@ var de_default = {
|
|
|
849
919
|
columns: "Spalten",
|
|
850
920
|
noPreview: "keine Vorschau",
|
|
851
921
|
"templates.none": "Keine Vorschau",
|
|
852
|
-
noChanges: "Keine ungespeicherten \xC4nderungen"
|
|
922
|
+
noChanges: "Keine ungespeicherten \xC4nderungen",
|
|
923
|
+
rowPreview: "Vorschau von {label} \xF6ffnen"
|
|
853
924
|
};
|
|
854
925
|
|
|
855
926
|
// admin/translations/it.json
|
|
@@ -963,7 +1034,8 @@ var it_default = {
|
|
|
963
1034
|
columns: "Colonne",
|
|
964
1035
|
noPreview: "nessuna anteprima",
|
|
965
1036
|
"templates.none": "Nessuna anteprima",
|
|
966
|
-
noChanges: "Nessuna modifica in sospeso"
|
|
1037
|
+
noChanges: "Nessuna modifica in sospeso",
|
|
1038
|
+
rowPreview: "Apri l\u2019anteprima di {label}"
|
|
967
1039
|
};
|
|
968
1040
|
|
|
969
1041
|
// admin/translations/nl.json
|
|
@@ -1077,7 +1149,8 @@ var nl_default = {
|
|
|
1077
1149
|
columns: "Kolommen",
|
|
1078
1150
|
noPreview: "geen voorbeeld",
|
|
1079
1151
|
"templates.none": "Geen voorbeeld",
|
|
1080
|
-
noChanges: "Geen niet-opgeslagen wijzigingen"
|
|
1152
|
+
noChanges: "Geen niet-opgeslagen wijzigingen",
|
|
1153
|
+
rowPreview: "Voorbeeld van {label} openen"
|
|
1081
1154
|
};
|
|
1082
1155
|
|
|
1083
1156
|
// admin/messages.ts
|
|
@@ -1097,26 +1170,224 @@ function useMessages() {
|
|
|
1097
1170
|
return out;
|
|
1098
1171
|
}
|
|
1099
1172
|
|
|
1173
|
+
// admin/RowPreviews.tsx
|
|
1174
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
1175
|
+
var ATTR = "data-blockscene-row-thumb";
|
|
1176
|
+
function useAnchors(zones, onOpen) {
|
|
1177
|
+
const [anchors, setAnchors] = React.useState([]);
|
|
1178
|
+
const open = React.useRef(onOpen);
|
|
1179
|
+
open.current = onOpen;
|
|
1180
|
+
const latest = React.useRef(zones);
|
|
1181
|
+
latest.current = zones;
|
|
1182
|
+
const sync = React.useRef(() => {
|
|
1183
|
+
});
|
|
1184
|
+
sync.current = () => {
|
|
1185
|
+
const next = [];
|
|
1186
|
+
for (const zone of latest.current) {
|
|
1187
|
+
const list = zone.uids?.length ? findZoneList(zone.label) : null;
|
|
1188
|
+
if (!list) continue;
|
|
1189
|
+
toggles(list).forEach((button, index) => {
|
|
1190
|
+
const uid = zone.uids[index];
|
|
1191
|
+
if (!uid) return;
|
|
1192
|
+
let el = button.querySelector(
|
|
1193
|
+
`:scope > [${ATTR}]`
|
|
1194
|
+
);
|
|
1195
|
+
if (!el) {
|
|
1196
|
+
el = document.createElement("span");
|
|
1197
|
+
el.setAttribute(ATTR, "");
|
|
1198
|
+
el.style.cssText = "display:inline-flex;align-items:center";
|
|
1199
|
+
const activate = (event) => {
|
|
1200
|
+
if (!event.currentTarget.getAttribute("role"))
|
|
1201
|
+
return;
|
|
1202
|
+
event.preventDefault();
|
|
1203
|
+
event.stopPropagation();
|
|
1204
|
+
open.current(
|
|
1205
|
+
String(event.currentTarget.dataset.uid || "")
|
|
1206
|
+
);
|
|
1207
|
+
};
|
|
1208
|
+
el.addEventListener("click", activate, true);
|
|
1209
|
+
el.addEventListener(
|
|
1210
|
+
"keydown",
|
|
1211
|
+
(event) => {
|
|
1212
|
+
if (event.key === "Enter" || event.key === " ") activate(event);
|
|
1213
|
+
},
|
|
1214
|
+
true
|
|
1215
|
+
);
|
|
1216
|
+
button.insertBefore(el, button.firstChild);
|
|
1217
|
+
}
|
|
1218
|
+
el.dataset.uid = uid;
|
|
1219
|
+
next.push({ el, uid, zone: zone.name, index });
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
for (const el of document.querySelectorAll(`[${ATTR}]`))
|
|
1223
|
+
if (!next.some((a) => a.el === el)) el.remove();
|
|
1224
|
+
setAnchors(
|
|
1225
|
+
(prev) => prev.length === next.length && prev.every((a, i) => a.el === next[i].el && a.uid === next[i].uid) ? prev : next
|
|
1226
|
+
);
|
|
1227
|
+
};
|
|
1228
|
+
React.useEffect(() => {
|
|
1229
|
+
sync.current();
|
|
1230
|
+
});
|
|
1231
|
+
React.useEffect(() => {
|
|
1232
|
+
let frame = 0;
|
|
1233
|
+
const observer = new MutationObserver(() => {
|
|
1234
|
+
if (frame) return;
|
|
1235
|
+
frame = requestAnimationFrame(() => {
|
|
1236
|
+
frame = 0;
|
|
1237
|
+
sync.current();
|
|
1238
|
+
});
|
|
1239
|
+
});
|
|
1240
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
1241
|
+
return () => {
|
|
1242
|
+
observer.disconnect();
|
|
1243
|
+
cancelAnimationFrame(frame);
|
|
1244
|
+
for (const el of document.querySelectorAll(`[${ATTR}]`)) el.remove();
|
|
1245
|
+
};
|
|
1246
|
+
}, []);
|
|
1247
|
+
return anchors;
|
|
1248
|
+
}
|
|
1249
|
+
function RowPreviews({ zones, components, catalog, Modal: Modal2 }) {
|
|
1250
|
+
const t = useMessages();
|
|
1251
|
+
const [resolved, setResolved] = React.useState({});
|
|
1252
|
+
const [open, setOpen] = React.useState(null);
|
|
1253
|
+
const anchors = useAnchors(zones, (uid) => setOpen(uid));
|
|
1254
|
+
const candidates = (uid) => candidatesFor(uid, catalog?.components?.[uid] || {}, catalog || {});
|
|
1255
|
+
const label = (uid) => catalog?.components?.[uid]?.label || components?.[uid]?.info?.displayName || uid;
|
|
1256
|
+
const srcOf = (uid) => candidates(uid)[resolved[uid] ?? -1] || "";
|
|
1257
|
+
React.useEffect(() => {
|
|
1258
|
+
for (const { el, uid } of anchors) {
|
|
1259
|
+
if (srcOf(uid)) {
|
|
1260
|
+
el.setAttribute("role", "button");
|
|
1261
|
+
el.setAttribute("tabindex", "0");
|
|
1262
|
+
el.setAttribute("aria-label", t.f("rowPreview", { label: label(uid) }));
|
|
1263
|
+
el.style.cursor = "zoom-in";
|
|
1264
|
+
} else
|
|
1265
|
+
for (const name of ["role", "tabindex", "aria-label"])
|
|
1266
|
+
el.removeAttribute(name);
|
|
1267
|
+
}
|
|
1268
|
+
});
|
|
1269
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1270
|
+
anchors.map(
|
|
1271
|
+
(a) => createPortal(
|
|
1272
|
+
/* @__PURE__ */ jsx2(
|
|
1273
|
+
"span",
|
|
1274
|
+
{
|
|
1275
|
+
style: {
|
|
1276
|
+
display: "block",
|
|
1277
|
+
width: "6.4rem",
|
|
1278
|
+
marginRight: "8px",
|
|
1279
|
+
flex: "0 0 auto"
|
|
1280
|
+
},
|
|
1281
|
+
children: /* @__PURE__ */ jsx2(
|
|
1282
|
+
Thumb,
|
|
1283
|
+
{
|
|
1284
|
+
candidates: candidates(a.uid),
|
|
1285
|
+
blank: true,
|
|
1286
|
+
onResolved: (index) => setResolved(
|
|
1287
|
+
(prev) => prev[a.uid] === index ? prev : { ...prev, [a.uid]: index }
|
|
1288
|
+
)
|
|
1289
|
+
}
|
|
1290
|
+
)
|
|
1291
|
+
}
|
|
1292
|
+
),
|
|
1293
|
+
a.el,
|
|
1294
|
+
`${a.zone}:${a.index}`
|
|
1295
|
+
)
|
|
1296
|
+
),
|
|
1297
|
+
open && srcOf(open) && /* @__PURE__ */ jsx2(
|
|
1298
|
+
Modal2,
|
|
1299
|
+
{
|
|
1300
|
+
open: true,
|
|
1301
|
+
onOpenChange: (value) => {
|
|
1302
|
+
if (!value) setOpen(null);
|
|
1303
|
+
},
|
|
1304
|
+
trigger: null,
|
|
1305
|
+
title: label(open),
|
|
1306
|
+
children: /* @__PURE__ */ jsx2(
|
|
1307
|
+
"img",
|
|
1308
|
+
{
|
|
1309
|
+
src: srcOf(open),
|
|
1310
|
+
alt: "",
|
|
1311
|
+
style: {
|
|
1312
|
+
display: "block",
|
|
1313
|
+
margin: "0 auto",
|
|
1314
|
+
maxWidth: "100%",
|
|
1315
|
+
maxHeight: "75vh",
|
|
1316
|
+
objectFit: "contain"
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
)
|
|
1320
|
+
}
|
|
1321
|
+
)
|
|
1322
|
+
] });
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1100
1325
|
// admin/Gallery.tsx
|
|
1101
|
-
import { jsx as
|
|
1326
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1102
1327
|
var Columns = styled.div`
|
|
1103
|
-
column-count: ${({ $columns }) => $columns};
|
|
1104
|
-
|
|
1328
|
+
column-count: ${({ $columns }) => $columns};
|
|
1329
|
+
column-gap: 12px;
|
|
1330
|
+
> * {
|
|
1331
|
+
break-inside: avoid;
|
|
1332
|
+
-webkit-column-break-inside: avoid;
|
|
1333
|
+
margin-bottom: 12px;
|
|
1334
|
+
}
|
|
1105
1335
|
`;
|
|
1106
1336
|
var Tile = styled.button`
|
|
1107
|
-
display: flex;
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1337
|
+
display: flex;
|
|
1338
|
+
flex-direction: column;
|
|
1339
|
+
gap: 8px;
|
|
1340
|
+
text-align: left;
|
|
1341
|
+
width: 100%;
|
|
1342
|
+
padding: 8px;
|
|
1343
|
+
border: 1px solid ${({ theme }) => theme.colors.neutral200};
|
|
1344
|
+
border-radius: 4px;
|
|
1345
|
+
background: ${({ theme }) => theme.colors.neutral0};
|
|
1346
|
+
cursor: pointer;
|
|
1347
|
+
&:hover {
|
|
1348
|
+
border-color: ${({ theme }) => theme.colors.primary600};
|
|
1349
|
+
}
|
|
1350
|
+
&:focus-visible {
|
|
1351
|
+
outline: 2px solid ${({ theme }) => theme.colors.primary600};
|
|
1352
|
+
outline-offset: 2px;
|
|
1353
|
+
}
|
|
1354
|
+
`;
|
|
1355
|
+
var Clamp = styled(Typography)`
|
|
1356
|
+
display: -webkit-box;
|
|
1357
|
+
-webkit-line-clamp: 2;
|
|
1358
|
+
-webkit-box-orient: vertical;
|
|
1359
|
+
overflow: hidden;
|
|
1112
1360
|
`;
|
|
1113
|
-
var Clamp = styled(Typography)` display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; `;
|
|
1114
1361
|
var Slider = styled.input`
|
|
1115
|
-
appearance: none;
|
|
1362
|
+
appearance: none;
|
|
1363
|
+
-webkit-appearance: none;
|
|
1364
|
+
width: 8rem;
|
|
1365
|
+
height: 0.4rem;
|
|
1366
|
+
border-radius: 0.4rem;
|
|
1367
|
+
cursor: pointer;
|
|
1116
1368
|
background: ${({ theme, $percent }) => `linear-gradient(to right, ${theme.colors.primary600} ${$percent}%, ${theme.colors.neutral200} ${$percent}%)`};
|
|
1117
|
-
&::-webkit-slider-thumb {
|
|
1118
|
-
|
|
1119
|
-
|
|
1369
|
+
&::-webkit-slider-thumb {
|
|
1370
|
+
appearance: none;
|
|
1371
|
+
-webkit-appearance: none;
|
|
1372
|
+
width: 1.6rem;
|
|
1373
|
+
height: 1.6rem;
|
|
1374
|
+
border-radius: 50%;
|
|
1375
|
+
background: ${({ theme }) => theme.colors.neutral0};
|
|
1376
|
+
border: 0.2rem solid ${({ theme }) => theme.colors.primary600};
|
|
1377
|
+
cursor: pointer;
|
|
1378
|
+
}
|
|
1379
|
+
&::-moz-range-thumb {
|
|
1380
|
+
width: 1.6rem;
|
|
1381
|
+
height: 1.6rem;
|
|
1382
|
+
border-radius: 50%;
|
|
1383
|
+
background: ${({ theme }) => theme.colors.neutral0};
|
|
1384
|
+
border: 0.2rem solid ${({ theme }) => theme.colors.primary600};
|
|
1385
|
+
cursor: pointer;
|
|
1386
|
+
}
|
|
1387
|
+
&:focus-visible {
|
|
1388
|
+
outline: 0.2rem solid ${({ theme }) => theme.colors.primary600};
|
|
1389
|
+
outline-offset: 0.2rem;
|
|
1390
|
+
}
|
|
1120
1391
|
`;
|
|
1121
1392
|
var COLUMNS = { key: "blockscene:columns", min: 1, max: 5, initial: 3 };
|
|
1122
1393
|
var SHOW_FIELDS_KEY = "blockscene:show-fields";
|
|
@@ -1142,16 +1413,31 @@ var remember = (key, value) => {
|
|
|
1142
1413
|
}
|
|
1143
1414
|
};
|
|
1144
1415
|
var Frame = styled.div`
|
|
1145
|
-
width: 100%;
|
|
1416
|
+
width: 100%;
|
|
1417
|
+
overflow: hidden;
|
|
1418
|
+
border-radius: 4px;
|
|
1419
|
+
line-height: 0;
|
|
1146
1420
|
aspect-ratio: ${({ $fixed }) => $fixed ? "16 / 9" : "auto"};
|
|
1147
1421
|
background: ${({ theme }) => theme.colors.neutral100};
|
|
1148
|
-
img {
|
|
1422
|
+
img {
|
|
1423
|
+
width: 100%;
|
|
1424
|
+
height: auto;
|
|
1425
|
+
display: block;
|
|
1426
|
+
}
|
|
1149
1427
|
`;
|
|
1150
|
-
function Thumb({
|
|
1428
|
+
function Thumb({
|
|
1429
|
+
candidates,
|
|
1430
|
+
template,
|
|
1431
|
+
palette,
|
|
1432
|
+
onResolved,
|
|
1433
|
+
noPreview,
|
|
1434
|
+
eager,
|
|
1435
|
+
blank
|
|
1436
|
+
}) {
|
|
1151
1437
|
const key = candidates.join("|");
|
|
1152
|
-
const [state, setState] =
|
|
1438
|
+
const [state, setState] = React2.useState({ key, index: 0 });
|
|
1153
1439
|
const index = state.key === key ? state.index : 0;
|
|
1154
|
-
const resolved =
|
|
1440
|
+
const resolved = React2.useRef("");
|
|
1155
1441
|
const report = (value) => {
|
|
1156
1442
|
const tag = `${key}:${value}`;
|
|
1157
1443
|
if (resolved.current !== tag) {
|
|
@@ -1159,11 +1445,19 @@ function Thumb({ candidates, template, palette, onResolved, noPreview, eager })
|
|
|
1159
1445
|
onResolved?.(value);
|
|
1160
1446
|
}
|
|
1161
1447
|
};
|
|
1162
|
-
|
|
1448
|
+
React2.useEffect(() => {
|
|
1163
1449
|
if (index >= candidates.length) report(-1);
|
|
1164
1450
|
});
|
|
1165
|
-
if (index >= candidates.length)
|
|
1166
|
-
|
|
1451
|
+
if (index >= candidates.length)
|
|
1452
|
+
return blank ? null : /* @__PURE__ */ jsx3(Frame, { $fixed: true, "data-thumb": "wireframe", children: /* @__PURE__ */ jsx3(
|
|
1453
|
+
Wireframe,
|
|
1454
|
+
{
|
|
1455
|
+
template,
|
|
1456
|
+
palette,
|
|
1457
|
+
noPreview
|
|
1458
|
+
}
|
|
1459
|
+
) });
|
|
1460
|
+
return /* @__PURE__ */ jsx3(Frame, { "data-thumb": String(index), children: /* @__PURE__ */ jsx3(
|
|
1167
1461
|
"img",
|
|
1168
1462
|
{
|
|
1169
1463
|
src: candidates[index],
|
|
@@ -1177,25 +1471,68 @@ function Thumb({ candidates, template, palette, onResolved, noPreview, eager })
|
|
|
1177
1471
|
}
|
|
1178
1472
|
function Card({ entry, palette, showFields, onSelect }) {
|
|
1179
1473
|
const t = useMessages();
|
|
1180
|
-
return /* @__PURE__ */
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1474
|
+
return /* @__PURE__ */ jsxs2(
|
|
1475
|
+
Tile,
|
|
1476
|
+
{
|
|
1477
|
+
type: "button",
|
|
1478
|
+
onClick: onSelect,
|
|
1479
|
+
title: entry.uid,
|
|
1480
|
+
"data-testid": `blockscene-${entry.uid}`,
|
|
1481
|
+
children: [
|
|
1482
|
+
/* @__PURE__ */ jsx3(
|
|
1483
|
+
Thumb,
|
|
1484
|
+
{
|
|
1485
|
+
candidates: entry.candidates,
|
|
1486
|
+
template: entry.template,
|
|
1487
|
+
palette,
|
|
1488
|
+
noPreview: t.noPreview
|
|
1489
|
+
}
|
|
1490
|
+
),
|
|
1491
|
+
/* @__PURE__ */ jsx3(
|
|
1492
|
+
Typography,
|
|
1493
|
+
{
|
|
1494
|
+
variant: "pi",
|
|
1495
|
+
fontWeight: "bold",
|
|
1496
|
+
textColor: "neutral800",
|
|
1497
|
+
ellipsis: true,
|
|
1498
|
+
children: entry.label
|
|
1499
|
+
}
|
|
1500
|
+
),
|
|
1501
|
+
entry.description && /* @__PURE__ */ jsx3(Clamp, { variant: "pi", textColor: "neutral600", children: entry.description }),
|
|
1502
|
+
showFields && entry.fields.length > 0 && /* @__PURE__ */ jsx3(
|
|
1503
|
+
Typography,
|
|
1504
|
+
{
|
|
1505
|
+
variant: "pi",
|
|
1506
|
+
textColor: "neutral500",
|
|
1507
|
+
style: { fontStyle: "italic" },
|
|
1508
|
+
"data-testid": "block-fields",
|
|
1509
|
+
children: entry.fields.map((f) => `${f.name} (${f.type})`).join(", ")
|
|
1510
|
+
}
|
|
1511
|
+
)
|
|
1512
|
+
]
|
|
1513
|
+
}
|
|
1514
|
+
);
|
|
1186
1515
|
}
|
|
1187
|
-
function ZoneGallery({
|
|
1516
|
+
function ZoneGallery({
|
|
1517
|
+
zone,
|
|
1518
|
+
components,
|
|
1519
|
+
add,
|
|
1520
|
+
Modal: Modal2,
|
|
1521
|
+
Toggle,
|
|
1522
|
+
get,
|
|
1523
|
+
controlled
|
|
1524
|
+
}) {
|
|
1188
1525
|
const t = useMessages();
|
|
1189
|
-
const [ownOpen, setOwnOpen] =
|
|
1526
|
+
const [ownOpen, setOwnOpen] = React2.useState(false);
|
|
1190
1527
|
const open = controlled ? controlled.open : ownOpen;
|
|
1191
1528
|
const setOpen = controlled ? controlled.onOpenChange : setOwnOpen;
|
|
1192
|
-
const [query, setQuery] =
|
|
1193
|
-
const [category, setCategory] =
|
|
1194
|
-
const [showFields, setShowFields] =
|
|
1195
|
-
const [columns, setColumns] =
|
|
1196
|
-
const [config, setConfig] =
|
|
1197
|
-
const [error, setError] =
|
|
1198
|
-
|
|
1529
|
+
const [query, setQuery] = React2.useState("");
|
|
1530
|
+
const [category, setCategory] = React2.useState("all");
|
|
1531
|
+
const [showFields, setShowFields] = React2.useState(readShowFields);
|
|
1532
|
+
const [columns, setColumns] = React2.useState(readColumns);
|
|
1533
|
+
const [config, setConfig] = React2.useState(null);
|
|
1534
|
+
const [error, setError] = React2.useState("");
|
|
1535
|
+
React2.useEffect(() => {
|
|
1199
1536
|
if (controlled) return;
|
|
1200
1537
|
const onClick = (event) => {
|
|
1201
1538
|
const button = event.target?.closest?.("button");
|
|
@@ -1207,7 +1544,7 @@ function ZoneGallery({ zone, components, add, Modal: Modal2, Toggle, get, contro
|
|
|
1207
1544
|
document.addEventListener("click", onClick, true);
|
|
1208
1545
|
return () => document.removeEventListener("click", onClick, true);
|
|
1209
1546
|
}, [controlled, zone.name, zone.label]);
|
|
1210
|
-
|
|
1547
|
+
React2.useEffect(() => {
|
|
1211
1548
|
if (!open) return;
|
|
1212
1549
|
let active = true;
|
|
1213
1550
|
setError("");
|
|
@@ -1223,7 +1560,10 @@ function ZoneGallery({ zone, components, add, Modal: Modal2, Toggle, get, contro
|
|
|
1223
1560
|
}, [open, get, t.failed]);
|
|
1224
1561
|
const entries = config ? entriesFor(zone, components, config, query, category) : [];
|
|
1225
1562
|
const categories = config ? categoriesFor(zone, components, config) : [];
|
|
1226
|
-
const total = categories.reduce(
|
|
1563
|
+
const total = categories.reduce(
|
|
1564
|
+
(sum, [, count]) => sum + count,
|
|
1565
|
+
0
|
|
1566
|
+
);
|
|
1227
1567
|
const filtering = query.trim() !== "" || category !== "all";
|
|
1228
1568
|
const reset = () => {
|
|
1229
1569
|
setQuery("");
|
|
@@ -1247,21 +1587,41 @@ function ZoneGallery({ zone, components, add, Modal: Modal2, Toggle, get, contro
|
|
|
1247
1587
|
setShowFields(value);
|
|
1248
1588
|
remember(SHOW_FIELDS_KEY, String(value));
|
|
1249
1589
|
};
|
|
1250
|
-
return /* @__PURE__ */
|
|
1590
|
+
return /* @__PURE__ */ jsx3(
|
|
1251
1591
|
Modal2,
|
|
1252
1592
|
{
|
|
1253
1593
|
open,
|
|
1254
1594
|
onOpenChange: setOpen,
|
|
1255
1595
|
title: t.gallery,
|
|
1256
|
-
trigger: controlled ? null : /* @__PURE__ */
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1596
|
+
trigger: controlled ? null : /* @__PURE__ */ jsxs2(
|
|
1597
|
+
Button,
|
|
1598
|
+
{
|
|
1599
|
+
variant: "secondary",
|
|
1600
|
+
fullWidth: true,
|
|
1601
|
+
onClick: () => setOpen(true),
|
|
1602
|
+
"data-testid": `open-gallery-${zone.name}`,
|
|
1603
|
+
children: [
|
|
1604
|
+
t.add,
|
|
1605
|
+
": ",
|
|
1606
|
+
zone.name
|
|
1607
|
+
]
|
|
1608
|
+
}
|
|
1609
|
+
),
|
|
1610
|
+
children: /* @__PURE__ */ jsxs2(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
|
|
1611
|
+
/* @__PURE__ */ jsxs2(Flex, { gap: 3, alignItems: "center", wrap: "wrap", children: [
|
|
1612
|
+
/* @__PURE__ */ jsx3(
|
|
1613
|
+
Typography,
|
|
1614
|
+
{
|
|
1615
|
+
variant: "omega",
|
|
1616
|
+
fontWeight: "bold",
|
|
1617
|
+
textColor: "neutral800",
|
|
1618
|
+
style: { whiteSpace: "nowrap" },
|
|
1619
|
+
"data-testid": `block-count-${zone.name}`,
|
|
1620
|
+
"aria-live": "polite",
|
|
1621
|
+
children: filtering ? t.f("countFiltered", { shown: entries.length, total }) : t.f("countAll", { count: total })
|
|
1622
|
+
}
|
|
1623
|
+
),
|
|
1624
|
+
/* @__PURE__ */ jsx3(Box, { style: { flex: 1, minWidth: "12rem" }, children: /* @__PURE__ */ jsx3(
|
|
1265
1625
|
Searchbar,
|
|
1266
1626
|
{
|
|
1267
1627
|
name: `block-search-${zone.name}`,
|
|
@@ -1273,14 +1633,54 @@ function ZoneGallery({ zone, components, add, Modal: Modal2, Toggle, get, contro
|
|
|
1273
1633
|
children: t.search
|
|
1274
1634
|
}
|
|
1275
1635
|
) }),
|
|
1276
|
-
categories.length > 1 && /* @__PURE__ */
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1636
|
+
categories.length > 1 && /* @__PURE__ */ jsx3(
|
|
1637
|
+
Box,
|
|
1638
|
+
{
|
|
1639
|
+
style: { width: "14rem" },
|
|
1640
|
+
"data-testid": `block-category-${zone.name}`,
|
|
1641
|
+
children: /* @__PURE__ */ jsxs2(
|
|
1642
|
+
SingleSelect,
|
|
1643
|
+
{
|
|
1644
|
+
"aria-label": t.filterCategory,
|
|
1645
|
+
size: "S",
|
|
1646
|
+
value: category,
|
|
1647
|
+
onChange: (value) => setCategory(String(value)),
|
|
1648
|
+
children: [
|
|
1649
|
+
/* @__PURE__ */ jsx3(SingleSelectOption, { value: "all", children: t.allCategories }),
|
|
1650
|
+
categories.map(([name, count]) => /* @__PURE__ */ jsx3(
|
|
1651
|
+
SingleSelectOption,
|
|
1652
|
+
{
|
|
1653
|
+
value: name,
|
|
1654
|
+
children: `${name} (${count})`
|
|
1655
|
+
},
|
|
1656
|
+
name
|
|
1657
|
+
))
|
|
1658
|
+
]
|
|
1659
|
+
}
|
|
1660
|
+
)
|
|
1661
|
+
}
|
|
1662
|
+
),
|
|
1663
|
+
Toggle && /* @__PURE__ */ jsx3(
|
|
1664
|
+
Toggle,
|
|
1665
|
+
{
|
|
1666
|
+
name: `block-fields-${zone.name}`,
|
|
1667
|
+
label: t.showFields,
|
|
1668
|
+
hint: t.showFieldsHint,
|
|
1669
|
+
value: showFields,
|
|
1670
|
+
onChange: changeShowFields
|
|
1671
|
+
}
|
|
1672
|
+
),
|
|
1673
|
+
/* @__PURE__ */ jsxs2(Flex, { gap: 2, alignItems: "center", children: [
|
|
1674
|
+
/* @__PURE__ */ jsx3(
|
|
1675
|
+
Typography,
|
|
1676
|
+
{
|
|
1677
|
+
variant: "pi",
|
|
1678
|
+
textColor: "neutral600",
|
|
1679
|
+
id: `block-columns-${zone.name}`,
|
|
1680
|
+
children: t.columns
|
|
1681
|
+
}
|
|
1682
|
+
),
|
|
1683
|
+
/* @__PURE__ */ jsx3(
|
|
1284
1684
|
Slider,
|
|
1285
1685
|
{
|
|
1286
1686
|
type: "range",
|
|
@@ -1293,16 +1693,52 @@ function ZoneGallery({ zone, components, add, Modal: Modal2, Toggle, get, contro
|
|
|
1293
1693
|
onChange: (e) => changeColumns(Number(e.target.value))
|
|
1294
1694
|
}
|
|
1295
1695
|
),
|
|
1296
|
-
/* @__PURE__ */
|
|
1696
|
+
/* @__PURE__ */ jsx3(Typography, { variant: "pi", fontWeight: "bold", children: columns })
|
|
1297
1697
|
] })
|
|
1298
1698
|
] }),
|
|
1299
|
-
/* @__PURE__ */
|
|
1300
|
-
error ? /* @__PURE__ */
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1699
|
+
/* @__PURE__ */ jsx3(Typography, { variant: "pi", textColor: "neutral600", children: t.example }),
|
|
1700
|
+
error ? /* @__PURE__ */ jsx3(Typography, { role: "alert", textColor: "danger600", children: error }) : !config ? /* @__PURE__ */ jsx3(Typography, { children: t.loading }) : entries.length ? /* @__PURE__ */ jsx3(
|
|
1701
|
+
Flex,
|
|
1702
|
+
{
|
|
1703
|
+
direction: "column",
|
|
1704
|
+
alignItems: "stretch",
|
|
1705
|
+
gap: 4,
|
|
1706
|
+
style: { overflowY: "auto", maxHeight: "60vh", padding: "4px" },
|
|
1707
|
+
children: groupEntries(entries).map(
|
|
1708
|
+
({ category: name, entries: items }) => /* @__PURE__ */ jsxs2(
|
|
1709
|
+
Flex,
|
|
1710
|
+
{
|
|
1711
|
+
direction: "column",
|
|
1712
|
+
alignItems: "stretch",
|
|
1713
|
+
gap: 2,
|
|
1714
|
+
children: [
|
|
1715
|
+
/* @__PURE__ */ jsx3(
|
|
1716
|
+
Typography,
|
|
1717
|
+
{
|
|
1718
|
+
variant: "sigma",
|
|
1719
|
+
textColor: "neutral600",
|
|
1720
|
+
"data-testid": `block-group-${name}`,
|
|
1721
|
+
children: `${name} (${items.length})`
|
|
1722
|
+
}
|
|
1723
|
+
),
|
|
1724
|
+
/* @__PURE__ */ jsx3(Columns, { $columns: columns, children: items.map((entry) => /* @__PURE__ */ jsx3("div", { children: /* @__PURE__ */ jsx3(
|
|
1725
|
+
Card,
|
|
1726
|
+
{
|
|
1727
|
+
entry,
|
|
1728
|
+
palette: config.palette,
|
|
1729
|
+
showFields,
|
|
1730
|
+
onSelect: () => select(entry.uid)
|
|
1731
|
+
}
|
|
1732
|
+
) }, entry.uid)) })
|
|
1733
|
+
]
|
|
1734
|
+
},
|
|
1735
|
+
name
|
|
1736
|
+
)
|
|
1737
|
+
)
|
|
1738
|
+
}
|
|
1739
|
+
) : /* @__PURE__ */ jsxs2(Flex, { gap: 3, alignItems: "center", children: [
|
|
1740
|
+
/* @__PURE__ */ jsx3(Typography, { children: t.empty }),
|
|
1741
|
+
filtering && /* @__PURE__ */ jsx3(Button, { variant: "tertiary", size: "S", onClick: reset, children: t.clear })
|
|
1306
1742
|
] })
|
|
1307
1743
|
] })
|
|
1308
1744
|
}
|
|
@@ -1316,13 +1752,19 @@ var storage = () => {
|
|
|
1316
1752
|
}
|
|
1317
1753
|
};
|
|
1318
1754
|
var memoryBase = () => `${window.location.origin}${window.location.pathname.split("/content-manager")[0]}`;
|
|
1319
|
-
function useInitialAccordions({
|
|
1320
|
-
|
|
1321
|
-
|
|
1755
|
+
function useInitialAccordions({
|
|
1756
|
+
zones,
|
|
1757
|
+
editor,
|
|
1758
|
+
docKey,
|
|
1759
|
+
contentType,
|
|
1760
|
+
userId
|
|
1761
|
+
}) {
|
|
1762
|
+
const applied = React2.useRef("");
|
|
1763
|
+
const user = React2.useRef(userId);
|
|
1322
1764
|
user.current = userId;
|
|
1323
|
-
const latest =
|
|
1765
|
+
const latest = React2.useRef(zones);
|
|
1324
1766
|
latest.current = zones;
|
|
1325
|
-
|
|
1767
|
+
React2.useEffect(() => {
|
|
1326
1768
|
if (!editor?.enabled || !docKey || applied.current === docKey) return;
|
|
1327
1769
|
if (applied.current.startsWith(`${contentType}:new`) && docKey.startsWith(`${contentType}:`)) {
|
|
1328
1770
|
applied.current = docKey;
|
|
@@ -1331,7 +1773,10 @@ function useInitialAccordions({ zones, editor, docKey, contentType, userId }) {
|
|
|
1331
1773
|
applied.current = docKey;
|
|
1332
1774
|
let tries = 0;
|
|
1333
1775
|
const cancel = (event) => {
|
|
1334
|
-
if (event.target?.closest?.(
|
|
1776
|
+
if (event.target?.closest?.(
|
|
1777
|
+
'button[aria-expanded], [data-testid^="block-accordion-controls-"]'
|
|
1778
|
+
))
|
|
1779
|
+
stop();
|
|
1335
1780
|
};
|
|
1336
1781
|
const stop = () => {
|
|
1337
1782
|
clearInterval(timer);
|
|
@@ -1349,8 +1794,17 @@ function useInitialAccordions({ zones, editor, docKey, contentType, userId }) {
|
|
|
1349
1794
|
for (const zone of pending) {
|
|
1350
1795
|
const list = findZoneList(zone.label);
|
|
1351
1796
|
if (!list) continue;
|
|
1352
|
-
const key = memoryKey({
|
|
1353
|
-
|
|
1797
|
+
const key = memoryKey({
|
|
1798
|
+
base: memoryBase(),
|
|
1799
|
+
userId: user.current,
|
|
1800
|
+
contentType,
|
|
1801
|
+
zone: zone.name
|
|
1802
|
+
});
|
|
1803
|
+
setAll(
|
|
1804
|
+
list,
|
|
1805
|
+
initialState(editor, readMemory(storage(), key)) === "open",
|
|
1806
|
+
unstable_batchedUpdates
|
|
1807
|
+
);
|
|
1354
1808
|
}
|
|
1355
1809
|
}, 200);
|
|
1356
1810
|
return stop;
|
|
@@ -1362,26 +1816,83 @@ function ZoneControls({ zone, editor, contentType, userId }) {
|
|
|
1362
1816
|
const apply = (open) => {
|
|
1363
1817
|
const list = findZoneList(zone.label);
|
|
1364
1818
|
if (list) setAll(list, open, unstable_batchedUpdates);
|
|
1365
|
-
writeMemory(
|
|
1819
|
+
writeMemory(
|
|
1820
|
+
storage(),
|
|
1821
|
+
memoryKey({ base: memoryBase(), userId, contentType, zone: zone.name }),
|
|
1822
|
+
open ? "open" : "closed"
|
|
1823
|
+
);
|
|
1366
1824
|
};
|
|
1367
|
-
return /* @__PURE__ */
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1825
|
+
return /* @__PURE__ */ jsxs2(
|
|
1826
|
+
Flex,
|
|
1827
|
+
{
|
|
1828
|
+
gap: 2,
|
|
1829
|
+
wrap: "wrap",
|
|
1830
|
+
"data-testid": `block-accordion-controls-${zone.name}`,
|
|
1831
|
+
children: [
|
|
1832
|
+
editor.showOpenAll && /* @__PURE__ */ jsx3(
|
|
1833
|
+
Button,
|
|
1834
|
+
{
|
|
1835
|
+
type: "button",
|
|
1836
|
+
variant: "tertiary",
|
|
1837
|
+
size: "S",
|
|
1838
|
+
onClick: () => apply(true),
|
|
1839
|
+
children: t.openAll
|
|
1840
|
+
}
|
|
1841
|
+
),
|
|
1842
|
+
editor.showCloseAll && /* @__PURE__ */ jsx3(
|
|
1843
|
+
Button,
|
|
1844
|
+
{
|
|
1845
|
+
type: "button",
|
|
1846
|
+
variant: "tertiary",
|
|
1847
|
+
size: "S",
|
|
1848
|
+
onClick: () => apply(false),
|
|
1849
|
+
children: t.closeAll
|
|
1850
|
+
}
|
|
1851
|
+
)
|
|
1852
|
+
]
|
|
1853
|
+
}
|
|
1854
|
+
);
|
|
1371
1855
|
}
|
|
1372
|
-
function Gallery({
|
|
1856
|
+
function Gallery({
|
|
1857
|
+
zones,
|
|
1858
|
+
editor,
|
|
1859
|
+
docKey,
|
|
1860
|
+
contentType,
|
|
1861
|
+
userId,
|
|
1862
|
+
catalog,
|
|
1863
|
+
...props
|
|
1864
|
+
}) {
|
|
1373
1865
|
useInitialAccordions({ zones, editor, docKey, contentType, userId });
|
|
1374
|
-
return /* @__PURE__ */
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1866
|
+
return /* @__PURE__ */ jsxs2(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
|
|
1867
|
+
/* @__PURE__ */ jsx3(
|
|
1868
|
+
RowPreviews,
|
|
1869
|
+
{
|
|
1870
|
+
zones,
|
|
1871
|
+
components: props.components,
|
|
1872
|
+
catalog,
|
|
1873
|
+
Modal: props.Modal
|
|
1874
|
+
}
|
|
1875
|
+
),
|
|
1876
|
+
zones.map((zone) => /* @__PURE__ */ jsxs2(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
|
1877
|
+
!zone.full && /* @__PURE__ */ jsx3(ZoneGallery, { zone, ...props }),
|
|
1878
|
+
/* @__PURE__ */ jsx3(
|
|
1879
|
+
ZoneControls,
|
|
1880
|
+
{
|
|
1881
|
+
zone,
|
|
1882
|
+
editor,
|
|
1883
|
+
contentType,
|
|
1884
|
+
userId
|
|
1885
|
+
}
|
|
1886
|
+
)
|
|
1887
|
+
] }, zone.name))
|
|
1888
|
+
] });
|
|
1378
1889
|
}
|
|
1379
1890
|
|
|
1380
1891
|
// admin/Settings.tsx
|
|
1381
|
-
import * as
|
|
1892
|
+
import * as React3 from "react";
|
|
1382
1893
|
import { Box as Box2, Button as Button2, Flex as Flex2, Searchbar as Searchbar2, Typography as Typography2 } from "@strapi/design-system";
|
|
1383
1894
|
import styled2 from "styled-components";
|
|
1384
|
-
import { Fragment, jsx as
|
|
1895
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1385
1896
|
var COLOR2 = /^#[0-9A-Fa-f]{6}$/;
|
|
1386
1897
|
var Grid = styled2.div` display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: 16px; `;
|
|
1387
1898
|
var Card2 = styled2.div`
|
|
@@ -1394,8 +1905,8 @@ var Bar = styled2.div`
|
|
|
1394
1905
|
box-shadow: 0 1px 4px rgba(33, 33, 52, 0.1);
|
|
1395
1906
|
`;
|
|
1396
1907
|
function useMainRect(anchor) {
|
|
1397
|
-
const [rect, setRect] =
|
|
1398
|
-
|
|
1908
|
+
const [rect, setRect] = React3.useState({ left: 0, width: 0 });
|
|
1909
|
+
React3.useEffect(() => {
|
|
1399
1910
|
const read = () => {
|
|
1400
1911
|
let host = document.getElementById("main-content");
|
|
1401
1912
|
for (let el = anchor.current?.parentElement; !host && el; el = el.parentElement) if (["auto", "scroll"].includes(getComputedStyle(el).overflowY) && el.scrollHeight > el.clientHeight) host = el;
|
|
@@ -1412,11 +1923,11 @@ var Swatches = styled2.div` display: grid; grid-template-columns: repeat(auto-fi
|
|
|
1412
1923
|
var Label = styled2.label` display: flex; flex-direction: column; gap: 4px; font-size: 12px; `;
|
|
1413
1924
|
function ColorField({ name, label, value, onChange, disabled }) {
|
|
1414
1925
|
const valid = COLOR2.test(value);
|
|
1415
|
-
return /* @__PURE__ */
|
|
1416
|
-
/* @__PURE__ */
|
|
1417
|
-
/* @__PURE__ */
|
|
1418
|
-
/* @__PURE__ */
|
|
1419
|
-
/* @__PURE__ */
|
|
1926
|
+
return /* @__PURE__ */ jsxs3(Label, { children: [
|
|
1927
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
|
|
1928
|
+
/* @__PURE__ */ jsxs3(Flex2, { gap: 2, children: [
|
|
1929
|
+
/* @__PURE__ */ jsx4("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" } }),
|
|
1930
|
+
/* @__PURE__ */ jsx4(
|
|
1420
1931
|
"input",
|
|
1421
1932
|
{
|
|
1422
1933
|
name,
|
|
@@ -1436,18 +1947,18 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
1436
1947
|
const t = useMessages();
|
|
1437
1948
|
const { get, put } = useClient();
|
|
1438
1949
|
const { canRead, canUpdate, isLoading } = usePermissions2();
|
|
1439
|
-
const [data, setData] =
|
|
1440
|
-
const [catalog, setCatalog] =
|
|
1441
|
-
const [settings, setSettings] =
|
|
1442
|
-
const [media, setMedia] =
|
|
1443
|
-
const [sources, setSources] =
|
|
1444
|
-
const [dirty, setDirty] =
|
|
1445
|
-
const [saving, setSaving] =
|
|
1446
|
-
const [status, setStatus] =
|
|
1447
|
-
const [failed, setFailed] =
|
|
1448
|
-
const [filter, setFilter] =
|
|
1449
|
-
const [picking, setPicking] =
|
|
1450
|
-
|
|
1950
|
+
const [data, setData] = React3.useState(null);
|
|
1951
|
+
const [catalog, setCatalog] = React3.useState(null);
|
|
1952
|
+
const [settings, setSettings] = React3.useState(null);
|
|
1953
|
+
const [media, setMedia] = React3.useState({});
|
|
1954
|
+
const [sources, setSources] = React3.useState({});
|
|
1955
|
+
const [dirty, setDirty] = React3.useState(false);
|
|
1956
|
+
const [saving, setSaving] = React3.useState(false);
|
|
1957
|
+
const [status, setStatus] = React3.useState("");
|
|
1958
|
+
const [failed, setFailed] = React3.useState(false);
|
|
1959
|
+
const [filter, setFilter] = React3.useState("");
|
|
1960
|
+
const [picking, setPicking] = React3.useState(null);
|
|
1961
|
+
React3.useEffect(() => {
|
|
1451
1962
|
if (!canRead || isLoading) return;
|
|
1452
1963
|
let active = true;
|
|
1453
1964
|
Promise.all([get("/blockscene/settings"), get("/blockscene/catalog")]).then(([s, c]) => {
|
|
@@ -1495,35 +2006,35 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
1495
2006
|
return index === 0 && manual ? t.manual : t.automatic;
|
|
1496
2007
|
};
|
|
1497
2008
|
const ready = !isLoading && canRead && !failed && settings && catalog;
|
|
1498
|
-
const header =
|
|
1499
|
-
const [floating, setFloating] =
|
|
2009
|
+
const header = React3.useRef(null);
|
|
2010
|
+
const [floating, setFloating] = React3.useState(false);
|
|
1500
2011
|
const main = useMainRect(header);
|
|
1501
|
-
|
|
2012
|
+
React3.useEffect(() => {
|
|
1502
2013
|
const el = header.current;
|
|
1503
2014
|
if (!el || typeof IntersectionObserver === "undefined") return;
|
|
1504
2015
|
const observer = new IntersectionObserver(([entry]) => setFloating(!entry.isIntersecting && entry.boundingClientRect.top < 0));
|
|
1505
2016
|
observer.observe(el);
|
|
1506
2017
|
return () => observer.disconnect();
|
|
1507
2018
|
}, [ready]);
|
|
1508
|
-
const controls = (suffix) => ready && /* @__PURE__ */
|
|
1509
|
-
/* @__PURE__ */
|
|
1510
|
-
/* @__PURE__ */
|
|
2019
|
+
const controls = (suffix) => ready && /* @__PURE__ */ jsxs3(Flex2, { gap: 3, alignItems: "center", wrap: "wrap", children: [
|
|
2020
|
+
/* @__PURE__ */ jsx4(Typography2, { role: "status", "aria-live": "polite", textColor: dirty ? "warning700" : "neutral600", "data-testid": `${dirty ? "unsaved-indicator" : "save-status"}${suffix}`, children: dirty ? t.unsaved : status || t.noChanges }),
|
|
2021
|
+
/* @__PURE__ */ jsx4(Button2, { onClick: save, disabled: !canUpdate || invalid || !dirty, loading: saving, "data-testid": `save-blockscene-settings${suffix}`, children: t.save })
|
|
1511
2022
|
] });
|
|
1512
|
-
return /* @__PURE__ */
|
|
1513
|
-
/* @__PURE__ */
|
|
1514
|
-
/* @__PURE__ */
|
|
2023
|
+
return /* @__PURE__ */ jsx4(Box2, { padding: 8, background: "neutral100", children: /* @__PURE__ */ jsxs3(Flex2, { direction: "column", alignItems: "stretch", gap: 5, children: [
|
|
2024
|
+
/* @__PURE__ */ jsx4("div", { ref: header, children: /* @__PURE__ */ jsxs3(Flex2, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
|
|
2025
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "alpha", tag: "h1", children: t.settingsTitle }),
|
|
1515
2026
|
controls("")
|
|
1516
2027
|
] }) }),
|
|
1517
|
-
floating && main.width > 0 && /* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
2028
|
+
floating && main.width > 0 && /* @__PURE__ */ jsx4(Bar, { style: { left: main.left, width: main.width }, "data-testid": "settings-floating-bar", children: /* @__PURE__ */ jsxs3(Flex2, { gap: 4, alignItems: "center", justifyContent: "space-between", wrap: "wrap", children: [
|
|
2029
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "beta", tag: "p", children: t.settingsTitle }),
|
|
1519
2030
|
controls("-floating")
|
|
1520
2031
|
] }) }),
|
|
1521
|
-
/* @__PURE__ */
|
|
1522
|
-
isLoading ? /* @__PURE__ */
|
|
1523
|
-
data.disabled && /* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
/* @__PURE__ */
|
|
1526
|
-
/* @__PURE__ */
|
|
2032
|
+
/* @__PURE__ */ jsx4(Typography2, { textColor: "neutral600", children: t.settingsIntro }),
|
|
2033
|
+
isLoading ? /* @__PURE__ */ jsx4(Typography2, { children: "\u2026" }) : !canRead ? /* @__PURE__ */ jsx4(Typography2, { role: "alert", children: t.denied }) : failed ? /* @__PURE__ */ jsx4(Typography2, { role: "alert", children: t.loadFailed }) : !settings || !catalog ? /* @__PURE__ */ jsx4(Typography2, { children: t.loading }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2034
|
+
data.disabled && /* @__PURE__ */ jsx4(Box2, { padding: 4, background: "warning100", hasRadius: true, children: /* @__PURE__ */ jsx4(Typography2, { role: "alert", textColor: "warning700", children: t.disabledByServer }) }),
|
|
2035
|
+
/* @__PURE__ */ jsx4(Box2, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs3(Flex2, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
2036
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "beta", tag: "h2", children: t.palette }),
|
|
2037
|
+
/* @__PURE__ */ jsx4(Swatches, { children: Object.keys(DEFAULT_PALETTE).map((key) => /* @__PURE__ */ jsx4(
|
|
1527
2038
|
ColorField,
|
|
1528
2039
|
{
|
|
1529
2040
|
name: `palette-${key}`,
|
|
@@ -1537,33 +2048,33 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
1537
2048
|
},
|
|
1538
2049
|
key
|
|
1539
2050
|
)) }),
|
|
1540
|
-
invalid && /* @__PURE__ */
|
|
1541
|
-
/* @__PURE__ */
|
|
1542
|
-
/* @__PURE__ */
|
|
1543
|
-
/* @__PURE__ */
|
|
1544
|
-
/* @__PURE__ */
|
|
2051
|
+
invalid && /* @__PURE__ */ jsx4(Typography2, { role: "alert", textColor: "danger600", children: t.invalidColor }),
|
|
2052
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", children: t.previewLabel }),
|
|
2053
|
+
/* @__PURE__ */ jsx4(Swatches, { "data-testid": "palette-preview", children: TEMPLATES.map((template) => /* @__PURE__ */ jsxs3(Flex2, { direction: "column", gap: 1, children: [
|
|
2054
|
+
/* @__PURE__ */ jsx4(Box2, { style: { aspectRatio: "16 / 9", overflow: "hidden" }, hasRadius: true, children: /* @__PURE__ */ jsx4(Wireframe, { template, palette: settings.palette }) }),
|
|
2055
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", children: t.templates[template] })
|
|
1545
2056
|
] }, template)) }),
|
|
1546
|
-
/* @__PURE__ */
|
|
2057
|
+
/* @__PURE__ */ jsx4(Flex2, { children: /* @__PURE__ */ jsx4(Button2, { variant: "tertiary", size: "S", disabled: !canUpdate, onClick: () => update((s) => {
|
|
1547
2058
|
s.palette = { ...DEFAULT_PALETTE };
|
|
1548
2059
|
return s;
|
|
1549
2060
|
}), children: t.resetPalette }) })
|
|
1550
2061
|
] }) }),
|
|
1551
|
-
/* @__PURE__ */
|
|
1552
|
-
/* @__PURE__ */
|
|
1553
|
-
/* @__PURE__ */
|
|
2062
|
+
/* @__PURE__ */ jsx4(Box2, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs3(Flex2, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
2063
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "beta", tag: "h2", children: t.editor }),
|
|
2064
|
+
/* @__PURE__ */ jsx4(ToggleField2, { name: "editor-enabled", label: t.enabled, value: editor.enabled, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
|
|
1554
2065
|
s.editor.enabled = v;
|
|
1555
2066
|
return s;
|
|
1556
2067
|
}) }),
|
|
1557
|
-
/* @__PURE__ */
|
|
1558
|
-
/* @__PURE__ */
|
|
2068
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", children: t.enabledHelp }),
|
|
2069
|
+
/* @__PURE__ */ jsx4(ToggleField2, { name: "editor-showOpenAll", label: t.showOpenAll, value: editor.showOpenAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
|
|
1559
2070
|
s.editor.showOpenAll = v;
|
|
1560
2071
|
return s;
|
|
1561
2072
|
}) }),
|
|
1562
|
-
/* @__PURE__ */
|
|
2073
|
+
/* @__PURE__ */ jsx4(ToggleField2, { name: "editor-showCloseAll", label: t.showCloseAll, value: editor.showCloseAll, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
|
|
1563
2074
|
s.editor.showCloseAll = v;
|
|
1564
2075
|
return s;
|
|
1565
2076
|
}) }),
|
|
1566
|
-
/* @__PURE__ */
|
|
2077
|
+
/* @__PURE__ */ jsx4(
|
|
1567
2078
|
SelectField2,
|
|
1568
2079
|
{
|
|
1569
2080
|
name: "editor-initialState",
|
|
@@ -1577,9 +2088,9 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
1577
2088
|
})
|
|
1578
2089
|
}
|
|
1579
2090
|
),
|
|
1580
|
-
/* @__PURE__ */
|
|
1581
|
-
previewSupported ? /* @__PURE__ */
|
|
1582
|
-
/* @__PURE__ */
|
|
2091
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", children: t.rememberHelp }),
|
|
2092
|
+
previewSupported ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2093
|
+
/* @__PURE__ */ jsx4(
|
|
1583
2094
|
TextField,
|
|
1584
2095
|
{
|
|
1585
2096
|
name: "editor-previewUrl",
|
|
@@ -1593,8 +2104,8 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
1593
2104
|
})
|
|
1594
2105
|
}
|
|
1595
2106
|
),
|
|
1596
|
-
/* @__PURE__ */
|
|
1597
|
-
/* @__PURE__ */
|
|
2107
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", children: t.previewUrlHelp }),
|
|
2108
|
+
/* @__PURE__ */ jsx4(
|
|
1598
2109
|
SelectField2,
|
|
1599
2110
|
{
|
|
1600
2111
|
name: "editor-previewMode",
|
|
@@ -1608,26 +2119,26 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
1608
2119
|
})
|
|
1609
2120
|
}
|
|
1610
2121
|
),
|
|
1611
|
-
/* @__PURE__ */
|
|
1612
|
-
data.blockPreviewAvailable && /* @__PURE__ */
|
|
1613
|
-
/* @__PURE__ */
|
|
2122
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", children: t.previewModeHelp }),
|
|
2123
|
+
data.blockPreviewAvailable && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2124
|
+
/* @__PURE__ */ jsx4(ToggleField2, { name: "editor-blockPreviewInForm", label: t.blockPreviewInForm, value: editor.blockPreviewInForm, disabled: !canUpdate || saving, onChange: (v) => update((s) => {
|
|
1614
2125
|
s.editor.blockPreviewInForm = v;
|
|
1615
2126
|
return s;
|
|
1616
2127
|
}) }),
|
|
1617
|
-
/* @__PURE__ */
|
|
2128
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", children: t.blockPreviewInFormHelp })
|
|
1618
2129
|
] })
|
|
1619
|
-
] }) : /* @__PURE__ */
|
|
2130
|
+
] }) : /* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", children: t.previewV4 })
|
|
1620
2131
|
] }) }),
|
|
1621
|
-
/* @__PURE__ */
|
|
1622
|
-
/* @__PURE__ */
|
|
1623
|
-
/* @__PURE__ */
|
|
1624
|
-
/* @__PURE__ */
|
|
1625
|
-
/* @__PURE__ */
|
|
2132
|
+
/* @__PURE__ */ jsx4(Box2, { padding: 6, background: "neutral0", hasRadius: true, children: /* @__PURE__ */ jsxs3(Flex2, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
2133
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "beta", tag: "h2", children: t.components }),
|
|
2134
|
+
/* @__PURE__ */ jsx4(Searchbar2, { name: "component-filter", value: filter, placeholder: t.filter, clearLabel: t.clear, onClear: () => setFilter(""), onChange: (e) => setFilter(e.target.value), children: t.filter }),
|
|
2135
|
+
/* @__PURE__ */ jsx4(Typography2, { variant: "pi", textColor: "neutral600", "data-testid": "components-count", children: t.f("countAll", { count: components.length }) }),
|
|
2136
|
+
/* @__PURE__ */ jsx4(Grid, { "data-testid": "components-grid", children: components.map((component) => {
|
|
1626
2137
|
const entry = settings.components[component.uid] || {};
|
|
1627
2138
|
const meta = { ...catalog.components?.[component.uid] || {}, ...media[component.uid] || {} };
|
|
1628
2139
|
const candidates = candidatesFor(component.uid, meta, catalog);
|
|
1629
|
-
return /* @__PURE__ */
|
|
1630
|
-
/* @__PURE__ */
|
|
2140
|
+
return /* @__PURE__ */ jsxs3(Card2, { "data-testid": `settings-${component.uid}`, children: [
|
|
2141
|
+
/* @__PURE__ */ jsx4(
|
|
1631
2142
|
Thumb,
|
|
1632
2143
|
{
|
|
1633
2144
|
candidates,
|
|
@@ -1638,23 +2149,23 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
1638
2149
|
onResolved: (index) => setSources((current) => current[component.uid] === index ? current : { ...current, [component.uid]: index })
|
|
1639
2150
|
}
|
|
1640
2151
|
),
|
|
1641
|
-
/* @__PURE__ */
|
|
1642
|
-
/* @__PURE__ */
|
|
1643
|
-
/* @__PURE__ */
|
|
2152
|
+
/* @__PURE__ */ jsxs3(Flex2, { direction: "column", alignItems: "flex-start", gap: 2, children: [
|
|
2153
|
+
/* @__PURE__ */ jsx4(Typography2, { fontWeight: "bold", textColor: "neutral800", children: component.displayName }),
|
|
2154
|
+
/* @__PURE__ */ jsxs3(Typography2, { variant: "pi", textColor: "neutral600", children: [
|
|
1644
2155
|
component.uid,
|
|
1645
2156
|
" \xB7 ",
|
|
1646
2157
|
component.category
|
|
1647
2158
|
] }),
|
|
1648
|
-
/* @__PURE__ */
|
|
2159
|
+
/* @__PURE__ */ jsxs3(Typography2, { variant: "pi", "data-testid": `source-${component.uid}`, children: [
|
|
1649
2160
|
t.source,
|
|
1650
2161
|
": ",
|
|
1651
2162
|
sourceOf(component.uid, Boolean(meta.manualImage)),
|
|
1652
2163
|
meta.manualName ? ` (${meta.manualName})` : ""
|
|
1653
2164
|
] }),
|
|
1654
|
-
meta.manualMissing && /* @__PURE__ */
|
|
1655
|
-
/* @__PURE__ */
|
|
1656
|
-
/* @__PURE__ */
|
|
1657
|
-
entry.mediaId && /* @__PURE__ */
|
|
2165
|
+
meta.manualMissing && /* @__PURE__ */ jsx4(Typography2, { variant: "pi", role: "alert", textColor: "danger600", children: t.brokenMedia }),
|
|
2166
|
+
/* @__PURE__ */ jsxs3(Flex2, { gap: 2, wrap: "wrap", children: [
|
|
2167
|
+
/* @__PURE__ */ jsx4(Button2, { variant: "secondary", size: "S", disabled: !canUpdate || saving, onClick: () => setPicking(component.uid), children: entry.mediaId ? t.replace : t.choose }),
|
|
2168
|
+
entry.mediaId && /* @__PURE__ */ jsx4(Button2, { variant: "tertiary", size: "S", disabled: !canUpdate || saving, onClick: () => {
|
|
1658
2169
|
update((s) => {
|
|
1659
2170
|
delete s.components[component.uid]?.mediaId;
|
|
1660
2171
|
if (!Object.keys(s.components[component.uid] || {}).length) delete s.components[component.uid];
|
|
@@ -1667,7 +2178,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
1667
2178
|
});
|
|
1668
2179
|
}, children: t.useAutomatic })
|
|
1669
2180
|
] }),
|
|
1670
|
-
/* @__PURE__ */
|
|
2181
|
+
/* @__PURE__ */ jsx4(
|
|
1671
2182
|
SelectField2,
|
|
1672
2183
|
{
|
|
1673
2184
|
name: `template-${component.uid}`,
|
|
@@ -1685,7 +2196,7 @@ function Settings({ useClient, usePermissions: usePermissions2, MediaPicker: Med
|
|
|
1685
2196
|
] }, component.uid);
|
|
1686
2197
|
}) })
|
|
1687
2198
|
] }) }),
|
|
1688
|
-
picking && /* @__PURE__ */
|
|
2199
|
+
picking && /* @__PURE__ */ jsx4(MediaPicker2, { onClose: () => setPicking(null), onSelect: (asset) => {
|
|
1689
2200
|
const uid = picking;
|
|
1690
2201
|
setPicking(null);
|
|
1691
2202
|
if (!asset?.id) return;
|
|
@@ -1714,10 +2225,10 @@ function register(app, Component, to) {
|
|
|
1714
2225
|
}
|
|
1715
2226
|
|
|
1716
2227
|
// admin/catalog.ts
|
|
1717
|
-
import * as
|
|
2228
|
+
import * as React4 from "react";
|
|
1718
2229
|
function useCatalog(get) {
|
|
1719
|
-
const [catalog, setCatalog] =
|
|
1720
|
-
|
|
2230
|
+
const [catalog, setCatalog] = React4.useState(null);
|
|
2231
|
+
React4.useEffect(() => {
|
|
1721
2232
|
let active = true;
|
|
1722
2233
|
get("/blockscene/catalog").then(({ data }) => {
|
|
1723
2234
|
if (active) setCatalog(data);
|
|
@@ -1732,14 +2243,14 @@ function useCatalog(get) {
|
|
|
1732
2243
|
}
|
|
1733
2244
|
|
|
1734
2245
|
// admin/strapi4.tsx
|
|
1735
|
-
import { Fragment as
|
|
2246
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1736
2247
|
function Modal({ open, onOpenChange, trigger, title, children }) {
|
|
1737
|
-
const id =
|
|
1738
|
-
return /* @__PURE__ */
|
|
2248
|
+
const id = React5.useId();
|
|
2249
|
+
return /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1739
2250
|
trigger,
|
|
1740
|
-
open && /* @__PURE__ */
|
|
1741
|
-
/* @__PURE__ */
|
|
1742
|
-
/* @__PURE__ */
|
|
2251
|
+
open && /* @__PURE__ */ jsxs4(ModalLayout, { onClose: () => onOpenChange(false), labelledBy: id, children: [
|
|
2252
|
+
/* @__PURE__ */ jsx5(ModalHeader, { children: /* @__PURE__ */ jsx5(Typography3, { id, variant: "beta", children: title }) }),
|
|
2253
|
+
/* @__PURE__ */ jsx5(ModalBody, { children })
|
|
1743
2254
|
] })
|
|
1744
2255
|
] });
|
|
1745
2256
|
}
|
|
@@ -1750,17 +2261,37 @@ function Picker() {
|
|
|
1750
2261
|
const components = c.allLayoutData?.components || {};
|
|
1751
2262
|
const schema = c.layout || c.allLayoutData?.contentType;
|
|
1752
2263
|
const allowed = (c.isCreatingEntry ? c.createActionAllowedFields : c.updateActionAllowedFields) || [];
|
|
1753
|
-
const zones = editableZones(
|
|
2264
|
+
const zones = editableZones(
|
|
2265
|
+
schema,
|
|
2266
|
+
c.modifiedData,
|
|
2267
|
+
(name) => allowed.includes(name) && schema?.metadatas?.[name]?.edit?.editable !== false,
|
|
2268
|
+
!c.addComponentToDynamicZone
|
|
2269
|
+
).map((zone) => ({
|
|
2270
|
+
...zone,
|
|
2271
|
+
label: schema?.metadatas?.[zone.name]?.edit?.label || zone.name
|
|
2272
|
+
}));
|
|
1754
2273
|
const add = (zone, uid) => {
|
|
1755
2274
|
const close = catalog?.groups?.[uid];
|
|
1756
|
-
if (!canInsert(zone, uid, c.modifiedData, components, close ? 2 : 1) || close && !zone.components.includes(close))
|
|
1757
|
-
|
|
1758
|
-
|
|
2275
|
+
if (!canInsert(zone, uid, c.modifiedData, components, close ? 2 : 1) || close && !zone.components.includes(close))
|
|
2276
|
+
return false;
|
|
2277
|
+
c.addComponentToDynamicZone(
|
|
2278
|
+
zone.name,
|
|
2279
|
+
components[uid],
|
|
2280
|
+
components,
|
|
2281
|
+
Boolean(c.formErrors?.[zone.name])
|
|
2282
|
+
);
|
|
2283
|
+
if (close)
|
|
2284
|
+
c.addComponentToDynamicZone(
|
|
2285
|
+
zone.name,
|
|
2286
|
+
components[close],
|
|
2287
|
+
components,
|
|
2288
|
+
Boolean(c.formErrors?.[zone.name])
|
|
2289
|
+
);
|
|
1759
2290
|
return true;
|
|
1760
2291
|
};
|
|
1761
2292
|
if (!catalog?.editor?.enabled) return null;
|
|
1762
2293
|
const docKey = `${c.slug}:${c.isCreatingEntry ? "new" : c.initialData?.id}:${c.initialData?.locale || ""}`;
|
|
1763
|
-
return /* @__PURE__ */
|
|
2294
|
+
return /* @__PURE__ */ jsx5(
|
|
1764
2295
|
Gallery,
|
|
1765
2296
|
{
|
|
1766
2297
|
zones,
|
|
@@ -1770,17 +2301,44 @@ function Picker() {
|
|
|
1770
2301
|
Toggle: ToggleField,
|
|
1771
2302
|
get,
|
|
1772
2303
|
editor: catalog.editor,
|
|
2304
|
+
catalog,
|
|
1773
2305
|
docKey,
|
|
1774
2306
|
contentType: c.slug,
|
|
1775
2307
|
userId: auth.getUserInfo?.()?.id
|
|
1776
2308
|
}
|
|
1777
2309
|
);
|
|
1778
2310
|
}
|
|
1779
|
-
var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */
|
|
1780
|
-
/* @__PURE__ */
|
|
1781
|
-
|
|
2311
|
+
var ToggleField = ({ name, label, value, onChange, disabled }) => /* @__PURE__ */ jsxs4(Flex3, { gap: 3, children: [
|
|
2312
|
+
/* @__PURE__ */ jsx5(
|
|
2313
|
+
Switch,
|
|
2314
|
+
{
|
|
2315
|
+
name,
|
|
2316
|
+
"aria-label": label,
|
|
2317
|
+
selected: Boolean(value),
|
|
2318
|
+
disabled,
|
|
2319
|
+
onChange: () => onChange(!value)
|
|
2320
|
+
}
|
|
2321
|
+
),
|
|
2322
|
+
/* @__PURE__ */ jsx5(Typography3, { children: label })
|
|
1782
2323
|
] });
|
|
1783
|
-
var SelectField = ({
|
|
2324
|
+
var SelectField = ({
|
|
2325
|
+
name,
|
|
2326
|
+
label,
|
|
2327
|
+
value,
|
|
2328
|
+
onChange,
|
|
2329
|
+
disabled,
|
|
2330
|
+
options
|
|
2331
|
+
}) => /* @__PURE__ */ jsx5(
|
|
2332
|
+
SingleSelect2,
|
|
2333
|
+
{
|
|
2334
|
+
name,
|
|
2335
|
+
label,
|
|
2336
|
+
value,
|
|
2337
|
+
disabled,
|
|
2338
|
+
onChange: (v) => onChange(String(v)),
|
|
2339
|
+
children: options.map((o) => /* @__PURE__ */ jsx5(SingleSelectOption2, { value: o.value, children: o.label }, o.value))
|
|
2340
|
+
}
|
|
2341
|
+
);
|
|
1784
2342
|
function MediaPicker({ onClose, onSelect }) {
|
|
1785
2343
|
const { components } = useLibrary();
|
|
1786
2344
|
const Dialog = components?.["media-library"];
|
|
@@ -1788,13 +2346,34 @@ function MediaPicker({ onClose, onSelect }) {
|
|
|
1788
2346
|
onClose();
|
|
1789
2347
|
return null;
|
|
1790
2348
|
}
|
|
1791
|
-
return /* @__PURE__ */
|
|
2349
|
+
return /* @__PURE__ */ jsx5(
|
|
2350
|
+
Dialog,
|
|
2351
|
+
{
|
|
2352
|
+
onClose,
|
|
2353
|
+
allowedTypes: ["images"],
|
|
2354
|
+
onSelectAssets: (assets) => onSelect(assets?.[0])
|
|
2355
|
+
}
|
|
2356
|
+
);
|
|
1792
2357
|
}
|
|
1793
2358
|
function usePermissions() {
|
|
1794
2359
|
const { allowedActions, isLoading } = useRBAC(permissions);
|
|
1795
|
-
return {
|
|
2360
|
+
return {
|
|
2361
|
+
canRead: allowedActions.canRead,
|
|
2362
|
+
canUpdate: allowedActions.canUpdate,
|
|
2363
|
+
isLoading
|
|
2364
|
+
};
|
|
1796
2365
|
}
|
|
1797
|
-
var SettingsPage = () => /* @__PURE__ */
|
|
2366
|
+
var SettingsPage = () => /* @__PURE__ */ jsx5(
|
|
2367
|
+
Settings,
|
|
2368
|
+
{
|
|
2369
|
+
useClient: useFetchClient,
|
|
2370
|
+
usePermissions,
|
|
2371
|
+
MediaPicker,
|
|
2372
|
+
ToggleField,
|
|
2373
|
+
SelectField,
|
|
2374
|
+
previewSupported: false
|
|
2375
|
+
}
|
|
2376
|
+
);
|
|
1798
2377
|
var strapi4_default = {
|
|
1799
2378
|
register(app) {
|
|
1800
2379
|
register(app, SettingsPage, "/settings/blockscene");
|
|
@@ -1802,7 +2381,10 @@ var strapi4_default = {
|
|
|
1802
2381
|
},
|
|
1803
2382
|
registerTrads,
|
|
1804
2383
|
bootstrap(app) {
|
|
1805
|
-
app.injectContentManagerComponent("editView", "right-links", {
|
|
2384
|
+
app.injectContentManagerComponent("editView", "right-links", {
|
|
2385
|
+
name: "blockscene",
|
|
2386
|
+
Component: Picker
|
|
2387
|
+
});
|
|
1806
2388
|
}
|
|
1807
2389
|
};
|
|
1808
2390
|
export {
|