@tightknitai/block-kitchen 0.9.8 → 0.9.10

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.js CHANGED
@@ -1,8 +1,8 @@
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, GripVertical, Sun, Moon, MessageSquare, AppWindow, Home, MailSearch, Plus, ChevronDown, BookOpen, ExternalLink, AlertTriangle, Trash2, Code2, Pencil, Send, Search, Check, Copy, Info, CheckCircle2, ChevronRight, LayoutGrid, ArrowUp, ArrowDown, Loader2, Type, Bold, Italic, Strikethrough, Underline, Code, List, ListOrdered, Quote, Undo2, Redo2, Smile, Link as Link$1 } from 'lucide-react';
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, Undo2, Redo2, Smile, Link as Link$1 } from 'lucide-react';
4
4
  import * as React from 'react';
5
- import { createContext, useMemo, useEffect, useState, useCallback, useRef, useId, useContext } from 'react';
5
+ import { createContext, useState, useRef, useEffect, useCallback, useMemo, useId, useContext } from 'react';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
  import * as DialogPrimitive from '@radix-ui/react-dialog';
8
8
  import { clsx } from 'clsx';
@@ -2015,6 +2015,7 @@ function computeValidation(blocks, surface) {
2015
2015
  const grouped = groupValidatorErrors(result.errors, blocks);
2016
2016
  return {
2017
2017
  valid: result.valid,
2018
+ errors: result.errors,
2018
2019
  byBlockId: grouped.byBlockId,
2019
2020
  general: grouped.general,
2020
2021
  total: grouped.total
@@ -2610,6 +2611,38 @@ function unwrapBlocksInput(parsed) {
2610
2611
  }
2611
2612
  return null;
2612
2613
  }
2614
+ var buttonVariants = cva(
2615
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
2616
+ {
2617
+ variants: {
2618
+ variant: {
2619
+ default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
2620
+ destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
2621
+ outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
2622
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
2623
+ ghost: "hover:bg-accent hover:text-accent-foreground",
2624
+ link: "text-primary underline-offset-4 hover:underline"
2625
+ },
2626
+ size: {
2627
+ default: "h-9 px-4 py-2",
2628
+ sm: "h-8 rounded-md px-3 text-xs",
2629
+ lg: "h-10 rounded-md px-8",
2630
+ icon: "h-9 w-9"
2631
+ }
2632
+ },
2633
+ defaultVariants: {
2634
+ variant: "default",
2635
+ size: "default"
2636
+ }
2637
+ }
2638
+ );
2639
+ var Button = React.forwardRef(
2640
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
2641
+ const Comp = asChild ? Slot : "button";
2642
+ return /* @__PURE__ */ jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
2643
+ }
2644
+ );
2645
+ Button.displayName = "Button";
2613
2646
  var MAX_JSON_BYTES = 1024 * 1024;
