@tightknitai/block-kitchen 0.10.4 → 0.10.6

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.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { B as BlockKitchenProps, S as SupportedBlock, C as ChannelOption, a as SendAsUserStatus, b as SendPayload, c as SendExtrasContext, T as Template, P as PreviewSurface, d as PreviewTheme } from './palette-Sz27861i.cjs';
4
- export { A as AlertBlock, e as AlertLevel, f as BlockKitchenBaseProps, g as BlockKitchenComposeOnlyProps, h as BlockKitchenSendProps, i as BrandPreset, j as BrandTheme, k as BrandTokens, l as BuilderBlock, m as CardBlock, n as CarouselBlock, o as CartesianChart, p as Chart, q as ChartAxisConfig, r as ChartDataPoint, s as ChartSeries, t as ChartType, u as ContainerBlock, v as ContainerChildBlock, w as ContextActionsBlock, x as ContextActionsElement, y as CustomEmoji, D as DataVisualizationBlock, E as EditableVia, F as FeedbackButtonSubobject, z as FeedbackButtonsElement, H as HeaderLevel, I as IconButtonElement, G as IconButtonIcon, J as InputBlock, L as LoadMessageInput, K as LoadResult, M as LoadedMessage, N as LoadingConfig, O as MarkdownBlock, Q as PaletteSection, R as PaletteVariant, U as PieChart, V as PieChartSegment, W as PlanBlock, X as PreviewHooks, Y as PrimaryActionConfig, Z as PrimaryActionContext, _ as RecentMessage, $ as SendResult, a0 as SupportedBlockType, a1 as SupportedHeaderBlock, a2 as TableBlock, a3 as TableCell, a4 as TableColumnSetting, a5 as TaskCardBlock, a6 as TaskCardStatus, a7 as UpdatePayload, a8 as UpdateResult, a9 as UrlSourceElement, aa as ValidationSummary, ab as VideoBlock, ac as defaultPalette, ad as extraAlertVariant, ae as legacyInputVariants } from './palette-Sz27861i.cjs';
3
+ import { B as BlockKitchenProps, S as SupportedBlock, C as ChannelOption, a as SendAsUserStatus, b as SendPayload, c as SendExtrasContext, T as Template, P as PreviewSurface, d as PreviewTheme } from './palette-QbOx7kAa.cjs';
4
+ export { A as AlertBlock, e as AlertLevel, f as BlockKitchenBaseProps, g as BlockKitchenComposeOnlyProps, h as BlockKitchenSendProps, i as BrandPreset, j as BrandTheme, k as BrandTokens, l as BuilderBlock, m as CardBlock, n as CarouselBlock, o as CartesianChart, p as Chart, q as ChartAxisConfig, r as ChartDataPoint, s as ChartSeries, t as ChartType, u as ContainerBlock, v as ContainerChildBlock, w as ContextActionsBlock, x as ContextActionsElement, y as CustomEmoji, D as DataVisualizationBlock, E as EditableVia, F as FeedbackButtonSubobject, z as FeedbackButtonsElement, H as HeaderLevel, I as IconButtonElement, G as IconButtonIcon, J as InputBlock, L as LoadMessageInput, K as LoadResult, M as LoadedMessage, N as LoadingConfig, O as MarkdownBlock, Q as PaletteMode, R as PaletteSection, U as PaletteVariant, V as PieChart, W as PieChartSegment, X as PlanBlock, Y as PreviewHooks, Z as PrimaryActionConfig, _ as PrimaryActionContext, $ as RecentMessage, a0 as SendResult, a1 as SupportedBlockType, a2 as SupportedHeaderBlock, a3 as TableBlock, a4 as TableCell, a5 as TableColumnSetting, a6 as TaskCardBlock, a7 as TaskCardStatus, a8 as UpdatePayload, a9 as UpdateResult, aa as UrlSourceElement, ab as ValidationSummary, ac as VideoBlock, ad as defaultPalette, ae as extraAlertVariant, af as legacyInputVariants } from './palette-QbOx7kAa.cjs';
5
5
  export { decodeBlocksFromString, encodeBlocksToString, toSlackBlocks } from './helpers.cjs';
6
6
  import 'slack-web-api-client';
