@tightknitai/block-kitchen 0.10.24 → 0.10.25

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/index.cjs CHANGED
@@ -1817,6 +1817,35 @@ function labelForBlockType(type) {
1817
1817
  return "Data Table";
1818
1818
  }
1819
1819
  }
1820
+ function historyShortcutOf(event) {
1821
+ if (!(event.metaKey || event.ctrlKey) || event.altKey) {
1822
+ return null;
1823
+ }
1824
+ const key = event.key.toLowerCase();
1825
+ if (key === "z") {
1826
+ return event.shiftKey ? "redo" : "undo";
1827
+ }
1828
+ return key === "y" ? "redo" : null;
1829
+ }
1830
+ function isTextEditingTarget(target) {
1831
+ if (!(target instanceof HTMLElement)) {
1832
+ return false;
1833
+ }
1834
+ return target.isContentEditable || // jsdom has no `isContentEditable`, so check the attribute too.
1835
+ target.closest('[contenteditable=""], [contenteditable="true"], [contenteditable="plaintext-only"]') !== null || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName);
1836
+ }
1837
+ function isApplePlatform() {
1838
+ if (typeof navigator === "undefined") {
1839
+ return false;
1840
+ }
1841
+ const { userAgentData } = navigator;
1842
+ return /mac|iphone|ipad|ipod/i.test(userAgentData?.platform ?? navigator.platform ?? "");
1843
+ }
1844
+ var subscribeToNothing = () => () => {
1845
+ };
1846
+ function useIsApplePlatform() {
1847
+ return React.useSyncExternalStore(subscribeToNothing, isApplePlatform, () => false);
1848
+ }
1820
1849
  var Sheet = DialogPrimitive__namespace.Root;
1821
1850
  var SheetOverlay = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1822
1851
  DialogPrimitive__namespace.Overlay,
@@ -1898,6 +1927,16 @@ function useIsMobile() {
1898
1927
  }, []);
1899
1928
  return isMobile;
1900
1929
  }
1930
+ var BlockEditorsContext = React.createContext([]);
1931
+ function BlockEditorsProvider({
1932
+ blockEditors,
1933
+ children
1934
+ }) {
1935
+ return /* @__PURE__ */ jsxRuntime.jsx(BlockEditorsContext.Provider, { value: blockEditors ?? [], children });
1936
+ }
1937
+ function useCustomBlockEditor(block) {
1938
+ return React.useContext(BlockEditorsContext).find((editor) => editor.match(block));
1939
+ }
1901
1940
  var EMPTY = {
1902
1941
  customEmojis: [],
1903
1942
  byName: /* @__PURE__ */ new Map()
@@ -4239,6 +4278,7 @@ function Palette({
4239
4278
  mode = "advanced",
4240
4279
  defaultAdvanced = false,
4241
4280
  onAdvancedChange,
4281
+ onLockedPicked,
4242
4282
  variant = "aside"
4243
4283
  }) {
4244
4284
  const [query, setQuery] = React.useState("");
@@ -4332,7 +4372,16 @@ function Palette({
4332
4372
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col", isSheet ? "px-2 pb-6" : "p-3"), children: !advanced ? (
4333
4373
  // Simple mode: a flat list, no section headings — with this few
4334
4374
  // rows the headings would outnumber the blocks under them.
4335
- basics.map((v) => /* @__PURE__ */ jsxRuntime.jsx(PaletteItem, { variant: v, onAdd: () => onAddBlock(v.factory()), mode: variant }, v.id))
4375
+ basics.map((v) => /* @__PURE__ */ jsxRuntime.jsx(
4376
+ PaletteItem,
4377
+ {
4378
+ variant: v,
4379
+ onAdd: () => onAddBlock(v.factory()),
4380
+ onLockedPicked,
4381
+ mode: variant
4382
+ },
4383
+ v.id
4384
+ ))
4336
4385
  ) : visibleSections.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-1 py-2 text-xs text-muted-foreground", children: "No blocks match." }) : visibleSections.map((section) => /* @__PURE__ */ jsxRuntime.jsx(
4337
4386
  PaletteSection,
4338
4387
  {
@@ -4340,6 +4389,7 @@ function Palette({
4340
4389
  defaultOpen: isDefaultOpen(section.name, defaultOpenSections),
4341
4390
  forceOpen: queryActive,
4342
4391
  onAddBlock,
4392
+ onLockedPicked,
4343
4393
  variant
4344
4394
  },
4345
4395
  section.name
@@ -4371,6 +4421,7 @@ function PaletteSection({
4371
4421
  defaultOpen,
4372
4422
  forceOpen,
4373
4423
  onAddBlock,
4424
+ onLockedPicked,
4374
4425
  variant = "aside"
4375
4426
  }) {
4376
4427
  const [open, setOpen] = React.useState(defaultOpen);
@@ -4402,18 +4453,32 @@ function PaletteSection({
4402
4453
  ]
4403
4454
  }
4404
4455
  ),
4405
- isOpen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 flex flex-col", children: section.variants.map((v) => /* @__PURE__ */ jsxRuntime.jsx(PaletteItem, { variant: v, onAdd: () => onAddBlock(v.factory()), mode: variant }, v.id)) }) : null
4456
+ isOpen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 flex flex-col", children: section.variants.map((v) => /* @__PURE__ */ jsxRuntime.jsx(
4457
+ PaletteItem,
4458
+ {
4459
+ variant: v,
4460
+ onAdd: () => onAddBlock(v.factory()),
4461
+ onLockedPicked,
4462
+ mode: variant
4463
+ },
4464
+ v.id
4465
+ )) }) : null
4406
4466
  ] });
