@tightknitai/block-kitchen 0.10.0 → 0.10.1
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/index.cjs +403 -198
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +404 -199
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -2066,6 +2066,69 @@ function useBlockKitValidation(blocks, surface) {
|
|
|
2066
2066
|
}, [blocks, surface]);
|
|
2067
2067
|
return state;
|
|
2068
2068
|
}
|
|
2069
|
+
var MAX_HISTORY = 20;
|
|
2070
|
+
function useHistoryState(initial) {
|
|
2071
|
+
const [record, setRecord] = React.useState(() => ({
|
|
2072
|
+
past: [],
|
|
2073
|
+
present: typeof initial === "function" ? initial() : initial,
|
|
2074
|
+
future: [],
|
|
2075
|
+
lastTag: null
|
|
2076
|
+
}));
|
|
2077
|
+
const commit = React.useCallback((updater, options) => {
|
|
2078
|
+
const tag = options?.tag ?? null;
|
|
2079
|
+
setRecord((h) => {
|
|
2080
|
+
const next = typeof updater === "function" ? updater(h.present) : updater;
|
|
2081
|
+
if (Object.is(next, h.present)) {
|
|
2082
|
+
return h;
|
|
2083
|
+
}
|
|
2084
|
+
if (tag !== null && h.lastTag === tag) {
|
|
2085
|
+
return { ...h, present: next, future: [] };
|
|
2086
|
+
}
|
|
2087
|
+
const past = [...h.past, h.present];
|
|
2088
|
+
return {
|
|
2089
|
+
past: past.length > MAX_HISTORY ? past.slice(past.length - MAX_HISTORY) : past,
|
|
2090
|
+
present: next,
|
|
2091
|
+
future: [],
|
|
2092
|
+
lastTag: tag
|
|
2093
|
+
};
|
|
2094
|
+
});
|
|
2095
|
+
}, []);
|
|
2096
|
+
const undo = React.useCallback(() => {
|
|
2097
|
+
setRecord((h) => {
|
|
2098
|
+
if (h.past.length === 0) {
|
|
2099
|
+
return h;
|
|
2100
|
+
}
|
|
2101
|
+
const previous = h.past[h.past.length - 1];
|
|
2102
|
+
return { past: h.past.slice(0, -1), present: previous, future: [h.present, ...h.future], lastTag: null };
|
|
2103
|
+
});
|
|
2104
|
+
}, []);
|
|
2105
|
+
const redo = React.useCallback(() => {
|
|
2106
|
+
setRecord((h) => {
|
|
2107
|
+
if (h.future.length === 0) {
|
|
2108
|
+
return h;
|
|
2109
|
+
}
|
|
2110
|
+
const [next, ...rest] = h.future;
|
|
2111
|
+
return { past: [...h.past, h.present], present: next, future: rest, lastTag: null };
|
|
2112
|
+
});
|
|
2113
|
+
}, []);
|
|
2114
|
+
const reset = React.useCallback((next) => {
|
|
2115
|
+
setRecord({ past: [], present: next, future: [], lastTag: null });
|
|
2116
|
+
}, []);
|
|
2117
|
+
return React.useMemo(
|
|
2118
|
+
() => ({
|
|
2119
|
+
present: record.present,
|
|
2120
|
+
canUndo: record.past.length > 0,
|
|
2121
|
+
canRedo: record.future.length > 0,
|
|
2122
|
+
commit,
|
|
2123
|
+
undo,
|
|
2124
|
+
redo,
|
|
2125
|
+
reset
|
|
2126
|
+
}),
|
|
2127
|
+
[record, commit, undo, redo, reset]
|
|
2128
|
+
);
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
// src/state/use-block-kitchen-state.ts
|
|
2069
2132
|
function mirror(node) {
|
|
2070
2133
|
if (!node.children) {
|
|
2071
2134
|
return node;
|
|
@@ -2116,7 +2179,15 @@ function useBlockKitchenState({
|
|
|
2116
2179
|
initialBlocks,
|
|
2117
2180
|
onChange
|
|
2118
2181
|
} = {}) {
|
|
2119
|
-
const
|
|
2182
|
+
const {
|
|
2183
|
+
present: blocks,
|
|
2184
|
+
commit,
|
|
2185
|
+
undo,
|
|
2186
|
+
redo,
|
|
2187
|
+
reset,
|
|
2188
|
+
canUndo,
|
|
2189
|
+
canRedo
|
|
2190
|
+
} = useHistoryState(() => (initialBlocks ?? []).map(wrap));
|
|
2120
2191
|
const onChangeRef = React.useRef(onChange);
|
|
2121
2192
|
React.useEffect(() => {
|
|
2122
2193
|
onChangeRef.current = onChange;
|
|
@@ -2129,121 +2200,155 @@ function useBlockKitchenState({
|
|
|
2129
2200
|
}
|
|
2130
2201
|
onChangeRef.current?.(blocks.map((b) => b.block));
|
|
2131
2202
|
}, [blocks]);
|
|
2132
|
-
const addBlock = React.useCallback(
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
next.splice(idx, 0, wrap(block));
|
|
2137
|
-
return next;
|
|
2138
|
-
});
|
|
2139
|
-
}, []);
|
|
2140
|
-
const addChild = React.useCallback((parentId, block, atIndex) => {
|
|
2141
|
-
if (!isContainerChildType(block.type)) {
|
|
2142
|
-
return;
|
|
2143
|
-
}
|
|
2144
|
-
setBlocks(
|
|
2145
|
-
(prev) => withChildren(prev, parentId, (children) => {
|
|
2146
|
-
if (children.length >= MAX_CONTAINER_CHILDREN) {
|
|
2147
|
-
return children;
|
|
2148
|
-
}
|
|
2149
|
-
const next = [...children];
|
|
2203
|
+
const addBlock = React.useCallback(
|
|
2204
|
+
(block, atIndex) => {
|
|
2205
|
+
commit((prev) => {
|
|
2206
|
+
const next = [...prev];
|
|
2150
2207
|
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
2151
2208
|
next.splice(idx, 0, wrap(block));
|
|
2152
2209
|
return next;
|
|
2153
|
-
})
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
}
|
|
2162
|
-
if (b.children?.some((c) => c.id === id)) {
|
|
2163
|
-
return mirror({ ...b, children: b.children.map((c) => c.id === id ? applyUpdate(c, block) : c) });
|
|
2164
|
-
}
|
|
2165
|
-
return b;
|
|
2166
|
-
})
|
|
2167
|
-
);
|
|
2168
|
-
}, []);
|
|
2169
|
-
const removeBlock = React.useCallback((id) => {
|
|
2170
|
-
setBlocks((prev) => {
|
|
2171
|
-
if (prev.some((b) => b.id === id)) {
|
|
2172
|
-
return prev.filter((b) => b.id !== id);
|
|
2210
|
+
});
|
|
2211
|
+
},
|
|
2212
|
+
[commit]
|
|
2213
|
+
);
|
|
2214
|
+
const addChild = React.useCallback(
|
|
2215
|
+
(parentId, block, atIndex) => {
|
|
2216
|
+
if (!isContainerChildType(block.type)) {
|
|
2217
|
+
return;
|
|
2173
2218
|
}
|
|
2174
|
-
|
|
2175
|
-
(
|
|
2219
|
+
commit(
|
|
2220
|
+
(prev) => withChildren(prev, parentId, (children) => {
|
|
2221
|
+
if (children.length >= MAX_CONTAINER_CHILDREN) {
|
|
2222
|
+
return children;
|
|
2223
|
+
}
|
|
2224
|
+
const next = [...children];
|
|
2225
|
+
const idx = atIndex === void 0 ? next.length : Math.max(0, Math.min(atIndex, next.length));
|
|
2226
|
+
next.splice(idx, 0, wrap(block));
|
|
2227
|
+
return next;
|
|
2228
|
+
})
|
|
2176
2229
|
);
|
|
2177
|
-
}
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2230
|
+
},
|
|
2231
|
+
[commit]
|
|
2232
|
+
);
|
|
2233
|
+
const updateBlock = React.useCallback(
|
|
2234
|
+
(id, block) => {
|
|
2235
|
+
commit(
|
|
2236
|
+
(prev) => prev.map((b) => {
|
|
2237
|
+
if (b.id === id) {
|
|
2238
|
+
return applyUpdate(b, block);
|
|
2239
|
+
}
|
|
2240
|
+
if (b.children?.some((c) => c.id === id)) {
|
|
2241
|
+
return mirror({ ...b, children: b.children.map((c) => c.id === id ? applyUpdate(c, block) : c) });
|
|
2242
|
+
}
|
|
2243
|
+
return b;
|
|
2244
|
+
}),
|
|
2245
|
+
// Coalesce a run of edits to the same block (every keystroke in an
|
|
2246
|
+
// editor field lands here) into a single undo step. Editing a
|
|
2247
|
+
// different block, or any structural change, starts a new step.
|
|
2248
|
+
{ tag: `update:${id}` }
|
|
2249
|
+
);
|
|
2250
|
+
},
|
|
2251
|
+
[commit]
|
|
2252
|
+
);
|
|
2253
|
+
const removeBlock = React.useCallback(
|
|
2254
|
+
(id) => {
|
|
2255
|
+
commit((prev) => {
|
|
2256
|
+
if (prev.some((b) => b.id === id)) {
|
|
2257
|
+
return prev.filter((b) => b.id !== id);
|
|
2258
|
+
}
|
|
2259
|
+
return prev.map(
|
|
2260
|
+
(b) => b.children?.some((c) => c.id === id) ? mirror({ ...b, children: b.children.filter((c) => c.id !== id) }) : b
|
|
2261
|
+
);
|
|
2194
2262
|
});
|
|
2195
|
-
}
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
const reorder = (list) => {
|
|
2204
|
-
const next = [...list];
|
|
2205
|
-
const [moved] = next.splice(loc.index, 1);
|
|
2206
|
-
next.splice(Math.max(0, Math.min(toIndex, next.length)), 0, moved);
|
|
2207
|
-
return next;
|
|
2208
|
-
};
|
|
2209
|
-
if (loc.kind === "top") {
|
|
2210
|
-
return reorder(prev);
|
|
2211
|
-
}
|
|
2212
|
-
return withChildren(prev, loc.parentId, reorder);
|
|
2213
|
-
});
|
|
2214
|
-
}, []);
|
|
2215
|
-
const moveBlock = React.useCallback((activeId, target) => {
|
|
2216
|
-
setBlocks((prev) => {
|
|
2217
|
-
const loc = locate(prev, activeId);
|
|
2218
|
-
if (!loc) {
|
|
2219
|
-
return prev;
|
|
2220
|
-
}
|
|
2221
|
-
const moved = loc.kind === "top" ? prev[loc.index] : prev.find((b) => b.id === loc.parentId)?.children?.[loc.index];
|
|
2222
|
-
if (!moved) {
|
|
2223
|
-
return prev;
|
|
2224
|
-
}
|
|
2225
|
-
if (target.kind === "container") {
|
|
2226
|
-
if (moved.children || !isContainerChildType(moved.block.type)) {
|
|
2263
|
+
},
|
|
2264
|
+
[commit]
|
|
2265
|
+
);
|
|
2266
|
+
const duplicateBlock = React.useCallback(
|
|
2267
|
+
(id) => {
|
|
2268
|
+
commit((prev) => {
|
|
2269
|
+
const loc = locate(prev, id);
|
|
2270
|
+
if (!loc) {
|
|
2227
2271
|
return prev;
|
|
2228
2272
|
}
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2273
|
+
if (loc.kind === "top") {
|
|
2274
|
+
const next = [...prev];
|
|
2275
|
+
next.splice(loc.index + 1, 0, cloneNode(prev[loc.index]));
|
|
2276
|
+
return next;
|
|
2277
|
+
}
|
|
2278
|
+
return withChildren(prev, loc.parentId, (children) => {
|
|
2279
|
+
const next = [...children];
|
|
2280
|
+
next.splice(loc.index + 1, 0, cloneNode(children[loc.index]));
|
|
2281
|
+
return next;
|
|
2282
|
+
});
|
|
2283
|
+
});
|
|
2284
|
+
},
|
|
2285
|
+
[commit]
|
|
2286
|
+
);
|
|
2287
|
+
const reorderBlock = React.useCallback(
|
|
2288
|
+
(fromId, toIndex) => {
|
|
2289
|
+
commit((prev) => {
|
|
2290
|
+
const loc = locate(prev, fromId);
|
|
2291
|
+
if (!loc) {
|
|
2232
2292
|
return prev;
|
|
2233
2293
|
}
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2294
|
+
const reorder = (list) => {
|
|
2295
|
+
const next = [...list];
|
|
2296
|
+
const [moved] = next.splice(loc.index, 1);
|
|
2297
|
+
next.splice(Math.max(0, Math.min(toIndex, next.length)), 0, moved);
|
|
2298
|
+
return next;
|
|
2299
|
+
};
|
|
2300
|
+
if (loc.kind === "top") {
|
|
2301
|
+
return reorder(prev);
|
|
2302
|
+
}
|
|
2303
|
+
return withChildren(prev, loc.parentId, reorder);
|
|
2304
|
+
});
|
|
2305
|
+
},
|
|
2306
|
+
[commit]
|
|
2307
|
+
);
|
|
2308
|
+
const moveBlock = React.useCallback(
|
|
2309
|
+
(activeId, target) => {
|
|
2310
|
+
commit((prev) => {
|
|
2311
|
+
const loc = locate(prev, activeId);
|
|
2312
|
+
if (!loc) {
|
|
2313
|
+
return prev;
|
|
2314
|
+
}
|
|
2315
|
+
const moved = loc.kind === "top" ? prev[loc.index] : prev.find((b) => b.id === loc.parentId)?.children?.[loc.index];
|
|
2316
|
+
if (!moved) {
|
|
2317
|
+
return prev;
|
|
2318
|
+
}
|
|
2319
|
+
if (target.kind === "container") {
|
|
2320
|
+
if (moved.children || !isContainerChildType(moved.block.type)) {
|
|
2321
|
+
return prev;
|
|
2322
|
+
}
|
|
2323
|
+
const sameContainer = loc.kind === "child" && loc.parentId === target.parentId;
|
|
2324
|
+
const destCount = prev.find((b) => b.id === target.parentId)?.children?.length ?? 0;
|
|
2325
|
+
if (!sameContainer && destCount >= MAX_CONTAINER_CHILDREN) {
|
|
2326
|
+
return prev;
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
const detached = loc.kind === "top" ? prev.filter((_, i) => i !== loc.index) : withChildren(prev, loc.parentId, (children) => children.filter((_, i) => i !== loc.index));
|
|
2330
|
+
const insert = (list) => {
|
|
2331
|
+
const next = [...list];
|
|
2332
|
+
next.splice(Math.max(0, Math.min(target.index, next.length)), 0, moved);
|
|
2333
|
+
return next;
|
|
2334
|
+
};
|
|
2335
|
+
return target.kind === "container" ? withChildren(detached, target.parentId, insert) : insert(detached);
|
|
2336
|
+
});
|
|
2337
|
+
},
|
|
2338
|
+
[commit]
|
|
2339
|
+
);
|
|
2340
|
+
const replaceAll = React.useCallback(
|
|
2341
|
+
(newBlocks) => {
|
|
2342
|
+
commit(sanitizeBlocks(newBlocks).map(wrap));
|
|
2343
|
+
},
|
|
2344
|
+
[commit]
|
|
2345
|
+
);
|
|
2346
|
+
const resetAll = React.useCallback(
|
|
2347
|
+
(newBlocks) => {
|
|
2348
|
+
reset(sanitizeBlocks(newBlocks).map(wrap));
|
|
2349
|
+
},
|
|
2350
|
+
[reset]
|
|
2351
|
+
);
|
|
2247
2352
|
return {
|
|
2248
2353
|
blocks,
|
|
2249
2354
|
addBlock,
|
|
@@ -2253,7 +2358,12 @@ function useBlockKitchenState({
|
|
|
2253
2358
|
duplicateBlock,
|
|
2254
2359
|
reorderBlock,
|
|
2255
2360
|
moveBlock,
|
|
2256
|
-
replaceAll
|
|
2361
|
+
replaceAll,
|
|
2362
|
+
resetAll,
|
|
2363
|
+
undo,
|
|
2364
|
+
redo,
|
|
2365
|
+
canUndo,
|
|
2366
|
+
canRedo
|
|
2257
2367
|
};
|
|
2258
2368
|
}
|
|
2259
2369
|
function useDevWarning(condition, message) {
|
|
@@ -8482,7 +8592,8 @@ function VideoEditor({ block, onChange }) {
|
|
|
8482
8592
|
function BlockEditor({
|
|
8483
8593
|
block,
|
|
8484
8594
|
errors,
|
|
8485
|
-
onChange
|
|
8595
|
+
onChange,
|
|
8596
|
+
onDone
|
|
8486
8597
|
}) {
|
|
8487
8598
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
8488
8599
|
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-sm font-semibold text-foreground", children: [
|
|
@@ -8490,7 +8601,8 @@ function BlockEditor({
|
|
|
8490
8601
|
labelForBlockType(block.type)
|
|
8491
8602
|
] }) }),
|
|
8492
8603
|
errors && errors.length > 0 ? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("li", { children: err }, i)) }) : null,
|
|
8493
|
-
dispatch(block, onChange)
|
|
8604
|
+
dispatch(block, onChange),
|
|
8605
|
+
onDone ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end border-t pt-3", children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", size: "sm", onClick: onDone, children: "Done" }) }) : null
|
|
8494
8606
|
] });
|
|
8495
8607
|
}
|
|
8496
8608
|
function dispatch(block, onChange) {
|
|
@@ -8707,7 +8819,8 @@ function BlockRow({
|
|
|
8707
8819
|
{
|
|
8708
8820
|
block: builderBlock.block,
|
|
8709
8821
|
errors,
|
|
8710
|
-
onChange: (next) => onUpdate(builderBlock.id, next)
|
|
8822
|
+
onChange: (next) => onUpdate(builderBlock.id, next),
|
|
8823
|
+
onDone: () => onOpenChange?.(false)
|
|
8711
8824
|
}
|
|
8712
8825
|
) })
|
|
8713
8826
|
] }),
|
|
@@ -8971,7 +9084,15 @@ function ContainerRow({
|
|
|
8971
9084
|
]
|
|
8972
9085
|
}
|
|
8973
9086
|
) }),
|
|
8974
|
-
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { className: "w-[min(32rem,calc(100vw-1.5rem))] sm:w-[32rem]", align: "start", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9087
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { className: "w-[min(32rem,calc(100vw-1.5rem))] sm:w-[32rem]", align: "start", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9088
|
+
BlockEditor,
|
|
9089
|
+
{
|
|
9090
|
+
block,
|
|
9091
|
+
errors,
|
|
9092
|
+
onChange: (next) => onUpdate(id, next),
|
|
9093
|
+
onDone: () => onOpenBlockChange?.(null)
|
|
9094
|
+
}
|
|
9095
|
+
) })
|
|
8975
9096
|
] }),
|
|
8976
9097
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8977
9098
|
"div",
|
|
@@ -9452,6 +9573,10 @@ function formatMessageTs(ts) {
|
|
|
9452
9573
|
}
|
|
9453
9574
|
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";
|
|
9454
9575
|
function Toolbar2({
|
|
9576
|
+
canUndo = false,
|
|
9577
|
+
canRedo = false,
|
|
9578
|
+
onUndo,
|
|
9579
|
+
onRedo,
|
|
9455
9580
|
onClear,
|
|
9456
9581
|
onOpenJson,
|
|
9457
9582
|
onOpenIssues,
|
|
@@ -9565,6 +9690,36 @@ function Toolbar2({
|
|
|
9565
9690
|
) : null
|
|
9566
9691
|
] }),
|
|
9567
9692
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
9693
|
+
onUndo && onRedo ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
|
|
9694
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9695
|
+
Button,
|
|
9696
|
+
{
|
|
9697
|
+
type: "button",
|
|
9698
|
+
variant: "ghost",
|
|
9699
|
+
size: "sm",
|
|
9700
|
+
onClick: onUndo,
|
|
9701
|
+
disabled: !canUndo,
|
|
9702
|
+
"aria-label": "Undo",
|
|
9703
|
+
title: "Undo (Ctrl+Z)",
|
|
9704
|
+
className: "px-2",
|
|
9705
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo2, { className: "h-3.5 w-3.5" })
|
|
9706
|
+
}
|
|
9707
|
+
),
|
|
9708
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9709
|
+
Button,
|
|
9710
|
+
{
|
|
9711
|
+
type: "button",
|
|
9712
|
+
variant: "ghost",
|
|
9713
|
+
size: "sm",
|
|
9714
|
+
onClick: onRedo,
|
|
9715
|
+
disabled: !canRedo,
|
|
9716
|
+
"aria-label": "Redo",
|
|
9717
|
+
title: "Redo (Ctrl+Shift+Z)",
|
|
9718
|
+
className: "px-2",
|
|
9719
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Redo2, { className: "h-3.5 w-3.5" })
|
|
9720
|
+
}
|
|
9721
|
+
)
|
|
9722
|
+
] }) : null,
|
|
9568
9723
|
errorCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9569
9724
|
Button,
|
|
9570
9725
|
{
|
|
@@ -9965,7 +10120,22 @@ function BlockKitchen(props) {
|
|
|
9965
10120
|
Boolean(primaryAction && sendEnabled),
|
|
9966
10121
|
"[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`."
|
|
9967
10122
|
);
|
|
9968
|
-
const {
|
|
10123
|
+
const {
|
|
10124
|
+
blocks,
|
|
10125
|
+
addBlock,
|
|
10126
|
+
addChild,
|
|
10127
|
+
updateBlock,
|
|
10128
|
+
removeBlock,
|
|
10129
|
+
duplicateBlock,
|
|
10130
|
+
reorderBlock,
|
|
10131
|
+
moveBlock,
|
|
10132
|
+
replaceAll,
|
|
10133
|
+
resetAll,
|
|
10134
|
+
undo,
|
|
10135
|
+
redo,
|
|
10136
|
+
canUndo,
|
|
10137
|
+
canRedo
|
|
10138
|
+
} = useBlockKitchenState({ initialBlocks: seededBlocks, onChange });
|
|
9969
10139
|
const childParentById = React.useMemo(() => {
|
|
9970
10140
|
const map = /* @__PURE__ */ new Map();
|
|
9971
10141
|
for (const top of blocks) {
|
|
@@ -10081,6 +10251,30 @@ function BlockKitchen(props) {
|
|
|
10081
10251
|
const handleDragCancel = React.useCallback(() => {
|
|
10082
10252
|
setActivePaletteVariantId(null);
|
|
10083
10253
|
}, []);
|
|
10254
|
+
const handleKeyDown = React.useCallback(
|
|
10255
|
+
(event) => {
|
|
10256
|
+
if (!(event.metaKey || event.ctrlKey) || event.altKey) {
|
|
10257
|
+
return;
|
|
10258
|
+
}
|
|
10259
|
+
const key = event.key.toLowerCase();
|
|
10260
|
+
const isUndo = key === "z" && !event.shiftKey;
|
|
10261
|
+
const isRedo = key === "y" || key === "z" && event.shiftKey;
|
|
10262
|
+
if (!isUndo && !isRedo) {
|
|
10263
|
+
return;
|
|
10264
|
+
}
|
|
10265
|
+
const target = event.target;
|
|
10266
|
+
if (target && (target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName))) {
|
|
10267
|
+
return;
|
|
10268
|
+
}
|
|
10269
|
+
event.preventDefault();
|
|
10270
|
+
if (isRedo) {
|
|
10271
|
+
if (canRedo) redo();
|
|
10272
|
+
} else if (canUndo) {
|
|
10273
|
+
undo();
|
|
10274
|
+
}
|
|
10275
|
+
},
|
|
10276
|
+
[canRedo, canUndo, redo, undo]
|
|
10277
|
+
);
|
|
10084
10278
|
const activePaletteVariant = activePaletteVariantId ? variantById.get(activePaletteVariantId) : null;
|
|
10085
10279
|
const blockPayloads = blocks.map((b) => b.block);
|
|
10086
10280
|
return /* @__PURE__ */ jsxRuntime.jsx(BrandThemeScope, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(CustomEmojiProvider, { customEmojis, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -10092,91 +10286,102 @@ function BlockKitchen(props) {
|
|
|
10092
10286
|
onDragEnd: handleDragEnd,
|
|
10093
10287
|
onDragCancel: handleDragCancel,
|
|
10094
10288
|
children: [
|
|
10095
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
|
|
10104
|
-
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
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
|
-
|
|
10289
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10290
|
+
"div",
|
|
10291
|
+
{
|
|
10292
|
+
className: "bk-root flex h-full w-full flex-col overflow-hidden rounded-md border bg-background text-foreground",
|
|
10293
|
+
onKeyDown: handleKeyDown,
|
|
10294
|
+
children: [
|
|
10295
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10296
|
+
Toolbar2,
|
|
10297
|
+
{
|
|
10298
|
+
canUndo,
|
|
10299
|
+
canRedo,
|
|
10300
|
+
onUndo: undo,
|
|
10301
|
+
onRedo: redo,
|
|
10302
|
+
onClear: () => replaceAll([]),
|
|
10303
|
+
onOpenJson: () => setJsonOpen(true),
|
|
10304
|
+
onOpenIssues: () => setIssuesOpen(true),
|
|
10305
|
+
onOpenSend: () => setSendOpen(true),
|
|
10306
|
+
onOpenPalette: () => setPaletteOpen(true),
|
|
10307
|
+
canSend: blocks.length > 0,
|
|
10308
|
+
canClear: blocks.length > 0,
|
|
10309
|
+
errorCount: validation.total,
|
|
10310
|
+
previewTheme,
|
|
10311
|
+
onPreviewThemeChange: setUncontrolledPreviewTheme,
|
|
10312
|
+
previewSurface,
|
|
10313
|
+
onPreviewSurfaceChange: setPreviewSurface,
|
|
10314
|
+
allowedSurfaces,
|
|
10315
|
+
showThemeControl: isPreviewThemeControlled ? false : showThemeControl,
|
|
10316
|
+
docsLink,
|
|
10317
|
+
showSend: sendEnabled,
|
|
10318
|
+
primaryAction: !sendEnabled && primaryAction ? {
|
|
10319
|
+
label: primaryAction.label,
|
|
10320
|
+
onClick: () => primaryAction.onClick({
|
|
10321
|
+
blocks: blockPayloads,
|
|
10322
|
+
validation: validationSummary,
|
|
10323
|
+
loadedMessage: activeEditTarget
|
|
10324
|
+
}),
|
|
10325
|
+
disabled: primaryAction.disableWhenInvalid ? !validationSummary.valid : false
|
|
10326
|
+
} : null,
|
|
10327
|
+
sendButtonLabel,
|
|
10328
|
+
loadEnabled,
|
|
10329
|
+
updateEnabled: Boolean(onUpdate),
|
|
10330
|
+
editBadge: activeEditTarget ? {
|
|
10331
|
+
channelLabel: activeEditTarget.channelName ? `#${activeEditTarget.channelName}` : activeEditTarget.channelId,
|
|
10332
|
+
ts: activeEditTarget.ts
|
|
10333
|
+
} : null,
|
|
10334
|
+
onOpenLoad: () => setLoadOpen(true),
|
|
10335
|
+
onOpenUpdate: () => setUpdateOpen(true),
|
|
10336
|
+
onExitEdit: () => {
|
|
10337
|
+
if (sendEnabled) {
|
|
10338
|
+
setEditTarget(null);
|
|
10339
|
+
resetAll([]);
|
|
10340
|
+
setLoadOpen(true);
|
|
10341
|
+
return;
|
|
10342
|
+
}
|
|
10343
|
+
setEditTarget(null);
|
|
10344
|
+
},
|
|
10345
|
+
loadButtonLabel,
|
|
10346
|
+
updateButtonLabel
|
|
10139
10347
|
}
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
|
|
10162
|
-
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
)
|
|
10178
|
-
] })
|
|
10179
|
-
] }),
|
|
10348
|
+
),
|
|
10349
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 items-stretch", children: [
|
|
10350
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden min-h-0 md:flex", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10351
|
+
Palette,
|
|
10352
|
+
{
|
|
10353
|
+
onAddBlock: (block) => addBlock(block),
|
|
10354
|
+
sections: paletteSections,
|
|
10355
|
+
showSearch: showPaletteSearch,
|
|
10356
|
+
searchPlaceholder: paletteSearchPlaceholder,
|
|
10357
|
+
defaultOpenSections
|
|
10358
|
+
}
|
|
10359
|
+
) }),
|
|
10360
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10361
|
+
Surface,
|
|
10362
|
+
{
|
|
10363
|
+
blocks,
|
|
10364
|
+
workspaceName,
|
|
10365
|
+
authorName: activeEditTarget?.username,
|
|
10366
|
+
authorIcon: activeEditTarget?.iconUrl,
|
|
10367
|
+
previewHooks: mergedPreviewHooks,
|
|
10368
|
+
previewTheme,
|
|
10369
|
+
previewSurface,
|
|
10370
|
+
errorsByBlockId: validation.byBlockId,
|
|
10371
|
+
openBlockId,
|
|
10372
|
+
onOpenBlockChange: setOpenBlockId,
|
|
10373
|
+
onUpdate: updateBlock,
|
|
10374
|
+
onDuplicate: duplicateBlock,
|
|
10375
|
+
onDelete: removeBlock,
|
|
10376
|
+
onReorder: reorderBlock,
|
|
10377
|
+
isPaletteDrag: activePaletteVariant !== null,
|
|
10378
|
+
onOpenPalette: () => setPaletteOpen(true)
|
|
10379
|
+
}
|
|
10380
|
+
)
|
|
10381
|
+
] })
|
|
10382
|
+
]
|
|
10383
|
+
}
|
|
10384
|
+
),
|
|
10180
10385
|
/* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { dropAnimation: null, children: activePaletteVariant ? /* @__PURE__ */ jsxRuntime.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: [
|
|
10181
10386
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, { className: "h-3 w-3 shrink-0" }),
|
|
10182
10387
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: activePaletteVariant.label })
|
|
@@ -10253,13 +10458,13 @@ function BlockKitchen(props) {
|
|
|
10253
10458
|
loadRecentMessages: loading.loadRecentMessages,
|
|
10254
10459
|
loadChannels: recentChannelSource,
|
|
10255
10460
|
onLoaded: (result) => {
|
|
10256
|
-
|
|
10461
|
+
resetAll(result.blocks);
|
|
10257
10462
|
setEditTarget(toLoadedMessage(result));
|
|
10258
10463
|
setLoadOpen(false);
|
|
10259
10464
|
},
|
|
10260
10465
|
onOpenAsNew: (loadedBlocks) => {
|
|
10261
10466
|
if (loadedBlocks) {
|
|
10262
|
-
|
|
10467
|
+
resetAll(loadedBlocks);
|
|
10263
10468
|
}
|
|
10264
10469
|
setEditTarget(null);
|
|
10265
10470
|
setLoadOpen(false);
|