@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.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);
|
|
@@ -1151,6 +1179,49 @@ var defaultPalette = [
|
|
|
1151
1179
|
})
|
|
1152
1180
|
}
|
|
1153
1181
|
]
|
|
1182
|
+
},
|
|
1183
|
+
{
|
|
1184
|
+
name: "Container",
|
|
1185
|
+
icon: lucideReact.Container,
|
|
1186
|
+
variants: [
|
|
1187
|
+
{
|
|
1188
|
+
id: "container_collapsible",
|
|
1189
|
+
label: "Collapsible container",
|
|
1190
|
+
factory: () => ({
|
|
1191
|
+
type: "container",
|
|
1192
|
+
title: { type: "plain_text", text: "Bulk update: 2 records selected" },
|
|
1193
|
+
subtitle: { type: "plain_text", text: "Review changes before confirming" },
|
|
1194
|
+
is_collapsible: true,
|
|
1195
|
+
child_blocks: [
|
|
1196
|
+
{
|
|
1197
|
+
type: "section",
|
|
1198
|
+
text: { type: "mrkdwn", text: "*DCW-1024*\nStatus: Open \u2192 Closed" }
|
|
1199
|
+
},
|
|
1200
|
+
{ type: "divider" },
|
|
1201
|
+
{
|
|
1202
|
+
type: "section",
|
|
1203
|
+
text: { type: "mrkdwn", text: "*DCW-1025*\nStatus: In Progress \u2192 Closed" }
|
|
1204
|
+
},
|
|
1205
|
+
{
|
|
1206
|
+
type: "actions",
|
|
1207
|
+
elements: [
|
|
1208
|
+
{
|
|
1209
|
+
type: "button",
|
|
1210
|
+
text: { type: "plain_text", text: "Confirm All", emoji: true },
|
|
1211
|
+
style: "primary",
|
|
1212
|
+
action_id: "bulk_confirm"
|
|
1213
|
+
},
|
|
1214
|
+
{
|
|
1215
|
+
type: "button",
|
|
1216
|
+
text: { type: "plain_text", text: "Cancel", emoji: true },
|
|
1217
|
+
action_id: "bulk_cancel"
|
|
1218
|
+
}
|
|
1219
|
+
]
|
|
1220
|
+
}
|
|
1221
|
+
]
|
|
1222
|
+
})
|
|
1223
|
+
}
|
|
1224
|
+
]
|
|
1154
1225
|
}
|
|
1155
1226
|
];
|
|
1156
1227
|
var legacyInputVariants = [
|
|
@@ -1631,6 +1702,8 @@ function labelForBlockType(type) {
|
|
|
1631
1702
|
return "Task Card";
|
|
1632
1703
|
case "data_visualization":
|
|
1633
1704
|
return "Data Visualization";
|
|
1705
|
+
case "container":
|
|
1706
|
+
return "Container";
|
|
1634
1707
|
}
|
|
1635
1708
|
}
|
|
1636
1709
|
function cn(...inputs) {
|
|
@@ -1967,9 +2040,52 @@ function useBlockKitValidation(blocks, surface) {
|
|
|
1967
2040
|
}, [blocks, surface]);
|
|
1968
2041
|
return state;
|
|
1969
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
|
+
}
|
|
1970
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
|
+
}
|
|
1971
2057
|
return { id: nanoid.nanoid(8), block };
|
|
1972
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
|
+
}
|
|
1973
2089
|
function useBlockKitchenState({
|
|
1974
2090
|
initialBlocks,
|
|
1975
2091
|
onChange
|
|
@@ -1990,41 +2106,113 @@ function useBlockKitchenState({
|
|
|
1990
2106
|
const addBlock = React.useCallback((block, atIndex) => {
|
|
1991
2107
|
setBlocks((prev) => {
|
|
1992
2108
|
const next = [...prev];
|
|
1993
|
-
const inserted = wrap(block);
|
|
1994
2109
|
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
1995
|
-
next.splice(idx, 0,
|
|
2110
|
+
next.splice(idx, 0, wrap(block));
|
|
1996
2111
|
return next;
|
|
1997
2112
|
});
|
|
1998
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
|
+
}, []);
|
|
1999
2130
|
const updateBlock = React.useCallback((id, block) => {
|
|
2000
|
-
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
|
+
);
|
|
2001
2142
|
}, []);
|
|
2002
2143
|
const removeBlock = React.useCallback((id) => {
|
|
2003
|
-
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
|
+
});
|
|
2004
2152
|
}, []);
|
|
2005
2153
|
const duplicateBlock = React.useCallback((id) => {
|
|
2006
2154
|
setBlocks((prev) => {
|
|
2007
|
-
const
|
|
2008
|
-
if (
|
|
2155
|
+
const loc = locate(prev, id);
|
|
2156
|
+
if (!loc) {
|
|
2009
2157
|
return prev;
|
|
2010
2158
|
}
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
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
|
+
});
|
|
2015
2169
|
});
|
|
2016
2170
|
}, []);
|
|
2017
2171
|
const reorderBlock = React.useCallback((fromId, toIndex) => {
|
|
2018
2172
|
setBlocks((prev) => {
|
|
2019
|
-
const
|
|
2020
|
-
if (
|
|
2173
|
+
const loc = locate(prev, fromId);
|
|
2174
|
+
if (!loc) {
|
|
2021
2175
|
return prev;
|
|
2022
2176
|
}
|
|
2023
|
-
const
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
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);
|
|
2028
2216
|
});
|
|
2029
2217
|
}, []);
|
|
2030
2218
|
const replaceAll = React.useCallback((newBlocks) => {
|
|
@@ -2033,10 +2221,12 @@ function useBlockKitchenState({
|
|
|
2033
2221
|
return {
|
|
2034
2222
|
blocks,
|
|
2035
2223
|
addBlock,
|
|
2224
|
+
addChild,
|
|
2036
2225
|
updateBlock,
|
|
2037
2226
|
removeBlock,
|
|
2038
2227
|
duplicateBlock,
|
|
2039
2228
|
reorderBlock,
|
|
2229
|
+
moveBlock,
|
|
2040
2230
|
replaceAll
|
|
2041
2231
|
};
|
|
2042
2232
|
}
|
|
@@ -3545,6 +3735,113 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3545
3735
|
] })
|
|
3546
3736
|
] });
|
|
3547
3737
|
}
|
|
3738
|
+
var WIDTHS = ["narrow", "standard", "wide", "full"];
|
|
3739
|
+
function ContainerEditor({ block, onChange }) {
|
|
3740
|
+
const iconUrl = block.icon && "image_url" in block.icon ? block.icon.image_url ?? "" : "";
|
|
3741
|
+
const iconAlt = block.icon?.alt_text ?? "";
|
|
3742
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3743
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Title", help: "Heading shown at the top of the container.", htmlFor: "container-title", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3744
|
+
Input,
|
|
3745
|
+
{
|
|
3746
|
+
id: "container-title",
|
|
3747
|
+
value: block.title?.text ?? "",
|
|
3748
|
+
maxLength: 150,
|
|
3749
|
+
placeholder: "e.g. Bulk update: 2 records selected",
|
|
3750
|
+
onChange: (e) => onChange({ ...block, title: { type: "plain_text", text: e.target.value } })
|
|
3751
|
+
}
|
|
3752
|
+
) }),
|
|
3753
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Subtitle", help: "Optional secondary line under the title.", htmlFor: "container-subtitle", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3754
|
+
Input,
|
|
3755
|
+
{
|
|
3756
|
+
id: "container-subtitle",
|
|
3757
|
+
value: block.subtitle?.text ?? "",
|
|
3758
|
+
maxLength: 150,
|
|
3759
|
+
placeholder: "e.g. Review changes before confirming",
|
|
3760
|
+
onChange: (e) => onChange({
|
|
3761
|
+
...block,
|
|
3762
|
+
subtitle: e.target.value ? { type: "plain_text", text: e.target.value } : void 0
|
|
3763
|
+
})
|
|
3764
|
+
}
|
|
3765
|
+
) }),
|
|
3766
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Icon URL", help: "Optional image shown left of the title.", htmlFor: "container-icon", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3767
|
+
Input,
|
|
3768
|
+
{
|
|
3769
|
+
id: "container-icon",
|
|
3770
|
+
type: "url",
|
|
3771
|
+
value: iconUrl,
|
|
3772
|
+
placeholder: "https://example.com/icon.png",
|
|
3773
|
+
onChange: (e) => onChange({
|
|
3774
|
+
...block,
|
|
3775
|
+
icon: e.target.value ? { type: "image", image_url: e.target.value, alt_text: iconAlt || "Container icon" } : void 0
|
|
3776
|
+
})
|
|
3777
|
+
}
|
|
3778
|
+
) }),
|
|
3779
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Width", help: "How wide the container renders in the message.", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3780
|
+
RadioGroup,
|
|
3781
|
+
{
|
|
3782
|
+
value: block.width ?? "standard",
|
|
3783
|
+
onValueChange: (v) => onChange({ ...block, width: v }),
|
|
3784
|
+
className: "flex flex-row flex-wrap gap-3",
|
|
3785
|
+
children: WIDTHS.map((w) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3786
|
+
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: w, id: `container-width-${w}` }),
|
|
3787
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `container-width-${w}`, className: "text-xs capitalize", children: w })
|
|
3788
|
+
] }, w))
|
|
3789
|
+
}
|
|
3790
|
+
) }),
|
|
3791
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3792
|
+
Checkbox,
|
|
3793
|
+
{
|
|
3794
|
+
id: "container-collapsible",
|
|
3795
|
+
label: "Collapsible",
|
|
3796
|
+
help: "Let readers expand and collapse the container.",
|
|
3797
|
+
checked: !!block.is_collapsible,
|
|
3798
|
+
onChange: (checked) => onChange({
|
|
3799
|
+
...block,
|
|
3800
|
+
is_collapsible: checked || void 0,
|
|
3801
|
+
default_collapsed: checked ? block.default_collapsed : void 0
|
|
3802
|
+
})
|
|
3803
|
+
}
|
|
3804
|
+
),
|
|
3805
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3806
|
+
Checkbox,
|
|
3807
|
+
{
|
|
3808
|
+
id: "container-default-collapsed",
|
|
3809
|
+
label: "Collapsed by default",
|
|
3810
|
+
help: "Start collapsed on first render. Requires Collapsible.",
|
|
3811
|
+
checked: !!block.default_collapsed,
|
|
3812
|
+
disabled: !block.is_collapsible,
|
|
3813
|
+
onChange: (checked) => onChange({ ...block, default_collapsed: checked || void 0 })
|
|
3814
|
+
}
|
|
3815
|
+
),
|
|
3816
|
+
/* @__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." })
|
|
3817
|
+
] });
|
|
3818
|
+
}
|
|
3819
|
+
function Checkbox({
|
|
3820
|
+
id,
|
|
3821
|
+
label,
|
|
3822
|
+
help,
|
|
3823
|
+
checked,
|
|
3824
|
+
disabled,
|
|
3825
|
+
onChange
|
|
3826
|
+
}) {
|
|
3827
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3828
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3829
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3830
|
+
"input",
|
|
3831
|
+
{
|
|
3832
|
+
id,
|
|
3833
|
+
type: "checkbox",
|
|
3834
|
+
checked,
|
|
3835
|
+
disabled,
|
|
3836
|
+
onChange: (e) => onChange(e.target.checked),
|
|
3837
|
+
className: "h-3.5 w-3.5 cursor-pointer rounded border-input disabled:cursor-not-allowed disabled:opacity-40"
|
|
3838
|
+
}
|
|
3839
|
+
),
|
|
3840
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: id, className: "cursor-pointer text-xs", children: label })
|
|
3841
|
+
] }),
|
|
3842
|
+
help ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ml-5 text-[11px] leading-snug text-muted-foreground", children: help }) : null
|
|
3843
|
+
] });
|
|
3844
|
+
}
|
|
3548
3845
|
var MAX_ELEMENTS = 5;
|
|
3549
3846
|
function ContextActionsEditor({ block, onChange }) {
|
|
3550
3847
|
const elements = block.elements ?? [];
|
|
@@ -7714,6 +8011,8 @@ function dispatch(block, onChange) {
|
|
|
7714
8011
|
return /* @__PURE__ */ jsxRuntime.jsx(TaskCardEditor, { block, onChange: (next) => onChange(next) });
|
|
7715
8012
|
case "data_visualization":
|
|
7716
8013
|
return /* @__PURE__ */ jsxRuntime.jsx(DataVisualizationEditor, { block, onChange: (next) => onChange(next) });
|
|
8014
|
+
case "container":
|
|
8015
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ContainerEditor, { block, onChange: (next) => onChange(next) });
|
|
7717
8016
|
default:
|
|
7718
8017
|
return null;
|
|
7719
8018
|
}
|
|
@@ -7790,7 +8089,8 @@ var BLOCK_TYPE_LABELS = {
|
|
|
7790
8089
|
video: "Video",
|
|
7791
8090
|
plan: "Plan",
|
|
7792
8091
|
task_card: "Task Card",
|
|
7793
|
-
data_visualization: "Data Visualization"
|
|
8092
|
+
data_visualization: "Data Visualization",
|
|
8093
|
+
container: "Container"
|
|
7794
8094
|
};
|
|
7795
8095
|
function BlockRow({
|
|
7796
8096
|
builderBlock,
|
|
@@ -8084,6 +8384,225 @@ function RichTextInlineEditor({
|
|
|
8084
8384
|
}
|
|
8085
8385
|
);
|
|
8086
8386
|
}
|
|
8387
|
+
function ContainerRow({
|
|
8388
|
+
builderBlock,
|
|
8389
|
+
previewHooks,
|
|
8390
|
+
previewTheme,
|
|
8391
|
+
errorsByBlockId,
|
|
8392
|
+
openBlockId,
|
|
8393
|
+
onOpenBlockChange,
|
|
8394
|
+
onUpdate,
|
|
8395
|
+
onDuplicate,
|
|
8396
|
+
onDelete,
|
|
8397
|
+
onReorder,
|
|
8398
|
+
index,
|
|
8399
|
+
total,
|
|
8400
|
+
isPaletteDrag = false
|
|
8401
|
+
}) {
|
|
8402
|
+
const { id } = builderBlock;
|
|
8403
|
+
const block = builderBlock.block;
|
|
8404
|
+
const children = builderBlock.children ?? [];
|
|
8405
|
+
const errors = errorsByBlockId?.get(id);
|
|
8406
|
+
const hasErrors = !!errors && errors.length > 0;
|
|
8407
|
+
const isOpen = openBlockId === id;
|
|
8408
|
+
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = sortable.useSortable({ id });
|
|
8409
|
+
const { role: _dndRole, tabIndex: _dndTabIndex, ...sortableA11yAttrs } = attributes;
|
|
8410
|
+
const { setNodeRef: setBodyRef, isOver: isBodyOver } = core.useDroppable({ id: containerBodyId(id) });
|
|
8411
|
+
const style = { transform: utilities.CSS.Transform.toString(transform), transition };
|
|
8412
|
+
const icon = block.icon && "image_url" in block.icon ? block.icon.image_url : void 0;
|
|
8413
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8414
|
+
"div",
|
|
8415
|
+
{
|
|
8416
|
+
ref: setNodeRef,
|
|
8417
|
+
style,
|
|
8418
|
+
className: cn("group/container relative mb-2 last:mb-0 hover:z-10", isDragging && "opacity-40"),
|
|
8419
|
+
children: [
|
|
8420
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8421
|
+
"div",
|
|
8422
|
+
{
|
|
8423
|
+
className: cn(
|
|
8424
|
+
"overflow-hidden rounded-md border bg-card transition-shadow",
|
|
8425
|
+
hasErrors ? "border-destructive/60" : "border-border"
|
|
8426
|
+
),
|
|
8427
|
+
children: [
|
|
8428
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: isOpen, onOpenChange: (open) => onOpenBlockChange?.(open ? id : null), children: [
|
|
8429
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8430
|
+
"div",
|
|
8431
|
+
{
|
|
8432
|
+
role: "button",
|
|
8433
|
+
tabIndex: 0,
|
|
8434
|
+
"aria-label": "Edit container",
|
|
8435
|
+
...sortableA11yAttrs,
|
|
8436
|
+
...listeners,
|
|
8437
|
+
onKeyDown: (e) => {
|
|
8438
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
8439
|
+
e.preventDefault();
|
|
8440
|
+
onOpenBlockChange?.(!isOpen ? id : null);
|
|
8441
|
+
}
|
|
8442
|
+
},
|
|
8443
|
+
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",
|
|
8444
|
+
children: [
|
|
8445
|
+
icon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: icon, alt: "", "aria-hidden": "true", className: "h-5 w-5 shrink-0 rounded object-cover" }) : null,
|
|
8446
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
8447
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs font-semibold text-foreground", children: block.title?.text || "Container" }),
|
|
8448
|
+
block.subtitle?.text ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: block.subtitle.text }) : null
|
|
8449
|
+
] }),
|
|
8450
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto shrink-0 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Container" })
|
|
8451
|
+
]
|
|
8452
|
+
}
|
|
8453
|
+
) }),
|
|
8454
|
+
/* @__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) }) })
|
|
8455
|
+
] }),
|
|
8456
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8457
|
+
"div",
|
|
8458
|
+
{
|
|
8459
|
+
ref: setBodyRef,
|
|
8460
|
+
className: cn(
|
|
8461
|
+
"flex flex-col gap-2 p-3 transition-colors",
|
|
8462
|
+
isPaletteDrag && "outline-2 -outline-offset-2 outline-dashed outline-primary/40",
|
|
8463
|
+
isPaletteDrag && isBodyOver && "bg-primary/5"
|
|
8464
|
+
),
|
|
8465
|
+
children: children.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8466
|
+
"div",
|
|
8467
|
+
{
|
|
8468
|
+
className: cn(
|
|
8469
|
+
"flex items-center justify-center rounded-md border border-dashed px-3 py-6 text-center text-[11px] transition-colors",
|
|
8470
|
+
isBodyOver ? "border-primary/60 text-primary" : "border-border text-muted-foreground"
|
|
8471
|
+
),
|
|
8472
|
+
children: "Drag blocks here"
|
|
8473
|
+
}
|
|
8474
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(sortable.SortableContext, { items: children.map((c) => c.id), strategy: sortable.verticalListSortingStrategy, children: [
|
|
8475
|
+
children.map((child, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8476
|
+
BlockRow,
|
|
8477
|
+
{
|
|
8478
|
+
builderBlock: child,
|
|
8479
|
+
previewHooks,
|
|
8480
|
+
previewTheme,
|
|
8481
|
+
errors: errorsByBlockId?.get(child.id),
|
|
8482
|
+
isOpen: openBlockId === child.id,
|
|
8483
|
+
onOpenChange: (open) => onOpenBlockChange?.(open ? child.id : null),
|
|
8484
|
+
onUpdate,
|
|
8485
|
+
onDuplicate,
|
|
8486
|
+
onDelete,
|
|
8487
|
+
index: idx,
|
|
8488
|
+
total: children.length,
|
|
8489
|
+
onReorder,
|
|
8490
|
+
isPaletteDrag
|
|
8491
|
+
},
|
|
8492
|
+
child.id
|
|
8493
|
+
)),
|
|
8494
|
+
isPaletteDrag && isBodyOver ? /* @__PURE__ */ jsxRuntime.jsx(DropIndicator, {}) : null
|
|
8495
|
+
] })
|
|
8496
|
+
}
|
|
8497
|
+
)
|
|
8498
|
+
]
|
|
8499
|
+
}
|
|
8500
|
+
),
|
|
8501
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8502
|
+
"div",
|
|
8503
|
+
{
|
|
8504
|
+
className: cn(
|
|
8505
|
+
"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",
|
|
8506
|
+
hasErrors ? "opacity-100" : "opacity-0 group-hover/container:opacity-100 group-focus-within/container:opacity-100"
|
|
8507
|
+
),
|
|
8508
|
+
children: [
|
|
8509
|
+
hasErrors ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
8510
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8511
|
+
"button",
|
|
8512
|
+
{
|
|
8513
|
+
type: "button",
|
|
8514
|
+
"aria-label": `Show ${errors.length} validation ${errors.length === 1 ? "issue" : "issues"}`,
|
|
8515
|
+
onClick: () => onOpenBlockChange?.(id),
|
|
8516
|
+
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",
|
|
8517
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" })
|
|
8518
|
+
}
|
|
8519
|
+
) }),
|
|
8520
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", align: "end", children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "flex flex-col gap-0.5", children: [
|
|
8521
|
+
errors.slice(0, 4).map((err, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: err }, i)),
|
|
8522
|
+
errors.length > 4 ? /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "text-muted-foreground", children: [
|
|
8523
|
+
"and ",
|
|
8524
|
+
errors.length - 4,
|
|
8525
|
+
" more"
|
|
8526
|
+
] }) : null
|
|
8527
|
+
] }) })
|
|
8528
|
+
] }) : null,
|
|
8529
|
+
onReorder && typeof index === "number" && typeof total === "number" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8530
|
+
/* @__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" }) }),
|
|
8531
|
+
/* @__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" }) })
|
|
8532
|
+
] }) : null,
|
|
8533
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Edit", onClick: () => onOpenBlockChange?.(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }) }),
|
|
8534
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Duplicate", onClick: () => onDuplicate(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3.5 w-3.5" }) }),
|
|
8535
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Delete", destructive: true, onClick: () => onDelete(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" }) })
|
|
8536
|
+
]
|
|
8537
|
+
}
|
|
8538
|
+
),
|
|
8539
|
+
/* @__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: [
|
|
8540
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[11px] font-medium text-muted-foreground", children: "Container" }),
|
|
8541
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
8542
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8543
|
+
"button",
|
|
8544
|
+
{
|
|
8545
|
+
type: "button",
|
|
8546
|
+
"aria-label": "Edit container",
|
|
8547
|
+
onClick: () => onOpenBlockChange?.(id),
|
|
8548
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
8549
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-4 w-4" })
|
|
8550
|
+
}
|
|
8551
|
+
),
|
|
8552
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8553
|
+
"button",
|
|
8554
|
+
{
|
|
8555
|
+
type: "button",
|
|
8556
|
+
"aria-label": "Duplicate container",
|
|
8557
|
+
onClick: () => onDuplicate(id),
|
|
8558
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
8559
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-4 w-4" })
|
|
8560
|
+
}
|
|
8561
|
+
),
|
|
8562
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8563
|
+
"button",
|
|
8564
|
+
{
|
|
8565
|
+
type: "button",
|
|
8566
|
+
"aria-label": "Delete container",
|
|
8567
|
+
onClick: () => onDelete(id),
|
|
8568
|
+
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
8569
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" })
|
|
8570
|
+
}
|
|
8571
|
+
)
|
|
8572
|
+
] })
|
|
8573
|
+
] })
|
|
8574
|
+
]
|
|
8575
|
+
}
|
|
8576
|
+
);
|
|
8577
|
+
}
|
|
8578
|
+
function ToolbarButton2({
|
|
8579
|
+
label,
|
|
8580
|
+
onClick,
|
|
8581
|
+
disabled,
|
|
8582
|
+
destructive,
|
|
8583
|
+
children
|
|
8584
|
+
}) {
|
|
8585
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
8586
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8587
|
+
"button",
|
|
8588
|
+
{
|
|
8589
|
+
type: "button",
|
|
8590
|
+
"aria-label": label,
|
|
8591
|
+
disabled,
|
|
8592
|
+
onClick,
|
|
8593
|
+
className: cn(
|
|
8594
|
+
"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",
|
|
8595
|
+
destructive ? "hover:bg-destructive/10 hover:text-destructive" : "hover:bg-accent hover:text-foreground"
|
|
8596
|
+
),
|
|
8597
|
+
children
|
|
8598
|
+
}
|
|
8599
|
+
) }),
|
|
8600
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: label })
|
|
8601
|
+
] });
|
|
8602
|
+
}
|
|
8603
|
+
function DropIndicator() {
|
|
8604
|
+
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)]" }) });
|
|
8605
|
+
}
|
|
8087
8606
|
var SURFACE_DROPPABLE_ID = "builder-surface";
|
|
8088
8607
|
function Surface({
|
|
8089
8608
|
blocks,
|
|
@@ -8115,26 +8634,46 @@ function Surface({
|
|
|
8115
8634
|
isPaletteDrag && isOver && (isDark ? "bg-[#2c3036]" : "bg-[#eaf0ff]")
|
|
8116
8635
|
),
|
|
8117
8636
|
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: [
|
|
8118
|
-
blocks.map(
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8637
|
+
blocks.map(
|
|
8638
|
+
(block, idx) => block.block.type === "container" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8639
|
+
ContainerRow,
|
|
8640
|
+
{
|
|
8641
|
+
builderBlock: block,
|
|
8642
|
+
previewHooks,
|
|
8643
|
+
previewTheme,
|
|
8644
|
+
errorsByBlockId,
|
|
8645
|
+
openBlockId,
|
|
8646
|
+
onOpenBlockChange,
|
|
8647
|
+
onUpdate,
|
|
8648
|
+
onDuplicate,
|
|
8649
|
+
onDelete,
|
|
8650
|
+
index: idx,
|
|
8651
|
+
total: blocks.length,
|
|
8652
|
+
onReorder,
|
|
8653
|
+
isPaletteDrag
|
|
8654
|
+
},
|
|
8655
|
+
block.id
|
|
8656
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8657
|
+
BlockRow,
|
|
8658
|
+
{
|
|
8659
|
+
builderBlock: block,
|
|
8660
|
+
previewHooks,
|
|
8661
|
+
previewTheme,
|
|
8662
|
+
errors: errorsByBlockId?.get(block.id),
|
|
8663
|
+
isOpen: openBlockId === block.id,
|
|
8664
|
+
onOpenChange: (open) => onOpenBlockChange?.(open ? block.id : null),
|
|
8665
|
+
onUpdate,
|
|
8666
|
+
onDuplicate,
|
|
8667
|
+
onDelete,
|
|
8668
|
+
index: idx,
|
|
8669
|
+
total: blocks.length,
|
|
8670
|
+
onReorder,
|
|
8671
|
+
isPaletteDrag
|
|
8672
|
+
},
|
|
8673
|
+
block.id
|
|
8674
|
+
)
|
|
8675
|
+
),
|
|
8676
|
+
showEndDropZone ? /* @__PURE__ */ jsxRuntime.jsx(DropIndicator2, {}) : null
|
|
8138
8677
|
] })
|
|
8139
8678
|
}
|
|
8140
8679
|
);
|
|
@@ -8374,7 +8913,7 @@ function EmptyState({
|
|
|
8374
8913
|
}
|
|
8375
8914
|
);
|
|
8376
8915
|
}
|
|
8377
|
-
function
|
|
8916
|
+
function DropIndicator2() {
|
|
8378
8917
|
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)]" }) });
|
|
8379
8918
|
}
|
|
8380
8919
|
var THEME_OPTIONS = [
|
|
@@ -8737,9 +9276,18 @@ function BlockKitchen(props) {
|
|
|
8737
9276
|
}, [palette, disabledBlockTypes]);
|
|
8738
9277
|
const variantById = React.useMemo(() => buildVariantById(paletteSections), [paletteSections]);
|
|
8739
9278
|
const allowedSurfaces = allowedSurfacesProp && allowedSurfacesProp.length > 0 ? allowedSurfacesProp : ["message"];
|
|
8740
|
-
const { blocks, addBlock, updateBlock, removeBlock, duplicateBlock, reorderBlock, replaceAll } = useBlockKitchenState(
|
|
8741
|
-
|
|
8742
|
-
|
|
9279
|
+
const { blocks, addBlock, addChild, updateBlock, removeBlock, duplicateBlock, reorderBlock, moveBlock, replaceAll } = useBlockKitchenState({ initialBlocks, onChange });
|
|
9280
|
+
const childParentById = React.useMemo(() => {
|
|
9281
|
+
const map = /* @__PURE__ */ new Map();
|
|
9282
|
+
for (const top of blocks) {
|
|
9283
|
+
if (top.children) {
|
|
9284
|
+
for (const child of top.children) {
|
|
9285
|
+
map.set(child.id, top.id);
|
|
9286
|
+
}
|
|
9287
|
+
}
|
|
9288
|
+
}
|
|
9289
|
+
return map;
|
|
9290
|
+
}, [blocks]);
|
|
8743
9291
|
const [jsonOpen, setJsonOpen] = React.useState(false);
|
|
8744
9292
|
const [sendOpen, setSendOpen] = React.useState(false);
|
|
8745
9293
|
const [issuesOpen, setIssuesOpen] = React.useState(false);
|
|
@@ -8764,14 +9312,22 @@ function BlockKitchen(props) {
|
|
|
8764
9312
|
core.useSensor(core.TouchSensor, { activationConstraint: { delay: 150, tolerance: 8 } }),
|
|
8765
9313
|
core.useSensor(core.KeyboardSensor, { coordinateGetter: sortable.sortableKeyboardCoordinates })
|
|
8766
9314
|
);
|
|
8767
|
-
const collisionDetection = React.useCallback(
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
9315
|
+
const collisionDetection = React.useCallback(
|
|
9316
|
+
(args) => {
|
|
9317
|
+
const hits = core.pointerWithin(args);
|
|
9318
|
+
if (hits.length > 0) {
|
|
9319
|
+
const child = hits.find((c) => childParentById.has(c.id));
|
|
9320
|
+
if (child) return [child];
|
|
9321
|
+
const body = hits.find((c) => parseContainerBodyId(c.id) !== null);
|
|
9322
|
+
if (body) return [body];
|
|
9323
|
+
const block = hits.find((c) => c.id !== SURFACE_DROPPABLE_ID && parseContainerBodyId(c.id) === null);
|
|
9324
|
+
if (block) return [block];
|
|
9325
|
+
return hits;
|
|
9326
|
+
}
|
|
9327
|
+
return core.closestCenter(args);
|
|
9328
|
+
},
|
|
9329
|
+
[childParentById]
|
|
9330
|
+
);
|
|
8775
9331
|
const handleDragStart = React.useCallback((event) => {
|
|
8776
9332
|
const variantId = parsePaletteDragId(event.active.id);
|
|
8777
9333
|
setActivePaletteVariantId(variantId);
|
|
@@ -8783,24 +9339,43 @@ function BlockKitchen(props) {
|
|
|
8783
9339
|
if (!over) {
|
|
8784
9340
|
return;
|
|
8785
9341
|
}
|
|
9342
|
+
const overId = over.id;
|
|
9343
|
+
let target;
|
|
9344
|
+
const bodyParent = parseContainerBodyId(overId);
|
|
9345
|
+
const childParent = childParentById.get(overId);
|
|
9346
|
+
if (overId === SURFACE_DROPPABLE_ID) {
|
|
9347
|
+
target = { kind: "top", index: blocks.length };
|
|
9348
|
+
} else if (bodyParent) {
|
|
9349
|
+
const count = blocks.find((b) => b.id === bodyParent)?.children?.length ?? 0;
|
|
9350
|
+
target = { kind: "container", parentId: bodyParent, index: count };
|
|
9351
|
+
} else if (childParent) {
|
|
9352
|
+
const siblings = blocks.find((b) => b.id === childParent)?.children ?? [];
|
|
9353
|
+
target = { kind: "container", parentId: childParent, index: siblings.findIndex((c) => c.id === overId) };
|
|
9354
|
+
} else {
|
|
9355
|
+
const topIndex = blocks.findIndex((b) => b.id === overId);
|
|
9356
|
+
target = topIndex === -1 ? null : { kind: "top", index: topIndex };
|
|
9357
|
+
}
|
|
9358
|
+
if (!target) {
|
|
9359
|
+
return;
|
|
9360
|
+
}
|
|
8786
9361
|
const variantId = parsePaletteDragId(active.id);
|
|
8787
9362
|
if (variantId) {
|
|
8788
9363
|
const variant = variantById.get(variantId);
|
|
8789
9364
|
if (!variant) {
|
|
8790
9365
|
return;
|
|
8791
9366
|
}
|
|
8792
|
-
|
|
8793
|
-
|
|
9367
|
+
if (target.kind === "container") {
|
|
9368
|
+
addChild(target.parentId, variant.factory(), target.index);
|
|
9369
|
+
} else {
|
|
9370
|
+
addBlock(variant.factory(), target.index);
|
|
9371
|
+
}
|
|
8794
9372
|
return;
|
|
8795
9373
|
}
|
|
8796
|
-
if (active.id !==
|
|
8797
|
-
|
|
8798
|
-
if (overIndex !== -1) {
|
|
8799
|
-
reorderBlock(active.id, overIndex);
|
|
8800
|
-
}
|
|
9374
|
+
if (active.id !== overId) {
|
|
9375
|
+
moveBlock(active.id, target);
|
|
8801
9376
|
}
|
|
8802
9377
|
},
|
|
8803
|
-
[addBlock, blocks,
|
|
9378
|
+
[addBlock, addChild, blocks, childParentById, moveBlock, variantById]
|
|
8804
9379
|
);
|
|
8805
9380
|
const handleDragCancel = React.useCallback(() => {
|
|
8806
9381
|
setActivePaletteVariantId(null);
|