4407
4467
  }
4408
4468
  function PaletteItem({
4409
4469
  variant,
4410
4470
  onAdd,
4471
+ onLockedPicked,
4411
4472
  mode = "aside"
4412
4473
  }) {
4413
4474
  const { attributes, listeners, setNodeRef, setActivatorNodeRef, isDragging } = core.useDraggable({
4414
- id: `${PALETTE_DRAG_PREFIX}${variant.id}`
4475
+ id: `${PALETTE_DRAG_PREFIX}${variant.id}`,
4476
+ disabled: variant.locked
4415
4477
  });
4416
4478
  const isSheet = mode === "sheet";
4479
+ if (variant.locked) {
4480
+ return /* @__PURE__ */ jsxRuntime.jsx(LockedPaletteItem, { variant, isSheet, onPicked: onLockedPicked });
4481
+ }
4417
4482
  if (isSheet) {
4418
4483
  return /* @__PURE__ */ jsxRuntime.jsxs(
4419
4484
  "button",
@@ -4428,6 +4493,7 @@ function PaletteItem({
4428
4493
  ),
4429
4494
  children: [
4430
4495
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: variant.label }),
4496
+ variant.badge ? /* @__PURE__ */ jsxRuntime.jsx(VariantBadge, { badge: variant.badge }) : null,
4431
4497
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground transition-colors group-hover:bg-primary/10 group-hover:text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4" }) })
4432
4498
  ]
4433
4499
  }
@@ -4451,7 +4517,11 @@ function PaletteItem({
4451
4517
  ...listeners,
4452
4518
  children: [
4453
4519
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, { className: "h-3.5 w-3.5 shrink-0" }),
4454
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: variant.label })
4520
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: variant.label }),
4521
+ variant.badge ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4522
+ " ",
4523
+ /* @__PURE__ */ jsxRuntime.jsx(VariantBadge, { badge: variant.badge })
4524
+ ] }) : null
4455
4525
  ]
4456
4526
  }
4457
4527
  ),
@@ -4469,6 +4539,48 @@ function PaletteItem({
4469
4539
  }
4470
4540
  );
4471
4541
  }
