@nextbridgehq/payload-block-builder 0.1.8 → 0.1.9
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 +199 -62
- package/dist/client.cjs +401 -283
- package/dist/client.d.cts +5 -1
- package/dist/client.d.ts +5 -1
- package/dist/client.js +202 -85
- package/dist/index.cjs +14 -1
- package/dist/index.js +14 -1
- package/package.json +1 -1
- package/src/components/BlockDataField/BlockDataField.css +170 -0
package/dist/client.cjs
CHANGED
|
@@ -32,6 +32,7 @@ var client_exports = {};
|
|
|
32
32
|
__export(client_exports, {
|
|
33
33
|
BlockBuilderNavLink: () => BlockBuilderNavLink,
|
|
34
34
|
BlockDataField: () => BlockDataField,
|
|
35
|
+
BlockVersionSync: () => BlockVersionSync,
|
|
35
36
|
BuilderShell: () => BuilderShell,
|
|
36
37
|
EditInBuilderButton: () => EditInBuilderButton,
|
|
37
38
|
SchemaBuilderField: () => SchemaBuilderField
|
|
@@ -77,55 +78,132 @@ function MediaPicker({ label, required, value, onChange }) {
|
|
|
77
78
|
"x"
|
|
78
79
|
))) : /* @__PURE__ */ import_react.default.createElement(ListDrawerToggler, { className: "bdf-upload-btn" }, "Choose from Media Library")), /* @__PURE__ */ import_react.default.createElement(ListDrawer, { onSelect: handleSelect }));
|
|
79
80
|
}
|
|
80
|
-
function
|
|
81
|
+
function toRelDoc(v) {
|
|
82
|
+
if (!v) return null;
|
|
83
|
+
if (typeof v === "object") {
|
|
84
|
+
const o = v;
|
|
85
|
+
if (!o.id) return null;
|
|
86
|
+
return { id: o.id, title: o.title ? String(o.title) : null };
|
|
87
|
+
}
|
|
88
|
+
if (typeof v === "string" || typeof v === "number") return { id: v, title: null };
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function RelationshipPicker({ label, required, collection, hasMany = false, value, onChange }) {
|
|
81
92
|
const changeRef = (0, import_react.useRef)(onChange);
|
|
82
93
|
const closeRef = (0, import_react.useRef)(() => {
|
|
83
94
|
});
|
|
84
95
|
(0, import_react.useEffect)(() => {
|
|
85
96
|
changeRef.current = onChange;
|
|
86
97
|
});
|
|
98
|
+
const items = hasMany ? Array.isArray(value) ? value.map(toRelDoc).filter(Boolean) : [] : (() => {
|
|
99
|
+
const d = toRelDoc(value);
|
|
100
|
+
return d ? [d] : [];
|
|
101
|
+
})();
|
|
102
|
+
const itemsRef = (0, import_react.useRef)(items);
|
|
103
|
+
(0, import_react.useEffect)(() => {
|
|
104
|
+
itemsRef.current = items;
|
|
105
|
+
});
|
|
87
106
|
const handleSelect = (0, import_react.useCallback)(
|
|
88
107
|
({ docID, doc }) => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
const title = String(doc?.title ?? doc?.name ?? doc?.slug ?? "") || null;
|
|
109
|
+
const entry = { id: docID, title };
|
|
110
|
+
if (hasMany) {
|
|
111
|
+
const alreadyExists = itemsRef.current.some((i) => String(i.id) === String(docID));
|
|
112
|
+
if (!alreadyExists) changeRef.current([...itemsRef.current, entry]);
|
|
113
|
+
} else {
|
|
114
|
+
changeRef.current(entry);
|
|
115
|
+
closeRef.current();
|
|
116
|
+
}
|
|
94
117
|
},
|
|
95
|
-
[]
|
|
118
|
+
[hasMany]
|
|
96
119
|
);
|
|
97
|
-
const [ListDrawer, ListDrawerToggler, { closeDrawer }] = (0, import_ui.useListDrawer)({
|
|
120
|
+
const [ListDrawer, ListDrawerToggler, { closeDrawer, openDrawer }] = (0, import_ui.useListDrawer)({
|
|
98
121
|
collectionSlugs: [collection]
|
|
99
122
|
});
|
|
100
123
|
closeRef.current = closeDrawer;
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
const relTitle = relObj?.title ? String(relObj.title) : null;
|
|
104
|
-
const [fetchedTitle, setFetchedTitle] = (0, import_react.useState)(null);
|
|
124
|
+
const [fetchedTitles, setFetchedTitles] = (0, import_react.useState)({});
|
|
125
|
+
const fetchingRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
|
|
105
126
|
(0, import_react.useEffect)(() => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
127
|
+
const missing = items.filter(
|
|
128
|
+
(i) => !i.title && !fetchedTitles[String(i.id)] && !fetchingRef.current.has(String(i.id))
|
|
129
|
+
);
|
|
130
|
+
if (missing.length === 0) return;
|
|
131
|
+
missing.forEach((item) => {
|
|
132
|
+
const idStr = String(item.id);
|
|
133
|
+
fetchingRef.current.add(idStr);
|
|
134
|
+
fetch(`/api/${collection}/${idStr}?depth=0`, { credentials: "same-origin" }).then((r) => r.ok ? r.json() : null).then((doc) => {
|
|
135
|
+
if (doc) {
|
|
136
|
+
const t = doc.title ?? doc.name ?? doc.slug ?? null;
|
|
137
|
+
if (t) setFetchedTitles((prev) => ({ ...prev, [idStr]: String(t) }));
|
|
138
|
+
}
|
|
139
|
+
}).catch(() => {
|
|
140
|
+
fetchingRef.current.delete(idStr);
|
|
141
|
+
});
|
|
116
142
|
});
|
|
117
|
-
}, [
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
143
|
+
}, [items, collection]);
|
|
144
|
+
function getTitle(item) {
|
|
145
|
+
return item.title ?? fetchedTitles[String(item.id)] ?? `ID: ${String(item.id)}`;
|
|
146
|
+
}
|
|
147
|
+
function clearOne(e, id) {
|
|
148
|
+
e.stopPropagation();
|
|
149
|
+
if (hasMany) onChange(items.filter((i) => String(i.id) !== String(id)));
|
|
150
|
+
else onChange(null);
|
|
151
|
+
}
|
|
152
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "bdf-field" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "bdf-label" }, label, required && /* @__PURE__ */ import_react.default.createElement("span", { className: "bdf-required" }, "*")), /* @__PURE__ */ import_react.default.createElement("div", { className: `bdf-rel${hasMany ? " bdf-rel--multi" : ""}` }, /* @__PURE__ */ import_react.default.createElement(
|
|
153
|
+
"div",
|
|
121
154
|
{
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
onClick:
|
|
155
|
+
role: "button",
|
|
156
|
+
tabIndex: 0,
|
|
157
|
+
className: "bdf-rel__control",
|
|
158
|
+
onClick: openDrawer,
|
|
159
|
+
onKeyDown: (e) => {
|
|
160
|
+
if (e.key === "Enter" || e.key === " ") openDrawer();
|
|
161
|
+
}
|
|
126
162
|
},
|
|
127
|
-
"
|
|
128
|
-
|
|
163
|
+
/* @__PURE__ */ import_react.default.createElement("div", { className: "bdf-rel__values" }, items.length === 0 && /* @__PURE__ */ import_react.default.createElement("span", { className: "bdf-rel__placeholder" }, "Select a value..."), !hasMany && items.length > 0 && /* @__PURE__ */ import_react.default.createElement("span", { className: "bdf-rel__single" }, getTitle(items[0])), hasMany && items.map((item) => /* @__PURE__ */ import_react.default.createElement("span", { key: String(item.id), className: "bdf-rel__chip" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "bdf-rel__chip-label" }, getTitle(item)), /* @__PURE__ */ import_react.default.createElement(
|
|
164
|
+
"button",
|
|
165
|
+
{
|
|
166
|
+
type: "button",
|
|
167
|
+
className: "bdf-rel__chip-remove",
|
|
168
|
+
onClick: (e) => clearOne(e, item.id),
|
|
169
|
+
"aria-label": `Remove ${getTitle(item)}`
|
|
170
|
+
},
|
|
171
|
+
/* @__PURE__ */ import_react.default.createElement("svg", { height: "12", width: "12", viewBox: "0 0 20 20", "aria-hidden": "true", focusable: "false", fill: "currentColor" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M14.348 14.849c-0.469 0.469-1.229 0.469-1.697 0l-2.651-3.030-2.651 3.029c-0.469 0.469-1.229 0.469-1.697 0-0.469-0.469-0.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-0.469-0.469-0.469-1.228 0-1.697s1.228-0.469 1.697 0l2.652 3.031 2.651-3.031c0.469-0.469 1.228-0.469 1.697 0s0.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c0.469 0.469 0.469 1.229 0 1.698z" }))
|
|
172
|
+
)))),
|
|
173
|
+
/* @__PURE__ */ import_react.default.createElement("div", { className: "bdf-rel__indicators" }, !hasMany && items.length > 0 && /* @__PURE__ */ import_react.default.createElement(
|
|
174
|
+
"button",
|
|
175
|
+
{
|
|
176
|
+
type: "button",
|
|
177
|
+
className: "bdf-rel__clear",
|
|
178
|
+
onClick: (e) => clearOne(e, items[0].id),
|
|
179
|
+
"aria-label": "Clear"
|
|
180
|
+
},
|
|
181
|
+
/* @__PURE__ */ import_react.default.createElement("svg", { height: "16", width: "16", viewBox: "0 0 20 20", "aria-hidden": "true", focusable: "false", fill: "currentColor" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M14.348 14.849c-0.469 0.469-1.229 0.469-1.697 0l-2.651-3.030-2.651 3.029c-0.469 0.469-1.229 0.469-1.697 0-0.469-0.469-0.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-0.469-0.469-0.469-1.228 0-1.697s1.228-0.469 1.697 0l2.652 3.031 2.651-3.031c0.469-0.469 1.228-0.469 1.697 0s0.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c0.469 0.469 0.469 1.229 0 1.698z" }))
|
|
182
|
+
), /* @__PURE__ */ import_react.default.createElement("span", { className: "bdf-rel__sep" }), /* @__PURE__ */ import_react.default.createElement("span", { className: "bdf-rel__chevron" }, /* @__PURE__ */ import_react.default.createElement("svg", { height: "16", width: "16", viewBox: "0 0 20 20", "aria-hidden": "true", focusable: "false", fill: "currentColor" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z" }))))
|
|
183
|
+
), hasMany && /* @__PURE__ */ import_react.default.createElement(ListDrawerToggler, { className: "bdf-rel__add", onClick: (e) => e.stopPropagation() }, "+")), /* @__PURE__ */ import_react.default.createElement("span", { className: "bdf-rel__hint" }, collection, hasMany ? " \xB7 multiple" : ""), /* @__PURE__ */ import_react.default.createElement(ListDrawer, { onSelect: handleSelect }));
|
|
184
|
+
}
|
|
185
|
+
function JsonField({ label, required, value, onChange }) {
|
|
186
|
+
const [text, setText] = (0, import_react.useState)(
|
|
187
|
+
() => value !== void 0 ? JSON.stringify(value, null, 2) : ""
|
|
188
|
+
);
|
|
189
|
+
const [hasError, setHasError] = (0, import_react.useState)(false);
|
|
190
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "bdf-field" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "bdf-label" }, label, required && /* @__PURE__ */ import_react.default.createElement("span", { className: "bdf-required" }, "*"), /* @__PURE__ */ import_react.default.createElement("span", { style: { marginLeft: 6, fontSize: 11, color: "var(--theme-elevation-400)", fontWeight: 400 } }, "(JSON)")), /* @__PURE__ */ import_react.default.createElement(
|
|
191
|
+
"textarea",
|
|
192
|
+
{
|
|
193
|
+
className: "bdf-input bdf-textarea bdf-mono",
|
|
194
|
+
value: text,
|
|
195
|
+
rows: 4,
|
|
196
|
+
onChange: (e) => {
|
|
197
|
+
setText(e.target.value);
|
|
198
|
+
try {
|
|
199
|
+
onChange(JSON.parse(e.target.value));
|
|
200
|
+
setHasError(false);
|
|
201
|
+
} catch {
|
|
202
|
+
setHasError(true);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
), hasError && /* @__PURE__ */ import_react.default.createElement("div", { className: "bdf-error", style: { marginTop: 4 } }, "Invalid JSON \u2014 changes not saved until fixed."));
|
|
129
207
|
}
|
|
130
208
|
function SchemaForm({ schema, value, onChange }) {
|
|
131
209
|
const set = (0, import_react.useCallback)(
|
|
@@ -152,7 +230,7 @@ function FieldInput({ field, value, onChange }) {
|
|
|
152
230
|
"input",
|
|
153
231
|
{
|
|
154
232
|
className: "bdf-input",
|
|
155
|
-
type: field.type === "email" ? "email" : "text",
|
|
233
|
+
type: field.type === "email" ? "email" : field.type === "url" ? "url" : "text",
|
|
156
234
|
value: value ?? "",
|
|
157
235
|
onChange: (e) => onChange(e.target.value)
|
|
158
236
|
}
|
|
@@ -205,7 +283,7 @@ function FieldInput({ field, value, onChange }) {
|
|
|
205
283
|
className: "bdf-input",
|
|
206
284
|
type: "number",
|
|
207
285
|
value: numVal,
|
|
208
|
-
onChange: (e) => onChange(e.target.value === "" ?
|
|
286
|
+
onChange: (e) => onChange(e.target.value === "" ? null : e.target.valueAsNumber)
|
|
209
287
|
}
|
|
210
288
|
));
|
|
211
289
|
}
|
|
@@ -265,33 +343,24 @@ function FieldInput({ field, value, onChange }) {
|
|
|
265
343
|
}
|
|
266
344
|
);
|
|
267
345
|
case "relationship": {
|
|
268
|
-
const
|
|
346
|
+
const relField = field;
|
|
347
|
+
if (!relField.collection) {
|
|
348
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "bdf-field" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "bdf-label" }, label), /* @__PURE__ */ import_react.default.createElement("div", { className: "bdf-error" }, "Relationship field ", /* @__PURE__ */ import_react.default.createElement("strong", null, field.name), " has no ", /* @__PURE__ */ import_react.default.createElement("code", null, "collection"), " defined in its schema."));
|
|
349
|
+
}
|
|
269
350
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
270
351
|
RelationshipPicker,
|
|
271
352
|
{
|
|
272
353
|
label,
|
|
273
354
|
required: field.required,
|
|
274
|
-
collection,
|
|
355
|
+
collection: relField.collection,
|
|
356
|
+
hasMany: relField.hasMany ?? false,
|
|
275
357
|
value,
|
|
276
358
|
onChange
|
|
277
359
|
}
|
|
278
360
|
);
|
|
279
361
|
}
|
|
280
362
|
case "json":
|
|
281
|
-
return /* @__PURE__ */ import_react.default.createElement(
|
|
282
|
-
"textarea",
|
|
283
|
-
{
|
|
284
|
-
className: "bdf-input bdf-textarea bdf-mono",
|
|
285
|
-
value: value !== void 0 ? JSON.stringify(value, null, 2) : "",
|
|
286
|
-
rows: 4,
|
|
287
|
-
onChange: (e) => {
|
|
288
|
-
try {
|
|
289
|
-
onChange(JSON.parse(e.target.value));
|
|
290
|
-
} catch {
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
));
|
|
363
|
+
return /* @__PURE__ */ import_react.default.createElement(JsonField, { label, required: field.required, value, onChange });
|
|
295
364
|
case "array": {
|
|
296
365
|
const rows = Array.isArray(value) ? value : [];
|
|
297
366
|
const subFields = field.fields ?? [];
|
|
@@ -387,15 +456,43 @@ function BlockDataField({ path }) {
|
|
|
387
456
|
)));
|
|
388
457
|
}
|
|
389
458
|
|
|
390
|
-
// src/components/
|
|
391
|
-
var
|
|
459
|
+
// src/components/BlockVersionSync/index.tsx
|
|
460
|
+
var import_react2 = require("react");
|
|
392
461
|
var import_ui2 = require("@payloadcms/ui");
|
|
462
|
+
function BlockVersionSync({ path }) {
|
|
463
|
+
const blockVersionPath = path.replace(/\.blockDefinition$/, ".blockVersion");
|
|
464
|
+
const { setValue: setVersion } = (0, import_ui2.useField)({ path: blockVersionPath });
|
|
465
|
+
const blockDefValue = (0, import_ui2.useFormFields)(([fields]) => fields[path]?.value);
|
|
466
|
+
const prevDefIdRef = (0, import_react2.useRef)(null);
|
|
467
|
+
(0, import_react2.useEffect)(() => {
|
|
468
|
+
const defId = blockDefValue && typeof blockDefValue === "object" ? blockDefValue.id : typeof blockDefValue === "string" || typeof blockDefValue === "number" ? blockDefValue : null;
|
|
469
|
+
if (defId === prevDefIdRef.current) return;
|
|
470
|
+
prevDefIdRef.current = defId;
|
|
471
|
+
if (!defId) {
|
|
472
|
+
setVersion(null);
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
fetch(`/api/block-definitions/${String(defId)}?depth=1`, { credentials: "same-origin" }).then((r) => r.ok ? r.json() : null).then((doc) => {
|
|
476
|
+
if (!doc) return;
|
|
477
|
+
const currentVersion = doc.currentVersion;
|
|
478
|
+
if (!currentVersion) return;
|
|
479
|
+
const versionId = typeof currentVersion === "object" ? currentVersion.id : currentVersion;
|
|
480
|
+
if (versionId) setVersion(versionId);
|
|
481
|
+
}).catch(() => {
|
|
482
|
+
});
|
|
483
|
+
}, [blockDefValue, setVersion]);
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// src/components/SchemaBuilderField/index.tsx
|
|
488
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
489
|
+
var import_ui3 = require("@payloadcms/ui");
|
|
393
490
|
|
|
394
491
|
// src/components/SchemaBuilderField/FieldRow.tsx
|
|
395
|
-
var
|
|
492
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
396
493
|
|
|
397
494
|
// src/components/SchemaBuilderField/OptionsEditor.tsx
|
|
398
|
-
var
|
|
495
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
399
496
|
function OptionsEditor({ options, onChange, readOnly }) {
|
|
400
497
|
function addOption() {
|
|
401
498
|
onChange([...options, { label: "", value: "" }]);
|
|
@@ -406,7 +503,7 @@ function OptionsEditor({ options, onChange, readOnly }) {
|
|
|
406
503
|
function removeOption(index) {
|
|
407
504
|
onChange(options.filter((_, i) => i !== index));
|
|
408
505
|
}
|
|
409
|
-
return /* @__PURE__ */
|
|
506
|
+
return /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 6 } }, /* @__PURE__ */ import_react3.default.createElement(
|
|
410
507
|
"span",
|
|
411
508
|
{
|
|
412
509
|
style: {
|
|
@@ -421,8 +518,8 @@ function OptionsEditor({ options, onChange, readOnly }) {
|
|
|
421
518
|
}
|
|
422
519
|
},
|
|
423
520
|
"Options",
|
|
424
|
-
options.length > 0 && /* @__PURE__ */
|
|
425
|
-
), options.length === 0 && /* @__PURE__ */
|
|
521
|
+
options.length > 0 && /* @__PURE__ */ import_react3.default.createElement("span", { style: { marginLeft: 6, fontSize: 11, color: "var(--theme-elevation-400)", fontWeight: 400 } }, "(", options.length, ")")
|
|
522
|
+
), options.length === 0 && /* @__PURE__ */ import_react3.default.createElement(
|
|
426
523
|
"p",
|
|
427
524
|
{
|
|
428
525
|
style: {
|
|
@@ -434,7 +531,7 @@ function OptionsEditor({ options, onChange, readOnly }) {
|
|
|
434
531
|
}
|
|
435
532
|
},
|
|
436
533
|
"No options yet."
|
|
437
|
-
), options.map((opt, i) => /* @__PURE__ */
|
|
534
|
+
), options.map((opt, i) => /* @__PURE__ */ import_react3.default.createElement("div", { key: i, className: "sbf-options-row" }, /* @__PURE__ */ import_react3.default.createElement(
|
|
438
535
|
"input",
|
|
439
536
|
{
|
|
440
537
|
className: "sbf-input",
|
|
@@ -444,7 +541,7 @@ function OptionsEditor({ options, onChange, readOnly }) {
|
|
|
444
541
|
disabled: readOnly,
|
|
445
542
|
onChange: (e) => updateOption(i, "label", e.target.value)
|
|
446
543
|
}
|
|
447
|
-
), /* @__PURE__ */
|
|
544
|
+
), /* @__PURE__ */ import_react3.default.createElement(
|
|
448
545
|
"input",
|
|
449
546
|
{
|
|
450
547
|
className: "sbf-input",
|
|
@@ -454,7 +551,7 @@ function OptionsEditor({ options, onChange, readOnly }) {
|
|
|
454
551
|
disabled: readOnly,
|
|
455
552
|
onChange: (e) => updateOption(i, "value", e.target.value)
|
|
456
553
|
}
|
|
457
|
-
), !readOnly && /* @__PURE__ */
|
|
554
|
+
), !readOnly && /* @__PURE__ */ import_react3.default.createElement(
|
|
458
555
|
"button",
|
|
459
556
|
{
|
|
460
557
|
type: "button",
|
|
@@ -463,37 +560,37 @@ function OptionsEditor({ options, onChange, readOnly }) {
|
|
|
463
560
|
onClick: () => removeOption(i)
|
|
464
561
|
},
|
|
465
562
|
"x"
|
|
466
|
-
))), !readOnly && /* @__PURE__ */
|
|
563
|
+
))), !readOnly && /* @__PURE__ */ import_react3.default.createElement(
|
|
467
564
|
"button",
|
|
468
565
|
{
|
|
469
566
|
type: "button",
|
|
470
567
|
className: "sbf-add-btn sbf-add-btn--small",
|
|
471
568
|
onClick: addOption
|
|
472
569
|
},
|
|
473
|
-
/* @__PURE__ */
|
|
570
|
+
/* @__PURE__ */ import_react3.default.createElement("span", { className: "sbf-add-btn__icon" }, "+"),
|
|
474
571
|
"Add Option"
|
|
475
572
|
));
|
|
476
573
|
}
|
|
477
574
|
|
|
478
575
|
// src/components/SchemaBuilderField/NestedFieldsEditor.tsx
|
|
479
|
-
var
|
|
576
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
480
577
|
function NestedFieldsEditor({ fields, onChange, readOnly, depth = 1 }) {
|
|
481
|
-
const addField = (0,
|
|
578
|
+
const addField = (0, import_react4.useCallback)(() => {
|
|
482
579
|
onChange([...fields, { name: "", type: "text", label: "", required: false }]);
|
|
483
580
|
}, [fields, onChange]);
|
|
484
|
-
const updateField = (0,
|
|
581
|
+
const updateField = (0, import_react4.useCallback)(
|
|
485
582
|
(index, updated) => {
|
|
486
583
|
onChange(fields.map((f, i) => i === index ? updated : f));
|
|
487
584
|
},
|
|
488
585
|
[fields, onChange]
|
|
489
586
|
);
|
|
490
|
-
const removeField = (0,
|
|
587
|
+
const removeField = (0, import_react4.useCallback)(
|
|
491
588
|
(index) => {
|
|
492
589
|
onChange(fields.filter((_, i) => i !== index));
|
|
493
590
|
},
|
|
494
591
|
[fields, onChange]
|
|
495
592
|
);
|
|
496
|
-
const moveField = (0,
|
|
593
|
+
const moveField = (0, import_react4.useCallback)(
|
|
497
594
|
(index, dir) => {
|
|
498
595
|
const next = [...fields];
|
|
499
596
|
const target = index + dir;
|
|
@@ -503,7 +600,7 @@ function NestedFieldsEditor({ fields, onChange, readOnly, depth = 1 }) {
|
|
|
503
600
|
},
|
|
504
601
|
[fields, onChange]
|
|
505
602
|
);
|
|
506
|
-
return /* @__PURE__ */
|
|
603
|
+
return /* @__PURE__ */ import_react4.default.createElement("div", { className: "sbf-nested" }, /* @__PURE__ */ import_react4.default.createElement(
|
|
507
604
|
"span",
|
|
508
605
|
{
|
|
509
606
|
style: {
|
|
@@ -518,8 +615,8 @@ function NestedFieldsEditor({ fields, onChange, readOnly, depth = 1 }) {
|
|
|
518
615
|
}
|
|
519
616
|
},
|
|
520
617
|
"Nested fields",
|
|
521
|
-
fields.length > 0 && /* @__PURE__ */
|
|
522
|
-
), fields.length === 0 && /* @__PURE__ */
|
|
618
|
+
fields.length > 0 && /* @__PURE__ */ import_react4.default.createElement("span", { style: { marginLeft: 6, fontSize: 11, color: "var(--theme-elevation-400)", fontWeight: 400 } }, "(", fields.length, ")")
|
|
619
|
+
), fields.length === 0 && /* @__PURE__ */ import_react4.default.createElement(
|
|
523
620
|
"p",
|
|
524
621
|
{
|
|
525
622
|
style: {
|
|
@@ -531,7 +628,7 @@ function NestedFieldsEditor({ fields, onChange, readOnly, depth = 1 }) {
|
|
|
531
628
|
}
|
|
532
629
|
},
|
|
533
630
|
"No nested fields yet."
|
|
534
|
-
), fields.length > 0 && /* @__PURE__ */
|
|
631
|
+
), fields.length > 0 && /* @__PURE__ */ import_react4.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "calc(var(--base, 16px) / 2)" } }, fields.map((field, i) => /* @__PURE__ */ import_react4.default.createElement(
|
|
535
632
|
FieldRow,
|
|
536
633
|
{
|
|
537
634
|
key: i,
|
|
@@ -545,14 +642,14 @@ function NestedFieldsEditor({ fields, onChange, readOnly, depth = 1 }) {
|
|
|
545
642
|
readOnly,
|
|
546
643
|
depth
|
|
547
644
|
}
|
|
548
|
-
))), !readOnly && /* @__PURE__ */
|
|
645
|
+
))), !readOnly && /* @__PURE__ */ import_react4.default.createElement("div", { style: { marginTop: "calc(var(--base, 16px) / 2)" } }, /* @__PURE__ */ import_react4.default.createElement(
|
|
549
646
|
"button",
|
|
550
647
|
{
|
|
551
648
|
type: "button",
|
|
552
649
|
className: "sbf-add-btn sbf-add-btn--small",
|
|
553
650
|
onClick: addField
|
|
554
651
|
},
|
|
555
|
-
/* @__PURE__ */
|
|
652
|
+
/* @__PURE__ */ import_react4.default.createElement("span", { className: "sbf-add-btn__icon" }, "+"),
|
|
556
653
|
"Add Nested Field"
|
|
557
654
|
)));
|
|
558
655
|
}
|
|
@@ -599,10 +696,10 @@ var TYPE_BADGE_COLORS = {
|
|
|
599
696
|
blocks: "var(--theme-elevation-150)"
|
|
600
697
|
};
|
|
601
698
|
function FieldLabel({ children, required }) {
|
|
602
|
-
return /* @__PURE__ */
|
|
699
|
+
return /* @__PURE__ */ import_react5.default.createElement("label", { className: `sbf-label${required ? " sbf-label--required" : ""}` }, children);
|
|
603
700
|
}
|
|
604
701
|
function FieldWrap({ children }) {
|
|
605
|
-
return /* @__PURE__ */
|
|
702
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { style: { display: "flex", flexDirection: "column" } }, children);
|
|
606
703
|
}
|
|
607
704
|
function FieldRow({
|
|
608
705
|
index,
|
|
@@ -614,9 +711,9 @@ function FieldRow({
|
|
|
614
711
|
readOnly,
|
|
615
712
|
depth = 0
|
|
616
713
|
}) {
|
|
617
|
-
const [expanded, setExpanded] = (0,
|
|
618
|
-
const [showAdmin, setShowAdmin] = (0,
|
|
619
|
-
const [showConditions, setShowConditions] = (0,
|
|
714
|
+
const [expanded, setExpanded] = (0, import_react5.useState)(false);
|
|
715
|
+
const [showAdmin, setShowAdmin] = (0, import_react5.useState)(false);
|
|
716
|
+
const [showConditions, setShowConditions] = (0, import_react5.useState)(false);
|
|
620
717
|
const maxDepth = 3;
|
|
621
718
|
const canNest = depth < maxDepth;
|
|
622
719
|
const needsOptions = field.type === "select" || field.type === "multiselect";
|
|
@@ -625,7 +722,7 @@ function FieldRow({
|
|
|
625
722
|
onChange({ ...field, [key]: val });
|
|
626
723
|
}
|
|
627
724
|
const badgeBg = TYPE_BADGE_COLORS[field.type] ?? "var(--theme-elevation-150)";
|
|
628
|
-
return /* @__PURE__ */
|
|
725
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: `sbf-row${expanded ? "" : " sbf-row--collapsed"}` }, /* @__PURE__ */ import_react5.default.createElement(
|
|
629
726
|
"div",
|
|
630
727
|
{
|
|
631
728
|
className: "sbf-row__header",
|
|
@@ -633,7 +730,7 @@ function FieldRow({
|
|
|
633
730
|
"aria-expanded": expanded,
|
|
634
731
|
onClick: () => setExpanded((p) => !p)
|
|
635
732
|
},
|
|
636
|
-
/* @__PURE__ */
|
|
733
|
+
/* @__PURE__ */ import_react5.default.createElement(
|
|
637
734
|
"span",
|
|
638
735
|
{
|
|
639
736
|
style: {
|
|
@@ -650,9 +747,9 @@ function FieldRow({
|
|
|
650
747
|
},
|
|
651
748
|
">"
|
|
652
749
|
),
|
|
653
|
-
/* @__PURE__ */
|
|
654
|
-
field.required && /* @__PURE__ */
|
|
655
|
-
/* @__PURE__ */
|
|
750
|
+
/* @__PURE__ */ import_react5.default.createElement("span", { className: `sbf-row__label${!field.name ? " sbf-row__label--empty" : ""}` }, field.name || "unnamed field"),
|
|
751
|
+
field.required && /* @__PURE__ */ import_react5.default.createElement("span", { style: { color: "var(--theme-error-500, #ef4444)", fontSize: 16, lineHeight: 1, flexShrink: 0 } }, "*"),
|
|
752
|
+
/* @__PURE__ */ import_react5.default.createElement(
|
|
656
753
|
"span",
|
|
657
754
|
{
|
|
658
755
|
className: "sbf-type-badge",
|
|
@@ -660,15 +757,15 @@ function FieldRow({
|
|
|
660
757
|
},
|
|
661
758
|
field.type
|
|
662
759
|
),
|
|
663
|
-
!readOnly && /* @__PURE__ */
|
|
760
|
+
!readOnly && /* @__PURE__ */ import_react5.default.createElement(
|
|
664
761
|
"div",
|
|
665
762
|
{
|
|
666
763
|
style: { display: "flex", gap: 2, flexShrink: 0, alignItems: "center" },
|
|
667
764
|
onClick: (e) => e.stopPropagation()
|
|
668
765
|
},
|
|
669
|
-
onMoveUp && /* @__PURE__ */
|
|
670
|
-
onMoveDown && /* @__PURE__ */
|
|
671
|
-
/* @__PURE__ */
|
|
766
|
+
onMoveUp && /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "sbf-icon-btn", onClick: onMoveUp, title: "Move up" }, "^"),
|
|
767
|
+
onMoveDown && /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "sbf-icon-btn", onClick: onMoveDown, title: "Move down" }, "v"),
|
|
768
|
+
/* @__PURE__ */ import_react5.default.createElement(
|
|
672
769
|
"button",
|
|
673
770
|
{
|
|
674
771
|
type: "button",
|
|
@@ -679,7 +776,7 @@ function FieldRow({
|
|
|
679
776
|
"x"
|
|
680
777
|
)
|
|
681
778
|
)
|
|
682
|
-
), expanded && /* @__PURE__ */
|
|
779
|
+
), expanded && /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-row__content" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-grid-2" }, /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, { required: true }, "Field Name"), /* @__PURE__ */ import_react5.default.createElement(
|
|
683
780
|
"input",
|
|
684
781
|
{
|
|
685
782
|
className: "sbf-input",
|
|
@@ -689,7 +786,7 @@ function FieldRow({
|
|
|
689
786
|
disabled: readOnly,
|
|
690
787
|
onChange: (e) => set("name", e.target.value)
|
|
691
788
|
}
|
|
692
|
-
)), /* @__PURE__ */
|
|
789
|
+
)), /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, { required: true }, "Type"), /* @__PURE__ */ import_react5.default.createElement(
|
|
693
790
|
"select",
|
|
694
791
|
{
|
|
695
792
|
className: "sbf-input sbf-select",
|
|
@@ -697,8 +794,8 @@ function FieldRow({
|
|
|
697
794
|
disabled: readOnly,
|
|
698
795
|
onChange: (e) => set("type", e.target.value)
|
|
699
796
|
},
|
|
700
|
-
ALL_FIELD_TYPES.map((t) => /* @__PURE__ */
|
|
701
|
-
))), /* @__PURE__ */
|
|
797
|
+
ALL_FIELD_TYPES.map((t) => /* @__PURE__ */ import_react5.default.createElement("option", { key: t, value: t }, t))
|
|
798
|
+
))), /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Label"), /* @__PURE__ */ import_react5.default.createElement(
|
|
702
799
|
"input",
|
|
703
800
|
{
|
|
704
801
|
className: "sbf-input",
|
|
@@ -708,7 +805,7 @@ function FieldRow({
|
|
|
708
805
|
disabled: readOnly,
|
|
709
806
|
onChange: (e) => set("label", e.target.value)
|
|
710
807
|
}
|
|
711
|
-
)), /* @__PURE__ */
|
|
808
|
+
)), /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-flags-row" }, /* @__PURE__ */ import_react5.default.createElement("label", { className: "sbf-checkbox-wrap" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
712
809
|
"input",
|
|
713
810
|
{
|
|
714
811
|
type: "checkbox",
|
|
@@ -716,7 +813,7 @@ function FieldRow({
|
|
|
716
813
|
disabled: readOnly,
|
|
717
814
|
onChange: (e) => set("required", e.target.checked)
|
|
718
815
|
}
|
|
719
|
-
), /* @__PURE__ */
|
|
816
|
+
), /* @__PURE__ */ import_react5.default.createElement("span", { className: "sbf-checkbox-label" }, "Required"))), field.type === "number" && /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-grid-2" }, /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Min"), /* @__PURE__ */ import_react5.default.createElement(
|
|
720
817
|
"input",
|
|
721
818
|
{
|
|
722
819
|
className: "sbf-input",
|
|
@@ -725,7 +822,7 @@ function FieldRow({
|
|
|
725
822
|
disabled: readOnly,
|
|
726
823
|
onChange: (e) => set("min", e.target.value === "" ? void 0 : e.target.valueAsNumber)
|
|
727
824
|
}
|
|
728
|
-
)), /* @__PURE__ */
|
|
825
|
+
)), /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Max"), /* @__PURE__ */ import_react5.default.createElement(
|
|
729
826
|
"input",
|
|
730
827
|
{
|
|
731
828
|
className: "sbf-input",
|
|
@@ -734,7 +831,7 @@ function FieldRow({
|
|
|
734
831
|
disabled: readOnly,
|
|
735
832
|
onChange: (e) => set("max", e.target.value === "" ? void 0 : e.target.valueAsNumber)
|
|
736
833
|
}
|
|
737
|
-
))), (field.type === "text" || field.type === "textarea") && /* @__PURE__ */
|
|
834
|
+
))), (field.type === "text" || field.type === "textarea") && /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-grid-2" }, /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Min Length"), /* @__PURE__ */ import_react5.default.createElement(
|
|
738
835
|
"input",
|
|
739
836
|
{
|
|
740
837
|
className: "sbf-input",
|
|
@@ -743,7 +840,7 @@ function FieldRow({
|
|
|
743
840
|
disabled: readOnly,
|
|
744
841
|
onChange: (e) => set("minLength", e.target.value === "" ? void 0 : e.target.valueAsNumber)
|
|
745
842
|
}
|
|
746
|
-
)), /* @__PURE__ */
|
|
843
|
+
)), /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Max Length"), /* @__PURE__ */ import_react5.default.createElement(
|
|
747
844
|
"input",
|
|
748
845
|
{
|
|
749
846
|
className: "sbf-input",
|
|
@@ -752,7 +849,7 @@ function FieldRow({
|
|
|
752
849
|
disabled: readOnly,
|
|
753
850
|
onChange: (e) => set("maxLength", e.target.value === "" ? void 0 : e.target.valueAsNumber)
|
|
754
851
|
}
|
|
755
|
-
))), field.type === "array" && /* @__PURE__ */
|
|
852
|
+
))), field.type === "array" && /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-grid-2" }, /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Min Rows"), /* @__PURE__ */ import_react5.default.createElement(
|
|
756
853
|
"input",
|
|
757
854
|
{
|
|
758
855
|
className: "sbf-input",
|
|
@@ -761,7 +858,7 @@ function FieldRow({
|
|
|
761
858
|
disabled: readOnly,
|
|
762
859
|
onChange: (e) => set("minRows", e.target.value === "" ? void 0 : e.target.valueAsNumber)
|
|
763
860
|
}
|
|
764
|
-
)), /* @__PURE__ */
|
|
861
|
+
)), /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Max Rows"), /* @__PURE__ */ import_react5.default.createElement(
|
|
765
862
|
"input",
|
|
766
863
|
{
|
|
767
864
|
className: "sbf-input",
|
|
@@ -770,7 +867,7 @@ function FieldRow({
|
|
|
770
867
|
disabled: readOnly,
|
|
771
868
|
onChange: (e) => set("maxRows", e.target.value === "" ? void 0 : e.target.valueAsNumber)
|
|
772
869
|
}
|
|
773
|
-
))), field.type === "relationship" && /* @__PURE__ */
|
|
870
|
+
))), field.type === "relationship" && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, { required: true }, "Collection slug"), /* @__PURE__ */ import_react5.default.createElement(
|
|
774
871
|
"input",
|
|
775
872
|
{
|
|
776
873
|
className: "sbf-input",
|
|
@@ -780,7 +877,7 @@ function FieldRow({
|
|
|
780
877
|
disabled: readOnly,
|
|
781
878
|
onChange: (e) => set("collection", e.target.value)
|
|
782
879
|
}
|
|
783
|
-
)), /* @__PURE__ */
|
|
880
|
+
)), /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-flags-row" }, /* @__PURE__ */ import_react5.default.createElement("label", { className: "sbf-checkbox-wrap" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
784
881
|
"input",
|
|
785
882
|
{
|
|
786
883
|
type: "checkbox",
|
|
@@ -788,14 +885,14 @@ function FieldRow({
|
|
|
788
885
|
disabled: readOnly,
|
|
789
886
|
onChange: (e) => set("hasMany", e.target.checked)
|
|
790
887
|
}
|
|
791
|
-
), /* @__PURE__ */
|
|
888
|
+
), /* @__PURE__ */ import_react5.default.createElement("span", { className: "sbf-checkbox-label" }, "Has Many")))), needsOptions && /* @__PURE__ */ import_react5.default.createElement(
|
|
792
889
|
OptionsEditor,
|
|
793
890
|
{
|
|
794
891
|
options: field.options ?? [],
|
|
795
892
|
onChange: (opts) => set("options", opts),
|
|
796
893
|
readOnly
|
|
797
894
|
}
|
|
798
|
-
), needsNested && canNest && /* @__PURE__ */
|
|
895
|
+
), needsNested && canNest && /* @__PURE__ */ import_react5.default.createElement(
|
|
799
896
|
NestedFieldsEditor,
|
|
800
897
|
{
|
|
801
898
|
fields: field.fields ?? [],
|
|
@@ -803,7 +900,7 @@ function FieldRow({
|
|
|
803
900
|
readOnly,
|
|
804
901
|
depth: depth + 1
|
|
805
902
|
}
|
|
806
|
-
), needsNested && !canNest && /* @__PURE__ */
|
|
903
|
+
), needsNested && !canNest && /* @__PURE__ */ import_react5.default.createElement("span", { className: "sbf-description" }, "Maximum nesting depth (", depth, ") reached."), /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-section" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
807
904
|
"button",
|
|
808
905
|
{
|
|
809
906
|
type: "button",
|
|
@@ -811,8 +908,8 @@ function FieldRow({
|
|
|
811
908
|
onClick: () => setShowAdmin((p) => !p)
|
|
812
909
|
},
|
|
813
910
|
"Admin & UI settings",
|
|
814
|
-
/* @__PURE__ */
|
|
815
|
-
), showAdmin && /* @__PURE__ */
|
|
911
|
+
/* @__PURE__ */ import_react5.default.createElement("span", { className: "sbf-section__toggle-icon" }, ">")
|
|
912
|
+
), showAdmin && /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-section__body" }, /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Description"), /* @__PURE__ */ import_react5.default.createElement(
|
|
816
913
|
"input",
|
|
817
914
|
{
|
|
818
915
|
className: "sbf-input",
|
|
@@ -822,7 +919,7 @@ function FieldRow({
|
|
|
822
919
|
disabled: readOnly,
|
|
823
920
|
onChange: (e) => set("admin", { ...field.admin, description: e.target.value })
|
|
824
921
|
}
|
|
825
|
-
)), /* @__PURE__ */
|
|
922
|
+
)), /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Placeholder"), /* @__PURE__ */ import_react5.default.createElement(
|
|
826
923
|
"input",
|
|
827
924
|
{
|
|
828
925
|
className: "sbf-input",
|
|
@@ -832,7 +929,7 @@ function FieldRow({
|
|
|
832
929
|
disabled: readOnly,
|
|
833
930
|
onChange: (e) => set("admin", { ...field.admin, placeholder: e.target.value })
|
|
834
931
|
}
|
|
835
|
-
)), /* @__PURE__ */
|
|
932
|
+
)), /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-flags-row" }, /* @__PURE__ */ import_react5.default.createElement("label", { className: "sbf-checkbox-wrap" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
836
933
|
"input",
|
|
837
934
|
{
|
|
838
935
|
type: "checkbox",
|
|
@@ -840,7 +937,7 @@ function FieldRow({
|
|
|
840
937
|
disabled: readOnly,
|
|
841
938
|
onChange: (e) => set("admin", { ...field.admin, readOnly: e.target.checked })
|
|
842
939
|
}
|
|
843
|
-
), /* @__PURE__ */
|
|
940
|
+
), /* @__PURE__ */ import_react5.default.createElement("span", { className: "sbf-checkbox-label" }, "Read Only")), /* @__PURE__ */ import_react5.default.createElement("label", { className: "sbf-checkbox-wrap" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
844
941
|
"input",
|
|
845
942
|
{
|
|
846
943
|
type: "checkbox",
|
|
@@ -848,7 +945,7 @@ function FieldRow({
|
|
|
848
945
|
disabled: readOnly,
|
|
849
946
|
onChange: (e) => set("admin", { ...field.admin, hidden: e.target.checked })
|
|
850
947
|
}
|
|
851
|
-
), /* @__PURE__ */
|
|
948
|
+
), /* @__PURE__ */ import_react5.default.createElement("span", { className: "sbf-checkbox-label" }, "Hidden"))))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-section" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
852
949
|
"button",
|
|
853
950
|
{
|
|
854
951
|
type: "button",
|
|
@@ -856,7 +953,7 @@ function FieldRow({
|
|
|
856
953
|
onClick: () => setShowConditions((p) => !p)
|
|
857
954
|
},
|
|
858
955
|
"Conditional logic",
|
|
859
|
-
(field.conditions?.length ?? 0) > 0 && /* @__PURE__ */
|
|
956
|
+
(field.conditions?.length ?? 0) > 0 && /* @__PURE__ */ import_react5.default.createElement(
|
|
860
957
|
"span",
|
|
861
958
|
{
|
|
862
959
|
style: {
|
|
@@ -870,8 +967,8 @@ function FieldRow({
|
|
|
870
967
|
" rule",
|
|
871
968
|
field.conditions.length !== 1 ? "s" : ""
|
|
872
969
|
),
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
), showConditions && /* @__PURE__ */
|
|
970
|
+
/* @__PURE__ */ import_react5.default.createElement("span", { className: "sbf-section__toggle-icon" }, ">")
|
|
971
|
+
), showConditions && /* @__PURE__ */ import_react5.default.createElement("div", { className: "sbf-section__body" }, /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Condition Mode"), /* @__PURE__ */ import_react5.default.createElement(
|
|
875
972
|
"select",
|
|
876
973
|
{
|
|
877
974
|
className: "sbf-input sbf-select",
|
|
@@ -880,9 +977,9 @@ function FieldRow({
|
|
|
880
977
|
onChange: (e) => set("conditionMode", e.target.value),
|
|
881
978
|
style: { width: "auto", minWidth: 240 }
|
|
882
979
|
},
|
|
883
|
-
/* @__PURE__ */
|
|
884
|
-
/* @__PURE__ */
|
|
885
|
-
)), (field.conditions ?? []).map((cond, ci) => /* @__PURE__ */
|
|
980
|
+
/* @__PURE__ */ import_react5.default.createElement("option", { value: "AND" }, "AND - all conditions must match"),
|
|
981
|
+
/* @__PURE__ */ import_react5.default.createElement("option", { value: "OR" }, "OR - any condition must match")
|
|
982
|
+
)), (field.conditions ?? []).map((cond, ci) => /* @__PURE__ */ import_react5.default.createElement("div", { key: ci, className: "sbf-conditions-grid" }, /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Field"), /* @__PURE__ */ import_react5.default.createElement(
|
|
886
983
|
"input",
|
|
887
984
|
{
|
|
888
985
|
className: "sbf-input",
|
|
@@ -896,7 +993,7 @@ function FieldRow({
|
|
|
896
993
|
set("conditions", next);
|
|
897
994
|
}
|
|
898
995
|
}
|
|
899
|
-
)), /* @__PURE__ */
|
|
996
|
+
)), /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Operator"), /* @__PURE__ */ import_react5.default.createElement(
|
|
900
997
|
"select",
|
|
901
998
|
{
|
|
902
999
|
className: "sbf-input sbf-select",
|
|
@@ -908,8 +1005,8 @@ function FieldRow({
|
|
|
908
1005
|
set("conditions", next);
|
|
909
1006
|
}
|
|
910
1007
|
},
|
|
911
|
-
["equals", "not_equals", "contains", "not_contains", "greater_than", "less_than", "in", "not_in", "exists", "empty"].map((op) => /* @__PURE__ */
|
|
912
|
-
)), /* @__PURE__ */
|
|
1008
|
+
["equals", "not_equals", "contains", "not_contains", "greater_than", "less_than", "in", "not_in", "exists", "empty"].map((op) => /* @__PURE__ */ import_react5.default.createElement("option", { key: op, value: op }, op.replace(/_/g, " ")))
|
|
1009
|
+
)), /* @__PURE__ */ import_react5.default.createElement(FieldWrap, null, /* @__PURE__ */ import_react5.default.createElement(FieldLabel, null, "Value"), /* @__PURE__ */ import_react5.default.createElement(
|
|
913
1010
|
"input",
|
|
914
1011
|
{
|
|
915
1012
|
className: "sbf-input",
|
|
@@ -922,7 +1019,7 @@ function FieldRow({
|
|
|
922
1019
|
set("conditions", next);
|
|
923
1020
|
}
|
|
924
1021
|
}
|
|
925
|
-
)), !readOnly && /* @__PURE__ */
|
|
1022
|
+
)), !readOnly && /* @__PURE__ */ import_react5.default.createElement(
|
|
926
1023
|
"button",
|
|
927
1024
|
{
|
|
928
1025
|
type: "button",
|
|
@@ -934,7 +1031,7 @@ function FieldRow({
|
|
|
934
1031
|
}
|
|
935
1032
|
},
|
|
936
1033
|
"x"
|
|
937
|
-
))), !readOnly && /* @__PURE__ */
|
|
1034
|
+
))), !readOnly && /* @__PURE__ */ import_react5.default.createElement(
|
|
938
1035
|
"button",
|
|
939
1036
|
{
|
|
940
1037
|
type: "button",
|
|
@@ -946,7 +1043,7 @@ function FieldRow({
|
|
|
946
1043
|
]);
|
|
947
1044
|
}
|
|
948
1045
|
},
|
|
949
|
-
/* @__PURE__ */
|
|
1046
|
+
/* @__PURE__ */ import_react5.default.createElement("span", { className: "sbf-add-btn__icon" }, "+"),
|
|
950
1047
|
"Add Condition"
|
|
951
1048
|
)))));
|
|
952
1049
|
}
|
|
@@ -963,38 +1060,38 @@ function parseSchema(raw) {
|
|
|
963
1060
|
return [];
|
|
964
1061
|
}
|
|
965
1062
|
function SchemaBuilderField({ path, readOnly }) {
|
|
966
|
-
const { value, setValue } = (0,
|
|
967
|
-
const setValueRef = (0,
|
|
968
|
-
(0,
|
|
1063
|
+
const { value, setValue } = (0, import_ui3.useField)({ path });
|
|
1064
|
+
const setValueRef = (0, import_react6.useRef)(setValue);
|
|
1065
|
+
(0, import_react6.useEffect)(() => {
|
|
969
1066
|
setValueRef.current = setValue;
|
|
970
1067
|
});
|
|
971
|
-
const [fields, setFields] = (0,
|
|
1068
|
+
const [fields, setFields] = (0, import_react6.useState)(() => parseSchema(value));
|
|
972
1069
|
const hasExistingValue = value !== void 0 && value !== null;
|
|
973
|
-
const [hydrated, setHydrated] = (0,
|
|
974
|
-
(0,
|
|
1070
|
+
const [hydrated, setHydrated] = (0, import_react6.useState)(!hasExistingValue);
|
|
1071
|
+
(0, import_react6.useEffect)(() => {
|
|
975
1072
|
if (hydrated) return;
|
|
976
1073
|
if (value !== void 0 && value !== null) {
|
|
977
1074
|
setFields(parseSchema(value));
|
|
978
1075
|
setHydrated(true);
|
|
979
1076
|
}
|
|
980
1077
|
}, [value, hydrated]);
|
|
981
|
-
(0,
|
|
1078
|
+
(0, import_react6.useEffect)(() => {
|
|
982
1079
|
if (!hydrated) return;
|
|
983
1080
|
setValueRef.current({ fields });
|
|
984
1081
|
}, [fields, hydrated]);
|
|
985
|
-
const addField = (0,
|
|
1082
|
+
const addField = (0, import_react6.useCallback)(() => {
|
|
986
1083
|
setFields((prev) => [
|
|
987
1084
|
...prev,
|
|
988
1085
|
{ name: "", type: "text", label: "", required: false }
|
|
989
1086
|
]);
|
|
990
1087
|
}, []);
|
|
991
|
-
const updateField = (0,
|
|
1088
|
+
const updateField = (0, import_react6.useCallback)((index, updated) => {
|
|
992
1089
|
setFields((prev) => prev.map((f, i) => i === index ? updated : f));
|
|
993
1090
|
}, []);
|
|
994
|
-
const removeField = (0,
|
|
1091
|
+
const removeField = (0, import_react6.useCallback)((index) => {
|
|
995
1092
|
setFields((prev) => prev.filter((_, i) => i !== index));
|
|
996
1093
|
}, []);
|
|
997
|
-
const moveField = (0,
|
|
1094
|
+
const moveField = (0, import_react6.useCallback)((index, dir) => {
|
|
998
1095
|
setFields((prev) => {
|
|
999
1096
|
const next = [...prev];
|
|
1000
1097
|
const target = index + dir;
|
|
@@ -1003,7 +1100,7 @@ function SchemaBuilderField({ path, readOnly }) {
|
|
|
1003
1100
|
return next;
|
|
1004
1101
|
});
|
|
1005
1102
|
}, []);
|
|
1006
|
-
return /* @__PURE__ */
|
|
1103
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", null, /* @__PURE__ */ import_react6.default.createElement("div", { className: "sbf-section-heading" }, /* @__PURE__ */ import_react6.default.createElement("span", { className: "sbf-section-label" }, "Fields", fields.length > 0 && /* @__PURE__ */ import_react6.default.createElement(
|
|
1007
1104
|
"span",
|
|
1008
1105
|
{
|
|
1009
1106
|
style: {
|
|
@@ -1016,7 +1113,7 @@ function SchemaBuilderField({ path, readOnly }) {
|
|
|
1016
1113
|
"(",
|
|
1017
1114
|
fields.length,
|
|
1018
1115
|
")"
|
|
1019
|
-
))), fields.length === 0 ? /* @__PURE__ */
|
|
1116
|
+
))), fields.length === 0 ? /* @__PURE__ */ import_react6.default.createElement("div", { className: "sbf-empty" }, "No fields defined. Click \u201CAdd Field\u201D below to add the first field to this block schema.") : /* @__PURE__ */ import_react6.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "calc(var(--base, 16px) / 2)" } }, fields.map((field, i) => /* @__PURE__ */ import_react6.default.createElement(
|
|
1020
1117
|
FieldRow,
|
|
1021
1118
|
{
|
|
1022
1119
|
key: i,
|
|
@@ -1029,18 +1126,18 @@ function SchemaBuilderField({ path, readOnly }) {
|
|
|
1029
1126
|
onMoveDown: i < fields.length - 1 ? () => moveField(i, 1) : void 0,
|
|
1030
1127
|
readOnly
|
|
1031
1128
|
}
|
|
1032
|
-
))), !readOnly && /* @__PURE__ */
|
|
1129
|
+
))), !readOnly && /* @__PURE__ */ import_react6.default.createElement("div", { style: { marginTop: "calc(var(--base, 16px) / 2)", marginBottom: "calc(var(--base, 16px) / 2)" } }, /* @__PURE__ */ import_react6.default.createElement("button", { type: "button", className: "sbf-add-btn", onClick: addField }, /* @__PURE__ */ import_react6.default.createElement("span", { className: "sbf-add-btn__icon" }, "+"), "Add Field")));
|
|
1033
1130
|
}
|
|
1034
1131
|
|
|
1035
1132
|
// src/components/EditInBuilderButton/index.tsx
|
|
1036
|
-
var
|
|
1037
|
-
var import_ui3 = require("@payloadcms/ui");
|
|
1133
|
+
var import_react7 = __toESM(require("react"), 1);
|
|
1038
1134
|
var import_ui4 = require("@payloadcms/ui");
|
|
1135
|
+
var import_ui5 = require("@payloadcms/ui");
|
|
1039
1136
|
function EditInBuilderButton() {
|
|
1040
|
-
const { id } = (0,
|
|
1041
|
-
const { value: slug } = (0,
|
|
1137
|
+
const { id } = (0, import_ui4.useDocumentInfo)();
|
|
1138
|
+
const { value: slug } = (0, import_ui5.useField)({ path: "slug" });
|
|
1042
1139
|
if (!id || !slug) return null;
|
|
1043
|
-
return /* @__PURE__ */
|
|
1140
|
+
return /* @__PURE__ */ import_react7.default.createElement("div", { style: { marginTop: "1rem" } }, /* @__PURE__ */ import_react7.default.createElement(
|
|
1044
1141
|
"a",
|
|
1045
1142
|
{
|
|
1046
1143
|
href: `/block-builder?load=${slug}`,
|
|
@@ -1066,7 +1163,7 @@ function EditInBuilderButton() {
|
|
|
1066
1163
|
}
|
|
1067
1164
|
|
|
1068
1165
|
// src/block-builder/components/canvas/BuilderShell.tsx
|
|
1069
|
-
var
|
|
1166
|
+
var import_react17 = __toESM(require("react"), 1);
|
|
1070
1167
|
|
|
1071
1168
|
// src/block-builder/store/builder.store.ts
|
|
1072
1169
|
var import_zustand = require("zustand");
|
|
@@ -1223,7 +1320,7 @@ var useBuilderStore = (0, import_zustand.create)()(
|
|
|
1223
1320
|
);
|
|
1224
1321
|
|
|
1225
1322
|
// src/block-builder/components/canvas/TopBar.tsx
|
|
1226
|
-
var
|
|
1323
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
1227
1324
|
var import_lucide_react = require("lucide-react");
|
|
1228
1325
|
|
|
1229
1326
|
// src/block-builder/lib/mapToSaveRequest.ts
|
|
@@ -1378,7 +1475,7 @@ function generateIndexFile(blocks) {
|
|
|
1378
1475
|
}
|
|
1379
1476
|
|
|
1380
1477
|
// src/block-builder/components/canvas/TopBar.tsx
|
|
1381
|
-
function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersionId, onVersionSelect, onRestoreVersion, onAfterPublish }) {
|
|
1478
|
+
function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersionId, onVersionSelect, onRestoreVersion, onAfterPublish, notification, onSetNotification }) {
|
|
1382
1479
|
const blocks = useBuilderStore((s) => s.blocks);
|
|
1383
1480
|
const activeBlockId = useBuilderStore((s) => s.activeBlockId);
|
|
1384
1481
|
const activeBlock = blocks.find((b) => b.id === activeBlockId);
|
|
@@ -1386,21 +1483,21 @@ function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersio
|
|
|
1386
1483
|
const isDirty = useBuilderStore((s) => s.isDirty);
|
|
1387
1484
|
const isReadOnly = useBuilderStore((s) => s.isReadOnly);
|
|
1388
1485
|
const setVersionMeta = useBuilderStore((s) => s.setVersionMeta);
|
|
1389
|
-
const
|
|
1390
|
-
const [versionDropdownOpen, setVersionDropdownOpen] = (0,
|
|
1391
|
-
const [blockPickerOpen, setBlockPickerOpen] = (0,
|
|
1392
|
-
const dropdownRef = (0,
|
|
1393
|
-
const blockPickerRef = (0,
|
|
1486
|
+
const setNotification = onSetNotification;
|
|
1487
|
+
const [versionDropdownOpen, setVersionDropdownOpen] = (0, import_react8.useState)(false);
|
|
1488
|
+
const [blockPickerOpen, setBlockPickerOpen] = (0, import_react8.useState)(false);
|
|
1489
|
+
const dropdownRef = (0, import_react8.useRef)(null);
|
|
1490
|
+
const blockPickerRef = (0, import_react8.useRef)(null);
|
|
1394
1491
|
const selectedVersion = versions.find((v) => v.id === selectedVersionId);
|
|
1395
1492
|
const currentVersion = versions.find((v) => v.isCurrent);
|
|
1396
1493
|
const activeBlockDef = blockDefs.find((b) => b.slug === activeSlug);
|
|
1397
|
-
(0,
|
|
1494
|
+
(0, import_react8.useEffect)(() => {
|
|
1398
1495
|
if (notification?.status === "success") {
|
|
1399
1496
|
const t = setTimeout(() => setNotification(null), 3e3);
|
|
1400
1497
|
return () => clearTimeout(t);
|
|
1401
1498
|
}
|
|
1402
1499
|
}, [notification]);
|
|
1403
|
-
(0,
|
|
1500
|
+
(0, import_react8.useEffect)(() => {
|
|
1404
1501
|
function handleClick(e) {
|
|
1405
1502
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
1406
1503
|
setVersionDropdownOpen(false);
|
|
@@ -1467,17 +1564,17 @@ function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersio
|
|
|
1467
1564
|
function formatDate(iso) {
|
|
1468
1565
|
return new Date(iso).toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
1469
1566
|
}
|
|
1470
|
-
return /* @__PURE__ */
|
|
1567
|
+
return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-topbar" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-topbar__brand" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-topbar__title" }, "Block Builder"), isDirty && !isReadOnly && /* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-topbar__dirty" }, "* unsaved")), /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-topbar__selectors" }, blockDefs.length > 0 && /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-block-picker", ref: blockPickerRef }, /* @__PURE__ */ import_react8.default.createElement(
|
|
1471
1568
|
"button",
|
|
1472
1569
|
{
|
|
1473
1570
|
type: "button",
|
|
1474
1571
|
className: "bb-block-picker__trigger",
|
|
1475
1572
|
onClick: () => setBlockPickerOpen((o) => !o)
|
|
1476
1573
|
},
|
|
1477
|
-
/* @__PURE__ */
|
|
1478
|
-
/* @__PURE__ */
|
|
1479
|
-
/* @__PURE__ */
|
|
1480
|
-
), blockPickerOpen && /* @__PURE__ */
|
|
1574
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react.Blocks, { size: 14, strokeWidth: 1.75, className: "bb-block-picker__icon" }),
|
|
1575
|
+
/* @__PURE__ */ import_react8.default.createElement("span", null, activeBlockDef?.name ?? activeSlug ?? "Select a block"),
|
|
1576
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react.ChevronDown, { size: 14, strokeWidth: 1.75, className: "bb-version-selector__chevron" })
|
|
1577
|
+
), blockPickerOpen && /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-block-picker__dropdown" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-version-dropdown__header" }, "Block Definitions"), blockDefs.map((b) => /* @__PURE__ */ import_react8.default.createElement(
|
|
1481
1578
|
"button",
|
|
1482
1579
|
{
|
|
1483
1580
|
key: b.id,
|
|
@@ -1488,20 +1585,20 @@ function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersio
|
|
|
1488
1585
|
onBlockSelect(b.slug);
|
|
1489
1586
|
}
|
|
1490
1587
|
},
|
|
1491
|
-
/* @__PURE__ */
|
|
1492
|
-
/* @__PURE__ */
|
|
1493
|
-
)))), versions.length > 0 && /* @__PURE__ */
|
|
1588
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-block-picker__item-name" }, b.name),
|
|
1589
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-version-dropdown__meta" }, b.slug)
|
|
1590
|
+
)))), versions.length > 0 && /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-version-selector", ref: dropdownRef }, /* @__PURE__ */ import_react8.default.createElement(
|
|
1494
1591
|
"button",
|
|
1495
1592
|
{
|
|
1496
1593
|
type: "button",
|
|
1497
1594
|
className: `bb-version-selector__trigger${isReadOnly ? " bb-version-selector__trigger--readonly" : ""}`,
|
|
1498
1595
|
onClick: () => setVersionDropdownOpen((o) => !o)
|
|
1499
1596
|
},
|
|
1500
|
-
/* @__PURE__ */
|
|
1501
|
-
/* @__PURE__ */
|
|
1502
|
-
selectedVersion?.isCurrent && /* @__PURE__ */
|
|
1503
|
-
/* @__PURE__ */
|
|
1504
|
-
), versionDropdownOpen && /* @__PURE__ */
|
|
1597
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { className: `bb-version-selector__dot${selectedVersion?.isCurrent ? " bb-version-selector__dot--current" : " bb-version-selector__dot--old"}` }),
|
|
1598
|
+
/* @__PURE__ */ import_react8.default.createElement("span", null, selectedVersion?.label ?? `v${selectedVersion?.versionNumber ?? "?"}`),
|
|
1599
|
+
selectedVersion?.isCurrent && /* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-version-selector__badge" }, "current"),
|
|
1600
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react.ChevronDown, { size: 14, strokeWidth: 1.75, className: "bb-version-selector__chevron" })
|
|
1601
|
+
), versionDropdownOpen && /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-version-dropdown" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-version-dropdown__header" }, "Version History"), versions.map((v) => /* @__PURE__ */ import_react8.default.createElement(
|
|
1505
1602
|
"button",
|
|
1506
1603
|
{
|
|
1507
1604
|
key: v.id,
|
|
@@ -1512,10 +1609,10 @@ function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersio
|
|
|
1512
1609
|
onVersionSelect(v.id);
|
|
1513
1610
|
}
|
|
1514
1611
|
},
|
|
1515
|
-
/* @__PURE__ */
|
|
1516
|
-
/* @__PURE__ */
|
|
1517
|
-
/* @__PURE__ */
|
|
1518
|
-
))))), /* @__PURE__ */
|
|
1612
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { className: `bb-version-selector__dot${v.isCurrent ? " bb-version-selector__dot--current" : " bb-version-selector__dot--old"}` }),
|
|
1613
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-version-dropdown__label" }, v.label, v.isCurrent && /* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-version-selector__badge" }, "current")),
|
|
1614
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-version-dropdown__meta" }, v.changelog ? `${v.changelog.slice(0, 32)}${v.changelog.length > 32 ? "..." : ""}` : formatDate(v.createdAt))
|
|
1615
|
+
))))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-topbar__actions" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
1519
1616
|
"button",
|
|
1520
1617
|
{
|
|
1521
1618
|
type: "button",
|
|
@@ -1525,7 +1622,7 @@ function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersio
|
|
|
1525
1622
|
style: { display: "none" }
|
|
1526
1623
|
},
|
|
1527
1624
|
"Export .ts"
|
|
1528
|
-
), isReadOnly ? /* @__PURE__ */
|
|
1625
|
+
), isReadOnly ? /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(
|
|
1529
1626
|
"button",
|
|
1530
1627
|
{
|
|
1531
1628
|
type: "button",
|
|
@@ -1536,7 +1633,7 @@ function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersio
|
|
|
1536
1633
|
disabled: !currentVersion
|
|
1537
1634
|
},
|
|
1538
1635
|
"Back to current"
|
|
1539
|
-
), /* @__PURE__ */
|
|
1636
|
+
), /* @__PURE__ */ import_react8.default.createElement(
|
|
1540
1637
|
"button",
|
|
1541
1638
|
{
|
|
1542
1639
|
type: "button",
|
|
@@ -1548,7 +1645,7 @@ function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersio
|
|
|
1548
1645
|
className: "bb-btn bb-btn--warning"
|
|
1549
1646
|
},
|
|
1550
1647
|
notification?.status === "publishing" ? "Restoring..." : "Restore as new version"
|
|
1551
|
-
)) : /* @__PURE__ */
|
|
1648
|
+
)) : /* @__PURE__ */ import_react8.default.createElement(
|
|
1552
1649
|
"button",
|
|
1553
1650
|
{
|
|
1554
1651
|
type: "button",
|
|
@@ -1557,37 +1654,55 @@ function TopBar({ blockDefs, activeSlug, onBlockSelect, versions, selectedVersio
|
|
|
1557
1654
|
className: "bb-btn bb-btn--primary"
|
|
1558
1655
|
},
|
|
1559
1656
|
notification?.status === "publishing" ? "Publishing..." : "Publish to Payload"
|
|
1560
|
-
))), notification?.status === "publishing" && /* @__PURE__ */
|
|
1657
|
+
))), notification?.status === "publishing" && /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify bb-notify--publishing" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify__box" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify__spinner" }), /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify__body" }, /* @__PURE__ */ import_react8.default.createElement("p", { className: "bb-notify__title" }, isReadOnly ? "Restoring version..." : "Publishing to Payload..."), /* @__PURE__ */ import_react8.default.createElement("p", { className: "bb-notify__sub" }, "Validating schema and saving block definition.")))), notification?.status === "success" && /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify bb-notify--success" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify__box" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-notify__icon" }, "OK"), /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify__body" }, /* @__PURE__ */ import_react8.default.createElement("p", { className: "bb-notify__title" }, notification.msg), /* @__PURE__ */ import_react8.default.createElement("p", { className: "bb-notify__sub" }, "The block definition and version have been saved.")), /* @__PURE__ */ import_react8.default.createElement("button", { className: "bb-notify__close", onClick: () => setNotification(null) }, /* @__PURE__ */ import_react8.default.createElement(import_lucide_react.X, { size: 12, strokeWidth: 2 })))), notification?.status === "error" && /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify bb-notify--error" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify__box" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "bb-notify__icon" }, "!"), /* @__PURE__ */ import_react8.default.createElement("div", { className: "bb-notify__body" }, /* @__PURE__ */ import_react8.default.createElement("p", { className: "bb-notify__title" }, notification.title), /* @__PURE__ */ import_react8.default.createElement("p", { className: "bb-notify__sub" }, "Fix the following errors before publishing:"), /* @__PURE__ */ import_react8.default.createElement("ul", { className: "bb-notify__error-list" }, notification.errors.map((e, i) => /* @__PURE__ */ import_react8.default.createElement("li", { key: i }, e)))), /* @__PURE__ */ import_react8.default.createElement("button", { className: "bb-notify__close", onClick: () => setNotification(null) }, /* @__PURE__ */ import_react8.default.createElement(import_lucide_react.X, { size: 12, strokeWidth: 2 })))));
|
|
1561
1658
|
}
|
|
1562
1659
|
|
|
1563
1660
|
// src/block-builder/components/canvas/BlockList.tsx
|
|
1564
|
-
var
|
|
1661
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
1565
1662
|
var import_lucide_react2 = require("lucide-react");
|
|
1566
|
-
function BlockList() {
|
|
1663
|
+
function BlockList({ blockDefs = [], activeSlug, onBlockSelect }) {
|
|
1567
1664
|
const blocks = useBuilderStore((s) => s.blocks);
|
|
1568
1665
|
const activeBlockId = useBuilderStore((s) => s.activeBlockId);
|
|
1569
1666
|
const addBlock = useBuilderStore((s) => s.addBlock);
|
|
1570
1667
|
const removeBlock = useBuilderStore((s) => s.removeBlock);
|
|
1571
1668
|
const duplicateBlock = useBuilderStore((s) => s.duplicateBlock);
|
|
1572
1669
|
const setActiveBlock = useBuilderStore((s) => s.setActiveBlock);
|
|
1573
|
-
|
|
1670
|
+
const useApiNav = blockDefs.length > 0;
|
|
1671
|
+
const loadedBlock = useApiNav ? blocks.find((b) => b.slug === activeSlug) : null;
|
|
1672
|
+
const localOnlyBlocks = blocks.filter(
|
|
1673
|
+
(b) => !blockDefs.some((d) => d.slug === b.slug)
|
|
1674
|
+
);
|
|
1675
|
+
return /* @__PURE__ */ import_react9.default.createElement("div", { className: "bb-sidebar bb-sidebar--200 bb-sidebar--blocks" }, /* @__PURE__ */ import_react9.default.createElement("div", { className: "bb-sidebar__header" }, /* @__PURE__ */ import_react9.default.createElement("span", { className: "bb-sidebar__title" }, "Blocks"), /* @__PURE__ */ import_react9.default.createElement("button", { type: "button", onClick: addBlock, title: "Add block", className: "bb-sidebar__add" }, /* @__PURE__ */ import_react9.default.createElement(import_lucide_react2.Plus, { size: 14, strokeWidth: 2 }))), /* @__PURE__ */ import_react9.default.createElement("div", { className: "bb-sidebar__body" }, useApiNav && blockDefs.map((def) => {
|
|
1676
|
+
const isActive = def.slug === activeSlug;
|
|
1677
|
+
const fieldCount = isActive && loadedBlock ? loadedBlock.fields.length : null;
|
|
1678
|
+
return /* @__PURE__ */ import_react9.default.createElement(
|
|
1679
|
+
"div",
|
|
1680
|
+
{
|
|
1681
|
+
key: def.id,
|
|
1682
|
+
onClick: () => onBlockSelect?.(def.slug),
|
|
1683
|
+
className: `bb-block-item${isActive ? " bb-block-item--active" : ""}`
|
|
1684
|
+
},
|
|
1685
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "bb-block-item__slug" }, def.slug),
|
|
1686
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "bb-block-item__meta" }, fieldCount !== null ? `${fieldCount} field${fieldCount !== 1 ? "s" : ""}` : def.name)
|
|
1687
|
+
);
|
|
1688
|
+
}), localOnlyBlocks.map((block) => {
|
|
1574
1689
|
const isActive = block.id === activeBlockId;
|
|
1575
|
-
return /* @__PURE__ */
|
|
1690
|
+
return /* @__PURE__ */ import_react9.default.createElement(
|
|
1576
1691
|
"div",
|
|
1577
1692
|
{
|
|
1578
1693
|
key: block.id,
|
|
1579
1694
|
onClick: () => setActiveBlock(block.id),
|
|
1580
1695
|
className: `bb-block-item${isActive ? " bb-block-item--active" : ""}`
|
|
1581
1696
|
},
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
/* @__PURE__ */
|
|
1584
|
-
/* @__PURE__ */
|
|
1697
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "bb-block-item__slug" }, block.slug),
|
|
1698
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "bb-block-item__meta" }, block.fields.length, " field", block.fields.length !== 1 ? "s" : ""),
|
|
1699
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
1585
1700
|
"div",
|
|
1586
1701
|
{
|
|
1587
1702
|
className: "bb-block-item__actions",
|
|
1588
1703
|
onClick: (e) => e.stopPropagation()
|
|
1589
1704
|
},
|
|
1590
|
-
/* @__PURE__ */
|
|
1705
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
1591
1706
|
"button",
|
|
1592
1707
|
{
|
|
1593
1708
|
type: "button",
|
|
@@ -1595,9 +1710,9 @@ function BlockList() {
|
|
|
1595
1710
|
className: "bb-block-action",
|
|
1596
1711
|
title: "Duplicate"
|
|
1597
1712
|
},
|
|
1598
|
-
/* @__PURE__ */
|
|
1713
|
+
/* @__PURE__ */ import_react9.default.createElement(import_lucide_react2.Copy, { size: 12, strokeWidth: 1.75 })
|
|
1599
1714
|
),
|
|
1600
|
-
/* @__PURE__ */
|
|
1715
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
1601
1716
|
"button",
|
|
1602
1717
|
{
|
|
1603
1718
|
type: "button",
|
|
@@ -1605,21 +1720,21 @@ function BlockList() {
|
|
|
1605
1720
|
className: "bb-block-action bb-block-action--danger",
|
|
1606
1721
|
title: "Delete"
|
|
1607
1722
|
},
|
|
1608
|
-
/* @__PURE__ */
|
|
1723
|
+
/* @__PURE__ */ import_react9.default.createElement(import_lucide_react2.Trash2, { size: 12, strokeWidth: 1.75 })
|
|
1609
1724
|
)
|
|
1610
1725
|
)
|
|
1611
1726
|
);
|
|
1612
|
-
})));
|
|
1727
|
+
}), !useApiNav && blocks.length === 0 && /* @__PURE__ */ import_react9.default.createElement("div", { className: "bb-block-empty" }, "No blocks yet.", /* @__PURE__ */ import_react9.default.createElement("br", null), "Click + to create one.")));
|
|
1613
1728
|
}
|
|
1614
1729
|
|
|
1615
1730
|
// src/block-builder/components/canvas/BuilderCanvas.tsx
|
|
1616
|
-
var
|
|
1731
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
1617
1732
|
var import_core = require("@dnd-kit/core");
|
|
1618
1733
|
var import_sortable2 = require("@dnd-kit/sortable");
|
|
1619
1734
|
var import_modifiers = require("@dnd-kit/modifiers");
|
|
1620
1735
|
|
|
1621
1736
|
// src/block-builder/components/canvas/SortableFieldCard.tsx
|
|
1622
|
-
var
|
|
1737
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
1623
1738
|
var import_sortable = require("@dnd-kit/sortable");
|
|
1624
1739
|
var import_utilities = require("@dnd-kit/utilities");
|
|
1625
1740
|
var import_lucide_react3 = require("lucide-react");
|
|
@@ -1649,7 +1764,7 @@ function SortableFieldCard({ field, blockId, index }) {
|
|
|
1649
1764
|
transform: import_utilities.CSS.Transform.toString(transform),
|
|
1650
1765
|
transition
|
|
1651
1766
|
};
|
|
1652
|
-
return /* @__PURE__ */
|
|
1767
|
+
return /* @__PURE__ */ import_react10.default.createElement(
|
|
1653
1768
|
"div",
|
|
1654
1769
|
{
|
|
1655
1770
|
ref: setNodeRef,
|
|
@@ -1658,16 +1773,16 @@ function SortableFieldCard({ field, blockId, index }) {
|
|
|
1658
1773
|
...attributes,
|
|
1659
1774
|
...listeners
|
|
1660
1775
|
},
|
|
1661
|
-
/* @__PURE__ */
|
|
1776
|
+
/* @__PURE__ */ import_react10.default.createElement(
|
|
1662
1777
|
"div",
|
|
1663
1778
|
{
|
|
1664
1779
|
className: `bb-field-card${isActive ? " bb-field-card--active" : ""}`,
|
|
1665
1780
|
onClick: () => setActiveField(isActive ? null : field.id)
|
|
1666
1781
|
},
|
|
1667
|
-
/* @__PURE__ */
|
|
1668
|
-
/* @__PURE__ */
|
|
1669
|
-
/* @__PURE__ */
|
|
1670
|
-
!isReadOnly && /* @__PURE__ */
|
|
1782
|
+
/* @__PURE__ */ import_react10.default.createElement("span", { className: "bb-field-card__icon" }, /* @__PURE__ */ import_react10.default.createElement(FieldIcon, { type: field.type })),
|
|
1783
|
+
/* @__PURE__ */ import_react10.default.createElement("div", { className: "bb-field-card__body" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "bb-field-card__name" }, field.name || /* @__PURE__ */ import_react10.default.createElement("span", { className: "bb-field-card__name--empty" }, "unnamed")), /* @__PURE__ */ import_react10.default.createElement("div", { className: "bb-field-card__type" }, field.type, field.required && /* @__PURE__ */ import_react10.default.createElement("span", { className: "bb-field-card__required" }, "*"))),
|
|
1784
|
+
/* @__PURE__ */ import_react10.default.createElement("span", { className: "bb-field-card__index" }, "#", index + 1),
|
|
1785
|
+
!isReadOnly && /* @__PURE__ */ import_react10.default.createElement(
|
|
1671
1786
|
"button",
|
|
1672
1787
|
{
|
|
1673
1788
|
type: "button",
|
|
@@ -1679,14 +1794,14 @@ function SortableFieldCard({ field, blockId, index }) {
|
|
|
1679
1794
|
className: "bb-field-card__delete",
|
|
1680
1795
|
title: "Remove field"
|
|
1681
1796
|
},
|
|
1682
|
-
/* @__PURE__ */
|
|
1797
|
+
/* @__PURE__ */ import_react10.default.createElement(import_lucide_react3.X, { size: 12, strokeWidth: 2 })
|
|
1683
1798
|
)
|
|
1684
1799
|
)
|
|
1685
1800
|
);
|
|
1686
1801
|
}
|
|
1687
1802
|
function FieldIcon({ type }) {
|
|
1688
1803
|
const Icon = ICON_MAP[type];
|
|
1689
|
-
return Icon ? /* @__PURE__ */
|
|
1804
|
+
return Icon ? /* @__PURE__ */ import_react10.default.createElement(Icon, { size: 13, strokeWidth: 1.75 }) : null;
|
|
1690
1805
|
}
|
|
1691
1806
|
|
|
1692
1807
|
// src/block-builder/components/canvas/BuilderCanvas.tsx
|
|
@@ -1710,9 +1825,9 @@ function BuilderCanvas() {
|
|
|
1710
1825
|
}
|
|
1711
1826
|
}
|
|
1712
1827
|
if (!block) {
|
|
1713
|
-
return /* @__PURE__ */
|
|
1828
|
+
return /* @__PURE__ */ import_react11.default.createElement("div", { className: "bb-canvas", style: { display: "flex", alignItems: "center", justifyContent: "center" } }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "bb-canvas__no-block" }, "Select or create a block from the left panel."));
|
|
1714
1829
|
}
|
|
1715
|
-
return /* @__PURE__ */
|
|
1830
|
+
return /* @__PURE__ */ import_react11.default.createElement("div", { className: `bb-canvas${isReadOnly ? " bb-canvas--readonly" : ""}` }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "bb-canvas__inner" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "bb-canvas__header" }, block.slug, " - ", block.fields.length, " field", block.fields.length !== 1 ? "s" : ""), block.fields.length === 0 ? /* @__PURE__ */ import_react11.default.createElement("div", { className: "bb-canvas__empty" }, "Add fields from the palette on the left") : /* @__PURE__ */ import_react11.default.createElement(
|
|
1716
1831
|
import_core.DndContext,
|
|
1717
1832
|
{
|
|
1718
1833
|
sensors,
|
|
@@ -1720,13 +1835,13 @@ function BuilderCanvas() {
|
|
|
1720
1835
|
modifiers: [import_modifiers.restrictToVerticalAxis, import_modifiers.restrictToParentElement],
|
|
1721
1836
|
onDragEnd: handleDragEnd
|
|
1722
1837
|
},
|
|
1723
|
-
/* @__PURE__ */
|
|
1838
|
+
/* @__PURE__ */ import_react11.default.createElement(
|
|
1724
1839
|
import_sortable2.SortableContext,
|
|
1725
1840
|
{
|
|
1726
1841
|
items: block.fields.map((f) => f.id),
|
|
1727
1842
|
strategy: import_sortable2.verticalListSortingStrategy
|
|
1728
1843
|
},
|
|
1729
|
-
/* @__PURE__ */
|
|
1844
|
+
/* @__PURE__ */ import_react11.default.createElement("div", { className: "bb-canvas__field-list" }, block.fields.map((field, i) => /* @__PURE__ */ import_react11.default.createElement(
|
|
1730
1845
|
SortableFieldCard,
|
|
1731
1846
|
{
|
|
1732
1847
|
key: field.id,
|
|
@@ -1740,18 +1855,18 @@ function BuilderCanvas() {
|
|
|
1740
1855
|
}
|
|
1741
1856
|
|
|
1742
1857
|
// src/block-builder/components/canvas/ConfigPanel.tsx
|
|
1743
|
-
var
|
|
1858
|
+
var import_react14 = __toESM(require("react"), 1);
|
|
1744
1859
|
|
|
1745
1860
|
// src/block-builder/components/config/BlockConfig.tsx
|
|
1746
|
-
var
|
|
1861
|
+
var import_react12 = __toESM(require("react"), 1);
|
|
1747
1862
|
function BlockConfig() {
|
|
1748
1863
|
const activeBlockId = useBuilderStore((s) => s.activeBlockId);
|
|
1749
1864
|
const block = useBuilderStore((s) => s.blocks.find((b) => b.id === activeBlockId));
|
|
1750
1865
|
const updateBlock = useBuilderStore((s) => s.updateBlock);
|
|
1751
1866
|
if (!block) {
|
|
1752
|
-
return /* @__PURE__ */
|
|
1867
|
+
return /* @__PURE__ */ import_react12.default.createElement("div", { className: "bb-form__empty" }, "No block selected.");
|
|
1753
1868
|
}
|
|
1754
|
-
return /* @__PURE__ */
|
|
1869
|
+
return /* @__PURE__ */ import_react12.default.createElement("div", { className: "bb-form" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react12.default.createElement("label", { className: "bb-form__label" }, "Slug *"), /* @__PURE__ */ import_react12.default.createElement(
|
|
1755
1870
|
"input",
|
|
1756
1871
|
{
|
|
1757
1872
|
type: "text",
|
|
@@ -1760,7 +1875,7 @@ function BlockConfig() {
|
|
|
1760
1875
|
placeholder: "myBlock",
|
|
1761
1876
|
className: "bb-input"
|
|
1762
1877
|
}
|
|
1763
|
-
), /* @__PURE__ */
|
|
1878
|
+
), /* @__PURE__ */ import_react12.default.createElement("span", { className: "bb-form__hint" }, "Unique identifier used in code and database")), /* @__PURE__ */ import_react12.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react12.default.createElement("label", { className: "bb-form__label" }, "Interface Name"), /* @__PURE__ */ import_react12.default.createElement(
|
|
1764
1879
|
"input",
|
|
1765
1880
|
{
|
|
1766
1881
|
type: "text",
|
|
@@ -1769,7 +1884,7 @@ function BlockConfig() {
|
|
|
1769
1884
|
placeholder: "MyBlock",
|
|
1770
1885
|
className: "bb-input"
|
|
1771
1886
|
}
|
|
1772
|
-
)), /* @__PURE__ */
|
|
1887
|
+
)), /* @__PURE__ */ import_react12.default.createElement("div", { className: "bb-grid-2" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react12.default.createElement("label", { className: "bb-form__label" }, "Singular Label"), /* @__PURE__ */ import_react12.default.createElement(
|
|
1773
1888
|
"input",
|
|
1774
1889
|
{
|
|
1775
1890
|
type: "text",
|
|
@@ -1778,7 +1893,7 @@ function BlockConfig() {
|
|
|
1778
1893
|
placeholder: "My Block",
|
|
1779
1894
|
className: "bb-input"
|
|
1780
1895
|
}
|
|
1781
|
-
)), /* @__PURE__ */
|
|
1896
|
+
)), /* @__PURE__ */ import_react12.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react12.default.createElement("label", { className: "bb-form__label" }, "Plural Label"), /* @__PURE__ */ import_react12.default.createElement(
|
|
1782
1897
|
"input",
|
|
1783
1898
|
{
|
|
1784
1899
|
type: "text",
|
|
@@ -1787,7 +1902,7 @@ function BlockConfig() {
|
|
|
1787
1902
|
placeholder: "My Blocks",
|
|
1788
1903
|
className: "bb-input"
|
|
1789
1904
|
}
|
|
1790
|
-
))), /* @__PURE__ */
|
|
1905
|
+
))), /* @__PURE__ */ import_react12.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react12.default.createElement("label", { className: "bb-form__label" }, "Image URL"), /* @__PURE__ */ import_react12.default.createElement(
|
|
1791
1906
|
"input",
|
|
1792
1907
|
{
|
|
1793
1908
|
type: "text",
|
|
@@ -1796,11 +1911,11 @@ function BlockConfig() {
|
|
|
1796
1911
|
placeholder: "https://...",
|
|
1797
1912
|
className: "bb-input"
|
|
1798
1913
|
}
|
|
1799
|
-
)), /* @__PURE__ */
|
|
1914
|
+
)), /* @__PURE__ */ import_react12.default.createElement("div", { className: "bb-stat-box" }, /* @__PURE__ */ import_react12.default.createElement("strong", null, block.fields.length), " field", block.fields.length !== 1 ? "s" : "", " defined"));
|
|
1800
1915
|
}
|
|
1801
1916
|
|
|
1802
1917
|
// src/block-builder/components/config/FieldConfig.tsx
|
|
1803
|
-
var
|
|
1918
|
+
var import_react13 = __toESM(require("react"), 1);
|
|
1804
1919
|
var ALL_TYPES = [
|
|
1805
1920
|
"text",
|
|
1806
1921
|
"textarea",
|
|
@@ -1821,13 +1936,13 @@ function FieldConfig() {
|
|
|
1821
1936
|
const field = block?.fields.find((f) => f.id === activeFieldId);
|
|
1822
1937
|
const updateField = useBuilderStore((s) => s.updateField);
|
|
1823
1938
|
if (!activeBlockId || !activeFieldId || !field) {
|
|
1824
|
-
return /* @__PURE__ */
|
|
1939
|
+
return /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form__empty" }, "Select a field to configure it.");
|
|
1825
1940
|
}
|
|
1826
1941
|
function upd(updates) {
|
|
1827
1942
|
updateField(activeBlockId, activeFieldId, updates);
|
|
1828
1943
|
}
|
|
1829
1944
|
const needsOptions = field.type === "select" || field.type === "radio";
|
|
1830
|
-
return /* @__PURE__ */
|
|
1945
|
+
return /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-grid-2" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-form__label" }, "Field Name *"), /* @__PURE__ */ import_react13.default.createElement(
|
|
1831
1946
|
"input",
|
|
1832
1947
|
{
|
|
1833
1948
|
type: "text",
|
|
@@ -1836,15 +1951,15 @@ function FieldConfig() {
|
|
|
1836
1951
|
placeholder: "fieldName",
|
|
1837
1952
|
className: "bb-input"
|
|
1838
1953
|
}
|
|
1839
|
-
)), /* @__PURE__ */
|
|
1954
|
+
)), /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-form__label" }, "Type *"), /* @__PURE__ */ import_react13.default.createElement(
|
|
1840
1955
|
"select",
|
|
1841
1956
|
{
|
|
1842
1957
|
value: field.type,
|
|
1843
1958
|
onChange: (e) => upd({ type: e.target.value }),
|
|
1844
1959
|
className: "bb-input bb-select"
|
|
1845
1960
|
},
|
|
1846
|
-
ALL_TYPES.map((t) => /* @__PURE__ */
|
|
1847
|
-
))), /* @__PURE__ */
|
|
1961
|
+
ALL_TYPES.map((t) => /* @__PURE__ */ import_react13.default.createElement("option", { key: t, value: t }, t))
|
|
1962
|
+
))), /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-form__label" }, "Label"), /* @__PURE__ */ import_react13.default.createElement(
|
|
1848
1963
|
"input",
|
|
1849
1964
|
{
|
|
1850
1965
|
type: "text",
|
|
@@ -1853,28 +1968,28 @@ function FieldConfig() {
|
|
|
1853
1968
|
placeholder: "Human-readable label",
|
|
1854
1969
|
className: "bb-input"
|
|
1855
1970
|
}
|
|
1856
|
-
)), /* @__PURE__ */
|
|
1971
|
+
)), /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-flags-row" }, /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-checkbox-row" }, /* @__PURE__ */ import_react13.default.createElement(
|
|
1857
1972
|
"input",
|
|
1858
1973
|
{
|
|
1859
1974
|
type: "checkbox",
|
|
1860
1975
|
checked: field.required ?? false,
|
|
1861
1976
|
onChange: (e) => upd({ required: e.target.checked })
|
|
1862
1977
|
}
|
|
1863
|
-
), "Required"), /* @__PURE__ */
|
|
1978
|
+
), "Required"), /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-checkbox-row" }, /* @__PURE__ */ import_react13.default.createElement(
|
|
1864
1979
|
"input",
|
|
1865
1980
|
{
|
|
1866
1981
|
type: "checkbox",
|
|
1867
1982
|
checked: field.unique ?? false,
|
|
1868
1983
|
onChange: (e) => upd({ unique: e.target.checked })
|
|
1869
1984
|
}
|
|
1870
|
-
), "Unique"), /* @__PURE__ */
|
|
1985
|
+
), "Unique"), /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-checkbox-row" }, /* @__PURE__ */ import_react13.default.createElement(
|
|
1871
1986
|
"input",
|
|
1872
1987
|
{
|
|
1873
1988
|
type: "checkbox",
|
|
1874
1989
|
checked: field.localized ?? false,
|
|
1875
1990
|
onChange: (e) => upd({ localized: e.target.checked })
|
|
1876
1991
|
}
|
|
1877
|
-
), "Localized")), /* @__PURE__ */
|
|
1992
|
+
), "Localized")), /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-form__label" }, "Default Value"), /* @__PURE__ */ import_react13.default.createElement(
|
|
1878
1993
|
"input",
|
|
1879
1994
|
{
|
|
1880
1995
|
type: "text",
|
|
@@ -1883,7 +1998,7 @@ function FieldConfig() {
|
|
|
1883
1998
|
placeholder: "Default value",
|
|
1884
1999
|
className: "bb-input"
|
|
1885
2000
|
}
|
|
1886
|
-
)), field.type === "relationship" && /* @__PURE__ */
|
|
2001
|
+
)), field.type === "relationship" && /* @__PURE__ */ import_react13.default.createElement(import_react13.default.Fragment, null, /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-form__label" }, "Relation To (collection slug)"), /* @__PURE__ */ import_react13.default.createElement(
|
|
1887
2002
|
"input",
|
|
1888
2003
|
{
|
|
1889
2004
|
type: "text",
|
|
@@ -1892,14 +2007,14 @@ function FieldConfig() {
|
|
|
1892
2007
|
placeholder: "pages",
|
|
1893
2008
|
className: "bb-input"
|
|
1894
2009
|
}
|
|
1895
|
-
)), /* @__PURE__ */
|
|
2010
|
+
)), /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-checkbox-row" }, /* @__PURE__ */ import_react13.default.createElement(
|
|
1896
2011
|
"input",
|
|
1897
2012
|
{
|
|
1898
2013
|
type: "checkbox",
|
|
1899
2014
|
checked: field.hasMany ?? false,
|
|
1900
2015
|
onChange: (e) => upd({ hasMany: e.target.checked })
|
|
1901
2016
|
}
|
|
1902
|
-
), "Has Many")), field.type === "array" && /* @__PURE__ */
|
|
2017
|
+
), "Has Many")), field.type === "array" && /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-grid-2" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-form__label" }, "Min Rows"), /* @__PURE__ */ import_react13.default.createElement(
|
|
1903
2018
|
"input",
|
|
1904
2019
|
{
|
|
1905
2020
|
type: "number",
|
|
@@ -1907,7 +2022,7 @@ function FieldConfig() {
|
|
|
1907
2022
|
onChange: (e) => upd({ minRows: e.target.value === "" ? void 0 : e.target.valueAsNumber }),
|
|
1908
2023
|
className: "bb-input"
|
|
1909
2024
|
}
|
|
1910
|
-
)), /* @__PURE__ */
|
|
2025
|
+
)), /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react13.default.createElement("label", { className: "bb-form__label" }, "Max Rows"), /* @__PURE__ */ import_react13.default.createElement(
|
|
1911
2026
|
"input",
|
|
1912
2027
|
{
|
|
1913
2028
|
type: "number",
|
|
@@ -1915,7 +2030,7 @@ function FieldConfig() {
|
|
|
1915
2030
|
onChange: (e) => upd({ maxRows: e.target.value === "" ? void 0 : e.target.valueAsNumber }),
|
|
1916
2031
|
className: "bb-input"
|
|
1917
2032
|
}
|
|
1918
|
-
))), needsOptions && /* @__PURE__ */
|
|
2033
|
+
))), needsOptions && /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-form__section" }, /* @__PURE__ */ import_react13.default.createElement("div", { className: "bb-options-label" }, "Options"), (field.options ?? []).map((opt, i) => /* @__PURE__ */ import_react13.default.createElement("div", { key: i, className: "bb-option-row" }, /* @__PURE__ */ import_react13.default.createElement(
|
|
1919
2034
|
"input",
|
|
1920
2035
|
{
|
|
1921
2036
|
type: "text",
|
|
@@ -1928,7 +2043,7 @@ function FieldConfig() {
|
|
|
1928
2043
|
},
|
|
1929
2044
|
className: "bb-input"
|
|
1930
2045
|
}
|
|
1931
|
-
), /* @__PURE__ */
|
|
2046
|
+
), /* @__PURE__ */ import_react13.default.createElement(
|
|
1932
2047
|
"input",
|
|
1933
2048
|
{
|
|
1934
2049
|
type: "text",
|
|
@@ -1941,7 +2056,7 @@ function FieldConfig() {
|
|
|
1941
2056
|
},
|
|
1942
2057
|
className: "bb-input"
|
|
1943
2058
|
}
|
|
1944
|
-
), /* @__PURE__ */
|
|
2059
|
+
), /* @__PURE__ */ import_react13.default.createElement(
|
|
1945
2060
|
"button",
|
|
1946
2061
|
{
|
|
1947
2062
|
type: "button",
|
|
@@ -1953,7 +2068,7 @@ function FieldConfig() {
|
|
|
1953
2068
|
title: "Remove option"
|
|
1954
2069
|
},
|
|
1955
2070
|
"x"
|
|
1956
|
-
))), /* @__PURE__ */
|
|
2071
|
+
))), /* @__PURE__ */ import_react13.default.createElement(
|
|
1957
2072
|
"button",
|
|
1958
2073
|
{
|
|
1959
2074
|
type: "button",
|
|
@@ -1966,11 +2081,11 @@ function FieldConfig() {
|
|
|
1966
2081
|
|
|
1967
2082
|
// src/block-builder/components/canvas/ConfigPanel.tsx
|
|
1968
2083
|
function ConfigPanel() {
|
|
1969
|
-
const [tab, setTab] = (0,
|
|
2084
|
+
const [tab, setTab] = (0, import_react14.useState)("block");
|
|
1970
2085
|
const activeFieldId = useBuilderStore((s) => s.activeFieldId);
|
|
1971
2086
|
const isReadOnly = useBuilderStore((s) => s.isReadOnly);
|
|
1972
2087
|
const activeTab = activeFieldId ? "field" : tab;
|
|
1973
|
-
return /* @__PURE__ */
|
|
2088
|
+
return /* @__PURE__ */ import_react14.default.createElement("div", { className: `bb-config${isReadOnly ? " bb-config--readonly" : ""}` }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "bb-config__tabs" }, ["block", "field"].map((t) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1974
2089
|
"button",
|
|
1975
2090
|
{
|
|
1976
2091
|
key: t,
|
|
@@ -1979,11 +2094,11 @@ function ConfigPanel() {
|
|
|
1979
2094
|
className: `bb-config__tab${activeTab === t ? " bb-config__tab--active" : ""}`
|
|
1980
2095
|
},
|
|
1981
2096
|
t
|
|
1982
|
-
))), /* @__PURE__ */
|
|
2097
|
+
))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "bb-config__body" }, activeTab === "block" ? /* @__PURE__ */ import_react14.default.createElement(BlockConfig, null) : /* @__PURE__ */ import_react14.default.createElement(FieldConfig, null)), isReadOnly && /* @__PURE__ */ import_react14.default.createElement("div", { className: "bb-config__readonly-overlay" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "bb-config__readonly-label" }, "Read only")));
|
|
1983
2098
|
}
|
|
1984
2099
|
|
|
1985
2100
|
// src/block-builder/components/sidebar/FieldPalette.tsx
|
|
1986
|
-
var
|
|
2101
|
+
var import_react15 = __toESM(require("react"), 1);
|
|
1987
2102
|
var import_lucide_react4 = require("lucide-react");
|
|
1988
2103
|
|
|
1989
2104
|
// src/block-builder/lib/field-palette.ts
|
|
@@ -2034,7 +2149,7 @@ var ICON_MAP2 = {
|
|
|
2034
2149
|
Braces: import_lucide_react4.Braces
|
|
2035
2150
|
};
|
|
2036
2151
|
function FieldPalette() {
|
|
2037
|
-
const [search, setSearch] = (0,
|
|
2152
|
+
const [search, setSearch] = (0, import_react15.useState)("");
|
|
2038
2153
|
const activeBlockId = useBuilderStore((s) => s.activeBlockId);
|
|
2039
2154
|
const addField = useBuilderStore((s) => s.addField);
|
|
2040
2155
|
const isReadOnly = useBuilderStore((s) => s.isReadOnly);
|
|
@@ -2045,7 +2160,7 @@ function FieldPalette() {
|
|
|
2045
2160
|
if (!activeBlockId || isReadOnly) return;
|
|
2046
2161
|
addField(activeBlockId, type);
|
|
2047
2162
|
}
|
|
2048
|
-
return /* @__PURE__ */
|
|
2163
|
+
return /* @__PURE__ */ import_react15.default.createElement("div", { className: `bb-sidebar bb-sidebar--200 bb-sidebar--palette${isReadOnly ? " bb-sidebar--readonly" : ""}` }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "bb-sidebar__header" }, /* @__PURE__ */ import_react15.default.createElement("span", { className: "bb-sidebar__title" }, "Fields")), /* @__PURE__ */ import_react15.default.createElement("div", { className: "bb-palette__search-wrap" }, /* @__PURE__ */ import_react15.default.createElement(
|
|
2049
2164
|
"input",
|
|
2050
2165
|
{
|
|
2051
2166
|
type: "text",
|
|
@@ -2054,7 +2169,7 @@ function FieldPalette() {
|
|
|
2054
2169
|
placeholder: "Search...",
|
|
2055
2170
|
className: "bb-palette__search"
|
|
2056
2171
|
}
|
|
2057
|
-
)), /* @__PURE__ */
|
|
2172
|
+
)), /* @__PURE__ */ import_react15.default.createElement("div", { className: "bb-sidebar__body" }, search.trim() ? /* @__PURE__ */ import_react15.default.createElement("div", { className: "bb-palette__items" }, filtered.map((item) => /* @__PURE__ */ import_react15.default.createElement(
|
|
2058
2173
|
FieldButton,
|
|
2059
2174
|
{
|
|
2060
2175
|
key: item.type,
|
|
@@ -2066,7 +2181,7 @@ function FieldPalette() {
|
|
|
2066
2181
|
}
|
|
2067
2182
|
))) : FIELD_CATEGORIES.map((cat) => {
|
|
2068
2183
|
const items = FIELD_PALETTE.filter((f) => f.category === cat.id);
|
|
2069
|
-
return /* @__PURE__ */
|
|
2184
|
+
return /* @__PURE__ */ import_react15.default.createElement("div", { key: cat.id, style: { marginTop: 6 } }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "bb-palette__cat-label" }, cat.label), /* @__PURE__ */ import_react15.default.createElement("div", { className: "bb-palette__items" }, items.map((item) => /* @__PURE__ */ import_react15.default.createElement(
|
|
2070
2185
|
FieldButton,
|
|
2071
2186
|
{
|
|
2072
2187
|
key: item.type,
|
|
@@ -2077,7 +2192,7 @@ function FieldPalette() {
|
|
|
2077
2192
|
disabled: !activeBlockId || isReadOnly
|
|
2078
2193
|
}
|
|
2079
2194
|
))));
|
|
2080
|
-
})), !activeBlockId && /* @__PURE__ */
|
|
2195
|
+
})), !activeBlockId && /* @__PURE__ */ import_react15.default.createElement("div", { className: "bb-sidebar__footer" }, "Select a block first"));
|
|
2081
2196
|
}
|
|
2082
2197
|
function FieldButton({
|
|
2083
2198
|
type,
|
|
@@ -2088,7 +2203,7 @@ function FieldButton({
|
|
|
2088
2203
|
}) {
|
|
2089
2204
|
const meta = getFieldMeta(type);
|
|
2090
2205
|
const Icon = ICON_MAP2[icon];
|
|
2091
|
-
return /* @__PURE__ */
|
|
2206
|
+
return /* @__PURE__ */ import_react15.default.createElement(
|
|
2092
2207
|
"button",
|
|
2093
2208
|
{
|
|
2094
2209
|
type: "button",
|
|
@@ -2097,14 +2212,14 @@ function FieldButton({
|
|
|
2097
2212
|
title: meta?.description,
|
|
2098
2213
|
className: "bb-palette__item"
|
|
2099
2214
|
},
|
|
2100
|
-
/* @__PURE__ */
|
|
2101
|
-
/* @__PURE__ */
|
|
2102
|
-
/* @__PURE__ */
|
|
2215
|
+
/* @__PURE__ */ import_react15.default.createElement("span", { className: "bb-palette__item__icon" }, Icon ? /* @__PURE__ */ import_react15.default.createElement(Icon, { size: 13, strokeWidth: 1.75 }) : null),
|
|
2216
|
+
/* @__PURE__ */ import_react15.default.createElement("span", { className: "bb-palette__item__label" }, label),
|
|
2217
|
+
/* @__PURE__ */ import_react15.default.createElement("span", { className: "bb-palette__item__type" }, type)
|
|
2103
2218
|
);
|
|
2104
2219
|
}
|
|
2105
2220
|
|
|
2106
2221
|
// src/block-builder/components/canvas/CodePreview.tsx
|
|
2107
|
-
var
|
|
2222
|
+
var import_react16 = __toESM(require("react"), 1);
|
|
2108
2223
|
var KEYWORDS = /* @__PURE__ */ new Set([
|
|
2109
2224
|
"import",
|
|
2110
2225
|
"export",
|
|
@@ -2192,16 +2307,16 @@ var TOKEN_COLORS = {
|
|
|
2192
2307
|
};
|
|
2193
2308
|
function HighlightedCode({ code }) {
|
|
2194
2309
|
const tokens = tokenise(code);
|
|
2195
|
-
return /* @__PURE__ */
|
|
2310
|
+
return /* @__PURE__ */ import_react16.default.createElement("code", { style: { fontFamily: "inherit" } }, tokens.map((tok, i) => /* @__PURE__ */ import_react16.default.createElement("span", { key: i, style: { color: TOKEN_COLORS[tok.kind] } }, tok.text)));
|
|
2196
2311
|
}
|
|
2197
2312
|
function CodePreview() {
|
|
2198
2313
|
const blocks = useBuilderStore((s) => s.blocks);
|
|
2199
|
-
const [fileMap, setFileMap] = (0,
|
|
2200
|
-
const [activeFile, setActiveFile] = (0,
|
|
2201
|
-
const [copied, setCopied] = (0,
|
|
2202
|
-
const timerRef = (0,
|
|
2203
|
-
const copyTimerRef = (0,
|
|
2204
|
-
const regenerate = (0,
|
|
2314
|
+
const [fileMap, setFileMap] = (0, import_react16.useState)({});
|
|
2315
|
+
const [activeFile, setActiveFile] = (0, import_react16.useState)(null);
|
|
2316
|
+
const [copied, setCopied] = (0, import_react16.useState)(false);
|
|
2317
|
+
const timerRef = (0, import_react16.useRef)(null);
|
|
2318
|
+
const copyTimerRef = (0, import_react16.useRef)(null);
|
|
2319
|
+
const regenerate = (0, import_react16.useCallback)(() => {
|
|
2205
2320
|
if (blocks.length === 0) {
|
|
2206
2321
|
setFileMap({});
|
|
2207
2322
|
setActiveFile(null);
|
|
@@ -2218,7 +2333,7 @@ function CodePreview() {
|
|
|
2218
2333
|
return prev && keys.includes(prev) ? prev : keys[0] ?? null;
|
|
2219
2334
|
});
|
|
2220
2335
|
}, [blocks]);
|
|
2221
|
-
(0,
|
|
2336
|
+
(0, import_react16.useEffect)(() => {
|
|
2222
2337
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
2223
2338
|
timerRef.current = setTimeout(regenerate, 300);
|
|
2224
2339
|
return () => {
|
|
@@ -2237,7 +2352,7 @@ function CodePreview() {
|
|
|
2237
2352
|
const activeCode = activeFile ? fileMap[activeFile] ?? "" : "";
|
|
2238
2353
|
const lineCount = activeCode ? activeCode.split("\n").length : 0;
|
|
2239
2354
|
if (fileNames.length === 0) {
|
|
2240
|
-
return /* @__PURE__ */
|
|
2355
|
+
return /* @__PURE__ */ import_react16.default.createElement(
|
|
2241
2356
|
"div",
|
|
2242
2357
|
{
|
|
2243
2358
|
className: "code-preview",
|
|
@@ -2254,7 +2369,7 @@ function CodePreview() {
|
|
|
2254
2369
|
"Add a block to see generated TypeScript code"
|
|
2255
2370
|
);
|
|
2256
2371
|
}
|
|
2257
|
-
return /* @__PURE__ */
|
|
2372
|
+
return /* @__PURE__ */ import_react16.default.createElement("div", { className: "code-preview", style: { height: "100%", display: "flex", flexDirection: "column", overflow: "hidden" } }, /* @__PURE__ */ import_react16.default.createElement(
|
|
2258
2373
|
"div",
|
|
2259
2374
|
{
|
|
2260
2375
|
style: {
|
|
@@ -2268,7 +2383,7 @@ function CodePreview() {
|
|
|
2268
2383
|
},
|
|
2269
2384
|
fileNames.map((name) => {
|
|
2270
2385
|
const isActive = activeFile === name;
|
|
2271
|
-
return /* @__PURE__ */
|
|
2386
|
+
return /* @__PURE__ */ import_react16.default.createElement(
|
|
2272
2387
|
"button",
|
|
2273
2388
|
{
|
|
2274
2389
|
key: name,
|
|
@@ -2291,8 +2406,8 @@ function CodePreview() {
|
|
|
2291
2406
|
name
|
|
2292
2407
|
);
|
|
2293
2408
|
}),
|
|
2294
|
-
/* @__PURE__ */
|
|
2295
|
-
lineCount > 0 && /* @__PURE__ */
|
|
2409
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { style: { flex: 1 } }),
|
|
2410
|
+
lineCount > 0 && /* @__PURE__ */ import_react16.default.createElement(
|
|
2296
2411
|
"span",
|
|
2297
2412
|
{
|
|
2298
2413
|
style: {
|
|
@@ -2305,7 +2420,7 @@ function CodePreview() {
|
|
|
2305
2420
|
lineCount,
|
|
2306
2421
|
" lines"
|
|
2307
2422
|
),
|
|
2308
|
-
/* @__PURE__ */
|
|
2423
|
+
/* @__PURE__ */ import_react16.default.createElement(
|
|
2309
2424
|
"button",
|
|
2310
2425
|
{
|
|
2311
2426
|
type: "button",
|
|
@@ -2328,7 +2443,7 @@ function CodePreview() {
|
|
|
2328
2443
|
},
|
|
2329
2444
|
copied ? "Copied" : "Copy"
|
|
2330
2445
|
)
|
|
2331
|
-
), /* @__PURE__ */
|
|
2446
|
+
), /* @__PURE__ */ import_react16.default.createElement("div", { style: { flex: 1, overflow: "auto", display: "flex" } }, /* @__PURE__ */ import_react16.default.createElement(
|
|
2332
2447
|
"div",
|
|
2333
2448
|
{
|
|
2334
2449
|
style: {
|
|
@@ -2345,8 +2460,8 @@ function CodePreview() {
|
|
|
2345
2460
|
},
|
|
2346
2461
|
"aria-hidden": "true"
|
|
2347
2462
|
},
|
|
2348
|
-
activeCode.split("\n").map((_, i) => /* @__PURE__ */
|
|
2349
|
-
), /* @__PURE__ */
|
|
2463
|
+
activeCode.split("\n").map((_, i) => /* @__PURE__ */ import_react16.default.createElement("div", { key: i }, i + 1))
|
|
2464
|
+
), /* @__PURE__ */ import_react16.default.createElement(
|
|
2350
2465
|
"pre",
|
|
2351
2466
|
{
|
|
2352
2467
|
style: {
|
|
@@ -2361,7 +2476,7 @@ function CodePreview() {
|
|
|
2361
2476
|
whiteSpace: "pre"
|
|
2362
2477
|
}
|
|
2363
2478
|
},
|
|
2364
|
-
/* @__PURE__ */
|
|
2479
|
+
/* @__PURE__ */ import_react16.default.createElement(HighlightedCode, { code: activeCode })
|
|
2365
2480
|
)));
|
|
2366
2481
|
}
|
|
2367
2482
|
|
|
@@ -2371,25 +2486,25 @@ function BuilderShell({ loadSlug }) {
|
|
|
2371
2486
|
const setVersionMeta = useBuilderStore((s) => s.setVersionMeta);
|
|
2372
2487
|
const setBlockSlug = useBuilderStore((s) => s.setBlockSlug);
|
|
2373
2488
|
const isReadOnly = useBuilderStore((s) => s.isReadOnly);
|
|
2374
|
-
const [activeSlug, setActiveSlug] = (0,
|
|
2375
|
-
const [loading, setLoading] = (0,
|
|
2376
|
-
const [
|
|
2377
|
-
const [showCodePreview, setShowCodePreview] = (0,
|
|
2378
|
-
const [versions, setVersions] = (0,
|
|
2379
|
-
const [selectedVersionId, setSelectedVersionId] = (0,
|
|
2380
|
-
const [blockDefs, setBlockDefs] = (0,
|
|
2381
|
-
const [mobilePanelTab, setMobilePanelTab] = (0,
|
|
2382
|
-
(0,
|
|
2489
|
+
const [activeSlug, setActiveSlug] = (0, import_react17.useState)(loadSlug ?? null);
|
|
2490
|
+
const [loading, setLoading] = (0, import_react17.useState)(!!loadSlug);
|
|
2491
|
+
const [notification, setNotification] = (0, import_react17.useState)(null);
|
|
2492
|
+
const [showCodePreview, setShowCodePreview] = (0, import_react17.useState)(false);
|
|
2493
|
+
const [versions, setVersions] = (0, import_react17.useState)([]);
|
|
2494
|
+
const [selectedVersionId, setSelectedVersionId] = (0, import_react17.useState)(null);
|
|
2495
|
+
const [blockDefs, setBlockDefs] = (0, import_react17.useState)([]);
|
|
2496
|
+
const [mobilePanelTab, setMobilePanelTab] = (0, import_react17.useState)("blocks");
|
|
2497
|
+
(0, import_react17.useEffect)(() => {
|
|
2383
2498
|
fetch("/api/block-definitions?limit=200&depth=0").then((r) => r.json()).then((json) => {
|
|
2384
2499
|
setBlockDefs(
|
|
2385
2500
|
(json.docs ?? []).map((d) => ({ id: String(d.id), slug: d.slug, name: d.name }))
|
|
2386
2501
|
);
|
|
2387
2502
|
}).catch((err) => {
|
|
2388
2503
|
console.error("[block-builder] Failed to load block definitions:", err);
|
|
2389
|
-
|
|
2504
|
+
setNotification({ status: "error", title: "Failed to load block definitions", errors: ["Could not load block definitions. Please refresh the page."] });
|
|
2390
2505
|
});
|
|
2391
2506
|
}, []);
|
|
2392
|
-
const loadVersionsForSlug = (0,
|
|
2507
|
+
const loadVersionsForSlug = (0, import_react17.useCallback)(async (slug) => {
|
|
2393
2508
|
try {
|
|
2394
2509
|
const res = await fetch(`/api/block-builder/versions/${encodeURIComponent(slug)}`);
|
|
2395
2510
|
const json = await res.json();
|
|
@@ -2398,9 +2513,9 @@ function BuilderShell({ loadSlug }) {
|
|
|
2398
2513
|
return [];
|
|
2399
2514
|
}
|
|
2400
2515
|
}, []);
|
|
2401
|
-
const loadVersion = (0,
|
|
2516
|
+
const loadVersion = (0, import_react17.useCallback)(async (slug, versionId) => {
|
|
2402
2517
|
setLoading(true);
|
|
2403
|
-
|
|
2518
|
+
setNotification(null);
|
|
2404
2519
|
const url = versionId ? `/api/block-builder/load/${encodeURIComponent(slug)}?versionId=${encodeURIComponent(versionId)}` : `/api/block-builder/load/${encodeURIComponent(slug)}`;
|
|
2405
2520
|
try {
|
|
2406
2521
|
const res = await fetch(url);
|
|
@@ -2410,20 +2525,20 @@ function BuilderShell({ loadSlug }) {
|
|
|
2410
2525
|
setVersionMeta(json.versionId ?? null, !(json.isCurrent ?? true));
|
|
2411
2526
|
setSelectedVersionId(json.versionId ?? null);
|
|
2412
2527
|
} else {
|
|
2413
|
-
|
|
2528
|
+
setNotification({ status: "error", title: "Failed to load block", errors: [json.error ?? "Unknown error"] });
|
|
2414
2529
|
}
|
|
2415
2530
|
} catch (err) {
|
|
2416
|
-
|
|
2531
|
+
setNotification({ status: "error", title: "Network error", errors: [err instanceof Error ? err.message : "Could not reach the server."] });
|
|
2417
2532
|
} finally {
|
|
2418
2533
|
setLoading(false);
|
|
2419
2534
|
}
|
|
2420
2535
|
}, [loadBlock, setVersionMeta]);
|
|
2421
|
-
const loadBlockBySlug = (0,
|
|
2536
|
+
const loadBlockBySlug = (0, import_react17.useCallback)(async (slug) => {
|
|
2422
2537
|
setActiveSlug(slug);
|
|
2423
2538
|
setBlockSlug(slug);
|
|
2424
2539
|
setVersions([]);
|
|
2425
2540
|
setSelectedVersionId(null);
|
|
2426
|
-
|
|
2541
|
+
setNotification(null);
|
|
2427
2542
|
setMobilePanelTab("canvas");
|
|
2428
2543
|
await loadVersion(slug);
|
|
2429
2544
|
const list = await loadVersionsForSlug(slug);
|
|
@@ -2431,7 +2546,7 @@ function BuilderShell({ loadSlug }) {
|
|
|
2431
2546
|
const current = list.find((v) => v.isCurrent) ?? list[0];
|
|
2432
2547
|
if (current) setSelectedVersionId(current.id);
|
|
2433
2548
|
}, [loadVersion, loadVersionsForSlug, setBlockSlug]);
|
|
2434
|
-
(0,
|
|
2549
|
+
(0, import_react17.useEffect)(() => {
|
|
2435
2550
|
if (!loadSlug) return;
|
|
2436
2551
|
loadBlockBySlug(loadSlug);
|
|
2437
2552
|
}, [loadSlug]);
|
|
@@ -2454,7 +2569,7 @@ function BuilderShell({ loadSlug }) {
|
|
|
2454
2569
|
const current = list.find((v) => v.isCurrent) ?? list[0];
|
|
2455
2570
|
if (current) setSelectedVersionId(current.id);
|
|
2456
2571
|
}
|
|
2457
|
-
return /* @__PURE__ */
|
|
2572
|
+
return /* @__PURE__ */ import_react17.default.createElement("div", { className: "bb-shell" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
2458
2573
|
TopBar,
|
|
2459
2574
|
{
|
|
2460
2575
|
blockDefs,
|
|
@@ -2464,9 +2579,11 @@ function BuilderShell({ loadSlug }) {
|
|
|
2464
2579
|
selectedVersionId,
|
|
2465
2580
|
onVersionSelect: handleVersionSelect,
|
|
2466
2581
|
onRestoreVersion: handleRestoreVersion,
|
|
2467
|
-
onAfterPublish: handleAfterPublish
|
|
2582
|
+
onAfterPublish: handleAfterPublish,
|
|
2583
|
+
notification,
|
|
2584
|
+
onSetNotification: setNotification
|
|
2468
2585
|
}
|
|
2469
|
-
), loading && /* @__PURE__ */
|
|
2586
|
+
), loading && /* @__PURE__ */ import_react17.default.createElement("div", { className: "bb-loading-bar" }, "Loading..."), isReadOnly && !loading && /* @__PURE__ */ import_react17.default.createElement("div", { className: "bb-readonly-banner" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "bb-readonly-banner__icon" }, "[i]"), /* @__PURE__ */ import_react17.default.createElement("span", null, "You are viewing a previous version - read only.", /* @__PURE__ */ import_react17.default.createElement(
|
|
2470
2587
|
"button",
|
|
2471
2588
|
{
|
|
2472
2589
|
type: "button",
|
|
@@ -2474,7 +2591,7 @@ function BuilderShell({ loadSlug }) {
|
|
|
2474
2591
|
onClick: handleRestoreVersion
|
|
2475
2592
|
},
|
|
2476
2593
|
"Switch to latest"
|
|
2477
|
-
))), /* @__PURE__ */
|
|
2594
|
+
))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "bb-main", "data-mobile-panel": mobilePanelTab }, /* @__PURE__ */ import_react17.default.createElement(BlockList, { blockDefs, activeSlug, onBlockSelect: loadBlockBySlug }), /* @__PURE__ */ import_react17.default.createElement("div", { className: "bb-main__center" }, /* @__PURE__ */ import_react17.default.createElement(FieldPalette, null), /* @__PURE__ */ import_react17.default.createElement(BuilderCanvas, null)), /* @__PURE__ */ import_react17.default.createElement(ConfigPanel, null)), /* @__PURE__ */ import_react17.default.createElement("div", { className: "bb-footer" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
2478
2595
|
"button",
|
|
2479
2596
|
{
|
|
2480
2597
|
type: "button",
|
|
@@ -2483,12 +2600,12 @@ function BuilderShell({ loadSlug }) {
|
|
|
2483
2600
|
},
|
|
2484
2601
|
showCodePreview ? "v" : ">",
|
|
2485
2602
|
" Code Preview"
|
|
2486
|
-
), showCodePreview && /* @__PURE__ */
|
|
2603
|
+
), showCodePreview && /* @__PURE__ */ import_react17.default.createElement("div", { className: "bb-footer__content" }, /* @__PURE__ */ import_react17.default.createElement(CodePreview, null))), /* @__PURE__ */ import_react17.default.createElement("nav", { className: "bb-mobile-nav", "aria-label": "Panel navigation" }, [
|
|
2487
2604
|
{ id: "blocks", icon: "B", label: "Blocks" },
|
|
2488
2605
|
{ id: "canvas", icon: "[]", label: "Canvas" },
|
|
2489
2606
|
{ id: "palette", icon: "+", label: "Fields" },
|
|
2490
2607
|
{ id: "config", icon: "*", label: "Config" }
|
|
2491
|
-
].map(({ id, icon, label }) => /* @__PURE__ */
|
|
2608
|
+
].map(({ id, icon, label }) => /* @__PURE__ */ import_react17.default.createElement(
|
|
2492
2609
|
"button",
|
|
2493
2610
|
{
|
|
2494
2611
|
key: id,
|
|
@@ -2496,16 +2613,16 @@ function BuilderShell({ loadSlug }) {
|
|
|
2496
2613
|
className: `bb-mobile-nav__tab${mobilePanelTab === id ? " bb-mobile-nav__tab--active" : ""}`,
|
|
2497
2614
|
onClick: () => setMobilePanelTab(id)
|
|
2498
2615
|
},
|
|
2499
|
-
/* @__PURE__ */
|
|
2616
|
+
/* @__PURE__ */ import_react17.default.createElement("span", { className: "bb-mobile-nav__icon" }, icon),
|
|
2500
2617
|
label
|
|
2501
2618
|
))));
|
|
2502
2619
|
}
|
|
2503
2620
|
|
|
2504
2621
|
// src/components/BlockBuilderNavLink/index.tsx
|
|
2505
|
-
var
|
|
2622
|
+
var import_react18 = __toESM(require("react"), 1);
|
|
2506
2623
|
var import_link = __toESM(require("next/link"), 1);
|
|
2507
2624
|
function BlockBuilderNavLink() {
|
|
2508
|
-
return /* @__PURE__ */
|
|
2625
|
+
return /* @__PURE__ */ import_react18.default.createElement("div", { style: { padding: "0 16px", marginTop: "8px" } }, /* @__PURE__ */ import_react18.default.createElement(
|
|
2509
2626
|
import_link.default,
|
|
2510
2627
|
{
|
|
2511
2628
|
href: "/block-builder",
|
|
@@ -2532,6 +2649,7 @@ function BlockBuilderNavLink() {
|
|
|
2532
2649
|
0 && (module.exports = {
|
|
2533
2650
|
BlockBuilderNavLink,
|
|
2534
2651
|
BlockDataField,
|
|
2652
|
+
BlockVersionSync,
|
|
2535
2653
|
BuilderShell,
|
|
2536
2654
|
EditInBuilderButton,
|
|
2537
2655
|
SchemaBuilderField
|