7
7
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { B as BlockKitchenProps, S as SupportedBlock, C as ChannelOption, a as SendAsUserStatus, b as SendPayload, c as SendExtrasContext, T as Template, P as PreviewSurface, d as PreviewTheme } from './palette-Sz27861i.js';
4
- export { A as AlertBlock, e as AlertLevel, f as BlockKitchenBaseProps, g as BlockKitchenComposeOnlyProps, h as BlockKitchenSendProps, i as BrandPreset, j as BrandTheme, k as BrandTokens, l as BuilderBlock, m as CardBlock, n as CarouselBlock, o as CartesianChart, p as Chart, q as ChartAxisConfig, r as ChartDataPoint, s as ChartSeries, t as ChartType, u as ContainerBlock, v as ContainerChildBlock, w as ContextActionsBlock, x as ContextActionsElement, y as CustomEmoji, D as DataVisualizationBlock, E as EditableVia, F as FeedbackButtonSubobject, z as FeedbackButtonsElement, H as HeaderLevel, I as IconButtonElement, G as IconButtonIcon, J as InputBlock, L as LoadMessageInput, K as LoadResult, M as LoadedMessage, N as LoadingConfig, O as MarkdownBlock, Q as PaletteSection, R as PaletteVariant, U as PieChart, V as PieChartSegment, W as PlanBlock, X as PreviewHooks, Y as PrimaryActionConfig, Z as PrimaryActionContext, _ as RecentMessage, $ as SendResult, a0 as SupportedBlockType, a1 as SupportedHeaderBlock, a2 as TableBlock, a3 as TableCell, a4 as TableColumnSetting, a5 as TaskCardBlock, a6 as TaskCardStatus, a7 as UpdatePayload, a8 as UpdateResult, a9 as UrlSourceElement, aa as ValidationSummary, ab as VideoBlock, ac as defaultPalette, ad as extraAlertVariant, ae as legacyInputVariants } from './palette-Sz27861i.js';
3
+ import { B as BlockKitchenProps, S as SupportedBlock, C as ChannelOption, a as SendAsUserStatus, b as SendPayload, c as SendExtrasContext, T as Template, P as PreviewSurface, d as PreviewTheme } from './palette-QbOx7kAa.js';
4
+ export { A as AlertBlock, e as AlertLevel, f as BlockKitchenBaseProps, g as BlockKitchenComposeOnlyProps, h as BlockKitchenSendProps, i as BrandPreset, j as BrandTheme, k as BrandTokens, l as BuilderBlock, m as CardBlock, n as CarouselBlock, o as CartesianChart, p as Chart, q as ChartAxisConfig, r as ChartDataPoint, s as ChartSeries, t as ChartType, u as ContainerBlock, v as ContainerChildBlock, w as ContextActionsBlock, x as ContextActionsElement, y as CustomEmoji, D as DataVisualizationBlock, E as EditableVia, F as FeedbackButtonSubobject, z as FeedbackButtonsElement, H as HeaderLevel, I as IconButtonElement, G as IconButtonIcon, J as InputBlock, L as LoadMessageInput, K as LoadResult, M as LoadedMessage, N as LoadingConfig, O as MarkdownBlock, Q as PaletteMode, R as PaletteSection, U as PaletteVariant, V as PieChart, W as PieChartSegment, X as PlanBlock, Y as PreviewHooks, Z as PrimaryActionConfig, _ as PrimaryActionContext, $ as RecentMessage, a0 as SendResult, a1 as SupportedBlockType, a2 as SupportedHeaderBlock, a3 as TableBlock, a4 as TableCell, a5 as TableColumnSetting, a6 as TaskCardBlock, a7 as TaskCardStatus, a8 as UpdatePayload, a9 as UpdateResult, aa as UrlSourceElement, ab as ValidationSummary, ac as VideoBlock, ad as defaultPalette, ae as extraAlertVariant, af as legacyInputVariants } from './palette-QbOx7kAa.js';
5
5
  export { decodeBlocksFromString, encodeBlocksToString, toSlackBlocks } from './helpers.js';
6
6
  import 'slack-web-api-client';
7
7
 
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useSensors, useSensor, PointerSensor, TouchSensor, KeyboardSensor, pointerWithin, closestCenter, DndContext, DragOverlay, useDroppable, useDraggable } from '@dnd-kit/core';
2
2
  import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, useSortable } from '@dnd-kit/sortable';