2614
2647
  function JsonDrawer({
2615
2648
  open,
@@ -2621,19 +2654,23 @@ function JsonDrawer({
2621
2654
  const [parseError, setParseError] = useState(null);
2622
2655
  const [validationErrors, setValidationErrors] = useState([]);
2623
2656
  const [copied, setCopied] = useState(false);
2657
+ const [accepted, setAccepted] = useState(false);
2624
2658
  const textareaRef = useRef(null);
2625
2659
  const gutterRef = useRef(null);
2626
2660
  const copyResetRef = useRef(null);
2661
+ const acceptResetRef = useRef(null);
2627
2662
  const blocksRef = useRef(blocks);
2628
2663
  useEffect(() => {
2629
2664
  blocksRef.current = blocks;
2630
2665
  });
2631
2666
  useEffect(() => {
2632
2667
  if (open) {
2633
- setValue(JSON.stringify(blocksRef.current, null, 2));
2668
+ const current = blocksRef.current;
2669
+ setValue(current.length === 0 ? "" : JSON.stringify(current, null, 2));
2634
2670
  setParseError(null);
2635
2671
  setValidationErrors([]);
2636
2672
  setCopied(false);
2673
+ setAccepted(false);
2637
2674
  }
2638
2675
  }, [open]);
2639
2676
  useEffect(
@@ -2641,6 +2678,9 @@ function JsonDrawer({
2641
2678
  if (copyResetRef.current) {
2642
2679
  clearTimeout(copyResetRef.current);
2643
2680
  }
2681
+ if (acceptResetRef.current) {
2682
+ clearTimeout(acceptResetRef.current);
2683
+ }
2644
2684
  },
2645
2685
  []
2646
2686
  );
@@ -2661,6 +2701,17 @@ function JsonDrawer({
2661
2701
  setValidationErrors([]);
2662
2702
  return;
2663
2703
  }
2704
+ if (next.trim() === "") {
2705
+ setParseError(null);
2706
+ setValidationErrors([]);
2707
+ onApply([]);
2708
+ setAccepted(true);
2709
+ if (acceptResetRef.current) {
2710
+ clearTimeout(acceptResetRef.current);
2711
+ }
2712
+ acceptResetRef.current = setTimeout(() => setAccepted(false), 1800);
2713
+ return;
2714
+ }
2664
2715
  let parsed;
2665
2716
  try {
2666
2717
  parsed = JSON.parse(next);
@@ -2677,6 +2728,11 @@ function JsonDrawer({
2677
2728
  }
2678
2729
  setParseError(null);
2679
2730
  onApply(blocks2);
2731
+ setAccepted(true);
2732
+ if (acceptResetRef.current) {
2733
+ clearTimeout(acceptResetRef.current);
2734
+ }
2735
+ acceptResetRef.current = setTimeout(() => setAccepted(false), 1800);
2680
2736
  const result = validateBlockKit(blocks2, {
2681
2737
  target: "blocks",
2682
2738
  surface: "message"
@@ -2701,16 +2757,30 @@ function JsonDrawer({
2701
2757
  /* @__PURE__ */ jsx(SheetDescription, { children: "Edits update the preview as you type. Parse errors show below." })
2702
2758
  ] }),
2703
2759
  /* @__PURE__ */ jsxs("div", { className: "relative flex flex-1 overflow-hidden rounded-md border border-input bg-muted/30 shadow-sm focus-within:ring-1 focus-within:ring-ring", children: [
2704
- /* @__PURE__ */ jsx(
2705
- "button",
2706
- {
2707
- type: "button",
2708
- onClick: handleCopy,
2709
- "aria-label": copied ? "Copied to clipboard" : "Copy JSON",
2710
- className: "absolute right-2 top-2 z-10 inline-flex items-center justify-center rounded-md border border-input bg-background/80 p-1.5 text-muted-foreground shadow-sm backdrop-blur transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2711
- children: copied ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 text-emerald-600" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" })
2712
- }
2713
- ),
2760
+ /* @__PURE__ */ jsxs("div", { className: "absolute right-2 top-2 z-10 flex items-center gap-1.5", children: [
2761
+ /* @__PURE__ */ jsxs(
2762
+ "div",
2763
+ {
2764
+ role: "status",
2765
+ "aria-hidden": !accepted,
2766
+ className: `pointer-events-none flex items-center justify-center rounded-md bg-background/80 p-1.5 shadow-sm backdrop-blur transition-opacity duration-300 ${accepted ? "opacity-100" : "opacity-0"}`,
2767
+ children: [
2768
+ /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 text-emerald-600" }),
2769
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Input accepted" })
2770
+ ]
2771
+ }
2772
+ ),
2773
+ /* @__PURE__ */ jsx(
2774
+ "button",
2775
+ {
2776
+ type: "button",
2777
+ onClick: handleCopy,
2778
+ "aria-label": copied ? "Copied to clipboard" : "Copy JSON",
2779
+ className: "inline-flex items-center justify-center rounded-md border border-input bg-background/80 p-1.5 text-muted-foreground shadow-sm backdrop-blur transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2780
+ children: copied ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 text-emerald-600" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" })
2781
+ }
2782
+ )
2783
+ ] }),
2714
2784
  /* @__PURE__ */ jsx(
2715
2785
  "div",
2716
2786
  {
@@ -2747,41 +2817,10 @@ function JsonDrawer({
2747
2817
  " more"
2748
2818
  ] })
2749
2819
  ] })
2750
- ] })
2820
+ ] }),
2821
+ /* @__PURE__ */ jsx("div", { className: "flex shrink-0 justify-end", children: /* @__PURE__ */ jsx(Button, { type: "button", onClick: () => onOpenChange(false), children: "Done" }) })
2751
2822
  ] }) });
