@tightknitai/block-kitchen 0.8.8 → 0.8.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +506 -150
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +507 -151
- package/dist/index.js.map +1 -1
- package/dist/{palette-5_Tx97Gk.d.cts → palette-DBTHRygt.d.cts} +7 -0
- package/dist/{palette-5_Tx97Gk.d.ts → palette-DBTHRygt.d.ts} +7 -0
- package/dist/palette.d.cts +1 -1
- package/dist/palette.d.ts +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -53,6 +53,34 @@ var Link__default = /*#__PURE__*/_interopDefault(Link);
|
|
|
53
53
|
var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
|
|
54
54
|
|
|
55
55
|
// src/components/block-kitchen.tsx
|
|
56
|
+
|
|
57
|
+
// src/lib/container-blocks.ts
|
|
58
|
+
var CONTAINER_CHILD_TYPES = /* @__PURE__ */ new Set([
|
|
59
|
+
"actions",
|
|
60
|
+
"context",
|
|
61
|
+
"divider",
|
|
62
|
+
"header",
|
|
63
|
+
"image",
|
|
64
|
+
"input",
|
|
65
|
+
"rich_text",
|
|
66
|
+
"section",
|
|
67
|
+
"table",
|
|
68
|
+
"video"
|
|
69
|
+
]);
|
|
70
|
+
var MAX_CONTAINER_CHILDREN = 10;
|
|
71
|
+
function isContainerChildType(type) {
|
|
72
|
+
return CONTAINER_CHILD_TYPES.has(type);
|
|
73
|
+
}
|
|
74
|
+
var BODY_PREFIX = "container-body:";
|
|
75
|
+
function containerBodyId(containerId) {
|
|
76
|
+
return `${BODY_PREFIX}${containerId}`;
|
|
77
|
+
}
|
|
78
|
+
function parseContainerBodyId(id) {
|
|
79
|
+
if (typeof id !== "string" || !id.startsWith(BODY_PREFIX)) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return id.slice(BODY_PREFIX.length);
|
|
83
|
+
}
|
|
56
84
|
function makeEmojiHook(byName) {
|
|
57
85
|
return (data, parse) => {
|
|
58
86
|
const entry = byName.get(data.name);
|
|
@@ -2012,9 +2040,52 @@ function useBlockKitValidation(blocks, surface) {
|
|
|
2012
2040
|
}, [blocks, surface]);
|
|
2013
2041
|
return state;
|
|
2014
2042
|
}
|
|
2043
|
+
function mirror(node) {
|
|
2044
|
+
if (!node.children) {
|
|
2045
|
+
return node;
|
|
2046
|
+
}
|
|
2047
|
+
return {
|
|
2048
|
+
...node,
|
|
2049
|
+
block: { ...node.block, child_blocks: node.children.map((c) => c.block) }
|
|
2050
|
+
};
|
|
2051
|
+
}
|
|
2015
2052
|
function wrap(block) {
|
|
2053
|
+
if (block.type === "container") {
|
|
2054
|
+
const children = (block.child_blocks ?? []).map(wrap);
|
|
2055
|
+
return mirror({ id: nanoid.nanoid(8), block, children });
|
|
2056
|
+
}
|
|
2016
2057
|
return { id: nanoid.nanoid(8), block };
|
|
2017
2058
|
}
|
|
2059
|
+
function cloneNode(node) {
|
|
2060
|
+
if (node.children) {
|
|
2061
|
+
return mirror({ id: nanoid.nanoid(8), block: structuredClone(node.block), children: node.children.map(cloneNode) });
|
|
2062
|
+
}
|
|
2063
|
+
return { id: nanoid.nanoid(8), block: structuredClone(node.block) };
|
|
2064
|
+
}
|
|
2065
|
+
function applyUpdate(node, block) {
|
|
2066
|
+
if (node.children) {
|
|
2067
|
+
return mirror({ ...node, block });
|
|
2068
|
+
}
|
|
2069
|
+
return { ...node, block };
|
|
2070
|
+
}
|
|
2071
|
+
function locate(blocks, id) {
|
|
2072
|
+
const top = blocks.findIndex((b) => b.id === id);
|
|
2073
|
+
if (top !== -1) {
|
|
2074
|
+
return { kind: "top", index: top };
|
|
2075
|
+
}
|
|
2076
|
+
for (const block of blocks) {
|
|
2077
|
+
if (block.children) {
|
|
2078
|
+
const idx = block.children.findIndex((c) => c.id === id);
|
|
2079
|
+
if (idx !== -1) {
|
|
2080
|
+
return { kind: "child", parentId: block.id, index: idx };
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
return null;
|
|
2085
|
+
}
|
|
2086
|
+
function withChildren(blocks, parentId, fn) {
|
|
2087
|
+
return blocks.map((b) => b.id === parentId && b.children ? mirror({ ...b, children: fn(b.children) }) : b);
|
|
2088
|
+
}
|
|
2018
2089
|
function useBlockKitchenState({
|
|
2019
2090
|
initialBlocks,
|
|
2020
2091
|
onChange
|
|
@@ -2035,41 +2106,113 @@ function useBlockKitchenState({
|
|
|
2035
2106
|
const addBlock = React.useCallback((block, atIndex) => {
|
|
2036
2107
|
setBlocks((prev) => {
|
|
2037
2108
|
const next = [...prev];
|
|
2038
|
-
const inserted = wrap(block);
|
|
2039
2109
|
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
2040
|
-
next.splice(idx, 0,
|
|
2110
|
+
next.splice(idx, 0, wrap(block));
|
|
2041
2111
|
return next;
|
|
2042
2112
|
});
|
|
2043
2113
|
}, []);
|
|
2114
|
+
const addChild = React.useCallback((parentId, block, atIndex) => {
|
|
2115
|
+
if (!isContainerChildType(block.type)) {
|
|
2116
|
+
return;
|
|
2117
|
+
}
|
|
2118
|
+
setBlocks(
|
|
2119
|
+
(prev) => withChildren(prev, parentId, (children) => {
|
|
2120
|
+
if (children.length >= MAX_CONTAINER_CHILDREN) {
|
|
2121
|
+
return children;
|
|
2122
|
+
}
|
|
2123
|
+
const next = [...children];
|
|
2124
|
+
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
2125
|
+
next.splice(idx, 0, wrap(block));
|
|
2126
|
+
return next;
|
|
2127
|
+
})
|
|
2128
|
+
);
|
|
2129
|
+
}, []);
|
|
2044
2130
|
const updateBlock = React.useCallback((id, block) => {
|
|
2045
|
-
setBlocks(
|
|
2131
|
+
setBlocks(
|
|
2132
|
+
(prev) => prev.map((b) => {
|
|
2133
|
+
if (b.id === id) {
|
|
2134
|
+
return applyUpdate(b, block);
|
|
2135
|
+
}
|
|
2136
|
+
if (b.children?.some((c) => c.id === id)) {
|
|
2137
|
+
return mirror({ ...b, children: b.children.map((c) => c.id === id ? applyUpdate(c, block) : c) });
|
|
2138
|
+
}
|
|
2139
|
+
return b;
|
|
2140
|
+
})
|
|
2141
|
+
);
|
|
2046
2142
|
}, []);
|
|
2047
2143
|
const removeBlock = React.useCallback((id) => {
|
|
2048
|
-
setBlocks((prev) =>
|
|
2144
|
+
setBlocks((prev) => {
|
|
2145
|
+
if (prev.some((b) => b.id === id)) {
|
|
2146
|
+
return prev.filter((b) => b.id !== id);
|
|
2147
|
+
}
|
|
2148
|
+
return prev.map(
|
|
2149
|
+
(b) => b.children?.some((c) => c.id === id) ? mirror({ ...b, children: b.children.filter((c) => c.id !== id) }) : b
|
|
2150
|
+
);
|
|
2151
|
+
});
|
|
2049
2152
|
}, []);
|
|
2050
2153
|
const duplicateBlock = React.useCallback((id) => {
|
|
2051
2154
|
setBlocks((prev) => {
|
|
2052
|
-
const
|
|
2053
|
-
if (
|
|
2155
|
+
const loc = locate(prev, id);
|
|
2156
|
+
if (!loc) {
|
|
2054
2157
|
return prev;
|
|
2055
2158
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2159
|
+
if (loc.kind === "top") {
|
|
2160
|
+
const next = [...prev];
|
|
2161
|
+
next.splice(loc.index + 1, 0, cloneNode(prev[loc.index]));
|
|
2162
|
+
return next;
|
|
2163
|
+
}
|
|
2164
|
+
return withChildren(prev, loc.parentId, (children) => {
|
|
2165
|
+
const next = [...children];
|
|
2166
|
+
next.splice(loc.index + 1, 0, cloneNode(children[loc.index]));
|
|
2167
|
+
return next;
|
|
2168
|
+
});
|
|
2060
2169
|
});
|
|
2061
2170
|
}, []);
|
|
2062
2171
|
const reorderBlock = React.useCallback((fromId, toIndex) => {
|
|
2063
2172
|
setBlocks((prev) => {
|
|
2064
|
-
const
|
|
2065
|
-
if (
|
|
2173
|
+
const loc = locate(prev, fromId);
|
|
2174
|
+
if (!loc) {
|
|
2066
2175
|
return prev;
|
|
2067
2176
|
}
|
|
2068
|
-
const
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2177
|
+
const reorder = (list) => {
|
|
2178
|
+
const next = [...list];
|
|
2179
|
+
const [moved] = next.splice(loc.index, 1);
|
|
2180
|
+
next.splice(Math.max(0, Math.min(toIndex, next.length)), 0, moved);
|
|
2181
|
+
return next;
|
|
2182
|
+
};
|
|
2183
|
+
if (loc.kind === "top") {
|
|
2184
|
+
return reorder(prev);
|
|
2185
|
+
}
|
|
2186
|
+
return withChildren(prev, loc.parentId, reorder);
|
|
2187
|
+
});
|
|
2188
|
+
}, []);
|
|
2189
|
+
const moveBlock = React.useCallback((activeId, target) => {
|
|
2190
|
+
setBlocks((prev) => {
|
|
2191
|
+
const loc = locate(prev, activeId);
|
|
2192
|
+
if (!loc) {
|
|
2193
|
+
return prev;
|
|
2194
|
+
}
|
|
2195
|
+
const moved = loc.kind === "top" ? prev[loc.index] : prev.find((b) => b.id === loc.parentId)?.children?.[loc.index];
|
|
2196
|
+
if (!moved) {
|
|
2197
|
+
return prev;
|
|
2198
|
+
}
|
|
2199
|
+
if (target.kind === "container") {
|
|
2200
|
+
if (moved.children || !isContainerChildType(moved.block.type)) {
|
|
2201
|
+
return prev;
|
|
2202
|
+
}
|
|
2203
|
+
const sameContainer = loc.kind === "child" && loc.parentId === target.parentId;
|
|
2204
|
+
const destCount = prev.find((b) => b.id === target.parentId)?.children?.length ?? 0;
|
|
2205
|
+
if (!sameContainer && destCount >= MAX_CONTAINER_CHILDREN) {
|
|
2206
|
+
return prev;
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
const detached = loc.kind === "top" ? prev.filter((_, i) => i !== loc.index) : withChildren(prev, loc.parentId, (children) => children.filter((_, i) => i !== loc.index));
|
|
2210
|
+
const insert = (list) => {
|
|
2211
|
+
const next = [...list];
|
|
2212
|
+
next.splice(Math.max(0, Math.min(target.index, next.length)), 0, moved);
|
|
2213
|
+
return next;
|
|
2214
|
+
};
|
|
2215
|
+
return target.kind === "container" ? withChildren(detached, target.parentId, insert) : insert(detached);
|
|
2073
2216
|
});
|
|
2074
2217
|
}, []);
|
|
2075
2218
|
const replaceAll = React.useCallback((newBlocks) => {
|
|
@@ -2078,10 +2221,12 @@ function useBlockKitchenState({
|
|
|
2078
2221
|
return {
|
|
2079
2222
|
blocks,
|
|
2080
2223
|
addBlock,
|
|
2224
|
+
addChild,
|
|
2081
2225
|
updateBlock,
|
|
2082
2226
|
removeBlock,
|
|
2083
2227
|
duplicateBlock,
|
|
2084
2228
|
reorderBlock,
|
|
2229
|
+
moveBlock,
|
|
2085
2230
|
replaceAll
|
|
2086
2231
|
};
|
|
2087
2232
|
}
|
|
@@ -3280,12 +3425,16 @@ function AlertEditor({ block, onChange }) {
|
|
|
3280
3425
|
) })
|
|
3281
3426
|
] });
|
|
3282
3427
|
}
|
|
3283
|
-
function CardEditor({
|
|
3428
|
+
function CardEditor({
|
|
3429
|
+
block,
|
|
3430
|
+
onChange,
|
|
3431
|
+
idPrefix = "card"
|
|
3432
|
+
}) {
|
|
3284
3433
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3285
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Title", help: "Up to 150 characters. Supports mrkdwn formatting.", htmlFor:
|
|
3434
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Title", help: "Up to 150 characters. Supports mrkdwn formatting.", htmlFor: `${idPrefix}-title`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3286
3435
|
Input,
|
|
3287
3436
|
{
|
|
3288
|
-
id:
|
|
3437
|
+
id: `${idPrefix}-title`,
|
|
3289
3438
|
value: block.title?.text ?? "",
|
|
3290
3439
|
maxLength: 150,
|
|
3291
3440
|
placeholder: "e.g. New launch update",
|
|
@@ -3295,10 +3444,10 @@ function CardEditor({ block, onChange }) {
|
|
|
3295
3444
|
})
|
|
3296
3445
|
}
|
|
3297
3446
|
) }),
|
|
3298
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Subtitle", help: "Up to 150 characters.", htmlFor:
|
|
3447
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Subtitle", help: "Up to 150 characters.", htmlFor: `${idPrefix}-subtitle`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3299
3448
|
Input,
|
|
3300
3449
|
{
|
|
3301
|
-
id:
|
|
3450
|
+
id: `${idPrefix}-subtitle`,
|
|
3302
3451
|
value: block.subtitle?.text ?? "",
|
|
3303
3452
|
maxLength: 150,
|
|
3304
3453
|
placeholder: "e.g. Released April 28",
|
|
@@ -3308,10 +3457,10 @@ function CardEditor({ block, onChange }) {
|
|
|
3308
3457
|
})
|
|
3309
3458
|
}
|
|
3310
3459
|
) }),
|
|
3311
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Body", help: "Up to 200 characters. Supports mrkdwn formatting.", htmlFor:
|
|
3460
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Body", help: "Up to 200 characters. Supports mrkdwn formatting.", htmlFor: `${idPrefix}-body`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3312
3461
|
Textarea,
|
|
3313
3462
|
{
|
|
3314
|
-
id:
|
|
3463
|
+
id: `${idPrefix}-body`,
|
|
3315
3464
|
value: block.body?.text ?? "",
|
|
3316
3465
|
maxLength: 200,
|
|
3317
3466
|
rows: 3,
|
|
@@ -3327,7 +3476,7 @@ function CardEditor({ block, onChange }) {
|
|
|
3327
3476
|
{
|
|
3328
3477
|
label: "Hero image",
|
|
3329
3478
|
help: "Wide image displayed at the top of the card.",
|
|
3330
|
-
idPrefix:
|
|
3479
|
+
idPrefix: `${idPrefix}-hero`,
|
|
3331
3480
|
image: block.hero_image,
|
|
3332
3481
|
onChange: (next) => onChange({ ...block, hero_image: next })
|
|
3333
3482
|
}
|
|
@@ -3337,7 +3486,7 @@ function CardEditor({ block, onChange }) {
|
|
|
3337
3486
|
{
|
|
3338
3487
|
label: "Icon",
|
|
3339
3488
|
help: "Small image shown next to the title.",
|
|
3340
|
-
idPrefix:
|
|
3489
|
+
idPrefix: `${idPrefix}-icon`,
|
|
3341
3490
|
image: block.icon,
|
|
3342
3491
|
onChange: (next) => onChange({ ...block, icon: next })
|
|
3343
3492
|
}
|
|
@@ -3345,6 +3494,7 @@ function CardEditor({ block, onChange }) {
|
|
|
3345
3494
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3346
3495
|
ButtonsField,
|
|
3347
3496
|
{
|
|
3497
|
+
idPrefix,
|
|
3348
3498
|
buttons: block.actions ?? [],
|
|
3349
3499
|
onChange: (next) => onChange({ ...block, actions: next.length > 0 ? next : void 0 })
|
|
3350
3500
|
}
|
|
@@ -3401,7 +3551,11 @@ function ImageFields({
|
|
|
3401
3551
|
) })
|
|
3402
3552
|
] });
|
|
3403
3553
|
}
|
|
3404
|
-
function ButtonsField({
|
|
3554
|
+
function ButtonsField({
|
|
3555
|
+
buttons,
|
|
3556
|
+
onChange,
|
|
3557
|
+
idPrefix = "card"
|
|
3558
|
+
}) {
|
|
3405
3559
|
const update = (idx, change) => {
|
|
3406
3560
|
onChange(buttons.map((b, i) => i === idx ? { ...b, ...change } : b));
|
|
3407
3561
|
};
|
|
@@ -3444,10 +3598,10 @@ function ButtonsField({ buttons, onChange }) {
|
|
|
3444
3598
|
}
|
|
3445
3599
|
)
|
|
3446
3600
|
] }),
|
|
3447
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Label", htmlFor:
|
|
3601
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Label", htmlFor: `${idPrefix}-btn-label-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3448
3602
|
Input,
|
|
3449
3603
|
{
|
|
3450
|
-
id:
|
|
3604
|
+
id: `${idPrefix}-btn-label-${idx}`,
|
|
3451
3605
|
value: label,
|
|
3452
3606
|
placeholder: "e.g. Open",
|
|
3453
3607
|
onChange: (e) => update(idx, {
|
|
@@ -3464,11 +3618,11 @@ function ButtonsField({ buttons, onChange }) {
|
|
|
3464
3618
|
{
|
|
3465
3619
|
label: "Link URL",
|
|
3466
3620
|
help: "Optional. If set, the button opens this link.",
|
|
3467
|
-
htmlFor:
|
|
3621
|
+
htmlFor: `${idPrefix}-btn-url-${idx}`,
|
|
3468
3622
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3469
3623
|
Input,
|
|
3470
3624
|
{
|
|
3471
|
-
id:
|
|
3625
|
+
id: `${idPrefix}-btn-url-${idx}`,
|
|
3472
3626
|
type: "url",
|
|
3473
3627
|
value: url,
|
|
3474
3628
|
placeholder: "e.g. https://example.com",
|
|
@@ -3487,8 +3641,8 @@ function ButtonsField({ buttons, onChange }) {
|
|
|
3487
3641
|
},
|
|
3488
3642
|
className: "flex flex-row gap-3",
|
|
3489
3643
|
children: ["default", "primary", "danger"].map((s) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3490
|
-
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: s, id:
|
|
3491
|
-
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor:
|
|
3644
|
+
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: s, id: `${idPrefix}-btn-style-${idx}-${s}` }),
|
|
3645
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `${idPrefix}-btn-style-${idx}-${s}`, className: "text-xs capitalize", children: s })
|
|
3492
3646
|
] }, s))
|
|
3493
3647
|
}
|
|
3494
3648
|
) })
|
|
@@ -3537,8 +3691,8 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3537
3691
|
});
|
|
3538
3692
|
};
|
|
3539
3693
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3540
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "Carousels hold 1-10 cards.
|
|
3541
|
-
elements.map((card, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-
|
|
3694
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "Carousels hold 1-10 cards." }),
|
|
3695
|
+
elements.map((card, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 rounded-md border bg-muted/20 p-3", children: [
|
|
3542
3696
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
3543
3697
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
3544
3698
|
"Card ",
|
|
@@ -3556,33 +3710,7 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3556
3710
|
}
|
|
3557
3711
|
)
|
|
3558
3712
|
] }),
|
|
3559
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3560
|
-
Input,
|
|
3561
|
-
{
|
|
3562
|
-
id: `carousel-card-title-${idx}`,
|
|
3563
|
-
value: card.title?.text ?? "",
|
|
3564
|
-
maxLength: 150,
|
|
3565
|
-
placeholder: "e.g. Card title",
|
|
3566
|
-
onChange: (e) => updateCard(idx, {
|
|
3567
|
-
...card,
|
|
3568
|
-
title: e.target.value ? { type: "mrkdwn", text: e.target.value } : void 0
|
|
3569
|
-
})
|
|
3570
|
-
}
|
|
3571
|
-
) }),
|
|
3572
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Body", htmlFor: `carousel-card-body-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3573
|
-
Textarea,
|
|
3574
|
-
{
|
|
3575
|
-
id: `carousel-card-body-${idx}`,
|
|
3576
|
-
value: card.body?.text ?? "",
|
|
3577
|
-
maxLength: 200,
|
|
3578
|
-
rows: 2,
|
|
3579
|
-
placeholder: "e.g. Short card description.",
|
|
3580
|
-
onChange: (e) => updateCard(idx, {
|
|
3581
|
-
...card,
|
|
3582
|
-
body: e.target.value ? { type: "mrkdwn", text: e.target.value } : void 0
|
|
3583
|
-
})
|
|
3584
|
-
}
|
|
3585
|
-
) })
|
|
3713
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardEditor, { block: card, idPrefix: `carousel-card-${idx}`, onChange: (next) => updateCard(idx, next) })
|
|
3586
3714
|
] }, idx)),
|
|
3587
3715
|
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addCard, disabled: elements.length >= MAX_CARDS, className: "self-start", children: [
|
|
3588
3716
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
@@ -3590,22 +3718,10 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3590
3718
|
] })
|
|
3591
3719
|
] });
|
|
3592
3720
|
}
|
|
3593
|
-
var MAX_CHILDREN = 10;
|
|
3594
3721
|
var WIDTHS = ["narrow", "standard", "wide", "full"];
|
|
3595
3722
|
function ContainerEditor({ block, onChange }) {
|
|
3596
|
-
const children = block.child_blocks ?? [];
|
|
3597
3723
|
const iconUrl = block.icon && "image_url" in block.icon ? block.icon.image_url ?? "" : "";
|
|
3598
3724
|
const iconAlt = block.icon?.alt_text ?? "";
|
|
3599
|
-
const removeChildAt = (idx) => {
|
|
3600
|
-
onChange({ ...block, child_blocks: children.filter((_, i) => i !== idx) });
|
|
3601
|
-
};
|
|
3602
|
-
const addChild = () => {
|
|
3603
|
-
const child = {
|
|
3604
|
-
type: "section",
|
|
3605
|
-
text: { type: "mrkdwn", text: "New block." }
|
|
3606
|
-
};
|
|
3607
|
-
onChange({ ...block, child_blocks: [...children, child] });
|
|
3608
|
-
};
|
|
3609
3725
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3610
3726
|
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Title", help: "Heading shown at the top of the container.", htmlFor: "container-title", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3611
3727
|
Input,
|
|
@@ -3680,42 +3796,7 @@ function ContainerEditor({ block, onChange }) {
|
|
|
3680
3796
|
onChange: (checked) => onChange({ ...block, default_collapsed: checked || void 0 })
|
|
3681
3797
|
}
|
|
3682
3798
|
),
|
|
3683
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3684
|
-
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Child blocks" }),
|
|
3685
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "A container holds 1-10 blocks. To edit a child's content, use the View JSON drawer." }),
|
|
3686
|
-
children.map((child, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 rounded-md border bg-muted/20 px-3 py-2", children: [
|
|
3687
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
3688
|
-
idx + 1,
|
|
3689
|
-
". ",
|
|
3690
|
-
labelForBlockType(child.type)
|
|
3691
|
-
] }),
|
|
3692
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3693
|
-
"button",
|
|
3694
|
-
{
|
|
3695
|
-
type: "button",
|
|
3696
|
-
"aria-label": "Remove child block",
|
|
3697
|
-
onClick: () => removeChildAt(idx),
|
|
3698
|
-
disabled: children.length <= 1,
|
|
3699
|
-
className: "rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive disabled:cursor-not-allowed disabled:opacity-40",
|
|
3700
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" })
|
|
3701
|
-
}
|
|
3702
|
-
)
|
|
3703
|
-
] }, idx)),
|
|
3704
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3705
|
-
Button,
|
|
3706
|
-
{
|
|
3707
|
-
type: "button",
|
|
3708
|
-
size: "sm",
|
|
3709
|
-
onClick: addChild,
|
|
3710
|
-
disabled: children.length >= MAX_CHILDREN,
|
|
3711
|
-
className: "self-start",
|
|
3712
|
-
children: [
|
|
3713
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
3714
|
-
" Add block"
|
|
3715
|
-
]
|
|
3716
|
-
}
|
|
3717
|
-
)
|
|
3718
|
-
] })
|
|
3799
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "Drag blocks into the container on the canvas to add them (1-10), and drag them out to remove. Click a child to edit it." })
|
|
3719
3800
|
] });
|
|
3720
3801
|
}
|
|
3721
3802
|
function Checkbox({
|
|
@@ -8286,6 +8367,225 @@ function RichTextInlineEditor({
|
|
|
8286
8367
|
}
|
|
8287
8368
|
);
|
|
8288
8369
|
}
|
|
8370
|
+
function ContainerRow({
|
|
8371
|
+
builderBlock,
|
|
8372
|
+
previewHooks,
|
|
8373
|
+
previewTheme,
|
|
8374
|
+
errorsByBlockId,
|
|
8375
|
+
openBlockId,
|
|
8376
|
+
onOpenBlockChange,
|
|
8377
|
+
onUpdate,
|
|
8378
|
+
onDuplicate,
|
|
8379
|
+
onDelete,
|
|
8380
|
+
onReorder,
|
|
8381
|
+
index,
|
|
8382
|
+
total,
|
|
8383
|
+
isPaletteDrag = false
|
|
8384
|
+
}) {
|
|
8385
|
+
const { id } = builderBlock;
|
|
8386
|
+
const block = builderBlock.block;
|
|
8387
|
+
const children = builderBlock.children ?? [];
|
|
8388
|
+
const errors = errorsByBlockId?.get(id);
|
|
8389
|
+
const hasErrors = !!errors && errors.length > 0;
|
|
8390
|
+
const isOpen = openBlockId === id;
|
|
8391
|
+
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = sortable.useSortable({ id });
|
|
8392
|
+
const { role: _dndRole, tabIndex: _dndTabIndex, ...sortableA11yAttrs } = attributes;
|
|
8393
|
+
const { setNodeRef: setBodyRef, isOver: isBodyOver } = core.useDroppable({ id: containerBodyId(id) });
|
|
8394
|
+
const style = { transform: utilities.CSS.Transform.toString(transform), transition };
|
|
8395
|
+
const icon = block.icon && "image_url" in block.icon ? block.icon.image_url : void 0;
|
|
8396
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8397
|
+
"div",
|
|
8398
|
+
{
|
|
8399
|
+
ref: setNodeRef,
|
|
8400
|
+
style,
|
|
8401
|
+
className: cn("group/container relative mb-2 last:mb-0 hover:z-10", isDragging && "opacity-40"),
|
|
8402
|
+
children: [
|
|
8403
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8404
|
+
"div",
|
|
8405
|
+
{
|
|
8406
|
+
className: cn(
|
|
8407
|
+
"overflow-hidden rounded-md border bg-card transition-shadow",
|
|
8408
|
+
hasErrors ? "border-destructive/60" : "border-border"
|
|
8409
|
+
),
|
|
8410
|
+
children: [
|
|
8411
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: isOpen, onOpenChange: (open) => onOpenBlockChange?.(open ? id : null), children: [
|
|
8412
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8413
|
+
"div",
|
|
8414
|
+
{
|
|
8415
|
+
role: "button",
|
|
8416
|
+
tabIndex: 0,
|
|
8417
|
+
"aria-label": "Edit container",
|
|
8418
|
+
...sortableA11yAttrs,
|
|
8419
|
+
...listeners,
|
|
8420
|
+
onKeyDown: (e) => {
|
|
8421
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
8422
|
+
e.preventDefault();
|
|
8423
|
+
onOpenBlockChange?.(!isOpen ? id : null);
|
|
8424
|
+
}
|
|
8425
|
+
},
|
|
8426
|
+
className: "flex w-full cursor-grab items-center gap-2 border-b bg-muted/40 px-3 py-2 text-left transition-colors hover:bg-muted active:cursor-grabbing",
|
|
8427
|
+
children: [
|
|
8428
|
+
icon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: icon, alt: "", "aria-hidden": "true", className: "h-5 w-5 shrink-0 rounded object-cover" }) : null,
|
|
8429
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
8430
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs font-semibold text-foreground", children: block.title?.text || "Container" }),
|
|
8431
|
+
block.subtitle?.text ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: block.subtitle.text }) : null
|
|
8432
|
+
] }),
|
|
8433
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto shrink-0 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Container" })
|
|
8434
|
+
]
|
|
8435
|
+
}
|
|
8436
|
+
) }),
|
|
8437
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { className: "w-[min(32rem,calc(100vw-1.5rem))] sm:w-[32rem]", align: "start", children: /* @__PURE__ */ jsxRuntime.jsx(BlockEditor, { block, errors, onChange: (next) => onUpdate(id, next) }) })
|
|
8438
|
+
] }),
|
|
8439
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8440
|
+
"div",
|
|
8441
|
+
{
|
|
8442
|
+
ref: setBodyRef,
|
|
8443
|
+
className: cn(
|
|
8444
|
+
"flex flex-col gap-2 p-3 transition-colors",
|
|
8445
|
+
isPaletteDrag && "outline-2 -outline-offset-2 outline-dashed outline-primary/40",
|
|
8446
|
+
isPaletteDrag && isBodyOver && "bg-primary/5"
|
|
8447
|
+
),
|
|
8448
|
+
children: children.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8449
|
+
"div",
|
|
8450
|
+
{
|
|
8451
|
+
className: cn(
|
|
8452
|
+
"flex items-center justify-center rounded-md border border-dashed px-3 py-6 text-center text-[11px] transition-colors",
|
|
8453
|
+
isBodyOver ? "border-primary/60 text-primary" : "border-border text-muted-foreground"
|
|
8454
|
+
),
|
|
8455
|
+
children: "Drag blocks here"
|
|
8456
|
+
}
|
|
8457
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(sortable.SortableContext, { items: children.map((c) => c.id), strategy: sortable.verticalListSortingStrategy, children: [
|
|
8458
|
+
children.map((child, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8459
|
+
BlockRow,
|
|
8460
|
+
{
|
|
8461
|
+
builderBlock: child,
|
|
8462
|
+
previewHooks,
|
|
8463
|
+
previewTheme,
|
|
8464
|
+
errors: errorsByBlockId?.get(child.id),
|
|
8465
|
+
isOpen: openBlockId === child.id,
|
|
8466
|
+
onOpenChange: (open) => onOpenBlockChange?.(open ? child.id : null),
|
|
8467
|
+
onUpdate,
|
|
8468
|
+
onDuplicate,
|
|
8469
|
+
onDelete,
|
|
8470
|
+
index: idx,
|
|
8471
|
+
total: children.length,
|
|
8472
|
+
onReorder,
|
|
8473
|
+
isPaletteDrag
|
|
8474
|
+
},
|
|
8475
|
+
child.id
|
|
8476
|
+
)),
|
|
8477
|
+
isPaletteDrag && isBodyOver ? /* @__PURE__ */ jsxRuntime.jsx(DropIndicator, {}) : null
|
|
8478
|
+
] })
|
|
8479
|
+
}
|
|
8480
|
+
)
|
|
8481
|
+
]
|
|
8482
|
+
}
|
|
8483
|
+
),
|
|
8484
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8485
|
+
"div",
|
|
8486
|
+
{
|
|
8487
|
+
className: cn(
|
|
8488
|
+
"absolute -top-3 right-2 z-10 hidden items-center gap-0.5 rounded-md border bg-background p-0.5 shadow-sm transition-opacity md:flex",
|
|
8489
|
+
hasErrors ? "opacity-100" : "opacity-0 group-hover/container:opacity-100 group-focus-within/container:opacity-100"
|
|
8490
|
+
),
|
|
8491
|
+
children: [
|
|
8492
|
+
hasErrors ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
8493
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8494
|
+
"button",
|
|
8495
|
+
{
|
|
8496
|
+
type: "button",
|
|
8497
|
+
"aria-label": `Show ${errors.length} validation ${errors.length === 1 ? "issue" : "issues"}`,
|
|
8498
|
+
onClick: () => onOpenBlockChange?.(id),
|
|
8499
|
+
className: "flex h-6 w-6 items-center justify-center rounded text-destructive hover:bg-destructive/10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
8500
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" })
|
|
8501
|
+
}
|
|
8502
|
+
) }),
|
|
8503
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", align: "end", children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "flex flex-col gap-0.5", children: [
|
|
8504
|
+
errors.slice(0, 4).map((err, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: err }, i)),
|
|
8505
|
+
errors.length > 4 ? /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "text-muted-foreground", children: [
|
|
8506
|
+
"and ",
|
|
8507
|
+
errors.length - 4,
|
|
8508
|
+
" more"
|
|
8509
|
+
] }) : null
|
|
8510
|
+
] }) })
|
|
8511
|
+
] }) : null,
|
|
8512
|
+
onReorder && typeof index === "number" && typeof total === "number" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8513
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Move up", disabled: index === 0, onClick: () => onReorder(id, index - 1), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-3.5 w-3.5" }) }),
|
|
8514
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Move down", disabled: index >= total - 1, onClick: () => onReorder(id, index + 1), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "h-3.5 w-3.5" }) })
|
|
8515
|
+
] }) : null,
|
|
8516
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Edit", onClick: () => onOpenBlockChange?.(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }) }),
|
|
8517
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Duplicate", onClick: () => onDuplicate(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3.5 w-3.5" }) }),
|
|
8518
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Delete", destructive: true, onClick: () => onDelete(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" }) })
|
|
8519
|
+
]
|
|
8520
|
+
}
|
|
8521
|
+
),
|
|
8522
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex items-center justify-between gap-2 rounded-md border border-dashed bg-muted/40 px-2 py-1 md:hidden", children: [
|
|
8523
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[11px] font-medium text-muted-foreground", children: "Container" }),
|
|
8524
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8525
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8526
|
+
"button",
|
|
8527
|
+
{
|
|
8528
|
+
type: "button",
|
|
8529
|
+
"aria-label": "Edit container",
|
|
8530
|
+
onClick: () => onOpenBlockChange?.(id),
|
|
8531
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
8532
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-4 w-4" })
|
|
8533
|
+
}
|
|
8534
|
+
),
|
|
8535
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8536
|
+
"button",
|
|
8537
|
+
{
|
|
8538
|
+
type: "button",
|
|
8539
|
+
"aria-label": "Duplicate container",
|
|
8540
|
+
onClick: () => onDuplicate(id),
|
|
8541
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
8542
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-4 w-4" })
|
|
8543
|
+
}
|
|
8544
|
+
),
|
|
8545
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8546
|
+
"button",
|
|
8547
|
+
{
|
|
8548
|
+
type: "button",
|
|
8549
|
+
"aria-label": "Delete container",
|
|
8550
|
+
onClick: () => onDelete(id),
|
|
8551
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
8552
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" })
|
|
8553
|
+
}
|
|
8554
|
+
)
|
|
8555
|
+
] })
|
|
8556
|
+
] })
|
|
8557
|
+
]
|
|
8558
|
+
}
|
|
8559
|
+
);
|
|
8560
|
+
}
|
|
8561
|
+
function ToolbarButton2({
|
|
8562
|
+
label,
|
|
8563
|
+
onClick,
|
|
8564
|
+
disabled,
|
|
8565
|
+
destructive,
|
|
8566
|
+
children
|
|
8567
|
+
}) {
|
|
8568
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
8569
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8570
|
+
"button",
|
|
8571
|
+
{
|
|
8572
|
+
type: "button",
|
|
8573
|
+
"aria-label": label,
|
|
8574
|
+
disabled,
|
|
8575
|
+
onClick,
|
|
8576
|
+
className: cn(
|
|
8577
|
+
"flex h-6 w-6 items-center justify-center rounded text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-40",
|
|
8578
|
+
destructive ? "hover:bg-destructive/10 hover:text-destructive" : "hover:bg-accent hover:text-foreground"
|
|
8579
|
+
),
|
|
8580
|
+
children
|
|
8581
|
+
}
|
|
8582
|
+
) }),
|
|
8583
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: label })
|
|
8584
|
+
] });
|
|
8585
|
+
}
|
|
8586
|
+
function DropIndicator() {
|
|
8587
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", className: "pointer-events-none relative my-1 h-0.5 w-full rounded-full bg-primary", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "-left-1 -top-[3px] absolute h-2 w-2 rounded-full bg-primary shadow-[0_0_0_2px_var(--color-background)]" }) });
|
|
8588
|
+
}
|
|
8289
8589
|
var SURFACE_DROPPABLE_ID = "builder-surface";
|
|
8290
8590
|
function Surface({
|
|
8291
8591
|
blocks,
|
|
@@ -8317,26 +8617,46 @@ function Surface({
|
|
|
8317
8617
|
isPaletteDrag && isOver && (isDark ? "bg-[#2c3036]" : "bg-[#eaf0ff]")
|
|
8318
8618
|
),
|
|
8319
8619
|
children: blocks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { isDark, isPaletteDrag, isOver, onOpenPalette }) : /* @__PURE__ */ jsxRuntime.jsxs(sortable.SortableContext, { items: blocks.map((b) => b.id), strategy: sortable.verticalListSortingStrategy, children: [
|
|
8320
|
-
blocks.map(
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8620
|
+
blocks.map(
|
|
8621
|
+
(block, idx) => block.block.type === "container" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8622
|
+
ContainerRow,
|
|
8623
|
+
{
|
|
8624
|
+
builderBlock: block,
|
|
8625
|
+
previewHooks,
|
|
8626
|
+
previewTheme,
|
|
8627
|
+
errorsByBlockId,
|
|
8628
|
+
openBlockId,
|
|
8629
|
+
onOpenBlockChange,
|
|
8630
|
+
onUpdate,
|
|
8631
|
+
onDuplicate,
|
|
8632
|
+
onDelete,
|
|
8633
|
+
index: idx,
|
|
8634
|
+
total: blocks.length,
|
|
8635
|
+
onReorder,
|
|
8636
|
+
isPaletteDrag
|
|
8637
|
+
},
|
|
8638
|
+
block.id
|
|
8639
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8640
|
+
BlockRow,
|
|
8641
|
+
{
|
|
8642
|
+
builderBlock: block,
|
|
8643
|
+
previewHooks,
|
|
8644
|
+
previewTheme,
|
|
8645
|
+
errors: errorsByBlockId?.get(block.id),
|
|
8646
|
+
isOpen: openBlockId === block.id,
|
|
8647
|
+
onOpenChange: (open) => onOpenBlockChange?.(open ? block.id : null),
|
|
8648
|
+
onUpdate,
|
|
8649
|
+
onDuplicate,
|
|
8650
|
+
onDelete,
|
|
8651
|
+
index: idx,
|
|
8652
|
+
total: blocks.length,
|
|
8653
|
+
onReorder,
|
|
8654
|
+
isPaletteDrag
|
|
8655
|
+
},
|
|
8656
|
+
block.id
|
|
8657
|
+
)
|
|
8658
|
+
),
|
|
8659
|
+
showEndDropZone ? /* @__PURE__ */ jsxRuntime.jsx(DropIndicator2, {}) : null
|
|
8340
8660
|
] })
|
|
8341
8661
|
}
|
|
8342
8662
|
);
|
|
@@ -8576,7 +8896,7 @@ function EmptyState({
|
|
|
8576
8896
|
}
|
|
8577
8897
|
);
|
|
8578
8898
|
}
|
|
8579
|
-
function
|
|
8899
|
+
function DropIndicator2() {
|
|
8580
8900
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", className: "pointer-events-none relative my-1 h-0.5 w-full rounded-full bg-primary", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "-left-1 -top-[3px] absolute h-2 w-2 rounded-full bg-primary shadow-[0_0_0_2px_var(--color-background)]" }) });
|
|
8581
8901
|
}
|
|
8582
8902
|
var THEME_OPTIONS = [
|
|
@@ -8939,9 +9259,18 @@ function BlockKitchen(props) {
|
|
|
8939
9259
|
}, [palette, disabledBlockTypes]);
|
|
8940
9260
|
const variantById = React.useMemo(() => buildVariantById(paletteSections), [paletteSections]);
|
|
8941
9261
|
const allowedSurfaces = allowedSurfacesProp && allowedSurfacesProp.length > 0 ? allowedSurfacesProp : ["message"];
|
|
8942
|
-
const { blocks, addBlock, updateBlock, removeBlock, duplicateBlock, reorderBlock, replaceAll } = useBlockKitchenState(
|
|
8943
|
-
|
|
8944
|
-
|
|
9262
|
+
const { blocks, addBlock, addChild, updateBlock, removeBlock, duplicateBlock, reorderBlock, moveBlock, replaceAll } = useBlockKitchenState({ initialBlocks, onChange });
|
|
9263
|
+
const childParentById = React.useMemo(() => {
|
|
9264
|
+
const map = /* @__PURE__ */ new Map();
|
|
9265
|
+
for (const top of blocks) {
|
|
9266
|
+
if (top.children) {
|
|
9267
|
+
for (const child of top.children) {
|
|
9268
|
+
map.set(child.id, top.id);
|
|
9269
|
+
}
|
|
9270
|
+
}
|
|
9271
|
+
}
|
|
9272
|
+
return map;
|
|
9273
|
+
}, [blocks]);
|
|
8945
9274
|
const [jsonOpen, setJsonOpen] = React.useState(false);
|
|
8946
9275
|
const [sendOpen, setSendOpen] = React.useState(false);
|
|
8947
9276
|
const [issuesOpen, setIssuesOpen] = React.useState(false);
|
|
@@ -8966,14 +9295,22 @@ function BlockKitchen(props) {
|
|
|
8966
9295
|
core.useSensor(core.TouchSensor, { activationConstraint: { delay: 150, tolerance: 8 } }),
|
|
8967
9296
|
core.useSensor(core.KeyboardSensor, { coordinateGetter: sortable.sortableKeyboardCoordinates })
|
|
8968
9297
|
);
|
|
8969
|
-
const collisionDetection = React.useCallback(
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
9298
|
+
const collisionDetection = React.useCallback(
|
|
9299
|
+
(args) => {
|
|
9300
|
+
const hits = core.pointerWithin(args);
|
|
9301
|
+
if (hits.length > 0) {
|
|
9302
|
+
const child = hits.find((c) => childParentById.has(c.id));
|
|
9303
|
+
if (child) return [child];
|
|
9304
|
+
const body = hits.find((c) => parseContainerBodyId(c.id) !== null);
|
|
9305
|
+
if (body) return [body];
|
|
9306
|
+
const block = hits.find((c) => c.id !== SURFACE_DROPPABLE_ID && parseContainerBodyId(c.id) === null);
|
|
9307
|
+
if (block) return [block];
|
|
9308
|
+
return hits;
|
|
9309
|
+
}
|
|
9310
|
+
return core.closestCenter(args);
|
|
9311
|
+
},
|
|
9312
|
+
[childParentById]
|
|
9313
|
+
);
|
|
8977
9314
|
const handleDragStart = React.useCallback((event) => {
|
|
8978
9315
|
const variantId = parsePaletteDragId(event.active.id);
|
|
8979
9316
|
setActivePaletteVariantId(variantId);
|
|
@@ -8985,24 +9322,43 @@ function BlockKitchen(props) {
|
|
|
8985
9322
|
if (!over) {
|
|
8986
9323
|
return;
|
|
8987
9324
|
}
|
|
9325
|
+
const overId = over.id;
|
|
9326
|
+
let target;
|
|
9327
|
+
const bodyParent = parseContainerBodyId(overId);
|
|
9328
|
+
const childParent = childParentById.get(overId);
|
|
9329
|
+
if (overId === SURFACE_DROPPABLE_ID) {
|
|
9330
|
+
target = { kind: "top", index: blocks.length };
|
|
9331
|
+
} else if (bodyParent) {
|
|
9332
|
+
const count = blocks.find((b) => b.id === bodyParent)?.children?.length ?? 0;
|
|
9333
|
+
target = { kind: "container", parentId: bodyParent, index: count };
|
|
9334
|
+
} else if (childParent) {
|
|
9335
|
+
const siblings = blocks.find((b) => b.id === childParent)?.children ?? [];
|
|
9336
|
+
target = { kind: "container", parentId: childParent, index: siblings.findIndex((c) => c.id === overId) };
|
|
9337
|
+
} else {
|
|
9338
|
+
const topIndex = blocks.findIndex((b) => b.id === overId);
|
|
9339
|
+
target = topIndex === -1 ? null : { kind: "top", index: topIndex };
|
|
9340
|
+
}
|
|
9341
|
+
if (!target) {
|
|
9342
|
+
return;
|
|
9343
|
+
}
|
|
8988
9344
|
const variantId = parsePaletteDragId(active.id);
|
|
8989
9345
|
if (variantId) {
|
|
8990
9346
|
const variant = variantById.get(variantId);
|
|
8991
9347
|
if (!variant) {
|
|
8992
9348
|
return;
|
|
8993
9349
|
}
|
|
8994
|
-
|
|
8995
|
-
|
|
9350
|
+
if (target.kind === "container") {
|
|
9351
|
+
addChild(target.parentId, variant.factory(), target.index);
|
|
9352
|
+
} else {
|
|
9353
|
+
addBlock(variant.factory(), target.index);
|
|
9354
|
+
}
|
|
8996
9355
|
return;
|
|
8997
9356
|
}
|
|
8998
|
-
if (active.id !==
|
|
8999
|
-
|
|
9000
|
-
if (overIndex !== -1) {
|
|
9001
|
-
reorderBlock(active.id, overIndex);
|
|
9002
|
-
}
|
|
9357
|
+
if (active.id !== overId) {
|
|
9358
|
+
moveBlock(active.id, target);
|
|
9003
9359
|
}
|
|
9004
9360
|
},
|
|
9005
|
-
[addBlock, blocks,
|
|
9361
|
+
[addBlock, addChild, blocks, childParentById, moveBlock, variantById]
|
|
9006
9362
|
);
|
|
9007
9363
|
const handleDragCancel = React.useCallback(() => {
|
|
9008
9364
|
setActivePaletteVariantId(null);
|