4542
+ function LockedPaletteItem({
4543
+ variant,
4544
+ isSheet,
4545
+ onPicked
4546
+ }) {
4547
+ const select = variant.onLockedSelect;
4548
+ const className = cn(
4549
+ "flex w-full items-center text-left text-muted-foreground",
4550
+ isSheet ? "min-h-11 gap-3 rounded-md px-3 py-2 text-sm font-medium" : "gap-2 rounded px-2 py-1 text-sm"
4551
+ );
4552
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4553
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Lock, { "aria-hidden": true, className: cn("shrink-0", isSheet ? "h-4 w-4" : "h-3.5 w-3.5") }),
4554
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: variant.label }),
4555
+ variant.badge ? /* @__PURE__ */ jsxRuntime.jsx(VariantBadge, { badge: variant.badge }) : null
4556
+ ] });
4557
+ if (!select) {
4558
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-disabled": "true", className, children: content });
4559
+ }
4560
+ return /* @__PURE__ */ jsxRuntime.jsx(
4561
+ "button",
4562
+ {
4563
+ type: "button",
4564
+ "aria-label": `${variant.label} (locked${variant.badge ? `, ${variant.badge.label}` : ""})`,
4565
+ onClick: () => {
4566
+ onPicked?.();
4567
+ select();
4568
+ },
4569
+ className: cn(
4570
+ className,
4571
+ "cursor-pointer appearance-none border-0 bg-transparent transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
4572
+ ),
4573
+ children: content
4574
+ }
4575
+ );
4576
+ }
4577
+ function VariantBadge({ badge }) {
4578
+ const Icon = badge.icon;
4579
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 rounded-full border bg-background px-1.5 text-[10px] font-medium leading-4 text-muted-foreground", children: [
4580
+ Icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { "aria-hidden": true, className: "h-2.5 w-2.5 shrink-0" }) : null,
4581
+ badge.label
4582
+ ] });
4583
+ }
4472
4584
  function SendDialog({
4473
4585
  open,
4474
4586
  onOpenChange,
@@ -6288,7 +6400,7 @@ function MentionPicker({
6288
6400
  const listRef = React.useRef(null);
6289
6401
  const listboxId = React.useId();
6290
6402
  const activeOptionId = items[activeIndex] ? `${listboxId}-${activeIndex}` : void 0;
6291
- React.useEffect(() => {
6403
+ React.useLayoutEffect(() => {
6292
6404
  const root = editor.view.dom;
6293
6405
  root.setAttribute("role", "combobox");
6294
6406
  root.setAttribute("aria-autocomplete", "list");
@@ -6307,7 +6419,7 @@ function MentionPicker({
6307
6419
  root.removeAttribute("aria-activedescendant");
6308
6420
  };
6309
6421
  }, [activeOptionId, editor, listboxId]);
6310
- React.useEffect(() => {
6422
+ React.useLayoutEffect(() => {
6311
6423
  keyHandlerRef.current = (event) => {
6312
6424
  if (event.key === "ArrowDown" || event.key === "ArrowUp") {
6313
6425
  if (items.length > 0) {
@@ -10397,13 +10509,15 @@ function BlockEditor({
10397
10509
  onChange,
10398
10510
  onDone
10399
10511
  }) {
10512
+ const custom = useCustomBlockEditor(block);
10513
+ const CustomForm = custom?.component;
10400
10514
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
10401
10515
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-sm font-semibold text-foreground", children: [
10402
10516
  "Edit ",
10403
- labelForBlockType(block.type)
10517
+ custom ? custom.label : labelForBlockType(block.type)
10404
10518
  ] }) }),
10405
10519
  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,
10406
- dispatch(block, onChange),
10520
+ CustomForm ? /* @__PURE__ */ jsxRuntime.jsx(CustomForm, { block, onChange }) : dispatch(block, onChange),
10407
10521
  /* @__PURE__ */ jsxRuntime.jsx(
10408
10522
  AdvancedIdField,
10409
10523
  {
@@ -10574,6 +10688,122 @@ function BlockRow({
10574
10688
  ) })
10575
10689
  ] });
10576
10690
  const adornment = position && renderBlockAdornment?.(position);
10691
+ const hoverChrome = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10692
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "-translate-x-1/2 pointer-events-none absolute bottom-full left-1/2 z-10 hidden bg-background px-1.5 text-[11px] text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100 md:block", children: BLOCK_TYPE_LABELS[builderBlock.block.type] }),
10693
+ /* @__PURE__ */ jsxRuntime.jsxs(
10694
+ "div",
10695
+ {
10696
+ className: cn(
10697
+ // Hidden on mobile in favor of the inline row below; on desktop
10698
+ // reveal on hover, on keyboard focus inside the row (so Tab-stops on
10699
+ // the floating buttons themselves keep them visible), and when there
10700
+ // are validation errors worth surfacing immediately.
10701
+ // :focus-visible, not :focus-within — a drag leaves pointer focus on
10702
+ // the block, which would otherwise pin the toolbar open until a click.
10703
+ "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",
10704
+ hasErrors ? "opacity-100" : "opacity-0 group-hover:opacity-100 group-has-[:focus-visible]:opacity-100"
10705
+ ),
10706
+ children: [
10707
+ hasErrors ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10708
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10709
+ "button",
10710
+ {
10711
+ type: "button",
10712
+ "aria-label": `Show ${errors.length} validation ${errors.length === 1 ? "issue" : "issues"}`,
10713
+ onClick: () => onOpenChange?.(true),
10714
+ 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",
10715
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" })
10716
+ }
10717
+ ) }),
10718
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", align: "end", children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "flex flex-col gap-0.5", children: [
10719
+ errors.slice(0, 4).map((err, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: err }, i)),
10720
+ errors.length > 4 ? /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "text-muted-foreground", children: [
10721
+ "and ",
10722
+ errors.length - 4,
10723
+ " more"
10724
+ ] }) : null
10725
+ ] }) })
10726
+ ] }) : null,
10727
+ onReorder && typeof index === "number" && typeof total === "number" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10728
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10729
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10730
+ "button",
10731
+ {
10732
+ type: "button",
10733
+ "aria-label": "Move block up",
10734
+ disabled: index === 0,
10735
+ onClick: () => onReorder(builderBlock.id, index - 1),
10736
+ className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-muted-foreground",
10737
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-3.5 w-3.5" })
10738
+ }
10739
+ ) }),
10740
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Move up" })
10741
+ ] }),
10742
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10743
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10744
+ "button",
10745
+ {
10746
+ type: "button",
10747
+ "aria-label": "Move block down",
10748
+ disabled: index >= total - 1,
10749
+ onClick: () => onReorder(builderBlock.id, index + 1),
10750
+ className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-muted-foreground",
10751
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "h-3.5 w-3.5" })
10752
+ }
10753
+ ) }),
10754
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Move down" })
10755
+ ] })
10756
+ ] }) : null,
10757
+ /* @__PURE__ */ jsxRuntime.jsx(BlockActionButtons, { actions: blockActions, position, variant: "toolbar" }),
10758
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10759
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10760
+ "button",
10761
+ {
10762
+ type: "button",
10763
+ "aria-label": "Edit block",
10764
+ onClick: () => {
10765
+ if (isRichText) {
10766
+ setInlineEditing(true);
10767
+ } else {
10768
+ onOpenChange?.(true);
10769
+ }
10770
+ },
10771
+ className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
10772
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" })
10773
+ }
10774
+ ) }),
10775
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Edit" })
10776
+ ] }),
10777
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10778
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10779
+ "button",
10780
+ {
10781
+ type: "button",
10782
+ "aria-label": "Duplicate block",
10783
+ onClick: () => onDuplicate(builderBlock.id),
10784
+ className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
10785
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3.5 w-3.5" })
10786
+ }
10787
+ ) }),
10788
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Duplicate" })
10789
+ ] }),
10790
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10791
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10792
+ "button",
10793
+ {
10794
+ type: "button",
10795
+ "aria-label": "Delete block",
10796
+ onClick: () => onDelete(builderBlock.id),
10797
+ className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
10798
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" })
10799
+ }
10800
+ ) }),
10801
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Delete" })
10802
+ ] })
10803
+ ]
10804
+ }
10805
+ )
10806
+ ] });
10577
10807
  return /* @__PURE__ */ jsxRuntime.jsxs(
10578
10808
  "div",
10579
10809
  {
@@ -10591,126 +10821,16 @@ function BlockRow({
10591
10821
  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)]" })
10592
10822
  }
10593
10823
  ) : null,