2752
2823
  }
2753
- var buttonVariants = cva(
2754
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
2755
- {
2756
- variants: {
2757
- variant: {
2758
- default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
2759
- destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
2760
- outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
2761
- secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
2762
- ghost: "hover:bg-accent hover:text-accent-foreground",
2763
- link: "text-primary underline-offset-4 hover:underline"
2764
- },
2765
- size: {
2766
- default: "h-9 px-4 py-2",
2767
- sm: "h-8 rounded-md px-3 text-xs",
2768
- lg: "h-10 rounded-md px-8",
2769
- icon: "h-9 w-9"
2770
- }
2771
- },
2772
- defaultVariants: {
2773
- variant: "default",
2774
- size: "default"
2775
- }
2776
- }
2777
- );
2778
- var Button = React.forwardRef(
2779
- ({ className, variant, size, asChild = false, ...props }, ref) => {
2780
- const Comp = asChild ? Slot : "button";
2781
- return /* @__PURE__ */ jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
2782
- }
2783
- );
2784
- Button.displayName = "Button";
2785
2824
  var Dialog = DialogPrimitive.Root;
2786
2825
  var DialogPortal = DialogPrimitive.Portal;
2787
2826
  var DialogOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
@@ -3494,6 +3533,7 @@ function SendDialog({
3494
3533
  loadChannels,
3495
3534
  loadSendAsUserStatus,
3496
3535
  onSend,
3536
+ renderSendExtras,
3497
3537
  confirmSendLabel = "Send",
3498
3538
  errorCount,
3499
3539
  onShowIssues
@@ -3503,6 +3543,10 @@ function SendDialog({
3503
3543
  const [channelId, setChannelId] = useState("");
3504
3544
  const [sendAs, setSendAs] = useState("bot");
3505
3545
  const [status, setStatus] = useState({ kind: "idle" });
3546
+ const [extras, setExtrasState] = useState({});
3547
+ const setExtras = useCallback((patch) => {
3548
+ setExtrasState((prev) => ({ ...prev, ...patch }));
3549
+ }, []);
3506
3550
  const { userStatus, polling, startSignIn } = useSlackSignIn(loadSendAsUserStatus, { open, enabled: true });
3507
3551
  const loadChannelsRef = useRef(loadChannels);
3508
3552
  useEffect(() => {
@@ -3517,6 +3561,7 @@ function SendDialog({
3517
3561
  setChannelsError(null);
3518
3562
  setChannelId("");
3519
3563
  setSendAs("bot");
3564
+ setExtrasState({});
3520
3565
  let cancelled = false;
3521
3566
  loadChannelsRef.current().then((list) => {
3522
3567
  if (cancelled) {
@@ -3544,7 +3589,10 @@ function SendDialog({
3544
3589
  const result = await onSend({
3545
3590
  channelId,
3546
3591
  blocks: toSlackBlocks(blocks),
3547
- sendAsUser: sendAs === "user"
3592
+ sendAsUser: sendAs === "user",
3593
+ // Only introduce the key when the extras slot is wired, so existing
3594
+ // consumers never see a new payload field.
3595
+ ...renderSendExtras ? { extras } : {}
3548
3596
  });
3549
3597
  if (result.ok) {
3550
3598
  setStatus({ kind: "idle" });
@@ -3611,6 +3659,12 @@ function SendDialog({
3611
3659
  }
3612
3660
  )
3613
3661
  ] }),
3662
+ renderSendExtras ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1.5", children: renderSendExtras({
3663
+ channelId: channelId || null,
3664
+ sendAsUser: sendAs === "user",
3665
+ extras,
3666
+ setExtras
3667
+ }) }) : null,
3614
3668
  errorCount > 0 ? /* @__PURE__ */ jsxs(
3615
3669
  "button",
3616
3670
  {
@@ -9357,6 +9411,8 @@ function Toolbar2({
9357
9411
  showThemeControl = true,
9358
9412
  docsLink,
9359
9413
  errorCount,
9414
+ showSend = true,
9415
+ primaryAction,
9360
9416
  sendButtonLabel = "Review & send",
9361
9417
  editingEnabled = false,
9362
9418
  editBadge,
@@ -9491,7 +9547,24 @@ function Toolbar2({
9491
9547
  /* @__PURE__ */ jsx(Code2, { className: "h-3.5 w-3.5" }),
9492
9548
  /* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: "View JSON" })
9493
9549
  ] }),
9494
- editBadge ? (
9550
+ !showSend ? primaryAction ? (
9551
+ // Compose-only mode with a host-owned primary action: same
9552
+ // placement and styling as the built-in send button. No icon —
9553
+ // the action's meaning is the host's, so the label always shows
9554
+ // (the send button can collapse to its icon on small screens;
9555
+ // an icon-less button can't).
9556
+ /* @__PURE__ */ jsx(
9557
+ Button,
9558
+ {
9559
+ type: "button",
9560
+ size: "sm",
9561
+ onClick: primaryAction.onClick,
9562
+ disabled: primaryAction.disabled,
9563
+ "aria-label": primaryAction.label,
9564
+ children: /* @__PURE__ */ jsx("span", { children: primaryAction.label })
9565
+ }
9566
+ )
9567
+ ) : null : editBadge ? (
9495
9568
  // A message is loaded: split button. Main action updates it in
9496
9569
  // place; the menu also offers posting the blocks as a new message.
9497
9570
  /* @__PURE__ */ jsxs("div", { className: "flex items-stretch", children: [
@@ -9734,12 +9807,15 @@ function BlockKitchen(props) {
9734
9807
  workspaceName,
9735
9808
  initialBlocks,
9736
9809
  onChange,
9810
+ onValidationChange,
9737
9811
  previewHooks,
9738
9812
  customEmojis,
9739
9813
  loadChannels,
9740
9814
  loadSendAsUserStatus,
9741
9815
  onSend,
9816
+ renderSendExtras,
9742
9817
  editing,
9818
+ primaryAction,
9743
9819
  loadButtonLabel,
9744
9820
  updateButtonLabel,
9745
9821
  confirmUpdateLabel,
@@ -9756,6 +9832,13 @@ function BlockKitchen(props) {
9756
9832
  sendButtonLabel,
9757
9833
  confirmSendLabel,
9758
9834
  theme
9835
+ // Widen the all-or-nothing union so the branch-specific props
9836
+ // destructure as independent optionals: untyped JS consumers can still
9837
+ // pass partial wiring (handled by the runtime guards below), and the
9838
+ // correlated-union narrowing would otherwise flag those guards as
9839
+ // "always true". `primaryAction` is pulled from the compose-only branch
9840
+ // (where it carries a real type) rather than the send branch's
9841
+ // `undefined` pin, which would collapse the intersection to `undefined`.
9759
9842
  } = props;
9760
9843
  const paletteSections = useMemo(() => {
9761
9844
  const sections = palette ?? defaultPalette;
@@ -9774,13 +9857,36 @@ function BlockKitchen(props) {
9774
9857
  }, [palette, disabledBlockTypes]);
9775
9858
  const variantById = useMemo(() => buildVariantById(paletteSections), [paletteSections]);
9776
9859
  const allowedSurfaces = allowedSurfacesProp && allowedSurfacesProp.length > 0 ? allowedSurfacesProp : ["message"];
9777
- const seededBlocks = editing?.initialTarget?.blocks ?? initialBlocks;
9860
+ const sendEnabled = Boolean(loadChannels && loadSendAsUserStatus && onSend);
9861
+ const editingConfig = sendEnabled ? editing : void 0;
9862
+ const seededBlocks = editingConfig?.initialTarget?.blocks ?? initialBlocks;
9778
9863
  useEffect(() => {
9779
- if (editing?.initialTarget && initialBlocks) {
9864
+ if (editingConfig?.initialTarget && initialBlocks) {
9780
9865
  console.warn(
9781
9866
  "[BlockKitchen] Both `initialBlocks` and `editing.initialTarget` were provided; using the target\u2019s blocks and ignoring `initialBlocks`."
9782
9867
  );
9783
9868
  }
9869
+ const sendPropsProvided = [loadChannels, loadSendAsUserStatus, onSend].filter(Boolean).length;
9870
+ if (sendPropsProvided > 0 && sendPropsProvided < 3) {
9871
+ console.warn(
9872
+ "[BlockKitchen] Partial send wiring: `loadChannels`, `loadSendAsUserStatus`, and `onSend` are all-or-nothing. The send button is hidden until all three are provided."
9873
+ );
9874
+ }
9875
+ if (editing && !sendEnabled) {
9876
+ console.warn(
9877
+ "[BlockKitchen] `editing` requires the send integration (`loadChannels`, `loadSendAsUserStatus`, `onSend`); ignoring `editing`."
9878
+ );
9879
+ }
9880
+ if (renderSendExtras && !sendEnabled) {
9881
+ console.warn(
9882
+ "[BlockKitchen] `renderSendExtras` extends the built-in send dialog, which requires the send integration (`loadChannels`, `loadSendAsUserStatus`, `onSend`); ignoring `renderSendExtras`."
9883
+ );
9884
+ }
9885
+ if (primaryAction && sendEnabled) {
9886
+ console.warn(
9887
+ "[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`."
9888
+ );
9889
+ }
9784
9890
  }, []);
9785
9891
  const { blocks, addBlock, addChild, updateBlock, removeBlock, duplicateBlock, reorderBlock, moveBlock, replaceAll } = useBlockKitchenState({ initialBlocks: seededBlocks, onChange });
9786
9892
  const childParentById = useMemo(() => {
@@ -9798,8 +9904,8 @@ function BlockKitchen(props) {
9798
9904
  const [sendOpen, setSendOpen] = useState(false);
9799
9905
  const [updateOpen, setUpdateOpen] = useState(false);
9800
9906
  const [loadOpen, setLoadOpen] = useState(false);
9801
- const [editTarget, setEditTarget] = useState(() => editing?.initialTarget ?? null);
9802
- const activeEditTarget = editing ? editTarget : null;
9907
+ const [editTarget, setEditTarget] = useState(() => editingConfig?.initialTarget ?? null);
9908
+ const activeEditTarget = editingConfig ? editTarget : null;
9803
9909
  const [issuesOpen, setIssuesOpen] = useState(false);
9804
9910
  const [paletteOpen, setPaletteOpen] = useState(false);
9805
9911
  const [openBlockId, setOpenBlockId] = useState(null);
@@ -9817,6 +9923,22 @@ function BlockKitchen(props) {
9817
9923
  return { emoji: makeEmojiHook(byName), ...previewHooks };
9818
9924
  }, [customEmojis, previewHooks]);
9819
9925
  const validation = useBlockKitValidation(blocks, "message");
9926
+ const validationSummary = useMemo(
9927
+ () => ({ valid: validation.valid, errorCount: validation.total, errors: validation.errors }),
9928
+ [validation]
9929
+ );
9930
+ const lastNotifiedValidationRef = useRef(null);
9931
+ useEffect(() => {
9932
+ if (!onValidationChange) {
9933
+ return;
9934
+ }
9935
+ const key = JSON.stringify([validationSummary.valid, validationSummary.errorCount, ...validationSummary.errors]);
9936
+ if (lastNotifiedValidationRef.current === key) {
9937
+ return;
9938
+ }
9939
+ lastNotifiedValidationRef.current = key;
9940
+ onValidationChange(validationSummary);
9941
+ }, [validationSummary, onValidationChange]);
9820
9942
  const sensors = useSensors(
9821
9943
  useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),
9822
9944
  useSensor(TouchSensor, { activationConstraint: { delay: 150, tolerance: 8 } }),
@@ -9920,8 +10042,14 @@ function BlockKitchen(props) {
9920
10042
  allowedSurfaces,
9921
10043
  showThemeControl: isPreviewThemeControlled ? false : showThemeControl,
9922
10044
  docsLink,
10045
+ showSend: sendEnabled,
10046
+ primaryAction: !sendEnabled && primaryAction ? {
10047
+ label: primaryAction.label,
10048
+ onClick: () => primaryAction.onClick({ blocks: blockPayloads, validation: validationSummary }),
10049
+ disabled: primaryAction.disableWhenInvalid ? !validationSummary.valid : false
10050
+ } : null,
9923
10051
  sendButtonLabel,
9924
- editingEnabled: !!editing,
10052
+ editingEnabled: !!editingConfig,
9925
10053
  editBadge: activeEditTarget ? {
9926
10054
  channelLabel: activeEditTarget.channelName ? `#${activeEditTarget.channelName}` : activeEditTarget.channelId,
9927
10055
  ts: activeEditTarget.ts
@@ -10003,7 +10131,7 @@ function BlockKitchen(props) {
10003
10131
  }
10004
10132
  ) }),
10005
10133
  /* @__PURE__ */ jsx(JsonDrawer, { open: jsonOpen, onOpenChange: setJsonOpen, blocks: blockPayloads, onApply: replaceAll }),
10006
- /* @__PURE__ */ jsx(
10134
+ loadChannels && loadSendAsUserStatus && onSend ? /* @__PURE__ */ jsx(
10007
10135
  SendDialog,
10008
10136
  {
10009
10137
  open: sendOpen,
@@ -10012,6 +10140,7 @@ function BlockKitchen(props) {
10012
10140
  loadChannels,
10013
10141
  loadSendAsUserStatus,
10014
10142
  onSend,
10143
+ renderSendExtras,
10015
10144
  confirmSendLabel,
10016
10145
  errorCount: validation.total,
10017
10146
  onShowIssues: () => {
@@ -10019,8 +10148,8 @@ function BlockKitchen(props) {
10019
10148
  setIssuesOpen(true);
10020
10149
  }
10021
10150
  }
10022
- ),
10023
- activeEditTarget && editing ? /* @__PURE__ */ jsx(
10151
+ ) : null,
10152
+ activeEditTarget && editingConfig && loadSendAsUserStatus ? /* @__PURE__ */ jsx(
10024
10153
  UpdateDialog,
10025
10154
  {
10026
10155
  open: updateOpen,
@@ -10028,7 +10157,7 @@ function BlockKitchen(props) {
10028
10157
  target: activeEditTarget,
10029
10158
  blocks: blockPayloads,
10030
10159
  loadSendAsUserStatus,
10031
- onUpdate: editing.onUpdate,
10160
+ onUpdate: editingConfig.onUpdate,
10032
10161
  confirmUpdateLabel,
10033
10162
  errorCount: validation.total,
10034
10163
  onShowIssues: () => {
@@ -10037,13 +10166,13 @@ function BlockKitchen(props) {
10037
10166
  }
10038
10167
  }
10039
10168
  ) : null,
10040
- editing ? /* @__PURE__ */ jsx(
10169
+ editingConfig && loadChannels ? /* @__PURE__ */ jsx(
10041
10170
  LoadMessageDialog,
10042
10171
  {
10043
10172
  open: loadOpen,
10044
10173
  onOpenChange: setLoadOpen,
10045
- onLoadMessage: editing.onLoadMessage,
10046
- loadRecentMessages: editing.loadRecentMessages,
10174
+ onLoadMessage: editingConfig.onLoadMessage,
10175
+ loadRecentMessages: editingConfig.loadRecentMessages,
10047
10176
  loadChannels,
10048
10177
  onLoaded: (result) => {
10049
10178
  replaceAll(result.blocks);
@@ -10237,6 +10366,6 @@ function fromBase64Url(b64url) {
10237
10366
  return b64 + "=".repeat(padLen);
10238
10367
  }
10239
10368
 
10240
- export { BlockKitchen, TemplatePicker, decodeBlocksFromString, defaultPalette, encodeBlocksToString, extraAlertVariant, legacyInputVariants, toSlackBlocks };
10369
+ export { BlockKitchen, SendDialog, SlackSignInButton, TemplatePicker, decodeBlocksFromString, defaultPalette, encodeBlocksToString, extraAlertVariant, legacyInputVariants, toSlackBlocks, useSlackSignIn };
10241
10370
  //# sourceMappingURL=index.js.map
10242
10371
  //# sourceMappingURL=index.js.map