@tightknitai/block-kitchen 0.8.7 → 0.8.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/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +633 -58
- 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 +634 -59
- package/dist/index.js.map +1 -1
- package/dist/{palette-WZCUVJTn.d.cts → palette-DBTHRygt.d.cts} +50 -3
- package/dist/{palette-WZCUVJTn.d.ts → palette-DBTHRygt.d.ts} +50 -3
- package/dist/palette.cjs +43 -0
- package/dist/palette.cjs.map +1 -1
- package/dist/palette.d.cts +1 -1
- package/dist/palette.d.ts +1 -1
- package/dist/palette.js +44 -1
- package/dist/palette.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -4
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, 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);
|
|
@@ -1121,6 +1149,49 @@ var defaultPalette = [
|
|
|
1121
1149
|
})
|
|
1122
1150
|
}
|
|
1123
1151
|
]
|
|
1152
|
+
},
|
|
1153
|
+
{
|
|
1154
|
+
name: "Container",
|
|
1155
|
+
icon: Container,
|
|
1156
|
+
variants: [
|
|
1157
|
+
{
|
|
1158
|
+
id: "container_collapsible",
|
|
1159
|
+
label: "Collapsible container",
|
|
1160
|
+
factory: () => ({
|
|
1161
|
+
type: "container",
|
|
1162
|
+
title: { type: "plain_text", text: "Bulk update: 2 records selected" },
|
|
1163
|
+
subtitle: { type: "plain_text", text: "Review changes before confirming" },
|
|
1164
|
+
is_collapsible: true,
|
|
1165
|
+
child_blocks: [
|
|
1166
|
+
{
|
|
1167
|
+
type: "section",
|
|
1168
|
+
text: { type: "mrkdwn", text: "*DCW-1024*\nStatus: Open \u2192 Closed" }
|
|
1169
|
+
},
|
|
1170
|
+
{ type: "divider" },
|
|
1171
|
+
{
|
|
1172
|
+
type: "section",
|
|
1173
|
+
text: { type: "mrkdwn", text: "*DCW-1025*\nStatus: In Progress \u2192 Closed" }
|
|
1174
|
+
},
|
|
1175
|
+
{
|
|
1176
|
+
type: "actions",
|
|
1177
|
+
elements: [
|
|
1178
|
+
{
|
|
1179
|
+
type: "button",
|
|
1180
|
+
text: { type: "plain_text", text: "Confirm All", emoji: true },
|
|
1181
|
+
style: "primary",
|
|
1182
|
+
action_id: "bulk_confirm"
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
type: "button",
|
|
1186
|
+
text: { type: "plain_text", text: "Cancel", emoji: true },
|
|
1187
|
+
action_id: "bulk_cancel"
|
|
1188
|
+
}
|
|
1189
|
+
]
|
|
1190
|
+
}
|
|
1191
|
+
]
|
|
1192
|
+
})
|
|
1193
|
+
}
|
|
1194
|
+
]
|
|
1124
1195
|
}
|
|
1125
1196
|
];
|
|
1126
1197
|
var legacyInputVariants = [
|
|
@@ -1601,6 +1672,8 @@ function labelForBlockType(type) {
|
|
|
1601
1672
|
return "Task Card";
|
|
1602
1673
|
case "data_visualization":
|
|
1603
1674
|
return "Data Visualization";
|
|
1675
|
+
case "container":
|
|
1676
|
+
return "Container";
|
|
1604
1677
|
}
|
|
1605
1678
|
}
|
|
1606
1679
|
function cn(...inputs) {
|
|
@@ -1937,9 +2010,52 @@ function useBlockKitValidation(blocks, surface) {
|
|
|
1937
2010
|
}, [blocks, surface]);
|
|
1938
2011
|
return state;
|
|
1939
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
|
+
}
|
|
1940
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
|
+
}
|
|
1941
2027
|
return { id: nanoid(8), block };
|
|
1942
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
|
+
}
|
|
1943
2059
|
function useBlockKitchenState({
|
|
1944
2060
|
initialBlocks,
|
|
1945
2061
|
onChange
|
|
@@ -1960,41 +2076,113 @@ function useBlockKitchenState({
|
|
|
1960
2076
|
const addBlock = useCallback((block, atIndex) => {
|
|
1961
2077
|
setBlocks((prev) => {
|
|
1962
2078
|
const next = [...prev];
|
|
1963
|
-
const inserted = wrap(block);
|
|
1964
2079
|
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
1965
|
-
next.splice(idx, 0,
|
|
2080
|
+
next.splice(idx, 0, wrap(block));
|
|
1966
2081
|
return next;
|
|
1967
2082
|
});
|
|
1968
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
|
+
}, []);
|
|
1969
2100
|
const updateBlock = useCallback((id, block) => {
|
|
1970
|
-
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
|
+
);
|
|
1971
2112
|
}, []);
|
|
1972
2113
|
const removeBlock = useCallback((id) => {
|
|
1973
|
-
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
|
+
});
|
|
1974
2122
|
}, []);
|
|
1975
2123
|
const duplicateBlock = useCallback((id) => {
|
|
1976
2124
|
setBlocks((prev) => {
|
|
1977
|
-
const
|
|
1978
|
-
if (
|
|
2125
|
+
const loc = locate(prev, id);
|
|
2126
|
+
if (!loc) {
|
|
1979
2127
|
return prev;
|
|
1980
2128
|
}
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
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
|
+
});
|
|
1985
2139
|
});
|
|
1986
2140
|
}, []);
|
|
1987
2141
|
const reorderBlock = useCallback((fromId, toIndex) => {
|
|
1988
2142
|
setBlocks((prev) => {
|
|
1989
|
-
const
|
|
1990
|
-
if (
|
|
2143
|
+
const loc = locate(prev, fromId);
|
|
2144
|
+
if (!loc) {
|
|
1991
2145
|
return prev;
|
|
1992
2146
|
}
|
|
1993
|
-
const
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
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);
|
|
1998
2186
|
});
|
|
1999
2187
|
}, []);
|
|
2000
2188
|
const replaceAll = useCallback((newBlocks) => {
|
|
@@ -2003,10 +2191,12 @@ function useBlockKitchenState({
|
|
|
2003
2191
|
return {
|
|
2004
2192
|
blocks,
|
|
2005
2193
|
addBlock,
|
|
2194
|
+
addChild,
|
|
2006
2195
|
updateBlock,
|
|
2007
2196
|
removeBlock,
|
|
2008
2197
|
duplicateBlock,
|
|
2009
2198
|
reorderBlock,
|
|
2199
|
+
moveBlock,
|
|
2010
2200
|
replaceAll
|
|
2011
2201
|
};
|
|
2012
2202
|
}
|
|
@@ -3515,6 +3705,113 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3515
3705
|
] })
|
|
3516
3706
|
] });
|
|
3517
3707
|
}
|
|
3708
|
+
var WIDTHS = ["narrow", "standard", "wide", "full"];
|
|
3709
|
+
function ContainerEditor({ block, onChange }) {
|
|
3710
|
+
const iconUrl = block.icon && "image_url" in block.icon ? block.icon.image_url ?? "" : "";
|
|
3711
|
+
const iconAlt = block.icon?.alt_text ?? "";
|
|
3712
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3713
|
+
/* @__PURE__ */ jsx(EditorField, { label: "Title", help: "Heading shown at the top of the container.", htmlFor: "container-title", children: /* @__PURE__ */ jsx(
|
|
3714
|
+
Input,
|
|
3715
|
+
{
|
|
3716
|
+
id: "container-title",
|
|
3717
|
+
value: block.title?.text ?? "",
|
|
3718
|
+
maxLength: 150,
|
|
3719
|
+
placeholder: "e.g. Bulk update: 2 records selected",
|
|
3720
|
+
onChange: (e) => onChange({ ...block, title: { type: "plain_text", text: e.target.value } })
|
|
3721
|
+
}
|
|
3722
|
+
) }),
|
|
3723
|
+
/* @__PURE__ */ jsx(EditorField, { label: "Subtitle", help: "Optional secondary line under the title.", htmlFor: "container-subtitle", children: /* @__PURE__ */ jsx(
|
|
3724
|
+
Input,
|
|
3725
|
+
{
|
|
3726
|
+
id: "container-subtitle",
|
|
3727
|
+
value: block.subtitle?.text ?? "",
|
|
3728
|
+
maxLength: 150,
|
|
3729
|
+
placeholder: "e.g. Review changes before confirming",
|
|
3730
|
+
onChange: (e) => onChange({
|
|
3731
|
+
...block,
|
|
3732
|
+
subtitle: e.target.value ? { type: "plain_text", text: e.target.value } : void 0
|
|
3733
|
+
})
|
|
3734
|
+
}
|
|
3735
|
+
) }),
|
|
3736
|
+
/* @__PURE__ */ jsx(EditorField, { label: "Icon URL", help: "Optional image shown left of the title.", htmlFor: "container-icon", children: /* @__PURE__ */ jsx(
|
|
3737
|
+
Input,
|
|
3738
|
+
{
|
|
3739
|
+
id: "container-icon",
|
|
3740
|
+
type: "url",
|
|
3741
|
+
value: iconUrl,
|
|
3742
|
+
placeholder: "https://example.com/icon.png",
|
|
3743
|
+
onChange: (e) => onChange({
|
|
3744
|
+
...block,
|
|
3745
|
+
icon: e.target.value ? { type: "image", image_url: e.target.value, alt_text: iconAlt || "Container icon" } : void 0
|
|
3746
|
+
})
|
|
3747
|
+
}
|
|
3748
|
+
) }),
|
|
3749
|
+
/* @__PURE__ */ jsx(EditorField, { label: "Width", help: "How wide the container renders in the message.", children: /* @__PURE__ */ jsx(
|
|
3750
|
+
RadioGroup,
|
|
3751
|
+
{
|
|
3752
|
+
value: block.width ?? "standard",
|
|
3753
|
+
onValueChange: (v) => onChange({ ...block, width: v }),
|
|
3754
|
+
className: "flex flex-row flex-wrap gap-3",
|
|
3755
|
+
children: WIDTHS.map((w) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3756
|
+
/* @__PURE__ */ jsx(RadioGroupItem, { value: w, id: `container-width-${w}` }),
|
|
3757
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: `container-width-${w}`, className: "text-xs capitalize", children: w })
|
|
3758
|
+
] }, w))
|
|
3759
|
+
}
|
|
3760
|
+
) }),
|
|
3761
|
+
/* @__PURE__ */ jsx(
|
|
3762
|
+
Checkbox,
|
|
3763
|
+
{
|
|
3764
|
+
id: "container-collapsible",
|
|
3765
|
+
label: "Collapsible",
|
|
3766
|
+
help: "Let readers expand and collapse the container.",
|
|
3767
|
+
checked: !!block.is_collapsible,
|
|
3768
|
+
onChange: (checked) => onChange({
|
|
3769
|
+
...block,
|
|
3770
|
+
is_collapsible: checked || void 0,
|
|
3771
|
+
default_collapsed: checked ? block.default_collapsed : void 0
|
|
3772
|
+
})
|
|
3773
|
+
}
|
|
3774
|
+
),
|
|
3775
|
+
/* @__PURE__ */ jsx(
|
|
3776
|
+
Checkbox,
|
|
3777
|
+
{
|
|
3778
|
+
id: "container-default-collapsed",
|
|
3779
|
+
label: "Collapsed by default",
|
|
3780
|
+
help: "Start collapsed on first render. Requires Collapsible.",
|
|
3781
|
+
checked: !!block.default_collapsed,
|
|
3782
|
+
disabled: !block.is_collapsible,
|
|
3783
|
+
onChange: (checked) => onChange({ ...block, default_collapsed: checked || void 0 })
|
|
3784
|
+
}
|
|
3785
|
+
),
|
|
3786
|
+
/* @__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." })
|
|
3787
|
+
] });
|
|
3788
|
+
}
|
|
3789
|
+
function Checkbox({
|
|
3790
|
+
id,
|
|
3791
|
+
label,
|
|
3792
|
+
help,
|
|
3793
|
+
checked,
|
|
3794
|
+
disabled,
|
|
3795
|
+
onChange
|
|
3796
|
+
}) {
|
|
3797
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3798
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3799
|
+
/* @__PURE__ */ jsx(
|
|
3800
|
+
"input",
|
|
3801
|
+
{
|
|
3802
|
+
id,
|
|
3803
|
+
type: "checkbox",
|
|
3804
|
+
checked,
|
|
3805
|
+
disabled,
|
|
3806
|
+
onChange: (e) => onChange(e.target.checked),
|
|
3807
|
+
className: "h-3.5 w-3.5 cursor-pointer rounded border-input disabled:cursor-not-allowed disabled:opacity-40"
|
|
3808
|
+
}
|
|
3809
|
+
),
|
|
3810
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: id, className: "cursor-pointer text-xs", children: label })
|
|
3811
|
+
] }),
|
|
3812
|
+
help ? /* @__PURE__ */ jsx("p", { className: "ml-5 text-[11px] leading-snug text-muted-foreground", children: help }) : null
|
|
3813
|
+
] });
|
|
3814
|
+
}
|
|
3518
3815
|
var MAX_ELEMENTS = 5;
|
|
3519
3816
|
function ContextActionsEditor({ block, onChange }) {
|
|
3520
3817
|
const elements = block.elements ?? [];
|
|
@@ -7684,6 +7981,8 @@ function dispatch(block, onChange) {
|
|
|
7684
7981
|
return /* @__PURE__ */ jsx(TaskCardEditor, { block, onChange: (next) => onChange(next) });
|
|
7685
7982
|
case "data_visualization":
|
|
7686
7983
|
return /* @__PURE__ */ jsx(DataVisualizationEditor, { block, onChange: (next) => onChange(next) });
|
|
7984
|
+
case "container":
|
|
7985
|
+
return /* @__PURE__ */ jsx(ContainerEditor, { block, onChange: (next) => onChange(next) });
|
|
7687
7986
|
default:
|
|
7688
7987
|
return null;
|
|
7689
7988
|
}
|
|
@@ -7760,7 +8059,8 @@ var BLOCK_TYPE_LABELS = {
|
|
|
7760
8059
|
video: "Video",
|
|
7761
8060
|
plan: "Plan",
|
|
7762
8061
|
task_card: "Task Card",
|
|
7763
|
-
data_visualization: "Data Visualization"
|
|
8062
|
+
data_visualization: "Data Visualization",
|
|
8063
|
+
container: "Container"
|
|
7764
8064
|
};
|
|
7765
8065
|
function BlockRow({
|
|
7766
8066
|
builderBlock,
|
|
@@ -8054,6 +8354,225 @@ function RichTextInlineEditor({
|
|
|
8054
8354
|
}
|
|
8055
8355
|
);
|
|
8056
8356
|
}
|
|
8357
|
+
function ContainerRow({
|
|
8358
|
+
builderBlock,
|
|
8359
|
+
previewHooks,
|
|
8360
|
+
previewTheme,
|
|
8361
|
+
errorsByBlockId,
|
|
8362
|
+
openBlockId,
|
|
8363
|
+
onOpenBlockChange,
|
|
8364
|
+
onUpdate,
|
|
8365
|
+
onDuplicate,
|
|
8366
|
+
onDelete,
|
|
8367
|
+
onReorder,
|
|
8368
|
+
index,
|
|
8369
|
+
total,
|
|
8370
|
+
isPaletteDrag = false
|
|
8371
|
+
}) {
|
|
8372
|
+
const { id } = builderBlock;
|
|
8373
|
+
const block = builderBlock.block;
|
|
8374
|
+
const children = builderBlock.children ?? [];
|
|
8375
|
+
const errors = errorsByBlockId?.get(id);
|
|
8376
|
+
const hasErrors = !!errors && errors.length > 0;
|
|
8377
|
+
const isOpen = openBlockId === id;
|
|
8378
|
+
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id });
|
|
8379
|
+
const { role: _dndRole, tabIndex: _dndTabIndex, ...sortableA11yAttrs } = attributes;
|
|
8380
|
+
const { setNodeRef: setBodyRef, isOver: isBodyOver } = useDroppable({ id: containerBodyId(id) });
|
|
8381
|
+
const style = { transform: CSS.Transform.toString(transform), transition };
|
|
8382
|
+
const icon = block.icon && "image_url" in block.icon ? block.icon.image_url : void 0;
|
|
8383
|
+
return /* @__PURE__ */ jsxs(
|
|
8384
|
+
"div",
|
|
8385
|
+
{
|
|
8386
|
+
ref: setNodeRef,
|
|
8387
|
+
style,
|
|
8388
|
+
className: cn("group/container relative mb-2 last:mb-0 hover:z-10", isDragging && "opacity-40"),
|
|
8389
|
+
children: [
|
|
8390
|
+
/* @__PURE__ */ jsxs(
|
|
8391
|
+
"div",
|
|
8392
|
+
{
|
|
8393
|
+
className: cn(
|
|
8394
|
+
"overflow-hidden rounded-md border bg-card transition-shadow",
|
|
8395
|
+
hasErrors ? "border-destructive/60" : "border-border"
|
|
8396
|
+
),
|
|
8397
|
+
children: [
|
|
8398
|
+
/* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: (open) => onOpenBlockChange?.(open ? id : null), children: [
|
|
8399
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
8400
|
+
"div",
|
|
8401
|
+
{
|
|
8402
|
+
role: "button",
|
|
8403
|
+
tabIndex: 0,
|
|
8404
|
+
"aria-label": "Edit container",
|
|
8405
|
+
...sortableA11yAttrs,
|
|
8406
|
+
...listeners,
|
|
8407
|
+
onKeyDown: (e) => {
|
|
8408
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
8409
|
+
e.preventDefault();
|
|
8410
|
+
onOpenBlockChange?.(!isOpen ? id : null);
|
|
8411
|
+
}
|
|
8412
|
+
},
|
|
8413
|
+
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",
|
|
8414
|
+
children: [
|
|
8415
|
+
icon ? /* @__PURE__ */ jsx("img", { src: icon, alt: "", "aria-hidden": "true", className: "h-5 w-5 shrink-0 rounded object-cover" }) : null,
|
|
8416
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
8417
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-xs font-semibold text-foreground", children: block.title?.text || "Container" }),
|
|
8418
|
+
block.subtitle?.text ? /* @__PURE__ */ jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: block.subtitle.text }) : null
|
|
8419
|
+
] }),
|
|
8420
|
+
/* @__PURE__ */ jsx("span", { className: "ml-auto shrink-0 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Container" })
|
|
8421
|
+
]
|
|
8422
|
+
}
|
|
8423
|
+
) }),
|
|
8424
|
+
/* @__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) }) })
|
|
8425
|
+
] }),
|
|
8426
|
+
/* @__PURE__ */ jsx(
|
|
8427
|
+
"div",
|
|
8428
|
+
{
|
|
8429
|
+
ref: setBodyRef,
|
|
8430
|
+
className: cn(
|
|
8431
|
+
"flex flex-col gap-2 p-3 transition-colors",
|
|
8432
|
+
isPaletteDrag && "outline-2 -outline-offset-2 outline-dashed outline-primary/40",
|
|
8433
|
+
isPaletteDrag && isBodyOver && "bg-primary/5"
|
|
8434
|
+
),
|
|
8435
|
+
children: children.length === 0 ? /* @__PURE__ */ jsx(
|
|
8436
|
+
"div",
|
|
8437
|
+
{
|
|
8438
|
+
className: cn(
|
|
8439
|
+
"flex items-center justify-center rounded-md border border-dashed px-3 py-6 text-center text-[11px] transition-colors",
|
|
8440
|
+
isBodyOver ? "border-primary/60 text-primary" : "border-border text-muted-foreground"
|
|
8441
|
+
),
|
|
8442
|
+
children: "Drag blocks here"
|
|
8443
|
+
}
|
|
8444
|
+
) : /* @__PURE__ */ jsxs(SortableContext, { items: children.map((c) => c.id), strategy: verticalListSortingStrategy, children: [
|
|
8445
|
+
children.map((child, idx) => /* @__PURE__ */ jsx(
|
|
8446
|
+
BlockRow,
|
|
8447
|
+
{
|
|
8448
|
+
builderBlock: child,
|
|
8449
|
+
previewHooks,
|
|
8450
|
+
previewTheme,
|
|
8451
|
+
errors: errorsByBlockId?.get(child.id),
|
|
8452
|
+
isOpen: openBlockId === child.id,
|
|
8453
|
+
onOpenChange: (open) => onOpenBlockChange?.(open ? child.id : null),
|
|
8454
|
+
onUpdate,
|
|
8455
|
+
onDuplicate,
|
|
8456
|
+
onDelete,
|
|
8457
|
+
index: idx,
|
|
8458
|
+
total: children.length,
|
|
8459
|
+
onReorder,
|
|
8460
|
+
isPaletteDrag
|
|
8461
|
+
},
|
|
8462
|
+
child.id
|
|
8463
|
+
)),
|
|
8464
|
+
isPaletteDrag && isBodyOver ? /* @__PURE__ */ jsx(DropIndicator, {}) : null
|
|
8465
|
+
] })
|
|
8466
|
+
}
|
|
8467
|
+
)
|
|
8468
|
+
]
|
|
8469
|
+
}
|
|
8470
|
+
),
|
|
8471
|
+
/* @__PURE__ */ jsxs(
|
|
8472
|
+
"div",
|
|
8473
|
+
{
|
|
8474
|
+
className: cn(
|
|
8475
|
+
"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",
|
|
8476
|
+
hasErrors ? "opacity-100" : "opacity-0 group-hover/container:opacity-100 group-focus-within/container:opacity-100"
|
|
8477
|
+
),
|
|
8478
|
+
children: [
|
|
8479
|
+
hasErrors ? /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
8480
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
8481
|
+
"button",
|
|
8482
|
+
{
|
|
8483
|
+
type: "button",
|
|
8484
|
+
"aria-label": `Show ${errors.length} validation ${errors.length === 1 ? "issue" : "issues"}`,
|
|
8485
|
+
onClick: () => onOpenBlockChange?.(id),
|
|
8486
|
+
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",
|
|
8487
|
+
children: /* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5" })
|
|
8488
|
+
}
|
|
8489
|
+
) }),
|
|
8490
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "top", align: "end", children: /* @__PURE__ */ jsxs("ul", { className: "flex flex-col gap-0.5", children: [
|
|
8491
|
+
errors.slice(0, 4).map((err, i) => /* @__PURE__ */ jsx("li", { children: err }, i)),
|
|
8492
|
+
errors.length > 4 ? /* @__PURE__ */ jsxs("li", { className: "text-muted-foreground", children: [
|
|
8493
|
+
"and ",
|
|
8494
|
+
errors.length - 4,
|
|
8495
|
+
" more"
|
|
8496
|
+
] }) : null
|
|
8497
|
+
] }) })
|
|
8498
|
+
] }) : null,
|
|
8499
|
+
onReorder && typeof index === "number" && typeof total === "number" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8500
|
+
/* @__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" }) }),
|
|
8501
|
+
/* @__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" }) })
|
|
8502
|
+
] }) : null,
|
|
8503
|
+
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Edit", onClick: () => onOpenBlockChange?.(id), children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }) }),
|
|
8504
|
+
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Duplicate", onClick: () => onDuplicate(id), children: /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" }) }),
|
|
8505
|
+
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Delete", destructive: true, onClick: () => onDelete(id), children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" }) })
|
|
8506
|
+
]
|
|
8507
|
+
}
|
|
8508
|
+
),
|
|
8509
|
+
/* @__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: [
|
|
8510
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-[11px] font-medium text-muted-foreground", children: "Container" }),
|
|
8511
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8512
|
+
/* @__PURE__ */ jsx(
|
|
8513
|
+
"button",
|
|
8514
|
+
{
|
|
8515
|
+
type: "button",
|
|
8516
|
+
"aria-label": "Edit container",
|
|
8517
|
+
onClick: () => onOpenBlockChange?.(id),
|
|
8518
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
8519
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" })
|
|
8520
|
+
}
|
|
8521
|
+
),
|
|
8522
|
+
/* @__PURE__ */ jsx(
|
|
8523
|
+
"button",
|
|
8524
|
+
{
|
|
8525
|
+
type: "button",
|
|
8526
|
+
"aria-label": "Duplicate container",
|
|
8527
|
+
onClick: () => onDuplicate(id),
|
|
8528
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
8529
|
+
children: /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" })
|
|
8530
|
+
}
|
|
8531
|
+
),
|
|
8532
|
+
/* @__PURE__ */ jsx(
|
|
8533
|
+
"button",
|
|
8534
|
+
{
|
|
8535
|
+
type: "button",
|
|
8536
|
+
"aria-label": "Delete container",
|
|
8537
|
+
onClick: () => onDelete(id),
|
|
8538
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
8539
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
|
|
8540
|
+
}
|
|
8541
|
+
)
|
|
8542
|
+
] })
|
|
8543
|
+
] })
|
|
8544
|
+
]
|
|
8545
|
+
}
|
|
8546
|
+
);
|
|
8547
|
+
}
|
|
8548
|
+
function ToolbarButton2({
|
|
8549
|
+
label,
|
|
8550
|
+
onClick,
|
|
8551
|
+
disabled,
|
|
8552
|
+
destructive,
|
|
8553
|
+
children
|
|
8554
|
+
}) {
|
|
8555
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
8556
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
8557
|
+
"button",
|
|
8558
|
+
{
|
|
8559
|
+
type: "button",
|
|
8560
|
+
"aria-label": label,
|
|
8561
|
+
disabled,
|
|
8562
|
+
onClick,
|
|
8563
|
+
className: cn(
|
|
8564
|
+
"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",
|
|
8565
|
+
destructive ? "hover:bg-destructive/10 hover:text-destructive" : "hover:bg-accent hover:text-foreground"
|
|
8566
|
+
),
|
|
8567
|
+
children
|
|
8568
|
+
}
|
|
8569
|
+
) }),
|
|
8570
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "top", children: label })
|
|
8571
|
+
] });
|
|
8572
|
+
}
|
|
8573
|
+
function DropIndicator() {
|
|
8574
|
+
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)]" }) });
|
|
8575
|
+
}
|
|
8057
8576
|
var SURFACE_DROPPABLE_ID = "builder-surface";
|
|
8058
8577
|
function Surface({
|
|
8059
8578
|
blocks,
|
|
@@ -8085,26 +8604,46 @@ function Surface({
|
|
|
8085
8604
|
isPaletteDrag && isOver && (isDark ? "bg-[#2c3036]" : "bg-[#eaf0ff]")
|
|
8086
8605
|
),
|
|
8087
8606
|
children: blocks.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { isDark, isPaletteDrag, isOver, onOpenPalette }) : /* @__PURE__ */ jsxs(SortableContext, { items: blocks.map((b) => b.id), strategy: verticalListSortingStrategy, children: [
|
|
8088
|
-
blocks.map(
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
|
|
8100
|
-
|
|
8101
|
-
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8607
|
+
blocks.map(
|
|
8608
|
+
(block, idx) => block.block.type === "container" ? /* @__PURE__ */ jsx(
|
|
8609
|
+
ContainerRow,
|
|
8610
|
+
{
|
|
8611
|
+
builderBlock: block,
|
|
8612
|
+
previewHooks,
|
|
8613
|
+
previewTheme,
|
|
8614
|
+
errorsByBlockId,
|
|
8615
|
+
openBlockId,
|
|
8616
|
+
onOpenBlockChange,
|
|
8617
|
+
onUpdate,
|
|
8618
|
+
onDuplicate,
|
|
8619
|
+
onDelete,
|
|
8620
|
+
index: idx,
|
|
8621
|
+
total: blocks.length,
|
|
8622
|
+
onReorder,
|
|
8623
|
+
isPaletteDrag
|
|
8624
|
+
},
|
|
8625
|
+
block.id
|
|
8626
|
+
) : /* @__PURE__ */ jsx(
|
|
8627
|
+
BlockRow,
|
|
8628
|
+
{
|
|
8629
|
+
builderBlock: block,
|
|
8630
|
+
previewHooks,
|
|
8631
|
+
previewTheme,
|
|
8632
|
+
errors: errorsByBlockId?.get(block.id),
|
|
8633
|
+
isOpen: openBlockId === block.id,
|
|
8634
|
+
onOpenChange: (open) => onOpenBlockChange?.(open ? block.id : null),
|
|
8635
|
+
onUpdate,
|
|
8636
|
+
onDuplicate,
|
|
8637
|
+
onDelete,
|
|
8638
|
+
index: idx,
|
|
8639
|
+
total: blocks.length,
|
|
8640
|
+
onReorder,
|
|
8641
|
+
isPaletteDrag
|
|
8642
|
+
},
|
|
8643
|
+
block.id
|
|
8644
|
+
)
|
|
8645
|
+
),
|
|
8646
|
+
showEndDropZone ? /* @__PURE__ */ jsx(DropIndicator2, {}) : null
|
|
8108
8647
|
] })
|
|
8109
8648
|
}
|
|
8110
8649
|
);
|
|
@@ -8344,7 +8883,7 @@ function EmptyState({
|
|
|
8344
8883
|
}
|
|
8345
8884
|
);
|
|
8346
8885
|
}
|
|
8347
|
-
function
|
|
8886
|
+
function DropIndicator2() {
|
|
8348
8887
|
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)]" }) });
|
|
8349
8888
|
}
|
|
8350
8889
|
var THEME_OPTIONS = [
|
|
@@ -8707,9 +9246,18 @@ function BlockKitchen(props) {
|
|
|
8707
9246
|
}, [palette, disabledBlockTypes]);
|
|
8708
9247
|
const variantById = useMemo(() => buildVariantById(paletteSections), [paletteSections]);
|
|
8709
9248
|
const allowedSurfaces = allowedSurfacesProp && allowedSurfacesProp.length > 0 ? allowedSurfacesProp : ["message"];
|
|
8710
|
-
const { blocks, addBlock, updateBlock, removeBlock, duplicateBlock, reorderBlock, replaceAll } = useBlockKitchenState(
|
|
8711
|
-
|
|
8712
|
-
|
|
9249
|
+
const { blocks, addBlock, addChild, updateBlock, removeBlock, duplicateBlock, reorderBlock, moveBlock, replaceAll } = useBlockKitchenState({ initialBlocks, onChange });
|
|
9250
|
+
const childParentById = useMemo(() => {
|
|
9251
|
+
const map = /* @__PURE__ */ new Map();
|
|
9252
|
+
for (const top of blocks) {
|
|
9253
|
+
if (top.children) {
|
|
9254
|
+
for (const child of top.children) {
|
|
9255
|
+
map.set(child.id, top.id);
|
|
9256
|
+
}
|
|
9257
|
+
}
|
|
9258
|
+
}
|
|
9259
|
+
return map;
|
|
9260
|
+
}, [blocks]);
|
|
8713
9261
|
const [jsonOpen, setJsonOpen] = useState(false);
|
|
8714
9262
|
const [sendOpen, setSendOpen] = useState(false);
|
|
8715
9263
|
const [issuesOpen, setIssuesOpen] = useState(false);
|
|
@@ -8734,14 +9282,22 @@ function BlockKitchen(props) {
|
|
|
8734
9282
|
useSensor(TouchSensor, { activationConstraint: { delay: 150, tolerance: 8 } }),
|
|
8735
9283
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
|
8736
9284
|
);
|
|
8737
|
-
const collisionDetection = useCallback(
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
|
|
9285
|
+
const collisionDetection = useCallback(
|
|
9286
|
+
(args) => {
|
|
9287
|
+
const hits = pointerWithin(args);
|
|
9288
|
+
if (hits.length > 0) {
|
|
9289
|
+
const child = hits.find((c) => childParentById.has(c.id));
|
|
9290
|
+
if (child) return [child];
|
|
9291
|
+
const body = hits.find((c) => parseContainerBodyId(c.id) !== null);
|
|
9292
|
+
if (body) return [body];
|
|
9293
|
+
const block = hits.find((c) => c.id !== SURFACE_DROPPABLE_ID && parseContainerBodyId(c.id) === null);
|
|
9294
|
+
if (block) return [block];
|
|
9295
|
+
return hits;
|
|
9296
|
+
}
|
|
9297
|
+
return closestCenter(args);
|
|
9298
|
+
},
|
|
9299
|
+
[childParentById]
|
|
9300
|
+
);
|
|
8745
9301
|
const handleDragStart = useCallback((event) => {
|
|
8746
9302
|
const variantId = parsePaletteDragId(event.active.id);
|
|
8747
9303
|
setActivePaletteVariantId(variantId);
|
|
@@ -8753,24 +9309,43 @@ function BlockKitchen(props) {
|
|
|
8753
9309
|
if (!over) {
|
|
8754
9310
|
return;
|
|
8755
9311
|
}
|
|
9312
|
+
const overId = over.id;
|
|
9313
|
+
let target;
|
|
9314
|
+
const bodyParent = parseContainerBodyId(overId);
|
|
9315
|
+
const childParent = childParentById.get(overId);
|
|
9316
|
+
if (overId === SURFACE_DROPPABLE_ID) {
|
|
9317
|
+
target = { kind: "top", index: blocks.length };
|
|
9318
|
+
} else if (bodyParent) {
|
|
9319
|
+
const count = blocks.find((b) => b.id === bodyParent)?.children?.length ?? 0;
|
|
9320
|
+
target = { kind: "container", parentId: bodyParent, index: count };
|
|
9321
|
+
} else if (childParent) {
|
|
9322
|
+
const siblings = blocks.find((b) => b.id === childParent)?.children ?? [];
|
|
9323
|
+
target = { kind: "container", parentId: childParent, index: siblings.findIndex((c) => c.id === overId) };
|
|
9324
|
+
} else {
|
|
9325
|
+
const topIndex = blocks.findIndex((b) => b.id === overId);
|
|
9326
|
+
target = topIndex === -1 ? null : { kind: "top", index: topIndex };
|
|
9327
|
+
}
|
|
9328
|
+
if (!target) {
|
|
9329
|
+
return;
|
|
9330
|
+
}
|
|
8756
9331
|
const variantId = parsePaletteDragId(active.id);
|
|
8757
9332
|
if (variantId) {
|
|
8758
9333
|
const variant = variantById.get(variantId);
|
|
8759
9334
|
if (!variant) {
|
|
8760
9335
|
return;
|
|
8761
9336
|
}
|
|
8762
|
-
|
|
8763
|
-
|
|
9337
|
+
if (target.kind === "container") {
|
|
9338
|
+
addChild(target.parentId, variant.factory(), target.index);
|
|
9339
|
+
} else {
|
|
9340
|
+
addBlock(variant.factory(), target.index);
|
|
9341
|
+
}
|
|
8764
9342
|
return;
|
|
8765
9343
|
}
|
|
8766
|
-
if (active.id !==
|
|
8767
|
-
|
|
8768
|
-
if (overIndex !== -1) {
|
|
8769
|
-
reorderBlock(active.id, overIndex);
|
|
8770
|
-
}
|
|
9344
|
+
if (active.id !== overId) {
|
|
9345
|
+
moveBlock(active.id, target);
|
|
8771
9346
|
}
|
|
8772
9347
|
},
|
|
8773
|
-
[addBlock, blocks,
|
|
9348
|
+
[addBlock, addChild, blocks, childParentById, moveBlock, variantById]
|
|
8774
9349
|
);
|
|
8775
9350
|
const handleDragCancel = useCallback(() => {
|
|
8776
9351
|
setActivePaletteVariantId(null);
|