10594
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full", children: [
10595
- renderBlockAdornment ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
10596
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: body }),
10597
- adornment != null && adornment !== false ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: adornment }) : null
10598
- ] }) : body,
10599
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "-translate-x-1/2 pointer-events-none absolute bottom-full left-1/2 z-10 hidden bg-background px-1.5 text-[11px] text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100 md:block", children: BLOCK_TYPE_LABELS[builderBlock.block.type] }),
10600
- /* @__PURE__ */ jsxRuntime.jsxs(
10601
- "div",
10602
- {
10603
- className: cn(
10604
- // Hidden on mobile in favor of the inline row below; on desktop
10605
- // reveal on hover, on keyboard focus inside the row (so Tab-stops on
10606
- // the floating buttons themselves keep them visible), and when there
10607
- // are validation errors worth surfacing immediately.
10608
- // :focus-visible, not :focus-within — a drag leaves pointer focus on
10609
- // the block, which would otherwise pin the toolbar open until a click.
10610
- "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",
10611
- hasErrors ? "opacity-100" : "opacity-0 group-hover:opacity-100 group-has-[:focus-visible]:opacity-100"
10612
- ),
10613
- children: [
10614
- hasErrors ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10615
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10616
- "button",
10617
- {
10618
- type: "button",
10619
- "aria-label": `Show ${errors.length} validation ${errors.length === 1 ? "issue" : "issues"}`,
10620
- onClick: () => onOpenChange?.(true),
10621
- 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",
10622
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" })
10623
- }
10624
- ) }),
10625
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", align: "end", children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "flex flex-col gap-0.5", children: [
10626
- errors.slice(0, 4).map((err, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: err }, i)),
10627
- errors.length > 4 ? /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "text-muted-foreground", children: [
10628
- "and ",
10629
- errors.length - 4,
10630
- " more"
10631
- ] }) : null
10632
- ] }) })
10633
- ] }) : null,
10634
- onReorder && typeof index === "number" && typeof total === "number" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10635
- /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10636
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10637
- "button",
10638
- {
10639
- type: "button",
10640
- "aria-label": "Move block up",
10641
- disabled: index === 0,
10642
- onClick: () => onReorder(builderBlock.id, index - 1),
10643
- className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-muted-foreground",
10644
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-3.5 w-3.5" })
10645
- }
10646
- ) }),
10647
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Move up" })
10648
- ] }),
10649
- /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10650
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10651
- "button",
10652
- {
10653
- type: "button",
10654
- "aria-label": "Move block down",
10655
- disabled: index >= total - 1,
10656
- onClick: () => onReorder(builderBlock.id, index + 1),
10657
- className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent disabled:hover:text-muted-foreground",
10658
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "h-3.5 w-3.5" })
10659
- }
10660
- ) }),
10661
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Move down" })
10662
- ] })
10663
- ] }) : null,
10664
- /* @__PURE__ */ jsxRuntime.jsx(BlockActionButtons, { actions: blockActions, position, variant: "toolbar" }),
10665
- /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10666
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10667
- "button",
10668
- {
10669
- type: "button",
10670
- "aria-label": "Edit block",
10671
- onClick: () => {
10672
- if (isRichText) {
10673
- setInlineEditing(true);
10674
- } else {
10675
- onOpenChange?.(true);
10676
- }
10677
- },
10678
- className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
10679
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" })
10680
- }
10681
- ) }),
10682
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Edit" })
10683
- ] }),
10684
- /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10685
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10686
- "button",
10687
- {
10688
- type: "button",
10689
- "aria-label": "Duplicate block",
10690
- onClick: () => onDuplicate(builderBlock.id),
10691
- className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
10692
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3.5 w-3.5" })
10693
- }
10694
- ) }),
10695
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Duplicate" })
10696
- ] }),
10697
- /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10698
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10699
- "button",
10700
- {
10701
- type: "button",
10702
- "aria-label": "Delete block",
10703
- onClick: () => onDelete(builderBlock.id),
10704
- className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
10705
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" })
10706
- }
10707
- ) }),
10708
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: "Delete" })
10709
- ] })
10710
- ]
10711
- }
10712
- )
10713
- ] }),
10824
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full", children: renderBlockAdornment ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
10825
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-w-0 flex-1", children: [
10826
+ body,
10827
+ hoverChrome
10828
+ ] }),
10829
+ adornment != null && adornment !== false ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: adornment }) : null
10830
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10831
+ body,
10832
+ hoverChrome
10833
+ ] }) }),
10714
10834
  /* @__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: [
10715
10835
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[11px] font-medium text-muted-foreground", children: BLOCK_TYPE_LABELS[builderBlock.block.type] }),
10716
10836
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
@@ -10915,6 +11035,45 @@ function ContainerRow({
10915
11035
  ]
10916
11036
  }
10917
11037
  );
11038
+ const toolbar = /* @__PURE__ */ jsxRuntime.jsxs(
11039
+ "div",
11040
+ {
11041
+ className: cn(
11042
+ "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",
11043
+ hasErrors ? "opacity-100" : "opacity-0 group-hover/container:opacity-100 group-has-[:focus-visible]/container:opacity-100"
11044
+ ),
11045
+ children: [
11046
+ hasErrors ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
11047
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
11048
+ "button",
11049
+ {
11050
+ type: "button",
11051
+ "aria-label": `Show ${errors.length} validation ${errors.length === 1 ? "issue" : "issues"}`,
11052
+ onClick: () => onOpenBlockChange?.(id),
11053
+ 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",
11054
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" })
11055
+ }
11056
+ ) }),
11057
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", align: "end", children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "flex flex-col gap-0.5", children: [
11058
+ errors.slice(0, 4).map((err, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: err }, i)),
11059
+ errors.length > 4 ? /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "text-muted-foreground", children: [
11060
+ "and ",
11061
+ errors.length - 4,
11062
+ " more"
11063
+ ] }) : null
11064
+ ] }) })
11065
+ ] }) : null,
11066
+ onReorder && typeof index === "number" && typeof total === "number" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11067
+ /* @__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" }) }),
11068
+ /* @__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" }) })
11069
+ ] }) : null,
11070
+ /* @__PURE__ */ jsxRuntime.jsx(BlockActionButtons, { actions: blockActions, position, variant: "toolbar" }),
11071
+ /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Edit", onClick: () => onOpenBlockChange?.(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }) }),
11072
+ /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Duplicate", onClick: () => onDuplicate(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3.5 w-3.5" }) }),
11073
+ /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Delete", destructive: true, onClick: () => onDelete(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" }) })
11074
+ ]
11075
+ }
11076
+ );
10918
11077
  return /* @__PURE__ */ jsxRuntime.jsxs(
10919
11078
  "div",
10920
11079
  {
@@ -10924,48 +11083,15 @@ function ContainerRow({
10924
11083
  className: cn("group/container relative mb-2 last:mb-0 hover:z-10", isDragging && "opacity-40"),
10925
11084
  children: [
10926
11085
  renderBlockAdornment ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
10927
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: card }),
11086
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-w-0 flex-1", children: [
11087
+ card,
11088
+ toolbar
11089
+ ] }),
10928
11090
  adornment != null && adornment !== false ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: adornment }) : null
