@tightknitai/block-kitchen 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +471 -201
- 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 +472 -202
- package/dist/index.js.map +1 -1
- package/dist/{palette-C8sPJuXx.d.cts → palette-BtSwlGUC.d.cts} +1 -1
- package/dist/{palette-C8sPJuXx.d.ts → palette-BtSwlGUC.d.ts} +1 -1
- package/dist/palette.d.cts +1 -1
- package/dist/palette.d.ts +1 -1
- package/dist/styles.css +1 -1
- package/package.json +44 -38
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, Loader2, ExternalLink, AlertTriangle, GripVertical, Sun, Moon, MessageSquare, AppWindow, Home, MailSearch, Plus, ChevronDown, BookOpen, Trash2, Code2, Pencil, Send, Search, Check, Copy, Info, CheckCircle2, ChevronRight, LayoutGrid, ArrowUp, ArrowDown, Type, Bold, Italic, Strikethrough, Underline, Code, List, ListOrdered, Quote,
|
|
3
|
+
import { X, Circle, Sparkles, FileText, AlignLeft, MousePointerClick, TextCursorInput, LayoutTemplate, Bell, Pilcrow, Image, Video, GalleryHorizontal, Table, ChartColumnBig, Container, Loader2, ExternalLink, AlertTriangle, GripVertical, Sun, Moon, MessageSquare, AppWindow, Home, MailSearch, Plus, ChevronDown, BookOpen, Undo2, Redo2, Trash2, Code2, Pencil, Send, Search, Check, Copy, Info, CheckCircle2, ChevronRight, LayoutGrid, ArrowUp, ArrowDown, Type, Bold, Italic, Strikethrough, Underline, Code, List, ListOrdered, Quote, Smile, Link as Link$1 } from 'lucide-react';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { createContext, useState, useRef, useEffect, useCallback, useMemo, useId, useContext } from 'react';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -2036,6 +2036,69 @@ function useBlockKitValidation(blocks, surface) {
|
|
|
2036
2036
|
}, [blocks, surface]);
|
|
2037
2037
|
return state;
|
|
2038
2038
|
}
|
|
2039
|
+
var MAX_HISTORY = 20;
|
|
2040
|
+
function useHistoryState(initial) {
|
|
2041
|
+
const [record, setRecord] = useState(() => ({
|
|
2042
|
+
past: [],
|
|
2043
|
+
present: typeof initial === "function" ? initial() : initial,
|
|
2044
|
+
future: [],
|
|
2045
|
+
lastTag: null
|
|
2046
|
+
}));
|
|
2047
|
+
const commit = useCallback((updater, options) => {
|
|
2048
|
+
const tag = options?.tag ?? null;
|
|
2049
|
+
setRecord((h) => {
|
|
2050
|
+
const next = typeof updater === "function" ? updater(h.present) : updater;
|
|
2051
|
+
if (Object.is(next, h.present)) {
|
|
2052
|
+
return h;
|
|
2053
|
+
}
|
|
2054
|
+
if (tag !== null && h.lastTag === tag) {
|
|
2055
|
+
return { ...h, present: next, future: [] };
|
|
2056
|
+
}
|
|
2057
|
+
const past = [...h.past, h.present];
|
|
2058
|
+
return {
|
|
2059
|
+
past: past.length > MAX_HISTORY ? past.slice(past.length - MAX_HISTORY) : past,
|
|
2060
|
+
present: next,
|
|
2061
|
+
future: [],
|
|
2062
|
+
lastTag: tag
|
|
2063
|
+
};
|
|
2064
|
+
});
|
|
2065
|
+
}, []);
|
|
2066
|
+
const undo = useCallback(() => {
|
|
2067
|
+
setRecord((h) => {
|
|
2068
|
+
if (h.past.length === 0) {
|
|
2069
|
+
return h;
|
|
2070
|
+
}
|
|
2071
|
+
const previous = h.past[h.past.length - 1];
|
|
2072
|
+
return { past: h.past.slice(0, -1), present: previous, future: [h.present, ...h.future], lastTag: null };
|
|
2073
|
+
});
|
|
2074
|
+
}, []);
|
|
2075
|
+
const redo = useCallback(() => {
|
|
2076
|
+
setRecord((h) => {
|
|
2077
|
+
if (h.future.length === 0) {
|
|
2078
|
+
return h;
|
|
2079
|
+
}
|
|
2080
|
+
const [next, ...rest] = h.future;
|
|
2081
|
+
return { past: [...h.past, h.present], present: next, future: rest, lastTag: null };
|
|
2082
|
+
});
|
|
2083
|
+
}, []);
|
|
2084
|
+
const reset = useCallback((next) => {
|
|
2085
|
+
setRecord({ past: [], present: next, future: [], lastTag: null });
|
|
2086
|
+
}, []);
|
|
2087
|
+
return useMemo(
|
|
2088
|
+
() => ({
|
|
2089
|
+
present: record.present,
|
|
2090
|
+
canUndo: record.past.length > 0,
|
|
2091
|
+
canRedo: record.future.length > 0,
|
|
2092
|
+
commit,
|
|
2093
|
+
undo,
|
|
2094
|
+
redo,
|
|
2095
|
+
reset
|
|
2096
|
+
}),
|
|
2097
|
+
[record, commit, undo, redo, reset]
|
|
2098
|
+
);
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
// src/state/use-block-kitchen-state.ts
|
|
2039
2102
|
function mirror(node) {
|
|
2040
2103
|
if (!node.children) {
|
|
2041
2104
|
return node;
|
|
@@ -2086,7 +2149,15 @@ function useBlockKitchenState({
|
|
|
2086
2149
|
initialBlocks,
|
|
2087
2150
|
onChange
|
|
2088
2151
|
} = {}) {
|
|
2089
|
-
const
|
|
2152
|
+
const {
|
|
2153
|
+
present: blocks,
|
|
2154
|
+
commit,
|
|
2155
|
+
undo,
|
|
2156
|
+
redo,
|
|
2157
|
+
reset,
|
|
2158
|
+
canUndo,
|
|
2159
|
+
canRedo
|
|
2160
|
+
} = useHistoryState(() => (initialBlocks ?? []).map(wrap));
|
|
2090
2161
|
const onChangeRef = useRef(onChange);
|
|
2091
2162
|
useEffect(() => {
|
|
2092
2163
|
onChangeRef.current = onChange;
|
|
@@ -2099,121 +2170,155 @@ function useBlockKitchenState({
|
|
|
2099
2170
|
}
|
|
2100
2171
|
onChangeRef.current?.(blocks.map((b) => b.block));
|
|
2101
2172
|
}, [blocks]);
|
|
2102
|
-
const addBlock = useCallback(
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
next.splice(idx, 0, wrap(block));
|
|
2107
|
-
return next;
|
|
2108
|
-
});
|
|
2109
|
-
}, []);
|
|
2110
|
-
const addChild = useCallback((parentId, block, atIndex) => {
|
|
2111
|
-
if (!isContainerChildType(block.type)) {
|
|
2112
|
-
return;
|
|
2113
|
-
}
|
|
2114
|
-
setBlocks(
|
|
2115
|
-
(prev) => withChildren(prev, parentId, (children) => {
|
|
2116
|
-
if (children.length >= MAX_CONTAINER_CHILDREN) {
|
|
2117
|
-
return children;
|
|
2118
|
-
}
|
|
2119
|
-
const next = [...children];
|
|
2173
|
+
const addBlock = useCallback(
|
|
2174
|
+
(block, atIndex) => {
|
|
2175
|
+
commit((prev) => {
|
|
2176
|
+
const next = [...prev];
|
|
2120
2177
|
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
2121
2178
|
next.splice(idx, 0, wrap(block));
|
|
2122
2179
|
return next;
|
|
2123
|
-
})
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
}
|
|
2132
|
-
if (b.children?.some((c) => c.id === id)) {
|
|
2133
|
-
return mirror({ ...b, children: b.children.map((c) => c.id === id ? applyUpdate(c, block) : c) });
|
|
2134
|
-
}
|
|
2135
|
-
return b;
|
|
2136
|
-
})
|
|
2137
|
-
);
|
|
2138
|
-
}, []);
|
|
2139
|
-
const removeBlock = useCallback((id) => {
|
|
2140
|
-
setBlocks((prev) => {
|
|
2141
|
-
if (prev.some((b) => b.id === id)) {
|
|
2142
|
-
return prev.filter((b) => b.id !== id);
|
|
2180
|
+
});
|
|
2181
|
+
},
|
|
2182
|
+
[commit]
|
|
2183
|
+
);
|
|
2184
|
+
const addChild = useCallback(
|
|
2185
|
+
(parentId, block, atIndex) => {
|
|
2186
|
+
if (!isContainerChildType(block.type)) {
|
|
2187
|
+
return;
|
|
2143
2188
|
}
|
|
2144
|
-
|
|
2145
|
-
(
|
|
2189
|
+
commit(
|
|
2190
|
+
(prev) => withChildren(prev, parentId, (children) => {
|
|
2191
|
+
if (children.length >= MAX_CONTAINER_CHILDREN) {
|
|
2192
|
+
return children;
|
|
2193
|
+
}
|
|
2194
|
+
const next = [...children];
|
|
2195
|
+
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
2196
|
+
next.splice(idx, 0, wrap(block));
|
|
2197
|
+
return next;
|
|
2198
|
+
})
|
|
2146
2199
|
);
|
|
2147
|
-
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2200
|
+
},
|
|
2201
|
+
[commit]
|
|
2202
|
+
);
|
|
2203
|
+
const updateBlock = useCallback(
|
|
2204
|
+
(id, block) => {
|
|
2205
|
+
commit(
|
|
2206
|
+
(prev) => prev.map((b) => {
|
|
2207
|
+
if (b.id === id) {
|
|
2208
|
+
return applyUpdate(b, block);
|
|
2209
|
+
}
|
|
2210
|
+
if (b.children?.some((c) => c.id === id)) {
|
|
2211
|
+
return mirror({ ...b, children: b.children.map((c) => c.id === id ? applyUpdate(c, block) : c) });
|
|
2212
|
+
}
|
|
2213
|
+
return b;
|
|
2214
|
+
}),
|
|
2215
|
+
// Coalesce a run of edits to the same block (every keystroke in an
|
|
2216
|
+
// editor field lands here) into a single undo step. Editing a
|
|
2217
|
+
// different block, or any structural change, starts a new step.
|
|
2218
|
+
{ tag: `update:${id}` }
|
|
2219
|
+
);
|
|
2220
|
+
},
|
|
2221
|
+
[commit]
|
|
2222
|
+
);
|
|
2223
|
+
const removeBlock = useCallback(
|
|
2224
|
+
(id) => {
|
|
2225
|
+
commit((prev) => {
|
|
2226
|
+
if (prev.some((b) => b.id === id)) {
|
|
2227
|
+
return prev.filter((b) => b.id !== id);
|
|
2228
|
+
}
|
|
2229
|
+
return prev.map(
|
|
2230
|
+
(b) => b.children?.some((c) => c.id === id) ? mirror({ ...b, children: b.children.filter((c) => c.id !== id) }) : b
|
|
2231
|
+
);
|
|
2164
2232
|
});
|
|
2165
|
-
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
const reorder = (list) => {
|
|
2174
|
-
const next = [...list];
|
|
2175
|
-
const [moved] = next.splice(loc.index, 1);
|
|
2176
|
-
next.splice(Math.max(0, Math.min(toIndex, next.length)), 0, moved);
|
|
2177
|
-
return next;
|
|
2178
|
-
};
|
|
2179
|
-
if (loc.kind === "top") {
|
|
2180
|
-
return reorder(prev);
|
|
2181
|
-
}
|
|
2182
|
-
return withChildren(prev, loc.parentId, reorder);
|
|
2183
|
-
});
|
|
2184
|
-
}, []);
|
|
2185
|
-
const moveBlock = useCallback((activeId, target) => {
|
|
2186
|
-
setBlocks((prev) => {
|
|
2187
|
-
const loc = locate(prev, activeId);
|
|
2188
|
-
if (!loc) {
|
|
2189
|
-
return prev;
|
|
2190
|
-
}
|
|
2191
|
-
const moved = loc.kind === "top" ? prev[loc.index] : prev.find((b) => b.id === loc.parentId)?.children?.[loc.index];
|
|
2192
|
-
if (!moved) {
|
|
2193
|
-
return prev;
|
|
2194
|
-
}
|
|
2195
|
-
if (target.kind === "container") {
|
|
2196
|
-
if (moved.children || !isContainerChildType(moved.block.type)) {
|
|
2233
|
+
},
|
|
2234
|
+
[commit]
|
|
2235
|
+
);
|
|
2236
|
+
const duplicateBlock = useCallback(
|
|
2237
|
+
(id) => {
|
|
2238
|
+
commit((prev) => {
|
|
2239
|
+
const loc = locate(prev, id);
|
|
2240
|
+
if (!loc) {
|
|
2197
2241
|
return prev;
|
|
2198
2242
|
}
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2243
|
+
if (loc.kind === "top") {
|
|
2244
|
+
const next = [...prev];
|
|
2245
|
+
next.splice(loc.index + 1, 0, cloneNode(prev[loc.index]));
|
|
2246
|
+
return next;
|
|
2247
|
+
}
|
|
2248
|
+
return withChildren(prev, loc.parentId, (children) => {
|
|
2249
|
+
const next = [...children];
|
|
2250
|
+
next.splice(loc.index + 1, 0, cloneNode(children[loc.index]));
|
|
2251
|
+
return next;
|
|
2252
|
+
});
|
|
2253
|
+
});
|
|
2254
|
+
},
|
|
2255
|
+
[commit]
|
|
2256
|
+
);
|
|
2257
|
+
const reorderBlock = useCallback(
|
|
2258
|
+
(fromId, toIndex) => {
|
|
2259
|
+
commit((prev) => {
|
|
2260
|
+
const loc = locate(prev, fromId);
|
|
2261
|
+
if (!loc) {
|
|
2202
2262
|
return prev;
|
|
2203
2263
|
}
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2264
|
+
const reorder = (list) => {
|
|
2265
|
+
const next = [...list];
|
|
2266
|
+
const [moved] = next.splice(loc.index, 1);
|
|
2267
|
+
next.splice(Math.max(0, Math.min(toIndex, next.length)), 0, moved);
|
|
2268
|
+
return next;
|
|
2269
|
+
};
|
|
2270
|
+
if (loc.kind === "top") {
|
|
2271
|
+
return reorder(prev);
|
|
2272
|
+
}
|
|
2273
|
+
return withChildren(prev, loc.parentId, reorder);
|
|
2274
|
+
});
|
|
2275
|
+
},
|
|
2276
|
+
[commit]
|
|
2277
|
+
);
|
|
2278
|
+
const moveBlock = useCallback(
|
|
2279
|
+
(activeId, target) => {
|
|
2280
|
+
commit((prev) => {
|
|
2281
|
+
const loc = locate(prev, activeId);
|
|
2282
|
+
if (!loc) {
|
|
2283
|
+
return prev;
|
|
2284
|
+
}
|
|
2285
|
+
const moved = loc.kind === "top" ? prev[loc.index] : prev.find((b) => b.id === loc.parentId)?.children?.[loc.index];
|
|
2286
|
+
if (!moved) {
|
|
2287
|
+
return prev;
|
|
2288
|
+
}
|
|
2289
|
+
if (target.kind === "container") {
|
|
2290
|
+
if (moved.children || !isContainerChildType(moved.block.type)) {
|
|
2291
|
+
return prev;
|
|
2292
|
+
}
|
|
2293
|
+
const sameContainer = loc.kind === "child" && loc.parentId === target.parentId;
|
|
2294
|
+
const destCount = prev.find((b) => b.id === target.parentId)?.children?.length ?? 0;
|
|
2295
|
+
if (!sameContainer && destCount >= MAX_CONTAINER_CHILDREN) {
|
|
2296
|
+
return prev;
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
const detached = loc.kind === "top" ? prev.filter((_, i) => i !== loc.index) : withChildren(prev, loc.parentId, (children) => children.filter((_, i) => i !== loc.index));
|
|
2300
|
+
const insert = (list) => {
|
|
2301
|
+
const next = [...list];
|
|
2302
|
+
next.splice(Math.max(0, Math.min(target.index, next.length)), 0, moved);
|
|
2303
|
+
return next;
|
|
2304
|
+
};
|
|
2305
|
+
return target.kind === "container" ? withChildren(detached, target.parentId, insert) : insert(detached);
|
|
2306
|
+
});
|
|
2307
|
+
},
|
|
2308
|
+
[commit]
|
|
2309
|
+
);
|
|
2310
|
+
const replaceAll = useCallback(
|
|
2311
|
+
(newBlocks) => {
|
|
2312
|
+
commit(sanitizeBlocks(newBlocks).map(wrap));
|
|
2313
|
+
},
|
|
2314
|
+
[commit]
|
|
2315
|
+
);
|
|
2316
|
+
const resetAll = useCallback(
|
|
2317
|
+
(newBlocks) => {
|
|
2318
|
+
reset(sanitizeBlocks(newBlocks).map(wrap));
|
|
2319
|
+
},
|
|
2320
|
+
[reset]
|
|
2321
|
+
);
|
|
2217
2322
|
return {
|
|
2218
2323
|
blocks,
|
|
2219
2324
|
addBlock,
|
|
@@ -2223,7 +2328,12 @@ function useBlockKitchenState({
|
|
|
2223
2328
|
duplicateBlock,
|
|
2224
2329
|
reorderBlock,
|
|
2225
2330
|
moveBlock,
|
|
2226
|
-
replaceAll
|
|
2331
|
+
replaceAll,
|
|
2332
|
+
resetAll,
|
|
2333
|
+
undo,
|
|
2334
|
+
redo,
|
|
2335
|
+
canUndo,
|
|
2336
|
+
canRedo
|
|
2227
2337
|
};
|
|
2228
2338
|
}
|
|
2229
2339
|
function useDevWarning(condition, message) {
|
|
@@ -3771,6 +3881,27 @@ function EditorField({
|
|
|
3771
3881
|
help && /* @__PURE__ */ jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: help })
|
|
3772
3882
|
] });
|
|
3773
3883
|
}
|
|
3884
|
+
function AdvancedIdField({
|
|
3885
|
+
label,
|
|
3886
|
+
help,
|
|
3887
|
+
htmlFor,
|
|
3888
|
+
value,
|
|
3889
|
+
placeholder,
|
|
3890
|
+
onChange
|
|
3891
|
+
}) {
|
|
3892
|
+
return /* @__PURE__ */ jsxs("details", { className: "rounded-md border bg-muted/20 px-2.5 py-1.5", children: [
|
|
3893
|
+
/* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-[11px] font-medium text-muted-foreground hover:text-foreground", children: "Advanced" }),
|
|
3894
|
+
/* @__PURE__ */ jsx("div", { className: "pt-2 pb-1", children: /* @__PURE__ */ jsx(EditorField, { label, help, htmlFor, children: /* @__PURE__ */ jsx(
|
|
3895
|
+
Input,
|
|
3896
|
+
{
|
|
3897
|
+
id: htmlFor,
|
|
3898
|
+
value: value ?? "",
|
|
3899
|
+
placeholder,
|
|
3900
|
+
onChange: (e) => onChange(e.target.value || void 0)
|
|
3901
|
+
}
|
|
3902
|
+
) }) })
|
|
3903
|
+
] });
|
|
3904
|
+
}
|
|
3774
3905
|
function ActionsEditor({ block, onChange }) {
|
|
3775
3906
|
const elements = block.elements ?? [];
|
|
3776
3907
|
const updateButton = (idx, update) => {
|
|
@@ -3869,7 +4000,18 @@ function ActionsEditor({ block, onChange }) {
|
|
|
3869
4000
|
/* @__PURE__ */ jsx(Label, { htmlFor: `btn-style-${idx}-${s}`, className: "text-xs capitalize", children: s })
|
|
3870
4001
|
] }, s))
|
|
3871
4002
|
}
|
|
3872
|
-
) })
|
|
4003
|
+
) }),
|
|
4004
|
+
/* @__PURE__ */ jsx(
|
|
4005
|
+
AdvancedIdField,
|
|
4006
|
+
{
|
|
4007
|
+
label: "Action ID",
|
|
4008
|
+
help: "Optional. Sent in the interaction payload so your app knows which button was clicked.",
|
|
4009
|
+
htmlFor: `btn-action-${idx}`,
|
|
4010
|
+
value: el.action_id,
|
|
4011
|
+
placeholder: "e.g. approve_request",
|
|
4012
|
+
onChange: (next) => updateButton(idx, { action_id: next })
|
|
4013
|
+
}
|
|
4014
|
+
)
|
|
3873
4015
|
] }, idx);
|
|
3874
4016
|
}),
|
|
3875
4017
|
/* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: addButton, className: "self-start", children: [
|
|
@@ -4152,7 +4294,18 @@ function ButtonsField({
|
|
|
4152
4294
|
/* @__PURE__ */ jsx(Label, { htmlFor: `${idPrefix}-btn-style-${idx}-${s}`, className: "text-xs capitalize", children: s })
|
|
4153
4295
|
] }, s))
|
|
4154
4296
|
}
|
|
4155
|
-
) })
|
|
4297
|
+
) }),
|
|
4298
|
+
/* @__PURE__ */ jsx(
|
|
4299
|
+
AdvancedIdField,
|
|
4300
|
+
{
|
|
4301
|
+
label: "Action ID",
|
|
4302
|
+
help: "Optional. Sent in the interaction payload so your app knows which button was clicked.",
|
|
4303
|
+
htmlFor: `${idPrefix}-btn-action-${idx}`,
|
|
4304
|
+
value: btn.action_id,
|
|
4305
|
+
placeholder: "e.g. open_details",
|
|
4306
|
+
onChange: (next) => update(idx, { action_id: next })
|
|
4307
|
+
}
|
|
4308
|
+
)
|
|
4156
4309
|
] }, idx);
|
|
4157
4310
|
}),
|
|
4158
4311
|
/* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: addButton, disabled: atLimit, className: "self-start", children: [
|
|
@@ -7980,7 +8133,18 @@ function ButtonAccessoryFields({ button, onChange }) {
|
|
|
7980
8133
|
/* @__PURE__ */ jsx(Label, { htmlFor: `section-acc-btn-style-${s}`, className: "text-xs capitalize", children: s })
|
|
7981
8134
|
] }, s))
|
|
7982
8135
|
}
|
|
7983
|
-
) })
|
|
8136
|
+
) }),
|
|
8137
|
+
/* @__PURE__ */ jsx(
|
|
8138
|
+
AdvancedIdField,
|
|
8139
|
+
{
|
|
8140
|
+
label: "Action ID",
|
|
8141
|
+
help: "Optional. Sent in the interaction payload so your app knows which button was clicked.",
|
|
8142
|
+
htmlFor: "section-acc-btn-action",
|
|
8143
|
+
value: button.action_id,
|
|
8144
|
+
placeholder: "e.g. learn_more",
|
|
8145
|
+
onChange: (next) => onChange({ ...button, action_id: next })
|
|
8146
|
+
}
|
|
8147
|
+
)
|
|
7984
8148
|
] });
|
|
7985
8149
|
}
|
|
7986
8150
|
function ImageAccessoryFields({ image, onChange }) {
|
|
@@ -8452,7 +8616,8 @@ function VideoEditor({ block, onChange }) {
|
|
|
8452
8616
|
function BlockEditor({
|
|
8453
8617
|
block,
|
|
8454
8618
|
errors,
|
|
8455
|
-
onChange
|
|
8619
|
+
onChange,
|
|
8620
|
+
onDone
|
|
8456
8621
|
}) {
|
|
8457
8622
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
8458
8623
|
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("h3", { className: "text-sm font-semibold text-foreground", children: [
|
|
@@ -8460,7 +8625,19 @@ function BlockEditor({
|
|
|
8460
8625
|
labelForBlockType(block.type)
|
|
8461
8626
|
] }) }),
|
|
8462
8627
|
errors && errors.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-0.5 rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: errors.map((err, i) => /* @__PURE__ */ jsx("li", { children: err }, i)) }) : null,
|
|
8463
|
-
dispatch(block, onChange)
|
|
8628
|
+
dispatch(block, onChange),
|
|
8629
|
+
/* @__PURE__ */ jsx(
|
|
8630
|
+
AdvancedIdField,
|
|
8631
|
+
{
|
|
8632
|
+
label: "Block ID",
|
|
8633
|
+
help: "Optional. Unique within the message or view. Slack returns it in interaction payloads.",
|
|
8634
|
+
htmlFor: "block-id",
|
|
8635
|
+
value: block.block_id,
|
|
8636
|
+
placeholder: "e.g. approval_row",
|
|
8637
|
+
onChange: (next) => onChange({ ...block, block_id: next })
|
|
8638
|
+
}
|
|
8639
|
+
),
|
|
8640
|
+
onDone ? /* @__PURE__ */ jsx("div", { className: "flex justify-end border-t pt-3", children: /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: onDone, children: "Done" }) }) : null
|
|
8464
8641
|
] });
|
|
8465
8642
|
}
|
|
8466
8643
|
function dispatch(block, onChange) {
|
|
@@ -8677,7 +8854,8 @@ function BlockRow({
|
|
|
8677
8854
|
{
|
|
8678
8855
|
block: builderBlock.block,
|
|
8679
8856
|
errors,
|
|
8680
|
-
onChange: (next) => onUpdate(builderBlock.id, next)
|
|
8857
|
+
onChange: (next) => onUpdate(builderBlock.id, next),
|
|
8858
|
+
onDone: () => onOpenChange?.(false)
|
|
8681
8859
|
}
|
|
8682
8860
|
) })
|
|
8683
8861
|
] }),
|
|
@@ -8941,7 +9119,15 @@ function ContainerRow({
|
|
|
8941
9119
|
]
|
|
8942
9120
|
}
|
|
8943
9121
|
) }),
|
|
8944
|
-
/* @__PURE__ */ jsx(PopoverContent, { className: "w-[min(32rem,calc(100vw-1.5rem))] sm:w-[32rem]", align: "start", children: /* @__PURE__ */ jsx(
|
|
9122
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "w-[min(32rem,calc(100vw-1.5rem))] sm:w-[32rem]", align: "start", children: /* @__PURE__ */ jsx(
|
|
9123
|
+
BlockEditor,
|
|
9124
|
+
{
|
|
9125
|
+
block,
|
|
9126
|
+
errors,
|
|
9127
|
+
onChange: (next) => onUpdate(id, next),
|
|
9128
|
+
onDone: () => onOpenBlockChange?.(null)
|
|
9129
|
+
}
|
|
9130
|
+
) })
|
|
8945
9131
|
] }),
|
|
8946
9132
|
/* @__PURE__ */ jsx(
|
|
8947
9133
|
"div",
|
|
@@ -9422,6 +9608,10 @@ function formatMessageTs(ts) {
|
|
|
9422
9608
|
}
|
|
9423
9609
|
var SEND_MENU_ITEM = "flex w-full cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-left text-sm text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50";
|
|
9424
9610
|
function Toolbar2({
|
|
9611
|
+
canUndo = false,
|
|
9612
|
+
canRedo = false,
|
|
9613
|
+
onUndo,
|
|
9614
|
+
onRedo,
|
|
9425
9615
|
onClear,
|
|
9426
9616
|
onOpenJson,
|
|
9427
9617
|
onOpenIssues,
|
|
@@ -9535,6 +9725,36 @@ function Toolbar2({
|
|
|
9535
9725
|
) : null
|
|
9536
9726
|
] }),
|
|
9537
9727
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
9728
|
+
onUndo && onRedo ? /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
9729
|
+
/* @__PURE__ */ jsx(
|
|
9730
|
+
Button,
|
|
9731
|
+
{
|
|
9732
|
+
type: "button",
|
|
9733
|
+
variant: "ghost",
|
|
9734
|
+
size: "sm",
|
|
9735
|
+
onClick: onUndo,
|
|
9736
|
+
disabled: !canUndo,
|
|
9737
|
+
"aria-label": "Undo",
|
|
9738
|
+
title: "Undo (Ctrl+Z)",
|
|
9739
|
+
className: "px-2",
|
|
9740
|
+
children: /* @__PURE__ */ jsx(Undo2, { className: "h-3.5 w-3.5" })
|
|
9741
|
+
}
|
|
9742
|
+
),
|
|
9743
|
+
/* @__PURE__ */ jsx(
|
|
9744
|
+
Button,
|
|
9745
|
+
{
|
|
9746
|
+
type: "button",
|
|
9747
|
+
variant: "ghost",
|
|
9748
|
+
size: "sm",
|
|
9749
|
+
onClick: onRedo,
|
|
9750
|
+
disabled: !canRedo,
|
|
9751
|
+
"aria-label": "Redo",
|
|
9752
|
+
title: "Redo (Ctrl+Shift+Z)",
|
|
9753
|
+
className: "px-2",
|
|
9754
|
+
children: /* @__PURE__ */ jsx(Redo2, { className: "h-3.5 w-3.5" })
|
|
9755
|
+
}
|
|
9756
|
+
)
|
|
9757
|
+
] }) : null,
|
|
9538
9758
|
errorCount > 0 ? /* @__PURE__ */ jsxs(
|
|
9539
9759
|
Button,
|
|
9540
9760
|
{
|
|
@@ -9935,7 +10155,22 @@ function BlockKitchen(props) {
|
|
|
9935
10155
|
Boolean(primaryAction && sendEnabled),
|
|
9936
10156
|
"[BlockKitchen] `primaryAction` is only available in compose-only mode \u2014 with the send integration wired, the built-in Send/Update flow owns the toolbar\u2019s primary action; ignoring `primaryAction`."
|
|
9937
10157
|
);
|
|
9938
|
-
const {
|
|
10158
|
+
const {
|
|
10159
|
+
blocks,
|
|
10160
|
+
addBlock,
|
|
10161
|
+
addChild,
|
|
10162
|
+
updateBlock,
|
|
10163
|
+
removeBlock,
|
|
10164
|
+
duplicateBlock,
|
|
10165
|
+
reorderBlock,
|
|
10166
|
+
moveBlock,
|
|
10167
|
+
replaceAll,
|
|
10168
|
+
resetAll,
|
|
10169
|
+
undo,
|
|
10170
|
+
redo,
|
|
10171
|
+
canUndo,
|
|
10172
|
+
canRedo
|
|
10173
|
+
} = useBlockKitchenState({ initialBlocks: seededBlocks, onChange });
|
|
9939
10174
|
const childParentById = useMemo(() => {
|
|
9940
10175
|
const map = /* @__PURE__ */ new Map();
|
|
9941
10176
|
for (const top of blocks) {
|
|
@@ -10051,6 +10286,30 @@ function BlockKitchen(props) {
|
|
|
10051
10286
|
const handleDragCancel = useCallback(() => {
|
|
10052
10287
|
setActivePaletteVariantId(null);
|
|
10053
10288
|
}, []);
|
|
10289
|
+
const handleKeyDown = useCallback(
|
|
10290
|
+
(event) => {
|
|
10291
|
+
if (!(event.metaKey || event.ctrlKey) || event.altKey) {
|
|
10292
|
+
return;
|
|
10293
|
+
}
|
|
10294
|
+
const key = event.key.toLowerCase();
|
|
10295
|
+
const isUndo = key === "z" && !event.shiftKey;
|
|
10296
|
+
const isRedo = key === "y" || key === "z" && event.shiftKey;
|
|
10297
|
+
if (!isUndo && !isRedo) {
|
|
10298
|
+
return;
|
|
10299
|
+
}
|
|
10300
|
+
const target = event.target;
|
|
10301
|
+
if (target && (target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName))) {
|
|
10302
|
+
return;
|
|
10303
|
+
}
|
|
10304
|
+
event.preventDefault();
|
|
10305
|
+
if (isRedo) {
|
|
10306
|
+
if (canRedo) redo();
|
|
10307
|
+
} else if (canUndo) {
|
|
10308
|
+
undo();
|
|
10309
|
+
}
|
|
10310
|
+
},
|
|
10311
|
+
[canRedo, canUndo, redo, undo]
|
|
10312
|
+
);
|
|
10054
10313
|
const activePaletteVariant = activePaletteVariantId ? variantById.get(activePaletteVariantId) : null;
|
|
10055
10314
|
const blockPayloads = blocks.map((b) => b.block);
|
|
10056
10315
|
return /* @__PURE__ */ jsx(BrandThemeScope, { theme, children: /* @__PURE__ */ jsx(CustomEmojiProvider, { customEmojis, children: /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs(
|
|
@@ -10062,91 +10321,102 @@ function BlockKitchen(props) {
|
|
|
10062
10321
|
onDragEnd: handleDragEnd,
|
|
10063
10322
|
onDragCancel: handleDragCancel,
|
|
10064
10323
|
children: [
|
|
10065
|
-
/* @__PURE__ */ jsxs(
|
|
10066
|
-
|
|
10067
|
-
|
|
10068
|
-
|
|
10069
|
-
|
|
10070
|
-
|
|
10071
|
-
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
|
|
10080
|
-
|
|
10081
|
-
|
|
10082
|
-
|
|
10083
|
-
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10324
|
+
/* @__PURE__ */ jsxs(
|
|
10325
|
+
"div",
|
|
10326
|
+
{
|
|
10327
|
+
className: "bk-root flex h-full w-full flex-col overflow-hidden rounded-md border bg-background text-foreground",
|
|
10328
|
+
onKeyDown: handleKeyDown,
|
|
10329
|
+
children: [
|
|
10330
|
+
/* @__PURE__ */ jsx(
|
|
10331
|
+
Toolbar2,
|
|
10332
|
+
{
|
|
10333
|
+
canUndo,
|
|
10334
|
+
canRedo,
|
|
10335
|
+
onUndo: undo,
|
|
10336
|
+
onRedo: redo,
|
|
10337
|
+
onClear: () => replaceAll([]),
|
|
10338
|
+
onOpenJson: () => setJsonOpen(true),
|
|
10339
|
+
onOpenIssues: () => setIssuesOpen(true),
|
|
10340
|
+
onOpenSend: () => setSendOpen(true),
|
|
10341
|
+
onOpenPalette: () => setPaletteOpen(true),
|
|
10342
|
+
canSend: blocks.length > 0,
|
|
10343
|
+
canClear: blocks.length > 0,
|
|
10344
|
+
errorCount: validation.total,
|
|
10345
|
+
previewTheme,
|
|
10346
|
+
onPreviewThemeChange: setUncontrolledPreviewTheme,
|
|
10347
|
+
previewSurface,
|
|
10348
|
+
onPreviewSurfaceChange: setPreviewSurface,
|
|
10349
|
+
allowedSurfaces,
|
|
10350
|
+
showThemeControl: isPreviewThemeControlled ? false : showThemeControl,
|
|
10351
|
+
docsLink,
|
|
10352
|
+
showSend: sendEnabled,
|
|
10353
|
+
primaryAction: !sendEnabled && primaryAction ? {
|
|
10354
|
+
label: primaryAction.label,
|
|
10355
|
+
onClick: () => primaryAction.onClick({
|
|
10356
|
+
blocks: blockPayloads,
|
|
10357
|
+
validation: validationSummary,
|
|
10358
|
+
loadedMessage: activeEditTarget
|
|
10359
|
+
}),
|
|
10360
|
+
disabled: primaryAction.disableWhenInvalid ? !validationSummary.valid : false
|
|
10361
|
+
} : null,
|
|
10362
|
+
sendButtonLabel,
|
|
10363
|
+
loadEnabled,
|
|
10364
|
+
updateEnabled: Boolean(onUpdate),
|
|
10365
|
+
editBadge: activeEditTarget ? {
|
|
10366
|
+
channelLabel: activeEditTarget.channelName ? `#${activeEditTarget.channelName}` : activeEditTarget.channelId,
|
|
10367
|
+
ts: activeEditTarget.ts
|
|
10368
|
+
} : null,
|
|
10369
|
+
onOpenLoad: () => setLoadOpen(true),
|
|
10370
|
+
onOpenUpdate: () => setUpdateOpen(true),
|
|
10371
|
+
onExitEdit: () => {
|
|
10372
|
+
if (sendEnabled) {
|
|
10373
|
+
setEditTarget(null);
|
|
10374
|
+
resetAll([]);
|
|
10375
|
+
setLoadOpen(true);
|
|
10376
|
+
return;
|
|
10377
|
+
}
|
|
10378
|
+
setEditTarget(null);
|
|
10379
|
+
},
|
|
10380
|
+
loadButtonLabel,
|
|
10381
|
+
updateButtonLabel
|
|
10109
10382
|
}
|
|
10110
|
-
|
|
10111
|
-
|
|
10112
|
-
|
|
10113
|
-
|
|
10114
|
-
|
|
10115
|
-
|
|
10116
|
-
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
|
|
10133
|
-
|
|
10134
|
-
|
|
10135
|
-
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
)
|
|
10148
|
-
] })
|
|
10149
|
-
] }),
|
|
10383
|
+
),
|
|
10384
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 items-stretch", children: [
|
|
10385
|
+
/* @__PURE__ */ jsx("div", { className: "hidden min-h-0 md:flex", children: /* @__PURE__ */ jsx(
|
|
10386
|
+
Palette,
|
|
10387
|
+
{
|
|
10388
|
+
onAddBlock: (block) => addBlock(block),
|
|
10389
|
+
sections: paletteSections,
|
|
10390
|
+
showSearch: showPaletteSearch,
|
|
10391
|
+
searchPlaceholder: paletteSearchPlaceholder,
|
|
10392
|
+
defaultOpenSections
|
|
10393
|
+
}
|
|
10394
|
+
) }),
|
|
10395
|
+
/* @__PURE__ */ jsx(
|
|
10396
|
+
Surface,
|
|
10397
|
+
{
|
|
10398
|
+
blocks,
|
|
10399
|
+
workspaceName,
|
|
10400
|
+
authorName: activeEditTarget?.username,
|
|
10401
|
+
authorIcon: activeEditTarget?.iconUrl,
|
|
10402
|
+
previewHooks: mergedPreviewHooks,
|
|
10403
|
+
previewTheme,
|
|
10404
|
+
previewSurface,
|
|
10405
|
+
errorsByBlockId: validation.byBlockId,
|
|
10406
|
+
openBlockId,
|
|
10407
|
+
onOpenBlockChange: setOpenBlockId,
|
|
10408
|
+
onUpdate: updateBlock,
|
|
10409
|
+
onDuplicate: duplicateBlock,
|
|
10410
|
+
onDelete: removeBlock,
|
|
10411
|
+
onReorder: reorderBlock,
|
|
10412
|
+
isPaletteDrag: activePaletteVariant !== null,
|
|
10413
|
+
onOpenPalette: () => setPaletteOpen(true)
|
|
10414
|
+
}
|
|
10415
|
+
)
|
|
10416
|
+
] })
|
|
10417
|
+
]
|
|
10418
|
+
}
|
|
10419
|
+
),
|
|
10150
10420
|
/* @__PURE__ */ jsx(DragOverlay, { dropAnimation: null, children: activePaletteVariant ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 rounded border bg-background px-1.5 py-1 text-xs text-foreground shadow-md", children: [
|
|
10151
10421
|
/* @__PURE__ */ jsx(GripVertical, { className: "h-3 w-3 shrink-0" }),
|
|
10152
10422
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: activePaletteVariant.label })
|
|
@@ -10223,13 +10493,13 @@ function BlockKitchen(props) {
|
|
|
10223
10493
|
loadRecentMessages: loading.loadRecentMessages,
|
|
10224
10494
|
loadChannels: recentChannelSource,
|
|
10225
10495
|
onLoaded: (result) => {
|
|
10226
|
-
|
|
10496
|
+
resetAll(result.blocks);
|
|
10227
10497
|
setEditTarget(toLoadedMessage(result));
|
|
10228
10498
|
setLoadOpen(false);
|
|
10229
10499
|
},
|
|
10230
10500
|
onOpenAsNew: (loadedBlocks) => {
|
|
10231
10501
|
if (loadedBlocks) {
|
|
10232
|
-
|
|
10502
|
+
resetAll(loadedBlocks);
|
|
10233
10503
|
}
|
|
10234
10504
|
setEditTarget(null);
|
|
10235
10505
|
setLoadOpen(false);
|