3
- import { X, Circle, Sparkles, FileText, AlignLeft, MousePointerClick, TextCursorInput, LayoutTemplate, Bell, Pilcrow, Image, Video, GalleryHorizontal, Table, ChartColumnBig, Container, Loader2, ExternalLink, AlertTriangle, GripVertical, Sun, Moon, MessageSquare, AppWindow, Home, MailSearch, Plus, ChevronDown, BookOpen, Undo2, Redo2, Trash2, Code2, Pencil, Send, Search, Check, Copy, CheckCircle2, ChevronRight, LayoutGrid, ArrowUp, ArrowDown, Type, Bold, Italic, Strikethrough, Underline, Code, List, ListOrdered, Quote, 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, Plus, ChevronDown, BookOpen, Undo2, Redo2, Trash2, Code2, Pencil, Send, Search, Check, Copy, Info, CheckCircle2, ChevronRight, LayoutGrid, ArrowUp, ArrowDown, Type, Bold, Italic, Strikethrough, Underline, Code, List, ListOrdered, Quote, Smile, Link as Link$1 } from 'lucide-react';
4
4
  import * as React from 'react';
5
5
  import { createContext, useState, useRef, useEffect, useCallback, useMemo, useId, useContext } from 'react';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -818,7 +818,10 @@ var defaultPalette = [
818
818
  variants: [
819
819
  {
820
820
  id: "rich_text_section",
821
- label: "Section",
821
+ label: "Rich Text Section",
822
+ // The one variant simple mode offers, where it's listed without its
823
+ // section heading — hence the self-describing label.
824
+ basic: true,
822
825
  factory: () => ({
823
826
  type: "rich_text",
824
827
  elements: [
@@ -3221,6 +3224,7 @@ function SlackSignInButton({ onClick, polling }) {
3221
3224
  }
3222
3225
  var LINK_DEBOUNCE_MS = 400;
3223
3226
  var LINK_HELP_TEXT = 'Click the \u2807menu while hovering over the message in Slack (or right-click), and select "Copy Link".';
3227
+ var LINK_HELP_LABEL = "Where to find a message link";
3224
3228
  var TABS = [
3225
3229
  { id: "recent", label: "Pick from Recent" },
3226
3230
  { id: "link", label: "Direct Link" }
@@ -3469,12 +3473,13 @@ function LoadMessageDialog({
3469
3473
  }, POLL_INTERVAL_MS2);
3470
3474
  };
3471
3475
  const preview = activeTab === "recent" ? selectedRecent ? { kind: "ready", target: { ...selectedRecent, editableVia: selectedRecent.editableVia ?? "bot" } } : { kind: "empty" } : linkStatus.kind === "idle" ? { kind: "empty" } : linkStatus.kind === "ready" ? { kind: "ready", target: linkStatus.result } : linkStatus;
3472
- const canLoad = activeTab === "recent" ? !!selectedRecent : !!link.trim();
3476
+ const verdictOwnsAction = linkStatus.kind === "not-editable" && (isSafeHref(linkStatus.oauthUrl) || (linkStatus.blocks?.length ?? 0) > 0);
3477
+ const canLoad = activeTab === "recent" ? !!selectedRecent : !!link.trim() && !verdictOwnsAction;
3473
3478
  const panelProps = (id) => hasRecent ? { role: "tabpanel", id: panelDomId(id), "aria-labelledby": tabDomId(id) } : {};
3474
3479
  return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
3475
3480
  DialogContent,
3476
3481
  {
3477
- className: "flex max-h-[85svh] w-[calc(100vw-1.5rem)] flex-col rounded-lg lg:max-w-4xl",
3482
+ className: "flex max-h-[85svh] w-[calc(100vw-1.5rem)] max-w-4xl flex-col rounded-lg max-lg:max-w-lg",
3478
3483
  onOpenAutoFocus: (e) => {
3479
3484
  if (hasRecent) {
3480
3485
  return;
@@ -3487,7 +3492,7 @@ function LoadMessageDialog({
3487
3492
  /* @__PURE__ */ jsx(DialogTitle, { children: "Find an existing message" }),
3488
3493
  /* @__PURE__ */ jsx(DialogDescription, { children: hasRecent ? "Pick a recent message your app posted, or paste a Slack message link. Preview it before loading." : `Paste a Slack message link (Slack's "Copy link") to preview it and load its blocks for editing.` })
3489
3494
  ] }),
3490
- /* @__PURE__ */ jsxs("div", { className: "-mx-1 flex min-h-0 min-w-0 flex-1 flex-col gap-4 overflow-y-auto px-1 lg:flex-row lg:gap-5 lg:overflow-hidden", children: [
3495
+ /* @__PURE__ */ jsxs("div", { className: "-mx-1 flex min-h-0 min-w-0 flex-1 px-1 max-lg:flex-col max-lg:gap-4 max-lg:overflow-y-auto lg:flex-row lg:gap-5 lg:overflow-hidden", children: [
3491
3496
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 shrink-0 flex-col gap-3 lg:min-h-0 lg:w-[19rem]", children: [
3492
3497
  hasRecent && /* @__PURE__ */ jsx(TabStrip, { activeTab, onSelect: setTab, tabDomId, panelDomId }),
3493
3498
  activeTab === "recent" ? /* @__PURE__ */ jsxs(
@@ -3522,7 +3527,7 @@ function LoadMessageDialog({
3522
3527
  channelId && recent === null && !recentError && /* @__PURE__ */ jsx("p", { className: "shrink-0 text-xs text-muted-foreground", children: "Loading recent messages\u2026" }),
3523
3528
  channelId && recentError && /* @__PURE__ */ jsx("p", { className: "shrink-0 text-xs text-destructive", children: recentError }),
3524
3529
  channelId && recent && recent.length === 0 && !recentError && /* @__PURE__ */ jsx("p", { className: "shrink-0 text-xs text-muted-foreground", children: "No recent messages from this app in this channel." }),
3525
- channelId && recent && recent.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex max-h-60 min-h-0 min-w-0 flex-col gap-1 overflow-y-auto lg:max-h-none lg:flex-1", children: recent.map((m) => {
3530
+ channelId && recent && recent.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex min-h-0 min-w-0 flex-col gap-1 overflow-y-auto max-lg:max-h-60 lg:flex-1", children: recent.map((m) => {
3526
3531
  const asUser = (m.editableVia ?? "bot") === "user";
3527
3532
  const authorName = m.username || (asUser ? "You" : "App bot");
3528
3533
  const safeIcon = isSafeImageSrc(m.iconUrl) ? m.iconUrl : void 0;
@@ -3580,7 +3585,21 @@ function LoadMessageDialog({
3580
3585
  className: "-mx-1 flex min-w-0 flex-col gap-2 px-1 lg:min-h-0 lg:flex-1 lg:overflow-y-auto",
3581
3586
  children: [
3582
3587
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
3583
- /* @__PURE__ */ jsx(Label, { htmlFor: "message-link", children: "Message link" }),
3588
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
3589
+ /* @__PURE__ */ jsx(Label, { htmlFor: "message-link", children: "Message link" }),
3590
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
3591
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
3592
+ "button",
3593
+ {
3594
+ type: "button",
3595
+ "aria-label": LINK_HELP_LABEL,
3596
+ className: "flex h-4 w-4 items-center justify-center rounded-full text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
3597
+ children: /* @__PURE__ */ jsx(Info, { className: "h-3.5 w-3.5" })
3598
+ }
3599
+ ) }),
3600
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", children: LINK_HELP_TEXT })
3601
+ ] })
3602
+ ] }),
3584
3603
  /* @__PURE__ */ jsx(
3585
3604
  Input,
3586
3605
  {
@@ -3602,8 +3621,7 @@ function LoadMessageDialog({
3602
3621
  autoComplete: "off",
3603
3622
  spellCheck: false
3604
3623
  }
3605
- ),
3606
- /* @__PURE__ */ jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: LINK_HELP_TEXT })
3624
+ )
3607
3625
  ] }),
3608
3626
  emptyLinkError && /* @__PURE__ */ jsx("p", { className: "rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: emptyLinkError })
3609
3627
  ]
@@ -3701,38 +3719,39 @@ function PreviewPane({
3701
3719
  editableLabel(target.editableVia)
3702
3720
  ] }) : null
3703
3721
  ] }),
3722
+ state.kind === "not-editable" && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col gap-2 rounded-md border border-amber-200! bg-amber-50 p-3 text-xs text-amber-800", children: [
3723
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
3724
+ /* @__PURE__ */ jsx(AlertTriangle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
3725
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children: state.reason })
3726
+ ] }),
3727
+ signInUrl && /* @__PURE__ */ jsx(SlackSignInButton, { onClick: () => onSignIn(signInUrl), polling: signInPolling }),
3728
+ verdictBlocks && verdictBlocks.length > 0 && /* @__PURE__ */ jsx(
3729
+ Button,
3730
+ {
3731
+ type: "button",
3732
+ variant: "outline",
3733
+ size: "sm",
3734
+ className: "self-start",
3735
+ onClick: () => onOpenAsNew(verdictBlocks),
3736
+ children: "Open as a new message instead"
3737
+ }
3738
+ )
3739
+ ] }),
3704
3740
  /* @__PURE__ */ jsxs(
3705
3741
  "div",
3706
3742
  {
3707
3743
  role: "region",
3708
3744
  "aria-label": "Message preview",
3709
3745
  tabIndex: 0,
3710
- className: "flex max-h-72 min-h-32 flex-1 flex-col gap-3 overflow-y-auto rounded-md border bg-muted/40 p-3 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring lg:max-h-none lg:min-h-0",
3746
+ className: "flex flex-1 flex-col gap-3 overflow-y-auto rounded-md border bg-muted/40 p-3 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring max-lg:max-h-72 max-lg:min-h-32 lg:min-h-0",
3711
3747
  children: [
3712
- state.kind === "not-editable" && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col gap-2 rounded-md border border-amber-200! bg-amber-50 p-3 text-xs text-amber-800", children: [
3713
- /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
3714
- /* @__PURE__ */ jsx(AlertTriangle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
3715
- /* @__PURE__ */ jsx("span", { className: "flex-1", children: state.reason })
3716
- ] }),
3717
- signInUrl && /* @__PURE__ */ jsx(SlackSignInButton, { onClick: () => onSignIn(signInUrl), polling: signInPolling }),
3718
- verdictBlocks && verdictBlocks.length > 0 && /* @__PURE__ */ jsx(
3719
- Button,
3720
- {
3721
- type: "button",
3722
- variant: "outline",
3723
- size: "sm",
3724
- className: "self-start",
3725
- onClick: () => onOpenAsNew(verdictBlocks),
3726
- children: "Open as a new message instead"
3727
- }
3728
- )
3729
- ] }),
3730
3748
  state.kind === "error" && /* @__PURE__ */ jsx("p", { className: "shrink-0 rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: state.error }),
3731
3749
  state.kind === "loading" && /* @__PURE__ */ jsxs("p", { className: "m-auto flex items-center gap-2 text-sm text-muted-foreground", children: [
3732
3750
  /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
3733
3751
  "Looking up that message\u2026"
3734
3752
  ] }),
3735
3753
  state.kind === "empty" && /* @__PURE__ */ jsx("p", { className: "m-auto px-4 text-center text-sm text-muted-foreground", children: emptyHint }),
3754
+ state.kind === "not-editable" && !(verdictBlocks && verdictBlocks.length > 0) && /* @__PURE__ */ jsx("p", { className: "m-auto px-4 text-center text-sm text-muted-foreground", children: "Nothing to preview." }),
3736
3755
  target && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: /* @__PURE__ */ jsx(
3737
3756
  SlackMessagePreview,
3738
3757
  {
@@ -3762,6 +3781,20 @@ function isDefaultOpen(sectionName, config) {
3762
3781
  if (typeof config === "boolean") return config;
3763
3782
  return config.includes(sectionName);
3764
3783
  }
3784
+ var PALETTE_TITLE = "Message Elements";
3785
+ var ADVANCED_HELP = "Browse every Slack block type \u2014 sections, images, buttons, inputs, tables and more \u2014 plus a search box.";
3786
+ var BASIC_HELP = "Go back to the short list: just the rich text block for writing a message.";
3787
+ function basicVariants(sections) {
3788
+ const out = [];
3789
+ for (const section of sections) {
3790
+ for (const variant of section.variants) {
3791
+ if (variant.basic) {
3792
+ out.push(variant);
3793
+ }
3794
+ }
3795
+ }
3796
+ return out;
3797
+ }
3765
3798
  function filterSections(sections, query) {
3766
3799
  const q = query.trim().toLowerCase();
3767
3800
  if (q.length === 0) return sections;
@@ -3784,14 +3817,26 @@ function Palette({
3784
3817
  defaultOpenSections = true,
3785
3818
  showSearch = true,
3786
3819
  searchPlaceholder = "Search blocks\u2026",
3820
+ mode = "advanced",
3787
3821
  variant = "aside"
3788
3822
  }) {
3789
3823
  const [query, setQuery] = useState("");
3824
+ const [advancedOpen, setAdvancedOpen] = useState(false);
3825
+ const [prevMode, setPrevMode] = useState(mode);
3826
+ if (prevMode !== mode) {
3827
+ setPrevMode(mode);
3828
+ setAdvancedOpen(false);
3829
+ setQuery("");
3830
+ }
3831
+ const basics = useMemo(() => mode === "simple" ? basicVariants(sections) : [], [mode, sections]);
3832
+ const offersSimple = mode === "simple" && basics.length > 0;
3833
+ const advanced = !offersSimple || advancedOpen;
3834
+ const searchVisible = showSearch && advanced;
3790
3835
  const visibleSections = useMemo(
3791
- () => showSearch ? filterSections(sections, query) : sections,
3792
- [sections, query, showSearch]
3836
+ () => searchVisible ? filterSections(sections, query) : sections,
3837
+ [sections, query, searchVisible]
3793
3838
  );
3794
- const queryActive = showSearch && query.trim().length > 0;
3839
+ const queryActive = searchVisible && query.trim().length > 0;
3795
3840
  const isSheet = variant === "sheet";
3796
3841
  return /* @__PURE__ */ jsxs(
3797
3842
  "aside",
@@ -3801,38 +3846,72 @@ function Palette({
3801
3846
  isSheet ? "w-full flex-1 bg-background" : "w-72 shrink-0 border-r bg-muted/20"
3802
3847
  ),
3803
3848
  children: [
3804
- showSearch ? /* @__PURE__ */ jsx(
3849
+ offersSimple || searchVisible ? /* @__PURE__ */ jsxs(
3805
3850
  "div",
3806
3851
  {
3807
3852
  className: cn(
3808
- "sticky top-0 z-10 border-b px-3 pt-3 pb-2 backdrop-blur",
3853
+ "sticky top-0 z-10 flex flex-col gap-2 border-b px-3 pt-3 pb-2 backdrop-blur",
3809
3854
  isSheet ? "bg-background" : "bg-muted/20"
3810
3855
  ),
3811
- children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
3812
- /* @__PURE__ */ jsx(
3813
- Search,
3814
- {
3815
- className: cn(
3816
- "pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 text-muted-foreground",
3817
- isSheet ? "h-4 w-4" : "h-3.5 w-3.5"
3856
+ children: [
3857
+ offersSimple ? (
3858
+ // Titled row: with the sections gone, simple mode's header would
3859
+ // otherwise be a lone right-aligned link over empty space, and
3860
+ // nothing would name what the rail below it holds.
3861
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
3862
+ /* @__PURE__ */ jsx(
3863
+ "span",
3864
+ {
3865
+ className: cn(
3866
+ "min-w-0 truncate font-medium uppercase tracking-wide text-muted-foreground",
3867
+ isSheet ? "text-xs" : "text-[11px]"
3868
+ ),
3869
+ children: PALETTE_TITLE
3870
+ }
3871
+ ),
3872
+ /* @__PURE__ */ jsx(
3873
+ ModeLink,
3874
+ {
3875
+ advanced,
3876
+ isSheet,
3877
+ onToggle: () => {
3878
+ setQuery("");
3879
+ setAdvancedOpen((v) => !v);
3880
+ }
3881
+ }
3818
3882
  )
3819
- }
3820
- ),
3821
- /* @__PURE__ */ jsx(
3822
- Input,
3823
- {
3824
- type: "search",
3825
- value: query,
3826
- onChange: (e) => setQuery(e.target.value),
3827
- placeholder: searchPlaceholder,
3828
- "aria-label": searchPlaceholder,
3829
- className: cn(isSheet ? "h-10 pl-8 text-base" : "h-8 pl-7 text-sm")
3830
- }
3831
- )
3832
- ] })
3883
+ ] })
3884
+ ) : null,
3885
+ searchVisible ? /* @__PURE__ */ jsxs("div", { className: "relative", children: [
3886
+ /* @__PURE__ */ jsx(
3887
+ Search,
3888
+ {
3889
+ className: cn(
3890
+ "pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 text-muted-foreground",
3891
+ isSheet ? "h-4 w-4" : "h-3.5 w-3.5"
3892
+ )
3893
+ }
3894
+ ),
3895
+ /* @__PURE__ */ jsx(
3896
+ Input,
3897
+ {
3898
+ type: "search",
3899
+ value: query,
3900
+ onChange: (e) => setQuery(e.target.value),
3901
+ placeholder: searchPlaceholder,
3902
+ "aria-label": searchPlaceholder,
3903
+ className: cn(isSheet ? "h-10 pl-8 text-base" : "h-8 pl-7 text-sm")
3904
+ }
3905
+ )
3906
+ ] }) : null
3907
+ ]
3833
3908
  }
3834
3909
  ) : null,
3835
- /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", isSheet ? "px-2 pb-6" : "p-3"), children: visibleSections.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-1 py-2 text-xs text-muted-foreground", children: "No blocks match." }) : visibleSections.map((section) => /* @__PURE__ */ jsx(
3910
+ /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", isSheet ? "px-2 pb-6" : "p-3"), children: !advanced ? (
3911
+ // Simple mode: a flat list, no section headings — with this few
3912
+ // rows the headings would outnumber the blocks under them.
3913
+ basics.map((v) => /* @__PURE__ */ jsx(PaletteItem, { variant: v, onAdd: () => onAddBlock(v.factory()), mode: variant }, v.id))
3914
+ ) : visibleSections.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-1 py-2 text-xs text-muted-foreground", children: "No blocks match." }) : visibleSections.map((section) => /* @__PURE__ */ jsx(
3836
3915
  PaletteSection,
3837
3916
  {
3838
3917
  section,
@@ -3847,6 +3926,24 @@ function Palette({
3847
3926
  }
3848
3927
  );
3849
3928
  }
3929
+ function ModeLink({ advanced, isSheet, onToggle }) {
3930
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
3931
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
3932
+ "button",
3933
+ {
3934
+ type: "button",
3935
+ onClick: onToggle,
3936
+ "aria-label": advanced ? "Basic block palette" : "Advanced block palette",
3937
+ className: cn(
3938
+ "shrink-0 cursor-pointer appearance-none rounded border-0 bg-transparent p-0 font-medium text-primary underline underline-offset-2 transition-colors hover:text-primary/80 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
3939
+ isSheet ? "min-h-8 text-sm" : "text-xs"
3940
+ ),
3941
+ children: advanced ? "Basic" : "Advanced"
3942
+ }
3943
+ ) }),
3944
+ /* @__PURE__ */ jsx(TooltipContent, { side: "bottom", align: "end", children: advanced ? BASIC_HELP : ADVANCED_HELP })
3945
+ ] }) });
3946
+ }
3850
3947
  function PaletteSection({
3851
3948
  section,
3852
3949
  defaultOpen,
@@ -9788,6 +9885,48 @@ function EmptyState({
9788
9885
  function DropIndicator2() {
9789
9886
  return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none relative my-1 h-0.5 w-full rounded-full bg-primary", children: /* @__PURE__ */ jsx("span", { className: "-left-1 -top-[3px] absolute h-2 w-2 rounded-full bg-primary shadow-[0_0_0_2px_var(--color-background)]" }) });
9790
9887
  }
9888
+ function SlackMark({ className }) {
9889
+ return /* @__PURE__ */ jsxs(
9890
+ "svg",
9891
+ {
9892
+ className,
9893
+ viewBox: "0 0 122.8 122.8",
9894
+ xmlns: "http://www.w3.org/2000/svg",
9895
+ "aria-hidden": "true",
9896
+ focusable: "false",
9897
+ children: [
9898
+ /* @__PURE__ */ jsx(
9899
+ "path",
9900
+ {
9901
+ fill: "#e01e5a",
9902
+ d: "M25.8 77.6c0 7.1-5.8 12.9-12.9 12.9S0 84.7 0 77.6s5.8-12.9 12.9-12.9h12.9v12.9zm6.5 0c0-7.1 5.8-12.9 12.9-12.9s12.9 5.8 12.9 12.9v32.3c0 7.1-5.8 12.9-12.9 12.9s-12.9-5.8-12.9-12.9V77.6z"
9903
+ }
9904
+ ),
9905
+ /* @__PURE__ */ jsx(
9906
+ "path",
9907
+ {
9908
+ fill: "#36c5f0",
9909
+ d: "M45.2 25.8c-7.1 0-12.9-5.8-12.9-12.9S38.1 0 45.2 0s12.9 5.8 12.9 12.9v12.9H45.2zm0 6.5c7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H12.9C5.8 58.1 0 52.3 0 45.2s5.8-12.9 12.9-12.9h32.3z"
9910
+ }
9911
+ ),
9912
+ /* @__PURE__ */ jsx(
9913
+ "path",
9914
+ {
9915
+ fill: "#2eb67d",
9916
+ d: "M97 45.2c0-7.1 5.8-12.9 12.9-12.9s12.9 5.8 12.9 12.9-5.8 12.9-12.9 12.9H97V45.2zm-6.5 0c0 7.1-5.8 12.9-12.9 12.9s-12.9-5.8-12.9-12.9V12.9C64.7 5.8 70.5 0 77.6 0s12.9 5.8 12.9 12.9v32.3z"
9917
+ }
9918
+ ),
9919
+ /* @__PURE__ */ jsx(
9920
+ "path",
9921
+ {
9922
+ fill: "#ecb22e",
9923
+ d: "M77.6 97c7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9-12.9-5.8-12.9-12.9V97h12.9zm0-6.5c-7.1 0-12.9-5.8-12.9-12.9s5.8-12.9 12.9-12.9h32.3c7.1 0 12.9 5.8 12.9 12.9s-5.8 12.9-12.9 12.9H77.6z"
9924
+ }
9925
+ )
9926
+ ]
9927
+ }
9928
+ );
9929
+ }
9791
9930
  var THEME_OPTIONS = [
9792
9931
  { value: "light", label: "Light", Icon: Sun },
9793
9932
  { value: "dark", label: "Dark", Icon: Moon }
@@ -9852,7 +9991,7 @@ function Toolbar2({
9852
9991
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-x-2 gap-y-1 border-b bg-background px-2 py-1.5 sm:px-3 sm:py-2", children: [
9853
9992
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1 sm:gap-2", children: [
9854
9993
  loadEnabled ? /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: onOpenLoad, "aria-label": loadButtonLabel, children: [
9855
- /* @__PURE__ */ jsx(MailSearch, { className: "h-3.5 w-3.5" }),
9994
+ /* @__PURE__ */ jsx(SlackMark, { className: "h-3.5 w-3.5" }),
9856
9995
  /* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: loadButtonLabel })
9857
9996
  ] }) : null,
9858
9997
  onOpenPalette ? /* @__PURE__ */ jsxs(
@@ -10285,6 +10424,7 @@ function BlockKitchen(props) {
10285
10424
  confirmUpdateLabel,
10286
10425
  palette,
10287
10426
  disabledBlockTypes,
10427
+ paletteMode,
10288
10428
  showPaletteSearch,
10289
10429
  paletteSearchPlaceholder,
10290
10430
  defaultOpenSections,
@@ -10587,6 +10727,7 @@ function BlockKitchen(props) {
10587
10727
  {
10588
10728
  onAddBlock: (block) => addBlock(block),
10589
10729
  sections: paletteSections,
10730
+ mode: paletteMode,
10590
10731
  showSearch: showPaletteSearch,
10591
10732
  searchPlaceholder: paletteSearchPlaceholder,
10592
10733
  defaultOpenSections
@@ -10639,6 +10780,7 @@ function BlockKitchen(props) {
10639
10780
  setPaletteOpen(false);
10640
10781
  },
10641
10782
  sections: paletteSections,
10783
+ mode: paletteMode,
10642
10784
  showSearch: showPaletteSearch,
10643
10785
  searchPlaceholder: paletteSearchPlaceholder,
10644
10786
  defaultOpenSections,