@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.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useSensors, useSensor, PointerSensor, TouchSensor, KeyboardSensor, pointerWithin, closestCenter, DndContext, DragOverlay, useDroppable, useDraggable } from '@dnd-kit/core';
|
|
2
2
|
import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, useSortable } from '@dnd-kit/sortable';
|
|
3
|
-
import { X, Circle, Sparkles, FileText, AlignLeft, MousePointerClick, TextCursorInput, LayoutTemplate, Bell, Pilcrow, Image, Video, GalleryHorizontal, Table, ChartColumnBig, Container, GripVertical, Sun, Moon, MessageSquare, AppWindow, Home, Plus, ChevronDown, BookOpen, ExternalLink, AlertTriangle, Trash2, Code2, MoreHorizontal, Send, Search, CheckCircle2, Check, ChevronRight, LayoutGrid, ArrowUp, ArrowDown, Pencil, Copy, Type, Bold, Italic, Strikethrough, Underline, Code, List, ListOrdered, Quote, Undo2, Redo2, Link as Link$1
|
|
3
|
+
import { X, Circle, Sparkles, FileText, AlignLeft, MousePointerClick, TextCursorInput, LayoutTemplate, Bell, Pilcrow, Image, Video, GalleryHorizontal, Table, ChartColumnBig, Container, GripVertical, Sun, Moon, MessageSquare, AppWindow, Home, Plus, ChevronDown, BookOpen, ExternalLink, AlertTriangle, Trash2, Code2, MoreHorizontal, Send, Search, CheckCircle2, Check, ChevronRight, LayoutGrid, ArrowUp, ArrowDown, Pencil, Copy, Type, Bold, Italic, Strikethrough, Underline, Code, List, ListOrdered, Quote, Undo2, Redo2, Smile, Link as Link$1 } from 'lucide-react';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { createContext, useMemo, useState, useCallback, useRef, useEffect, useId, useContext } from 'react';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -23,6 +23,34 @@ import 'slack-blocks-to-jsx/dist/style.css';
|
|
|
23
23
|
import { Message } from 'slack-blocks-to-jsx';
|
|
24
24
|
|
|
25
25
|
// src/components/block-kitchen.tsx
|
|
26
|
+
|
|
27
|
+
// src/lib/container-blocks.ts
|
|
28
|
+
var CONTAINER_CHILD_TYPES = /* @__PURE__ */ new Set([
|
|
29
|
+
"actions",
|
|
30
|
+
"context",
|
|
31
|
+
"divider",
|
|
32
|
+
"header",
|
|
33
|
+
"image",
|
|
34
|
+
"input",
|
|
35
|
+
"rich_text",
|
|
36
|
+
"section",
|
|
37
|
+
"table",
|
|
38
|
+
"video"
|
|
39
|
+
]);
|
|
40
|
+
var MAX_CONTAINER_CHILDREN = 10;
|
|
41
|
+
function isContainerChildType(type) {
|
|
42
|
+
return CONTAINER_CHILD_TYPES.has(type);
|
|
43
|
+
}
|
|
44
|
+
var BODY_PREFIX = "container-body:";
|
|
45
|
+
function containerBodyId(containerId) {
|
|
46
|
+
return `${BODY_PREFIX}${containerId}`;
|
|
47
|
+
}
|
|
48
|
+
function parseContainerBodyId(id) {
|
|
49
|
+
if (typeof id !== "string" || !id.startsWith(BODY_PREFIX)) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return id.slice(BODY_PREFIX.length);
|
|
53
|
+
}
|
|
26
54
|
function makeEmojiHook(byName) {
|
|
27
55
|
return (data, parse) => {
|
|
28
56
|
const entry = byName.get(data.name);
|
|
@@ -1982,9 +2010,52 @@ function useBlockKitValidation(blocks, surface) {
|
|
|
1982
2010
|
}, [blocks, surface]);
|
|
1983
2011
|
return state;
|
|
1984
2012
|
}
|
|
2013
|
+
function mirror(node) {
|
|
2014
|
+
if (!node.children) {
|
|
2015
|
+
return node;
|
|
2016
|
+
}
|
|
2017
|
+
return {
|
|
2018
|
+
...node,
|
|
2019
|
+
block: { ...node.block, child_blocks: node.children.map((c) => c.block) }
|
|
2020
|
+
};
|
|
2021
|
+
}
|
|
1985
2022
|
function wrap(block) {
|
|
2023
|
+
if (block.type === "container") {
|
|
2024
|
+
const children = (block.child_blocks ?? []).map(wrap);
|
|
2025
|
+
return mirror({ id: nanoid(8), block, children });
|
|
2026
|
+
}
|
|
1986
2027
|
return { id: nanoid(8), block };
|
|
1987
2028
|
}
|
|
2029
|
+
function cloneNode(node) {
|
|
2030
|
+
if (node.children) {
|
|
2031
|
+
return mirror({ id: nanoid(8), block: structuredClone(node.block), children: node.children.map(cloneNode) });
|
|
2032
|
+
}
|
|
2033
|
+
return { id: nanoid(8), block: structuredClone(node.block) };
|
|
2034
|
+
}
|
|
2035
|
+
function applyUpdate(node, block) {
|
|
2036
|
+
if (node.children) {
|
|
2037
|
+
return mirror({ ...node, block });
|
|
2038
|
+
}
|
|
2039
|
+
return { ...node, block };
|
|
2040
|
+
}
|
|
2041
|
+
function locate(blocks, id) {
|
|
2042
|
+
const top = blocks.findIndex((b) => b.id === id);
|
|
2043
|
+
if (top !== -1) {
|
|
2044
|
+
return { kind: "top", index: top };
|
|
2045
|
+
}
|
|
2046
|
+
for (const block of blocks) {
|
|
2047
|
+
if (block.children) {
|
|
2048
|
+
const idx = block.children.findIndex((c) => c.id === id);
|
|
2049
|
+
if (idx !== -1) {
|
|
2050
|
+
return { kind: "child", parentId: block.id, index: idx };
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
return null;
|
|
2055
|
+
}
|
|
2056
|
+
function withChildren(blocks, parentId, fn) {
|
|
2057
|
+
return blocks.map((b) => b.id === parentId && b.children ? mirror({ ...b, children: fn(b.children) }) : b);
|
|
2058
|
+
}
|
|
1988
2059
|
function useBlockKitchenState({
|
|
1989
2060
|
initialBlocks,
|
|
1990
2061
|
onChange
|
|
@@ -2005,41 +2076,113 @@ function useBlockKitchenState({
|
|
|
2005
2076
|
const addBlock = useCallback((block, atIndex) => {
|
|
2006
2077
|
setBlocks((prev) => {
|
|
2007
2078
|
const next = [...prev];
|
|
2008
|
-
const inserted = wrap(block);
|
|
2009
2079
|
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
2010
|
-
next.splice(idx, 0,
|
|
2080
|
+
next.splice(idx, 0, wrap(block));
|
|
2011
2081
|
return next;
|
|
2012
2082
|
});
|
|
2013
2083
|
}, []);
|
|
2084
|
+
const addChild = useCallback((parentId, block, atIndex) => {
|
|
2085
|
+
if (!isContainerChildType(block.type)) {
|
|
2086
|
+
return;
|
|
2087
|
+
}
|
|
2088
|
+
setBlocks(
|
|
2089
|
+
(prev) => withChildren(prev, parentId, (children) => {
|
|
2090
|
+
if (children.length >= MAX_CONTAINER_CHILDREN) {
|
|
2091
|
+
return children;
|
|
2092
|
+
}
|
|
2093
|
+
const next = [...children];
|
|
2094
|
+
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
2095
|
+
next.splice(idx, 0, wrap(block));
|
|
2096
|
+
return next;
|
|
2097
|
+
})
|
|
2098
|
+
);
|
|
2099
|
+
}, []);
|
|
2014
2100
|
const updateBlock = useCallback((id, block) => {
|
|
2015
|
-
setBlocks(
|
|
2101
|
+
setBlocks(
|
|
2102
|
+
(prev) => prev.map((b) => {
|
|
2103
|
+
if (b.id === id) {
|
|
2104
|
+
return applyUpdate(b, block);
|
|
2105
|
+
}
|
|
2106
|
+
if (b.children?.some((c) => c.id === id)) {
|
|
2107
|
+
return mirror({ ...b, children: b.children.map((c) => c.id === id ? applyUpdate(c, block) : c) });
|
|
2108
|
+
}
|
|
2109
|
+
return b;
|
|
2110
|
+
})
|
|
2111
|
+
);
|
|
2016
2112
|
}, []);
|
|
2017
2113
|
const removeBlock = useCallback((id) => {
|
|
2018
|
-
setBlocks((prev) =>
|
|
2114
|
+
setBlocks((prev) => {
|
|
2115
|
+
if (prev.some((b) => b.id === id)) {
|
|
2116
|
+
return prev.filter((b) => b.id !== id);
|
|
2117
|
+
}
|
|
2118
|
+
return prev.map(
|
|
2119
|
+
(b) => b.children?.some((c) => c.id === id) ? mirror({ ...b, children: b.children.filter((c) => c.id !== id) }) : b
|
|
2120
|
+
);
|
|
2121
|
+
});
|
|
2019
2122
|
}, []);
|
|
2020
2123
|
const duplicateBlock = useCallback((id) => {
|
|
2021
2124
|
setBlocks((prev) => {
|
|
2022
|
-
const
|
|
2023
|
-
if (
|
|
2125
|
+
const loc = locate(prev, id);
|
|
2126
|
+
if (!loc) {
|
|
2024
2127
|
return prev;
|
|
2025
2128
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2129
|
+
if (loc.kind === "top") {
|
|
2130
|
+
const next = [...prev];
|
|
2131
|
+
next.splice(loc.index + 1, 0, cloneNode(prev[loc.index]));
|
|
2132
|
+
return next;
|
|
2133
|
+
}
|
|
2134
|
+
return withChildren(prev, loc.parentId, (children) => {
|
|
2135
|
+
const next = [...children];
|
|
2136
|
+
next.splice(loc.index + 1, 0, cloneNode(children[loc.index]));
|
|
2137
|
+
return next;
|
|
2138
|
+
});
|
|
2030
2139
|
});
|
|
2031
2140
|
}, []);
|
|
2032
2141
|
const reorderBlock = useCallback((fromId, toIndex) => {
|
|
2033
2142
|
setBlocks((prev) => {
|
|
2034
|
-
const
|
|
2035
|
-
if (
|
|
2143
|
+
const loc = locate(prev, fromId);
|
|
2144
|
+
if (!loc) {
|
|
2036
2145
|
return prev;
|
|
2037
2146
|
}
|
|
2038
|
-
const
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2147
|
+
const reorder = (list) => {
|
|
2148
|
+
const next = [...list];
|
|
2149
|
+
const [moved] = next.splice(loc.index, 1);
|
|
2150
|
+
next.splice(Math.max(0, Math.min(toIndex, next.length)), 0, moved);
|
|
2151
|
+
return next;
|
|
2152
|
+
};
|
|
2153
|
+
if (loc.kind === "top") {
|
|
2154
|
+
return reorder(prev);
|
|
2155
|
+
}
|
|
2156
|
+
return withChildren(prev, loc.parentId, reorder);
|
|
2157
|
+
});
|
|
2158
|
+
}, []);
|
|
2159
|
+
const moveBlock = useCallback((activeId, target) => {
|
|
2160
|
+
setBlocks((prev) => {
|
|
2161
|
+
const loc = locate(prev, activeId);
|
|
2162
|
+
if (!loc) {
|
|
2163
|
+
return prev;
|
|
2164
|
+
}
|
|
2165
|
+
const moved = loc.kind === "top" ? prev[loc.index] : prev.find((b) => b.id === loc.parentId)?.children?.[loc.index];
|
|
2166
|
+
if (!moved) {
|
|
2167
|
+
return prev;
|
|
2168
|
+
}
|
|
2169
|
+
if (target.kind === "container") {
|
|
2170
|
+
if (moved.children || !isContainerChildType(moved.block.type)) {
|
|
2171
|
+
return prev;
|
|
2172
|
+
}
|
|
2173
|
+
const sameContainer = loc.kind === "child" && loc.parentId === target.parentId;
|
|
2174
|
+
const destCount = prev.find((b) => b.id === target.parentId)?.children?.length ?? 0;
|
|
2175
|
+
if (!sameContainer && destCount >= MAX_CONTAINER_CHILDREN) {
|
|
2176
|
+
return prev;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
const detached = loc.kind === "top" ? prev.filter((_, i) => i !== loc.index) : withChildren(prev, loc.parentId, (children) => children.filter((_, i) => i !== loc.index));
|
|
2180
|
+
const insert = (list) => {
|
|
2181
|
+
const next = [...list];
|
|
2182
|
+
next.splice(Math.max(0, Math.min(target.index, next.length)), 0, moved);
|
|
2183
|
+
return next;
|
|
2184
|
+
};
|
|
2185
|
+
return target.kind === "container" ? withChildren(detached, target.parentId, insert) : insert(detached);
|
|
2043
2186
|
});
|
|
2044
2187
|
}, []);
|
|
2045
2188
|
const replaceAll = useCallback((newBlocks) => {
|
|
@@ -2048,10 +2191,12 @@ function useBlockKitchenState({
|
|
|
2048
2191
|
return {
|
|
2049
2192
|
blocks,
|
|
2050
2193
|
addBlock,
|
|
2194
|
+
addChild,
|
|
2051
2195
|
updateBlock,
|
|
2052
2196
|
removeBlock,
|
|
2053
2197
|
duplicateBlock,
|
|
2054
2198
|
reorderBlock,
|
|
2199
|
+
moveBlock,
|
|
2055
2200
|
replaceAll
|
|
2056
2201
|
};
|
|
2057
2202
|
}
|
|
@@ -3250,12 +3395,16 @@ function AlertEditor({ block, onChange }) {
|
|
|
3250
3395
|
) })
|
|
3251
3396
|
] });
|
|
3252
3397
|
}
|
|
3253
|
-
function CardEditor({
|
|
3398
|
+
function CardEditor({
|
|
3399
|
+
block,
|
|
3400
|
+
onChange,
|
|
3401
|
+
idPrefix = "card"
|
|
3402
|
+
}) {
|
|
3254
3403
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3255
|
-
/* @__PURE__ */ jsx(EditorField, { label: "Title", help: "Up to 150 characters. Supports mrkdwn formatting.", htmlFor:
|
|
3404
|
+
/* @__PURE__ */ jsx(EditorField, { label: "Title", help: "Up to 150 characters. Supports mrkdwn formatting.", htmlFor: `${idPrefix}-title`, children: /* @__PURE__ */ jsx(
|
|
3256
3405
|
Input,
|
|
3257
3406
|
{
|
|
3258
|
-
id:
|
|
3407
|
+
id: `${idPrefix}-title`,
|
|
3259
3408
|
value: block.title?.text ?? "",
|
|
3260
3409
|
maxLength: 150,
|
|
3261
3410
|
placeholder: "e.g. New launch update",
|
|
@@ -3265,10 +3414,10 @@ function CardEditor({ block, onChange }) {
|
|
|
3265
3414
|
})
|
|
3266
3415
|
}
|
|
3267
3416
|
) }),
|
|
3268
|
-
/* @__PURE__ */ jsx(EditorField, { label: "Subtitle", help: "Up to 150 characters.", htmlFor:
|
|
3417
|
+
/* @__PURE__ */ jsx(EditorField, { label: "Subtitle", help: "Up to 150 characters.", htmlFor: `${idPrefix}-subtitle`, children: /* @__PURE__ */ jsx(
|
|
3269
3418
|
Input,
|
|
3270
3419
|
{
|
|
3271
|
-
id:
|
|
3420
|
+
id: `${idPrefix}-subtitle`,
|
|
3272
3421
|
value: block.subtitle?.text ?? "",
|
|
3273
3422
|
maxLength: 150,
|
|
3274
3423
|
placeholder: "e.g. Released April 28",
|
|
@@ -3278,10 +3427,10 @@ function CardEditor({ block, onChange }) {
|
|
|
3278
3427
|
})
|
|
3279
3428
|
}
|
|
3280
3429
|
) }),
|
|
3281
|
-
/* @__PURE__ */ jsx(EditorField, { label: "Body", help: "Up to 200 characters. Supports mrkdwn formatting.", htmlFor:
|
|
3430
|
+
/* @__PURE__ */ jsx(EditorField, { label: "Body", help: "Up to 200 characters. Supports mrkdwn formatting.", htmlFor: `${idPrefix}-body`, children: /* @__PURE__ */ jsx(
|
|
3282
3431
|
Textarea,
|
|
3283
3432
|
{
|
|
3284
|
-
id:
|
|
3433
|
+
id: `${idPrefix}-body`,
|
|
3285
3434
|
value: block.body?.text ?? "",
|
|
3286
3435
|
maxLength: 200,
|
|
3287
3436
|
rows: 3,
|
|
@@ -3297,7 +3446,7 @@ function CardEditor({ block, onChange }) {
|
|
|
3297
3446
|
{
|
|
3298
3447
|
label: "Hero image",
|
|
3299
3448
|
help: "Wide image displayed at the top of the card.",
|
|
3300
|
-
idPrefix:
|
|
3449
|
+
idPrefix: `${idPrefix}-hero`,
|
|
3301
3450
|
image: block.hero_image,
|
|
3302
3451
|
onChange: (next) => onChange({ ...block, hero_image: next })
|
|
3303
3452
|
}
|
|
@@ -3307,7 +3456,7 @@ function CardEditor({ block, onChange }) {
|
|
|
3307
3456
|
{
|
|
3308
3457
|
label: "Icon",
|
|
3309
3458
|
help: "Small image shown next to the title.",
|
|
3310
|
-
idPrefix:
|
|
3459
|
+
idPrefix: `${idPrefix}-icon`,
|
|
3311
3460
|
image: block.icon,
|
|
3312
3461
|
onChange: (next) => onChange({ ...block, icon: next })
|
|
3313
3462
|
}
|
|
@@ -3315,6 +3464,7 @@ function CardEditor({ block, onChange }) {
|
|
|
3315
3464
|
/* @__PURE__ */ jsx(
|
|
3316
3465
|
ButtonsField,
|
|
3317
3466
|
{
|
|
3467
|
+
idPrefix,
|
|
3318
3468
|
buttons: block.actions ?? [],
|
|
3319
3469
|
onChange: (next) => onChange({ ...block, actions: next.length > 0 ? next : void 0 })
|
|
3320
3470
|
}
|
|
@@ -3371,7 +3521,11 @@ function ImageFields({
|
|
|
3371
3521
|
) })
|
|
3372
3522
|
] });
|
|
3373
3523
|
}
|
|
3374
|
-
function ButtonsField({
|
|
3524
|
+
function ButtonsField({
|
|
3525
|
+
buttons,
|
|
3526
|
+
onChange,
|
|
3527
|
+
idPrefix = "card"
|
|
3528
|
+
}) {
|
|
3375
3529
|
const update = (idx, change) => {
|
|
3376
3530
|
onChange(buttons.map((b, i) => i === idx ? { ...b, ...change } : b));
|
|
3377
3531
|
};
|
|
@@ -3414,10 +3568,10 @@ function ButtonsField({ buttons, onChange }) {
|
|
|
3414
3568
|
}
|
|
3415
3569
|
)
|
|
3416
3570
|
] }),
|
|
3417
|
-
/* @__PURE__ */ jsx(EditorField, { label: "Label", htmlFor:
|
|
3571
|
+
/* @__PURE__ */ jsx(EditorField, { label: "Label", htmlFor: `${idPrefix}-btn-label-${idx}`, children: /* @__PURE__ */ jsx(
|
|
3418
3572
|
Input,
|
|
3419
3573
|
{
|
|
3420
|
-
id:
|
|
3574
|
+
id: `${idPrefix}-btn-label-${idx}`,
|
|
3421
3575
|
value: label,
|
|
3422
3576
|
placeholder: "e.g. Open",
|
|
3423
3577
|
onChange: (e) => update(idx, {
|
|
@@ -3434,11 +3588,11 @@ function ButtonsField({ buttons, onChange }) {
|
|
|
3434
3588
|
{
|
|
3435
3589
|
label: "Link URL",
|
|
3436
3590
|
help: "Optional. If set, the button opens this link.",
|
|
3437
|
-
htmlFor:
|
|
3591
|
+
htmlFor: `${idPrefix}-btn-url-${idx}`,
|
|
3438
3592
|
children: /* @__PURE__ */ jsx(
|
|
3439
3593
|
Input,
|
|
3440
3594
|
{
|
|
3441
|
-
id:
|
|
3595
|
+
id: `${idPrefix}-btn-url-${idx}`,
|
|
3442
3596
|
type: "url",
|
|
3443
3597
|
value: url,
|
|
3444
3598
|
placeholder: "e.g. https://example.com",
|
|
@@ -3457,8 +3611,8 @@ function ButtonsField({ buttons, onChange }) {
|
|
|
3457
3611
|
},
|
|
3458
3612
|
className: "flex flex-row gap-3",
|
|
3459
3613
|
children: ["default", "primary", "danger"].map((s) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3460
|
-
/* @__PURE__ */ jsx(RadioGroupItem, { value: s, id:
|
|
3461
|
-
/* @__PURE__ */ jsx(Label, { htmlFor:
|
|
3614
|
+
/* @__PURE__ */ jsx(RadioGroupItem, { value: s, id: `${idPrefix}-btn-style-${idx}-${s}` }),
|
|
3615
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: `${idPrefix}-btn-style-${idx}-${s}`, className: "text-xs capitalize", children: s })
|
|
3462
3616
|
] }, s))
|
|
3463
3617
|
}
|
|
3464
3618
|
) })
|
|
@@ -3507,8 +3661,8 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3507
3661
|
});
|
|
3508
3662
|
};
|
|
3509
3663
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3510
|
-
/* @__PURE__ */ jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "Carousels hold 1-10 cards.
|
|
3511
|
-
elements.map((card, idx) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-
|
|
3664
|
+
/* @__PURE__ */ jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "Carousels hold 1-10 cards." }),
|
|
3665
|
+
elements.map((card, idx) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 rounded-md border bg-muted/20 p-3", children: [
|
|
3512
3666
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
3513
3667
|
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
3514
3668
|
"Card ",
|
|
@@ -3526,33 +3680,7 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3526
3680
|
}
|
|
3527
3681
|
)
|
|
3528
3682
|
] }),
|
|
3529
|
-
/* @__PURE__ */ jsx(
|
|
3530
|
-
Input,
|
|
3531
|
-
{
|
|
3532
|
-
id: `carousel-card-title-${idx}`,
|
|
3533
|
-
value: card.title?.text ?? "",
|
|
3534
|
-
maxLength: 150,
|
|
3535
|
-
placeholder: "e.g. Card title",
|
|
3536
|
-
onChange: (e) => updateCard(idx, {
|
|
3537
|
-
...card,
|
|
3538
|
-
title: e.target.value ? { type: "mrkdwn", text: e.target.value } : void 0
|
|
3539
|
-
})
|
|
3540
|
-
}
|
|
3541
|
-
) }),
|
|
3542
|
-
/* @__PURE__ */ jsx(EditorField, { label: "Body", htmlFor: `carousel-card-body-${idx}`, children: /* @__PURE__ */ jsx(
|
|
3543
|
-
Textarea,
|
|
3544
|
-
{
|
|
3545
|
-
id: `carousel-card-body-${idx}`,
|
|
3546
|
-
value: card.body?.text ?? "",
|
|
3547
|
-
maxLength: 200,
|
|
3548
|
-
rows: 2,
|
|
3549
|
-
placeholder: "e.g. Short card description.",
|
|
3550
|
-
onChange: (e) => updateCard(idx, {
|
|
3551
|
-
...card,
|
|
3552
|
-
body: e.target.value ? { type: "mrkdwn", text: e.target.value } : void 0
|
|
3553
|
-
})
|
|
3554
|
-
}
|
|
3555
|
-
) })
|
|
3683
|
+
/* @__PURE__ */ jsx(CardEditor, { block: card, idPrefix: `carousel-card-${idx}`, onChange: (next) => updateCard(idx, next) })
|
|
3556
3684
|
] }, idx)),
|
|
3557
3685
|
/* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: addCard, disabled: elements.length >= MAX_CARDS, className: "self-start", children: [
|
|
3558
3686
|
/* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
|
|
@@ -3560,22 +3688,10 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3560
3688
|
] })
|
|
3561
3689
|
] });
|
|
3562
3690
|
}
|
|
3563
|
-
var MAX_CHILDREN = 10;
|
|
3564
3691
|
var WIDTHS = ["narrow", "standard", "wide", "full"];
|
|
3565
3692
|
function ContainerEditor({ block, onChange }) {
|
|
3566
|
-
const children = block.child_blocks ?? [];
|
|
3567
3693
|
const iconUrl = block.icon && "image_url" in block.icon ? block.icon.image_url ?? "" : "";
|
|
3568
3694
|
const iconAlt = block.icon?.alt_text ?? "";
|
|
3569
|
-
const removeChildAt = (idx) => {
|
|
3570
|
-
onChange({ ...block, child_blocks: children.filter((_, i) => i !== idx) });
|
|
3571
|
-
};
|
|
3572
|
-
const addChild = () => {
|
|
3573
|
-
const child = {
|
|
3574
|
-
type: "section",
|
|
3575
|
-
text: { type: "mrkdwn", text: "New block." }
|
|
3576
|
-
};
|
|
3577
|
-
onChange({ ...block, child_blocks: [...children, child] });
|
|
3578
|
-
};
|
|
3579
3695
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3580
3696
|
/* @__PURE__ */ jsx(EditorField, { label: "Title", help: "Heading shown at the top of the container.", htmlFor: "container-title", children: /* @__PURE__ */ jsx(
|
|
3581
3697
|
Input,
|
|
@@ -3650,42 +3766,7 @@ function ContainerEditor({ block, onChange }) {
|
|
|
3650
3766
|
onChange: (checked) => onChange({ ...block, default_collapsed: checked || void 0 })
|
|
3651
3767
|
}
|
|
3652
3768
|
),
|
|
3653
|
-
/* @__PURE__ */
|
|
3654
|
-
/* @__PURE__ */ jsx(Label, { children: "Child blocks" }),
|
|
3655
|
-
/* @__PURE__ */ 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." }),
|
|
3656
|
-
children.map((child, idx) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 rounded-md border bg-muted/20 px-3 py-2", children: [
|
|
3657
|
-
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
3658
|
-
idx + 1,
|
|
3659
|
-
". ",
|
|
3660
|
-
labelForBlockType(child.type)
|
|
3661
|
-
] }),
|
|
3662
|
-
/* @__PURE__ */ jsx(
|
|
3663
|
-
"button",
|
|
3664
|
-
{
|
|
3665
|
-
type: "button",
|
|
3666
|
-
"aria-label": "Remove child block",
|
|
3667
|
-
onClick: () => removeChildAt(idx),
|
|
3668
|
-
disabled: children.length <= 1,
|
|
3669
|
-
className: "rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive disabled:cursor-not-allowed disabled:opacity-40",
|
|
3670
|
-
children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
|
|
3671
|
-
}
|
|
3672
|
-
)
|
|
3673
|
-
] }, idx)),
|
|
3674
|
-
/* @__PURE__ */ jsxs(
|
|
3675
|
-
Button,
|
|
3676
|
-
{
|
|
3677
|
-
type: "button",
|
|
3678
|
-
size: "sm",
|
|
3679
|
-
onClick: addChild,
|
|
3680
|
-
disabled: children.length >= MAX_CHILDREN,
|
|
3681
|
-
className: "self-start",
|
|
3682
|
-
children: [
|
|
3683
|
-
/* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
|
|
3684
|
-
" Add block"
|
|
3685
|
-
]
|
|
3686
|
-
}
|
|
3687
|
-
)
|
|
3688
|
-
] })
|
|
3769
|
+
/* @__PURE__ */ 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." })
|
|
3689
3770
|
] });
|
|
3690
3771
|
}
|
|
3691
3772
|
function Checkbox({
|
|
@@ -8256,6 +8337,225 @@ function RichTextInlineEditor({
|
|
|
8256
8337
|
}
|
|
8257
8338
|
);
|
|
8258
8339
|
}
|
|
8340
|
+
function ContainerRow({
|
|
8341
|
+
builderBlock,
|
|
8342
|
+
previewHooks,
|
|
8343
|
+
previewTheme,
|
|
8344
|
+
errorsByBlockId,
|
|
8345
|
+
openBlockId,
|
|
8346
|
+
onOpenBlockChange,
|
|
8347
|
+
onUpdate,
|
|
8348
|
+
onDuplicate,
|
|
8349
|
+
onDelete,
|
|
8350
|
+
onReorder,
|
|
8351
|
+
index,
|
|
8352
|
+
total,
|
|
8353
|
+
isPaletteDrag = false
|
|
8354
|
+
}) {
|
|
8355
|
+
const { id } = builderBlock;
|
|
8356
|
+
const block = builderBlock.block;
|
|
8357
|
+
const children = builderBlock.children ?? [];
|
|
8358
|
+
const errors = errorsByBlockId?.get(id);
|
|
8359
|
+
const hasErrors = !!errors && errors.length > 0;
|
|
8360
|
+
const isOpen = openBlockId === id;
|
|
8361
|
+
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id });
|
|
8362
|
+
const { role: _dndRole, tabIndex: _dndTabIndex, ...sortableA11yAttrs } = attributes;
|
|
8363
|
+
const { setNodeRef: setBodyRef, isOver: isBodyOver } = useDroppable({ id: containerBodyId(id) });
|
|
8364
|
+
const style = { transform: CSS.Transform.toString(transform), transition };
|
|
8365
|
+
const icon = block.icon && "image_url" in block.icon ? block.icon.image_url : void 0;
|
|
8366
|
+
return /* @__PURE__ */ jsxs(
|
|
8367
|
+
"div",
|
|
8368
|
+
{
|
|
8369
|
+
ref: setNodeRef,
|
|
8370
|
+
style,
|
|
8371
|
+
className: cn("group/container relative mb-2 last:mb-0 hover:z-10", isDragging && "opacity-40"),
|
|
8372
|
+
children: [
|
|
8373
|
+
/* @__PURE__ */ jsxs(
|
|
8374
|
+
"div",
|
|
8375
|
+
{
|
|
8376
|
+
className: cn(
|
|
8377
|
+
"overflow-hidden rounded-md border bg-card transition-shadow",
|
|
8378
|
+
hasErrors ? "border-destructive/60" : "border-border"
|
|
8379
|
+
),
|
|
8380
|
+
children: [
|
|
8381
|
+
/* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: (open) => onOpenBlockChange?.(open ? id : null), children: [
|
|
8382
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
8383
|
+
"div",
|
|
8384
|
+
{
|
|
8385
|
+
role: "button",
|
|
8386
|
+
tabIndex: 0,
|
|
8387
|
+
"aria-label": "Edit container",
|
|
8388
|
+
...sortableA11yAttrs,
|
|
8389
|
+
...listeners,
|
|
8390
|
+
onKeyDown: (e) => {
|
|
8391
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
8392
|
+
e.preventDefault();
|
|
8393
|
+
onOpenBlockChange?.(!isOpen ? id : null);
|
|
8394
|
+
}
|
|
8395
|
+
},
|
|
8396
|
+
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",
|
|
8397
|
+
children: [
|
|
8398
|
+
icon ? /* @__PURE__ */ jsx("img", { src: icon, alt: "", "aria-hidden": "true", className: "h-5 w-5 shrink-0 rounded object-cover" }) : null,
|
|
8399
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
8400
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-xs font-semibold text-foreground", children: block.title?.text || "Container" }),
|
|
8401
|
+
block.subtitle?.text ? /* @__PURE__ */ jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: block.subtitle.text }) : null
|
|
8402
|
+
] }),
|
|
8403
|
+
/* @__PURE__ */ jsx("span", { className: "ml-auto shrink-0 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Container" })
|
|
8404
|
+
]
|
|
8405
|
+
}
|
|
8406
|
+
) }),
|
|
8407
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "w-[min(32rem,calc(100vw-1.5rem))] sm:w-[32rem]", align: "start", children: /* @__PURE__ */ jsx(BlockEditor, { block, errors, onChange: (next) => onUpdate(id, next) }) })
|
|
8408
|
+
] }),
|
|
8409
|
+
/* @__PURE__ */ jsx(
|
|
8410
|
+
"div",
|
|
8411
|
+
{
|
|
8412
|
+
ref: setBodyRef,
|
|
8413
|
+
className: cn(
|
|
8414
|
+
"flex flex-col gap-2 p-3 transition-colors",
|
|
8415
|
+
isPaletteDrag && "outline-2 -outline-offset-2 outline-dashed outline-primary/40",
|
|
8416
|
+
isPaletteDrag && isBodyOver && "bg-primary/5"
|
|
8417
|
+
),
|
|
8418
|
+
children: children.length === 0 ? /* @__PURE__ */ jsx(
|
|
8419
|
+
"div",
|
|
8420
|
+
{
|
|
8421
|
+
className: cn(
|
|
8422
|
+
"flex items-center justify-center rounded-md border border-dashed px-3 py-6 text-center text-[11px] transition-colors",
|
|
8423
|
+
isBodyOver ? "border-primary/60 text-primary" : "border-border text-muted-foreground"
|
|
8424
|
+
),
|
|
8425
|
+
children: "Drag blocks here"
|
|
8426
|
+
}
|
|
8427
|
+
) : /* @__PURE__ */ jsxs(SortableContext, { items: children.map((c) => c.id), strategy: verticalListSortingStrategy, children: [
|
|
8428
|
+
children.map((child, idx) => /* @__PURE__ */ jsx(
|
|
8429
|
+
BlockRow,
|
|
8430
|
+
{
|
|
8431
|
+
builderBlock: child,
|
|
8432
|
+
previewHooks,
|
|
8433
|
+
previewTheme,
|
|
8434
|
+
errors: errorsByBlockId?.get(child.id),
|
|
8435
|
+
isOpen: openBlockId === child.id,
|
|
8436
|
+
onOpenChange: (open) => onOpenBlockChange?.(open ? child.id : null),
|
|
8437
|
+
onUpdate,
|
|
8438
|
+
onDuplicate,
|
|
8439
|
+
onDelete,
|
|
8440
|
+
index: idx,
|
|
8441
|
+
total: children.length,
|
|
8442
|
+
onReorder,
|
|
8443
|
+
isPaletteDrag
|
|
8444
|
+
},
|
|
8445
|
+
child.id
|
|
8446
|
+
)),
|
|
8447
|
+
isPaletteDrag && isBodyOver ? /* @__PURE__ */ jsx(DropIndicator, {}) : null
|
|
8448
|
+
] })
|
|
8449
|
+
}
|
|
8450
|
+
)
|
|
8451
|
+
]
|
|
8452
|
+
}
|
|
8453
|
+
),
|
|
8454
|
+
/* @__PURE__ */ jsxs(
|
|
8455
|
+
"div",
|
|
8456
|
+
{
|
|
8457
|
+
className: cn(
|
|
8458
|
+
"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",
|
|
8459
|
+
hasErrors ? "opacity-100" : "opacity-0 group-hover/container:opacity-100 group-focus-within/container:opacity-100"
|
|
8460
|
+
),
|
|
8461
|
+
children: [
|
|
8462
|
+
hasErrors ? /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
8463
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
8464
|
+
"button",
|
|
8465
|
+
{
|
|
8466
|
+
type: "button",
|
|
8467
|
+
"aria-label": `Show ${errors.length} validation ${errors.length === 1 ? "issue" : "issues"}`,
|
|
8468
|
+
onClick: () => onOpenBlockChange?.(id),
|
|
8469
|
+
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",
|
|
8470
|
+
children: /* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5" })
|
|
8471
|
+
}
|
|
8472
|
+
) }),
|
|
8473
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "top", align: "end", children: /* @__PURE__ */ jsxs("ul", { className: "flex flex-col gap-0.5", children: [
|
|
8474
|
+
errors.slice(0, 4).map((err, i) => /* @__PURE__ */ jsx("li", { children: err }, i)),
|
|
8475
|
+
errors.length > 4 ? /* @__PURE__ */ jsxs("li", { className: "text-muted-foreground", children: [
|
|
8476
|
+
"and ",
|
|
8477
|
+
errors.length - 4,
|
|
8478
|
+
" more"
|
|
8479
|
+
] }) : null
|
|
8480
|
+
] }) })
|
|
8481
|
+
] }) : null,
|
|
8482
|
+
onReorder && typeof index === "number" && typeof total === "number" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8483
|
+
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Move up", disabled: index === 0, onClick: () => onReorder(id, index - 1), children: /* @__PURE__ */ jsx(ArrowUp, { className: "h-3.5 w-3.5" }) }),
|
|
8484
|
+
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Move down", disabled: index >= total - 1, onClick: () => onReorder(id, index + 1), children: /* @__PURE__ */ jsx(ArrowDown, { className: "h-3.5 w-3.5" }) })
|
|
8485
|
+
] }) : null,
|
|
8486
|
+
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Edit", onClick: () => onOpenBlockChange?.(id), children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }) }),
|
|
8487
|
+
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Duplicate", onClick: () => onDuplicate(id), children: /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" }) }),
|
|
8488
|
+
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Delete", destructive: true, onClick: () => onDelete(id), children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" }) })
|
|
8489
|
+
]
|
|
8490
|
+
}
|
|
8491
|
+
),
|
|
8492
|
+
/* @__PURE__ */ 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: [
|
|
8493
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-[11px] font-medium text-muted-foreground", children: "Container" }),
|
|
8494
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8495
|
+
/* @__PURE__ */ jsx(
|
|
8496
|
+
"button",
|
|
8497
|
+
{
|
|
8498
|
+
type: "button",
|
|
8499
|
+
"aria-label": "Edit container",
|
|
8500
|
+
onClick: () => onOpenBlockChange?.(id),
|
|
8501
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
8502
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" })
|
|
8503
|
+
}
|
|
8504
|
+
),
|
|
8505
|
+
/* @__PURE__ */ jsx(
|
|
8506
|
+
"button",
|
|
8507
|
+
{
|
|
8508
|
+
type: "button",
|
|
8509
|
+
"aria-label": "Duplicate container",
|
|
8510
|
+
onClick: () => onDuplicate(id),
|
|
8511
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
8512
|
+
children: /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" })
|
|
8513
|
+
}
|
|
8514
|
+
),
|
|
8515
|
+
/* @__PURE__ */ jsx(
|
|
8516
|
+
"button",
|
|
8517
|
+
{
|
|
8518
|
+
type: "button",
|
|
8519
|
+
"aria-label": "Delete container",
|
|
8520
|
+
onClick: () => onDelete(id),
|
|
8521
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
8522
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
|
|
8523
|
+
}
|
|
8524
|
+
)
|
|
8525
|
+
] })
|
|
8526
|
+
] })
|
|
8527
|
+
]
|
|
8528
|
+
}
|
|
8529
|
+
);
|
|
8530
|
+
}
|
|
8531
|
+
function ToolbarButton2({
|
|
8532
|
+
label,
|
|
8533
|
+
onClick,
|
|
8534
|
+
disabled,
|
|
8535
|
+
destructive,
|
|
8536
|
+
children
|
|
8537
|
+
}) {
|
|
8538
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
8539
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
8540
|
+
"button",
|
|
8541
|
+
{
|
|
8542
|
+
type: "button",
|
|
8543
|
+
"aria-label": label,
|
|
8544
|
+
disabled,
|
|
8545
|
+
onClick,
|
|
8546
|
+
className: cn(
|
|
8547
|
+
"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",
|
|
8548
|
+
destructive ? "hover:bg-destructive/10 hover:text-destructive" : "hover:bg-accent hover:text-foreground"
|
|
8549
|
+
),
|
|
8550
|
+
children
|
|
8551
|
+
}
|
|
8552
|
+
) }),
|
|
8553
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "top", children: label })
|
|
8554
|
+
] });
|
|
8555
|
+
}
|
|
8556
|
+
function DropIndicator() {
|
|
8557
|
+
return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none relative my-1 h-0.5 w-full rounded-full bg-primary", children: /* @__PURE__ */ jsx("span", { className: "-left-1 -top-[3px] absolute h-2 w-2 rounded-full bg-primary shadow-[0_0_0_2px_var(--color-background)]" }) });
|
|
8558
|
+
}
|
|
8259
8559
|
var SURFACE_DROPPABLE_ID = "builder-surface";
|
|
8260
8560
|
function Surface({
|
|
8261
8561
|
blocks,
|
|
@@ -8287,26 +8587,46 @@ function Surface({
|
|
|
8287
8587
|
isPaletteDrag && isOver && (isDark ? "bg-[#2c3036]" : "bg-[#eaf0ff]")
|
|
8288
8588
|
),
|
|
8289
8589
|
children: blocks.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { isDark, isPaletteDrag, isOver, onOpenPalette }) : /* @__PURE__ */ jsxs(SortableContext, { items: blocks.map((b) => b.id), strategy: verticalListSortingStrategy, children: [
|
|
8290
|
-
blocks.map(
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8590
|
+
blocks.map(
|
|
8591
|
+
(block, idx) => block.block.type === "container" ? /* @__PURE__ */ jsx(
|
|
8592
|
+
ContainerRow,
|
|
8593
|
+
{
|
|
8594
|
+
builderBlock: block,
|
|
8595
|
+
previewHooks,
|
|
8596
|
+
previewTheme,
|
|
8597
|
+
errorsByBlockId,
|
|
8598
|
+
openBlockId,
|
|
8599
|
+
onOpenBlockChange,
|
|
8600
|
+
onUpdate,
|
|
8601
|
+
onDuplicate,
|
|
8602
|
+
onDelete,
|
|
8603
|
+
index: idx,
|
|
8604
|
+
total: blocks.length,
|
|
8605
|
+
onReorder,
|
|
8606
|
+
isPaletteDrag
|
|
8607
|
+
},
|
|
8608
|
+
block.id
|
|
8609
|
+
) : /* @__PURE__ */ jsx(
|
|
8610
|
+
BlockRow,
|
|
8611
|
+
{
|
|
8612
|
+
builderBlock: block,
|
|
8613
|
+
previewHooks,
|
|
8614
|
+
previewTheme,
|
|
8615
|
+
errors: errorsByBlockId?.get(block.id),
|
|
8616
|
+
isOpen: openBlockId === block.id,
|
|
8617
|
+
onOpenChange: (open) => onOpenBlockChange?.(open ? block.id : null),
|
|
8618
|
+
onUpdate,
|
|
8619
|
+
onDuplicate,
|
|
8620
|
+
onDelete,
|
|
8621
|
+
index: idx,
|
|
8622
|
+
total: blocks.length,
|
|
8623
|
+
onReorder,
|
|
8624
|
+
isPaletteDrag
|
|
8625
|
+
},
|
|
8626
|
+
block.id
|
|
8627
|
+
)
|
|
8628
|
+
),
|
|
8629
|
+
showEndDropZone ? /* @__PURE__ */ jsx(DropIndicator2, {}) : null
|
|
8310
8630
|
] })
|
|
8311
8631
|
}
|
|
8312
8632
|
);
|
|
@@ -8546,7 +8866,7 @@ function EmptyState({
|
|
|
8546
8866
|
}
|
|
8547
8867
|
);
|
|
8548
8868
|
}
|
|
8549
|
-
function
|
|
8869
|
+
function DropIndicator2() {
|
|
8550
8870
|
return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none relative my-1 h-0.5 w-full rounded-full bg-primary", children: /* @__PURE__ */ jsx("span", { className: "-left-1 -top-[3px] absolute h-2 w-2 rounded-full bg-primary shadow-[0_0_0_2px_var(--color-background)]" }) });
|
|
8551
8871
|
}
|
|
8552
8872
|
var THEME_OPTIONS = [
|
|
@@ -8909,9 +9229,18 @@ function BlockKitchen(props) {
|
|
|
8909
9229
|
}, [palette, disabledBlockTypes]);
|
|
8910
9230
|
const variantById = useMemo(() => buildVariantById(paletteSections), [paletteSections]);
|
|
8911
9231
|
const allowedSurfaces = allowedSurfacesProp && allowedSurfacesProp.length > 0 ? allowedSurfacesProp : ["message"];
|
|
8912
|
-
const { blocks, addBlock, updateBlock, removeBlock, duplicateBlock, reorderBlock, replaceAll } = useBlockKitchenState(
|
|
8913
|
-
|
|
8914
|
-
|
|
9232
|
+
const { blocks, addBlock, addChild, updateBlock, removeBlock, duplicateBlock, reorderBlock, moveBlock, replaceAll } = useBlockKitchenState({ initialBlocks, onChange });
|
|
9233
|
+
const childParentById = useMemo(() => {
|
|
9234
|
+
const map = /* @__PURE__ */ new Map();
|
|
9235
|
+
for (const top of blocks) {
|
|
9236
|
+
if (top.children) {
|
|
9237
|
+
for (const child of top.children) {
|
|
9238
|
+
map.set(child.id, top.id);
|
|
9239
|
+
}
|
|
9240
|
+
}
|
|
9241
|
+
}
|
|
9242
|
+
return map;
|
|
9243
|
+
}, [blocks]);
|
|
8915
9244
|
const [jsonOpen, setJsonOpen] = useState(false);
|
|
8916
9245
|
const [sendOpen, setSendOpen] = useState(false);
|
|
8917
9246
|
const [issuesOpen, setIssuesOpen] = useState(false);
|
|
@@ -8936,14 +9265,22 @@ function BlockKitchen(props) {
|
|
|
8936
9265
|
useSensor(TouchSensor, { activationConstraint: { delay: 150, tolerance: 8 } }),
|
|
8937
9266
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
|
8938
9267
|
);
|
|
8939
|
-
const collisionDetection = useCallback(
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
9268
|
+
const collisionDetection = useCallback(
|
|
9269
|
+
(args) => {
|
|
9270
|
+
const hits = pointerWithin(args);
|
|
9271
|
+
if (hits.length > 0) {
|
|
9272
|
+
const child = hits.find((c) => childParentById.has(c.id));
|
|
9273
|
+
if (child) return [child];
|
|
9274
|
+
const body = hits.find((c) => parseContainerBodyId(c.id) !== null);
|
|
9275
|
+
if (body) return [body];
|
|
9276
|
+
const block = hits.find((c) => c.id !== SURFACE_DROPPABLE_ID && parseContainerBodyId(c.id) === null);
|
|
9277
|
+
if (block) return [block];
|
|
9278
|
+
return hits;
|
|
9279
|
+
}
|
|
9280
|
+
return closestCenter(args);
|
|
9281
|
+
},
|
|
9282
|
+
[childParentById]
|
|
9283
|
+
);
|
|
8947
9284
|
const handleDragStart = useCallback((event) => {
|
|
8948
9285
|
const variantId = parsePaletteDragId(event.active.id);
|
|
8949
9286
|
setActivePaletteVariantId(variantId);
|
|
@@ -8955,24 +9292,43 @@ function BlockKitchen(props) {
|
|
|
8955
9292
|
if (!over) {
|
|
8956
9293
|
return;
|
|
8957
9294
|
}
|
|
9295
|
+
const overId = over.id;
|
|
9296
|
+
let target;
|
|
9297
|
+
const bodyParent = parseContainerBodyId(overId);
|
|
9298
|
+
const childParent = childParentById.get(overId);
|
|
9299
|
+
if (overId === SURFACE_DROPPABLE_ID) {
|
|
9300
|
+
target = { kind: "top", index: blocks.length };
|
|
9301
|
+
} else if (bodyParent) {
|
|
9302
|
+
const count = blocks.find((b) => b.id === bodyParent)?.children?.length ?? 0;
|
|
9303
|
+
target = { kind: "container", parentId: bodyParent, index: count };
|
|
9304
|
+
} else if (childParent) {
|
|
9305
|
+
const siblings = blocks.find((b) => b.id === childParent)?.children ?? [];
|
|
9306
|
+
target = { kind: "container", parentId: childParent, index: siblings.findIndex((c) => c.id === overId) };
|
|
9307
|
+
} else {
|
|
9308
|
+
const topIndex = blocks.findIndex((b) => b.id === overId);
|
|
9309
|
+
target = topIndex === -1 ? null : { kind: "top", index: topIndex };
|
|
9310
|
+
}
|
|
9311
|
+
if (!target) {
|
|
9312
|
+
return;
|
|
9313
|
+
}
|
|
8958
9314
|
const variantId = parsePaletteDragId(active.id);
|
|
8959
9315
|
if (variantId) {
|
|
8960
9316
|
const variant = variantById.get(variantId);
|
|
8961
9317
|
if (!variant) {
|
|
8962
9318
|
return;
|
|
8963
9319
|
}
|
|
8964
|
-
|
|
8965
|
-
|
|
9320
|
+
if (target.kind === "container") {
|
|
9321
|
+
addChild(target.parentId, variant.factory(), target.index);
|
|
9322
|
+
} else {
|
|
9323
|
+
addBlock(variant.factory(), target.index);
|
|
9324
|
+
}
|
|
8966
9325
|
return;
|
|
8967
9326
|
}
|
|
8968
|
-
if (active.id !==
|
|
8969
|
-
|
|
8970
|
-
if (overIndex !== -1) {
|
|
8971
|
-
reorderBlock(active.id, overIndex);
|
|
8972
|
-
}
|
|
9327
|
+
if (active.id !== overId) {
|
|
9328
|
+
moveBlock(active.id, target);
|
|
8973
9329
|
}
|
|
8974
9330
|
},
|
|
8975
|
-
[addBlock, blocks,
|
|
9331
|
+
[addBlock, addChild, blocks, childParentById, moveBlock, variantById]
|
|
8976
9332
|
);
|
|
8977
9333
|
const handleDragCancel = useCallback(() => {
|
|
8978
9334
|
setActivePaletteVariantId(null);
|