10929
- ] }) : card,
10930
- /* @__PURE__ */ jsxRuntime.jsxs(
10931
- "div",
10932
- {
10933
- className: cn(
10934
- "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",
10935
- hasErrors ? "opacity-100" : "opacity-0 group-hover/container:opacity-100 group-has-[:focus-visible]/container:opacity-100"
10936
- ),
10937
- children: [
10938
- hasErrors ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10939
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
10940
- "button",
10941
- {
10942
- type: "button",
10943
- "aria-label": `Show ${errors.length} validation ${errors.length === 1 ? "issue" : "issues"}`,
10944
- onClick: () => onOpenBlockChange?.(id),
10945
- 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",
10946
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" })
10947
- }
10948
- ) }),
10949
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", align: "end", children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "flex flex-col gap-0.5", children: [
10950
- errors.slice(0, 4).map((err, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: err }, i)),
10951
- errors.length > 4 ? /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "text-muted-foreground", children: [
10952
- "and ",
10953
- errors.length - 4,
10954
- " more"
10955
- ] }) : null
10956
- ] }) })
10957
- ] }) : null,
10958
- onReorder && typeof index === "number" && typeof total === "number" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10959
- /* @__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" }) }),
10960
- /* @__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" }) })
10961
- ] }) : null,
10962
- /* @__PURE__ */ jsxRuntime.jsx(BlockActionButtons, { actions: blockActions, position, variant: "toolbar" }),
10963
- /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Edit", onClick: () => onOpenBlockChange?.(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }) }),
10964
- /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Duplicate", onClick: () => onDuplicate(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "h-3.5 w-3.5" }) }),
10965
- /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton2, { label: "Delete", destructive: true, onClick: () => onDelete(id), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" }) })
10966
- ]
10967
- }
10968
- ),
11091
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11092
+ card,
11093
+ toolbar
11094
+ ] }),
10969
11095
  /* @__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: [
10970
11096
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[11px] font-medium text-muted-foreground", children: "Container" }),
10971
11097
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
@@ -11382,6 +11508,7 @@ function Toolbar2({
11382
11508
  canRedo = false,
11383
11509
  onUndo,
11384
11510
  onRedo,
11511
+ undoRedoShortcuts = true,
11385
11512
  onClear,
11386
11513
  onOpenJson,
11387
11514
  onOpenIssues,
@@ -11415,6 +11542,7 @@ function Toolbar2({
11415
11542
  const showSurfaceControl = surfaceOptions.length > 1;
11416
11543
  const docsHref = docsLink === false ? null : docsLink?.href ?? DEFAULT_DOCS_HREF;
11417
11544
  const docsLabel = docsLink === false ? null : docsLink?.label ?? DEFAULT_DOCS_LABEL;
11545
+ const isApple = useIsApplePlatform();
11418
11546
  const [surfaceMenuOpen, setSurfaceMenuOpen] = React.useState(false);
11419
11547
  const [themeMenuOpen, setThemeMenuOpen] = React.useState(false);
11420
11548
  const [sendMenuOpen, setSendMenuOpen] = React.useState(false);
@@ -11505,7 +11633,8 @@ function Toolbar2({
11505
11633
  onClick: onUndo,
11506
11634
  disabled: !canUndo,
11507
11635
  "aria-label": "Undo",
11508
- title: "Undo (Ctrl+Z)",
11636
+ "aria-keyshortcuts": undoRedoShortcuts ? "Control+Z Meta+Z" : void 0,
11637
+ title: undoRedoShortcuts ? `Undo (${isApple ? "\u2318Z" : "Ctrl+Z"})` : "Undo",
11509
11638
  className: "px-2",
11510
11639
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo2, { className: "h-3.5 w-3.5" })
11511
11640
  }
@@ -11519,7 +11648,8 @@ function Toolbar2({
11519
11648
  onClick: onRedo,
11520
11649
  disabled: !canRedo,
11521
11650
  "aria-label": "Redo",
11522
- title: "Redo (Ctrl+Shift+Z)",
11651
+ "aria-keyshortcuts": undoRedoShortcuts ? "Control+Shift+Z Meta+Shift+Z Control+Y" : void 0,
11652
+ title: undoRedoShortcuts ? `Redo (${isApple ? "\u21E7\u2318Z" : "Ctrl+Shift+Z"})` : "Redo",
11523
11653
  className: "px-2",
11524
11654
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Redo2, { className: "h-3.5 w-3.5" })
11525
11655
  }
@@ -11868,6 +11998,7 @@ function BlockKitchen(props) {
11868
11998
  previewHooks,
11869
11999
  blockActions,
11870
12000
  renderBlockAdornment,
12001
+ blockEditors,
11871
12002
  customEmojis,
11872
12003
  mentions,
11873
12004
  loadChannels,
@@ -11893,7 +12024,8 @@ function BlockKitchen(props) {
11893
12024
  previewTheme: controlledPreviewTheme,
11894
12025
  sendButtonLabel,
11895
12026
  confirmSendLabel,
11896
- theme
12027
+ theme,
12028
+ undoRedoShortcuts = true
11897
12029
  // Widen the all-or-nothing union so the branch-specific props
11898
12030
  // destructure as independent optionals: untyped JS consumers can still
11899
12031
  // pass partial wiring (handled by the runtime guards below), and the
@@ -12073,7 +12205,7 @@ function BlockKitchen(props) {
12073
12205
  const variantId = parsePaletteDragId(active.id);
12074
12206
  if (variantId) {
12075
12207
  const variant = variantById.get(variantId);
12076
- if (!variant) {
12208
+ if (!variant || variant.locked) {
12077
12209
  return;
12078
12210
  }
12079
12211
  if (target.kind === "container") {
@@ -12092,30 +12224,47 @@ function BlockKitchen(props) {
12092
12224
  const handleDragCancel = React.useCallback(() => {
12093
12225
  setActivePaletteVariantId(null);
12094
12226
  }, []);
12095
- const handleKeyDown = React.useCallback(
12227
+ const runHistoryShortcut = React.useCallback(
12096
12228
  (event) => {
12097
- if (!(event.metaKey || event.ctrlKey) || event.altKey) {
12098
- return;
12099
- }
12100
- const key = event.key.toLowerCase();
12101
- const isUndo = key === "z" && !event.shiftKey;
12102
- const isRedo = key === "y" || key === "z" && event.shiftKey;
12103
- if (!isUndo && !isRedo) {
12229
+ const action = historyShortcutOf(event);
12230
+ if (!undoRedoShortcuts || !action || event.defaultPrevented || isTextEditingTarget(event.target)) {
12104
12231
  return;
12105
12232
  }
12106
- const target = event.target;
12107
- if (target && (target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName))) {
12233
+ if (action === "undo" ? !canUndo : !canRedo) {
12108
12234
  return;
12109
12235
  }
12110
12236
  event.preventDefault();
12111
- if (isRedo) {
12112
- if (canRedo) redo();
12113
- } else if (canUndo) {
12237
+ if (action === "undo") {
12114
12238
  undo();
12239
+ } else {
12240
+ redo();
12115
12241
  }
12116
12242
  },
12117
- [canRedo, canUndo, redo, undo]
12243
+ [canRedo, canUndo, redo, undo, undoRedoShortcuts]
12118
12244
  );
12245
+ const rootRef = React.useRef(null);
12246
+ const lastClickInBuilderRef = React.useRef(false);
12247
+ React.useEffect(() => {
12248
+ if (!undoRedoShortcuts) {
12249
+ return;
12250
+ }
12251
+ const onPointerDown = () => {
12252
+ lastClickInBuilderRef.current = false;
12253
+ };
12254
+ const onKeyDown = (event) => {
12255
+ const root = rootRef.current;
12256
+ const focusAroundBuilder = event.target instanceof Node && root !== null && event.target.contains(root);
12257
+ if (focusAroundBuilder && lastClickInBuilderRef.current) {
12258
+ runHistoryShortcut(event);
12259
+ }
12260
+ };
12261
+ window.addEventListener("pointerdown", onPointerDown, true);
12262
+ window.addEventListener("keydown", onKeyDown);
12263
+ return () => {
12264
+ window.removeEventListener("pointerdown", onPointerDown, true);
12265
+ window.removeEventListener("keydown", onKeyDown);
12266
+ };
12267
+ }, [runHistoryShortcut, undoRedoShortcuts]);
12119
12268
  const activePaletteVariant = activePaletteVariantId ? variantById.get(activePaletteVariantId) : null;
12120
12269
  const blockPayloads = blocks.map((b) => b.block);
12121
12270
  return /* @__PURE__ */ jsxRuntime.jsx(BrandThemeScope, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(CustomEmojiProvider, { customEmojis, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxRuntime.jsxs(
@@ -12130,8 +12279,12 @@ function BlockKitchen(props) {
12130
12279
  /* @__PURE__ */ jsxRuntime.jsxs(
12131
12280
  "div",
12132
12281
  {
12282
+ ref: rootRef,
12133
12283
  className: "bk-root flex h-full max-h-[var(--bk-max-height,100svh)] w-full flex-col overflow-hidden rounded-md border bg-background text-foreground",
12134
- onKeyDown: handleKeyDown,
12284
+ onKeyDown: runHistoryShortcut,
12285
+ onPointerDownCapture: () => {
12286
+ lastClickInBuilderRef.current = true;
12287
+ },
12135
12288
  children: [
12136
12289
  /* @__PURE__ */ jsxRuntime.jsx(
12137
12290
  Toolbar2,
@@ -12140,6 +12293,7 @@ function BlockKitchen(props) {
12140
12293
  canRedo,
12141
12294
  onUndo: undo,
12142
12295
  onRedo: redo,
12296
+ undoRedoShortcuts,
12143
12297
  onClear: () => replaceAll([]),
12144
12298
  onOpenJson: () => setJsonOpen(true),
12145
12299
  onOpenIssues: () => setIssuesOpen(true),
@@ -12230,7 +12384,7 @@ function BlockKitchen(props) {
12230
12384
  }
12231
12385
  )
12232
12386
  ] }),
12233
- /* @__PURE__ */ jsxRuntime.jsx(MentionsProvider, { mentions, children: /* @__PURE__ */ jsxRuntime.jsx(
12387
+ /* @__PURE__ */ jsxRuntime.jsx(MentionsProvider, { mentions, children: /* @__PURE__ */ jsxRuntime.jsx(BlockEditorsProvider, { blockEditors, children: /* @__PURE__ */ jsxRuntime.jsx(
12234
12388
  Surface,
12235
12389
  {
12236
12390
  blocks,
@@ -12252,7 +12406,7 @@ function BlockKitchen(props) {
12252
12406
  blockActions,
12253
12407
  renderBlockAdornment
12254
12408
  }
12255
- ) })
12409
+ ) }) })
12256
12410
  ] })
12257
12411
  ]
12258
12412
  }
@@ -12283,6 +12437,7 @@ function BlockKitchen(props) {
12283
12437
  addBlock(block);
12284
12438
  setPaletteOpen(false);
12285
12439
  },
12440
+ onLockedPicked: () => setPaletteOpen(false),
12286
12441
  sections: paletteSections,
12287
12442
  mode: paletteMode,
12288
12443
  showSearch: showPaletteSearch,