composeai 0.1.3 → 0.1.4

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
@@ -797,11 +797,11 @@ function EditorShell({
797
797
  }) {
798
798
  const { classNames, sx, dir } = useComposerContext();
799
799
  const isMarkdown = mode === "markdown";
800
- const editorClass = multiline ? "composer-editor min-h-[44px] max-h-56 scrollbar-thin overflow-y-auto px-5 py-3.5" : "composer-editor composer-editor--inline h-9 overflow-x-auto overflow-y-hidden whitespace-nowrap px-2 leading-9";
800
+ const editorClass = multiline ? "composer-editor composer-editor--multiline" : "composer-editor composer-editor--inline";
801
801
  const editor = slotProps("editor", editorClass, classNames, sx);
802
802
  const editorResolved = resolveSx(sx?.editor);
803
803
  const placeholderBase = mirrorEditorPadding(editorResolved);
804
- const placeholderClass = multiline ? "composer-placeholder pointer-events-none absolute inset-x-0 top-0 select-none px-5 py-3.5 text-[15px] leading-relaxed text-muted-foreground" : "composer-placeholder pointer-events-none absolute inset-y-0 inset-x-0 select-none px-2 text-[15px] leading-9 text-muted-foreground truncate";
804
+ const placeholderClass = multiline ? "composer-placeholder composer-placeholder--multiline" : "composer-placeholder composer-placeholder--inline";
805
805
  const placeholderProps = slotProps(
806
806
  "placeholder",
807
807
  placeholderClass,
@@ -815,9 +815,9 @@ function EditorShell({
815
815
  "div",
816
816
  {
817
817
  className: cn(
818
- "composer-editor-block relative min-w-0",
818
+ "composer-editor-block",
819
819
  // Inline: the editor block is the flex child that fills the row.
820
- !multiline && "flex-1"
820
+ !multiline && "composer-editor-block--inline"
821
821
  ),
822
822
  children: isMarkdown ? /* @__PURE__ */ jsxRuntime.jsx(
823
823
  LexicalRichTextPlugin.RichTextPlugin,
@@ -839,10 +839,10 @@ function EditorShell({
839
839
  if (!multiline) {
840
840
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
841
841
  header,
842
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "composer-inline-row flex items-center gap-1 px-2 py-1.5", children: [
843
- toolbar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-inline-toolbar flex shrink-0 items-center", children: toolbar }),
842
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "composer-inline-row", children: [
843
+ toolbar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-inline-toolbar", children: toolbar }),
844
844
  editorBlock,
845
- sendButton && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-inline-send flex shrink-0 items-center", children: sendButton })
845
+ sendButton && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-inline-send", children: sendButton })
846
846
  ] }),
847
847
  /* @__PURE__ */ jsxRuntime.jsx(LexicalHistoryPlugin.HistoryPlugin, {})
848
848
  ] });
@@ -850,7 +850,7 @@ function EditorShell({
850
850
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
851
851
  header,
852
852
  editorBlock,
853
- (toolbar || sendButton) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-3 pb-2.5", children: [
853
+ (toolbar || sendButton) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "composer-toolbar-row", children: [
854
854
  toolbar ?? /* @__PURE__ */ jsxRuntime.jsx("span", {}),
855
855
  sendButton
856
856
  ] }),
@@ -2344,14 +2344,15 @@ function ImageLightbox({ src, alt, onClose }) {
2344
2344
  {
2345
2345
  role: "dialog",
2346
2346
  "aria-modal": "true",
2347
- className: "fixed inset-0 z-50 flex items-center justify-center p-6",
2347
+ "data-composer-scope": "",
2348
+ className: "composer-lightbox",
2348
2349
  style: tokenStyle,
2349
2350
  children: [
2350
2351
  /* @__PURE__ */ jsxRuntime.jsx(
2351
2352
  "div",
2352
2353
  {
2353
2354
  "aria-hidden": true,
2354
- className: "absolute inset-0 bg-foreground/70 backdrop-blur-sm",
2355
+ className: "composer-lightbox-backdrop",
2355
2356
  onClick: onClose
2356
2357
  }
2357
2358
  ),
@@ -2361,18 +2362,11 @@ function ImageLightbox({ src, alt, onClose }) {
2361
2362
  type: "button",
2362
2363
  onClick: onClose,
2363
2364
  "aria-label": "Close",
2364
- className: "absolute end-5 top-5 flex h-9 w-9 items-center justify-center rounded-full bg-card text-foreground shadow-soft transition-colors hover:bg-accent",
2365
- children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "h-4 w-4" })
2365
+ className: "composer-lightbox-close",
2366
+ children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {})
2366
2367
  }
2367
2368
  ),
2368
- /* @__PURE__ */ jsxRuntime.jsx(
2369
- "img",
2370
- {
2371
- src,
2372
- alt,
2373
- className: "relative max-h-[85vh] max-w-[85vw] rounded-lg object-contain shadow-xl"
2374
- }
2375
- )
2369
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt, className: "composer-lightbox-img" })
2376
2370
  ]
2377
2371
  }
2378
2372
  ) });
@@ -2500,16 +2494,16 @@ function MermaidPlugin() {
2500
2494
  if (diagrams.length === 0) return null;
2501
2495
  const preview = slotProps(
2502
2496
  "mermaidPreview",
2503
- "border-t border-border/60 bg-muted/30 px-4 py-3",
2497
+ "composer-mermaid",
2504
2498
  classNames,
2505
2499
  sx
2506
2500
  );
2507
2501
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...preview, children: [
2508
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1.5 flex items-center gap-1.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: [
2509
- /* @__PURE__ */ jsxRuntime.jsx(SparkleIcon, { className: "h-3 w-3" }),
2502
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "composer-mermaid-head", children: [
2503
+ /* @__PURE__ */ jsxRuntime.jsx(SparkleIcon, {}),
2510
2504
  "Diagram preview"
2511
2505
  ] }),
2512
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2 overflow-x-auto scrollbar-thin", children: diagrams.map((d) => /* @__PURE__ */ jsxRuntime.jsx(
2506
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-mermaid-row", children: diagrams.map((d) => /* @__PURE__ */ jsxRuntime.jsx(
2513
2507
  DiagramTile,
2514
2508
  {
2515
2509
  diagram: d,
@@ -2534,9 +2528,9 @@ function ConsumerTile({
2534
2528
  content = renderDiagram({ code: diagram.code, language: "mermaid" });
2535
2529
  } catch (err) {
2536
2530
  console.error("[composeai] renderDiagram threw", err);
2537
- content = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-24 w-40 items-center justify-center px-2 text-center text-[10px] text-destructive", children: err instanceof Error ? err.message.slice(0, 80) : "Render failed" });
2531
+ content = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-mermaid-msg composer-mermaid-msg--error", children: err instanceof Error ? err.message.slice(0, 80) : "Render failed" });
2538
2532
  }
2539
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 overflow-hidden rounded-lg border border-border bg-card", children: content });
2533
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-mermaid-tile", children: content });
2540
2534
  }
2541
2535
  function MermaidTile({ diagram }) {
2542
2536
  const { icons } = useComposerContext();
@@ -2583,24 +2577,22 @@ function MermaidTile({ diagram }) {
2583
2577
  type: "button",
2584
2578
  onClick: () => svg && setZoom(true),
2585
2579
  "aria-label": "Zoom diagram",
2586
- className: "group/dia relative shrink-0 overflow-hidden rounded-lg border border-border bg-card transition-colors hover:border-primary/40",
2580
+ className: "composer-mermaid-tile",
2587
2581
  children: svg ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2588
2582
  /* @__PURE__ */ jsxRuntime.jsx(
2589
2583
  "div",
2590
2584
  {
2591
- className: "h-24 w-40 [&_svg]:h-full [&_svg]:w-full",
2585
+ className: "composer-mermaid-svg",
2592
2586
  dangerouslySetInnerHTML: { __html: svg }
2593
2587
  }
2594
2588
  ),
2595
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute end-1 top-1 flex h-5 w-5 items-center justify-center rounded-full bg-foreground/70 text-background opacity-0 transition-opacity group-hover/dia:opacity-100", children: /* @__PURE__ */ jsxRuntime.jsx(ZoomIcon, { className: "h-3 w-3" }) })
2596
- ] }) : mermaidMissing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid h-24 w-40 place-items-center px-3 text-center text-[11px] leading-snug text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2589
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-mermaid-zoom", children: /* @__PURE__ */ jsxRuntime.jsx(ZoomIcon, {}) })
2590
+ ] }) : mermaidMissing ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-mermaid-msg", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2597
2591
  "Install ",
2598
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "rounded bg-muted px-1 font-mono", children: "mermaid" }),
2599
- " ",
2600
- "or pass",
2601
- " ",
2602
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "rounded bg-muted px-1 font-mono", children: "renderDiagram" })
2603
- ] }) }) : error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid h-24 w-40 place-items-center px-2 text-center text-[10px] leading-snug text-destructive", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: error.slice(0, 80) }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid h-24 w-40 place-items-center text-[10px] text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rendering\u2026" }) })
2592
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "composer-mermaid-code", children: "mermaid" }),
2593
+ " or pass ",
2594
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "composer-mermaid-code", children: "renderDiagram" })
2595
+ ] }) }) : error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-mermaid-msg composer-mermaid-msg--error", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: error.slice(0, 80) }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-mermaid-msg", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Rendering\u2026" }) })
2604
2596
  }
2605
2597
  ),
2606
2598
  zoom && svg && /* @__PURE__ */ jsxRuntime.jsx(
@@ -2639,7 +2631,7 @@ function SlashMenu({
2639
2631
  );
2640
2632
  const menu = slotProps(
2641
2633
  "slashMenu",
2642
- "z-50 w-72 origin-top animate-slide-up overflow-hidden rounded-xl border border-border bg-popover text-popover-foreground shadow-soft",
2634
+ "composer-menu composer-menu--slash",
2643
2635
  classNames,
2644
2636
  sx
2645
2637
  );
@@ -2653,10 +2645,10 @@ function SlashMenu({
2653
2645
  "aria-label": "Slash commands",
2654
2646
  "aria-busy": isLoading || void 0,
2655
2647
  ...menu,
2656
- children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { ref: listRef, className: "max-h-72 overflow-y-auto scrollbar-thin py-1", children: [
2648
+ children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { ref: listRef, className: "composer-menu-list", children: [
2657
2649
  showSkeleton && /* @__PURE__ */ jsxRuntime.jsx(SlashSkeleton, { rows: 4 }),
2658
2650
  Object.entries(grouped).map(([group, entries]) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
2659
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: group }),
2651
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "composer-menu-group", children: group }),
2660
2652
  /* @__PURE__ */ jsxRuntime.jsx("ul", { children: entries.map(({ item, index }) => /* @__PURE__ */ jsxRuntime.jsxs(
2661
2653
  "li",
2662
2654
  {
@@ -2668,19 +2660,15 @@ function SlashMenu({
2668
2660
  onSelect(index);
2669
2661
  },
2670
2662
  onMouseEnter: () => onHover(index),
2671
- className: cn(
2672
- "flex cursor-pointer items-center gap-2.5 px-2.5 py-1.5 text-sm",
2673
- selectedIndex === index ? "bg-accent text-accent-foreground" : "text-foreground",
2674
- classNames?.slashItem
2675
- ),
2663
+ className: cn("composer-menu-item", classNames?.slashItem),
2676
2664
  style: itemStyle,
2677
2665
  children: [
2678
- item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground", children: item.icon }),
2679
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col leading-tight", children: [
2680
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: item.label }),
2681
- item.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: item.description })
2666
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-menu-icon", children: item.icon }),
2667
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "composer-menu-text", children: [
2668
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-menu-label", children: item.label }),
2669
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-menu-desc", children: item.description })
2682
2670
  ] }),
2683
- item.shortcut && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ms-auto rounded border border-border bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
2671
+ item.shortcut && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-menu-shortcut", children: item.shortcut })
2684
2672
  ]
2685
2673
  },
2686
2674
  item.id
@@ -2691,35 +2679,28 @@ function SlashMenu({
2691
2679
  );
2692
2680
  }
2693
2681
  function SlashSkeleton({ rows = 4 }) {
2694
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { "aria-hidden": "true", className: "px-2.5 py-1.5", children: [
2695
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-0.5 pb-1.5 pt-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block h-2 w-16 animate-pulse rounded bg-muted/70" }) }),
2696
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-1", children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs(
2697
- "li",
2698
- {
2699
- className: "flex items-center gap-2.5 rounded-md px-0 py-1.5",
2700
- children: [
2701
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-7 w-7 shrink-0 animate-pulse rounded-md bg-muted" }),
2702
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [
2703
- /* @__PURE__ */ jsxRuntime.jsx(
2704
- "span",
2705
- {
2706
- className: "h-2.5 animate-pulse rounded bg-muted",
2707
- style: { width: `${50 + i * 19 % 35}%` }
2708
- }
2709
- ),
2710
- /* @__PURE__ */ jsxRuntime.jsx(
2711
- "span",
2712
- {
2713
- className: "h-2 animate-pulse rounded bg-muted/70",
2714
- style: { width: `${30 + i * 13 % 30}%` }
2715
- }
2716
- )
2717
- ] })
2718
- ]
2719
- },
2720
- i
2721
- )) }),
2722
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading commands\u2026" })
2682
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { "aria-hidden": "true", className: "composer-skel-row", children: [
2683
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-skel-grouplabel composer-pulse" }),
2684
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "composer-skel-group", children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "composer-skel-line", children: [
2685
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-skel-avatar composer-skel-avatar--square composer-pulse" }),
2686
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "composer-skel-text", children: [
2687
+ /* @__PURE__ */ jsxRuntime.jsx(
2688
+ "span",
2689
+ {
2690
+ className: "composer-skel-bar composer-pulse",
2691
+ style: { width: `${50 + i * 19 % 35}%` }
2692
+ }
2693
+ ),
2694
+ /* @__PURE__ */ jsxRuntime.jsx(
2695
+ "span",
2696
+ {
2697
+ className: "composer-skel-bar--sm composer-pulse",
2698
+ style: { width: `${30 + i * 13 % 30}%` }
2699
+ }
2700
+ )
2701
+ ] })
2702
+ ] }, i)) }),
2703
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-sr-only", children: "Loading commands\u2026" })
2723
2704
  ] });
2724
2705
  }
2725
2706
  var MARGIN = 8;
@@ -2886,6 +2867,7 @@ function SmartPopover({ children, gap = 6 }) {
2886
2867
  "div",
2887
2868
  {
2888
2869
  ref,
2870
+ "data-composer-scope": "",
2889
2871
  "data-composer-popover-placement": placement?.bottom !== void 0 ? "above-composer" : "below",
2890
2872
  dir: placement?.rtl ? "rtl" : "ltr",
2891
2873
  style: mergedStyle,
@@ -3035,14 +3017,14 @@ function Avatar({ src, alt, size = 28, className }) {
3035
3017
  return /* @__PURE__ */ jsxRuntime.jsx(
3036
3018
  "span",
3037
3019
  {
3038
- className: "inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full bg-primary/10 text-xs font-semibold text-primary" + (className ? ` ${className}` : ""),
3020
+ className: "composer-avatar" + (className ? ` ${className}` : ""),
3039
3021
  style: { width: size, height: size },
3040
3022
  children: showImage ? /* @__PURE__ */ jsxRuntime.jsx(
3041
3023
  "img",
3042
3024
  {
3043
3025
  src,
3044
3026
  alt,
3045
- className: "h-full w-full object-cover",
3027
+ className: "composer-avatar-img",
3046
3028
  onError: () => setErrored(true)
3047
3029
  }
3048
3030
  ) : initial
@@ -3064,12 +3046,7 @@ function MentionMenu({
3064
3046
  );
3065
3047
  if (el) el.scrollIntoView({ block: "nearest" });
3066
3048
  }, [selectedIndex]);
3067
- const menu = slotProps(
3068
- "mentionMenu",
3069
- "z-50 w-64 origin-top animate-slide-up overflow-hidden rounded-xl border border-border bg-popover text-popover-foreground shadow-soft",
3070
- classNames,
3071
- sx
3072
- );
3049
+ const menu = slotProps("mentionMenu", "composer-menu", classNames, sx);
3073
3050
  const itemStyle = react.useMemo(() => resolveSx(sx?.mentionItem), [sx]);
3074
3051
  const showSkeleton = isLoading && options.length === 0;
3075
3052
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -3080,7 +3057,7 @@ function MentionMenu({
3080
3057
  "aria-label": "Mentions",
3081
3058
  "aria-busy": isLoading || void 0,
3082
3059
  ...menu,
3083
- children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { ref: listRef, className: "max-h-72 overflow-y-auto scrollbar-thin py-1", children: [
3060
+ children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { ref: listRef, className: "composer-menu-list", children: [
3084
3061
  showSkeleton ? /* @__PURE__ */ jsxRuntime.jsx(MentionSkeleton, { rows: 3 }) : null,
3085
3062
  options.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
3086
3063
  "li",
@@ -3093,17 +3070,13 @@ function MentionMenu({
3093
3070
  onSelect(index);
3094
3071
  },
3095
3072
  onMouseEnter: () => onHover(index),
3096
- className: cn(
3097
- "flex cursor-pointer items-center gap-2.5 px-2.5 py-1.5 text-sm",
3098
- selectedIndex === index ? "bg-accent text-accent-foreground" : "text-foreground",
3099
- classNames?.mentionItem
3100
- ),
3073
+ className: cn("composer-menu-item", classNames?.mentionItem),
3101
3074
  style: itemStyle,
3102
3075
  children: [
3103
- item.avatarUrl ? /* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: item.avatarUrl, alt: item.label }) : item.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary/10 text-primary", children: item.icon }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary/10 text-xs font-semibold text-primary", children: item.label.slice(0, 1).toUpperCase() }),
3104
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-col leading-tight", children: [
3105
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: item.label }),
3106
- item.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: item.description })
3076
+ item.avatarUrl ? /* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: item.avatarUrl, alt: item.label }) : item.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-menu-avatar", children: item.icon }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-menu-avatar", children: item.label.slice(0, 1).toUpperCase() }),
3077
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "composer-menu-text", children: [
3078
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-menu-label", children: item.label }),
3079
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-menu-desc", children: item.description })
3107
3080
  ] })
3108
3081
  ]
3109
3082
  },
@@ -3114,34 +3087,27 @@ function MentionMenu({
3114
3087
  );
3115
3088
  }
3116
3089
  function MentionSkeleton({ rows = 3 }) {
3117
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { "aria-hidden": "true", className: "px-2.5 py-1.5", children: [
3118
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-1", children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs(
3119
- "li",
3120
- {
3121
- className: "flex items-center gap-2.5 rounded-md px-0 py-1.5",
3122
- children: [
3123
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-7 w-7 shrink-0 animate-pulse rounded-full bg-muted" }),
3124
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [
3125
- /* @__PURE__ */ jsxRuntime.jsx(
3126
- "span",
3127
- {
3128
- className: "h-2.5 animate-pulse rounded bg-muted",
3129
- style: { width: `${60 + i * 17 % 30}%` }
3130
- }
3131
- ),
3132
- /* @__PURE__ */ jsxRuntime.jsx(
3133
- "span",
3134
- {
3135
- className: "h-2 animate-pulse rounded bg-muted/70",
3136
- style: { width: `${35 + i * 23 % 25}%` }
3137
- }
3138
- )
3139
- ] })
3140
- ]
3141
- },
3142
- i
3143
- )) }),
3144
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Loading suggestions\u2026" })
3090
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { "aria-hidden": "true", className: "composer-skel-row", children: [
3091
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "composer-skel-group", children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "composer-skel-line", children: [
3092
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-skel-avatar composer-pulse" }),
3093
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "composer-skel-text", children: [
3094
+ /* @__PURE__ */ jsxRuntime.jsx(
3095
+ "span",
3096
+ {
3097
+ className: "composer-skel-bar composer-pulse",
3098
+ style: { width: `${60 + i * 17 % 30}%` }
3099
+ }
3100
+ ),
3101
+ /* @__PURE__ */ jsxRuntime.jsx(
3102
+ "span",
3103
+ {
3104
+ className: "composer-skel-bar--sm composer-pulse",
3105
+ style: { width: `${35 + i * 23 % 25}%` }
3106
+ }
3107
+ )
3108
+ ] })
3109
+ ] }, i)) }),
3110
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-sr-only", children: "Loading suggestions\u2026" })
3145
3111
  ] });
3146
3112
  }
3147
3113
  var MentionOption = class extends LexicalTypeaheadMenuPlugin.MenuOption {
@@ -3368,14 +3334,14 @@ function GhostOverlay({ typed, remainder, multiline }) {
3368
3334
  setContainer(block);
3369
3335
  }, [editor]);
3370
3336
  if (!container) return null;
3371
- const paddingClass = multiline ? "composer-ghost-overlay--multiline px-5 py-3.5" : "composer-ghost-overlay--inline px-2 leading-9";
3337
+ const paddingClass = multiline ? "composer-ghost-overlay--multiline" : "composer-ghost-overlay--inline";
3372
3338
  return reactDom.createPortal(
3373
3339
  /* @__PURE__ */ jsxRuntime.jsxs(
3374
3340
  "div",
3375
3341
  {
3376
3342
  "aria-hidden": true,
3377
3343
  "data-composer-ghost": "",
3378
- className: `composer-ghost-overlay pointer-events-none absolute inset-0 select-none ${paddingClass}`,
3344
+ className: `composer-ghost-overlay ${paddingClass}`,
3379
3345
  children: [
3380
3346
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-ghost-overlay-typed", "aria-hidden": true, children: typed }),
3381
3347
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-ghost-suggestion", children: remainder })
@@ -3407,7 +3373,7 @@ function AttachmentChip({ attachment, onRemove, onZoom }) {
3407
3373
  if (isImage) {
3408
3374
  const chip2 = slotProps(
3409
3375
  "attachmentChip",
3410
- "group/chip relative h-16 w-16 overflow-hidden rounded-xl border border-border bg-muted",
3376
+ "composer-chip composer-chip--image",
3411
3377
  classNames,
3412
3378
  sx
3413
3379
  );
@@ -3417,23 +3383,23 @@ function AttachmentChip({ attachment, onRemove, onZoom }) {
3417
3383
  {
3418
3384
  src: attachment.previewUrl,
3419
3385
  alt: attachment.name,
3420
- className: "h-full w-full object-cover"
3386
+ className: "composer-chip-img"
3421
3387
  }
3422
3388
  ),
3423
3389
  isUploading && /* @__PURE__ */ jsxRuntime.jsx(
3424
3390
  "div",
3425
3391
  {
3426
3392
  "aria-label": "Uploading",
3427
- className: "absolute inset-0 grid place-items-center bg-foreground/50",
3428
- children: /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, { className: "h-5 w-5 animate-spin text-background" })
3393
+ className: "composer-chip-overlay composer-chip-overlay--uploading",
3394
+ children: /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, { className: "composer-spin" })
3429
3395
  }
3430
3396
  ),
3431
3397
  isFailed && /* @__PURE__ */ jsxRuntime.jsx(
3432
3398
  "div",
3433
3399
  {
3434
3400
  "aria-label": "Upload failed",
3435
- className: "absolute inset-0 grid place-items-center bg-destructive/55",
3436
- children: /* @__PURE__ */ jsxRuntime.jsx(WarningIcon, { className: "h-5 w-5 text-destructive-foreground" })
3401
+ className: "composer-chip-overlay composer-chip-overlay--failed",
3402
+ children: /* @__PURE__ */ jsxRuntime.jsx(WarningIcon, {})
3437
3403
  }
3438
3404
  ),
3439
3405
  !isUploading && !isFailed && /* @__PURE__ */ jsxRuntime.jsx(
@@ -3442,8 +3408,8 @@ function AttachmentChip({ attachment, onRemove, onZoom }) {
3442
3408
  type: "button",
3443
3409
  onClick: onZoom,
3444
3410
  "aria-label": `Zoom ${attachment.name}`,
3445
- className: "absolute inset-0 flex items-center justify-center bg-foreground/40 opacity-0 transition-opacity group-hover/chip:opacity-100",
3446
- children: /* @__PURE__ */ jsxRuntime.jsx(ZoomIcon, { className: "h-4 w-4 text-background" })
3411
+ className: "composer-chip-zoom",
3412
+ children: /* @__PURE__ */ jsxRuntime.jsx(ZoomIcon, {})
3447
3413
  }
3448
3414
  ),
3449
3415
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3452,8 +3418,9 @@ function AttachmentChip({ attachment, onRemove, onZoom }) {
3452
3418
  type: "button",
3453
3419
  onClick: onRemove,
3454
3420
  "aria-label": `Remove ${attachment.name}`,
3455
- className: "absolute end-1 top-1 z-10 flex h-5 w-5 items-center justify-center rounded-full bg-foreground text-background transition-opacity " + (isUploading || isFailed ? "opacity-100" : "opacity-0 group-hover/chip:opacity-100"),
3456
- children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "h-3 w-3", strokeWidth: 2.5 })
3421
+ className: "composer-chip-remove",
3422
+ "data-visible": isUploading || isFailed ? "" : void 0,
3423
+ children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { strokeWidth: 2.5 })
3457
3424
  }
3458
3425
  )
3459
3426
  ] });
@@ -3461,27 +3428,15 @@ function AttachmentChip({ attachment, onRemove, onZoom }) {
3461
3428
  const KindIcon = attachment.kind === "audio" ? AudioIcon : FileIcon;
3462
3429
  const chip = slotProps(
3463
3430
  "attachmentChip",
3464
- "group/chip flex items-center gap-2 rounded-xl border bg-card ps-2 pe-1 py-1.5 " + (isFailed ? "border-destructive/60" : "border-border"),
3431
+ "composer-chip composer-chip--file",
3465
3432
  classNames,
3466
3433
  sx
3467
3434
  );
3468
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...chip, title: titleText, children: [
3469
- /* @__PURE__ */ jsxRuntime.jsx(
3470
- "span",
3471
- {
3472
- className: "flex h-8 w-8 items-center justify-center rounded-md " + (isFailed ? "bg-destructive/15 text-destructive" : "bg-muted text-muted-foreground"),
3473
- children: isUploading ? /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, { className: "h-4 w-4 animate-spin" }) : isFailed ? /* @__PURE__ */ jsxRuntime.jsx(WarningIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(KindIcon, { className: "h-4 w-4" })
3474
- }
3475
- ),
3476
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col", children: [
3477
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-[160px] truncate text-xs font-medium leading-tight", children: attachment.name }),
3478
- /* @__PURE__ */ jsxRuntime.jsx(
3479
- "span",
3480
- {
3481
- className: "text-[10px] " + (isFailed ? "text-destructive" : "text-muted-foreground"),
3482
- children: isUploading ? "Uploading\u2026" : isFailed ? attachment.error || "Upload failed" : formatBytes(attachment.size)
3483
- }
3484
- )
3435
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...chip, "data-failed": isFailed ? "" : void 0, title: titleText, children: [
3436
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-chip-icon", "data-failed": isFailed ? "" : void 0, children: isUploading ? /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, { className: "composer-spin" }) : isFailed ? /* @__PURE__ */ jsxRuntime.jsx(WarningIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(KindIcon, {}) }),
3437
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "composer-chip-text", children: [
3438
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-chip-name", children: attachment.name }),
3439
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-chip-meta", "data-failed": isFailed ? "" : void 0, children: isUploading ? "Uploading\u2026" : isFailed ? attachment.error || "Upload failed" : formatBytes(attachment.size) })
3485
3440
  ] }),
3486
3441
  /* @__PURE__ */ jsxRuntime.jsx(
3487
3442
  "button",
@@ -3489,8 +3444,8 @@ function AttachmentChip({ attachment, onRemove, onZoom }) {
3489
3444
  type: "button",
3490
3445
  onClick: onRemove,
3491
3446
  "aria-label": `Remove ${attachment.name}`,
3492
- className: "flex h-6 w-6 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
3493
- children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "h-3.5 w-3.5" })
3447
+ className: "composer-chip-remove-inline",
3448
+ children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {})
3494
3449
  }
3495
3450
  )
3496
3451
  ] });
@@ -3501,7 +3456,7 @@ function AttachmentTray() {
3501
3456
  if (attachments.length === 0) return null;
3502
3457
  const tray = slotProps(
3503
3458
  "attachmentTray",
3504
- "flex flex-wrap gap-2 px-4 pt-3",
3459
+ "composer-attachment-tray",
3505
3460
  classNames,
3506
3461
  sx
3507
3462
  );
@@ -3526,10 +3481,10 @@ function AttachmentTray() {
3526
3481
  ] });
3527
3482
  }
3528
3483
  var sideClasses = {
3529
- top: "bottom-full left-1/2 mb-2 -translate-x-1/2",
3530
- bottom: "top-full left-1/2 mt-2 -translate-x-1/2",
3531
- left: "end-full top-1/2 me-2 -translate-y-1/2",
3532
- right: "start-full top-1/2 ms-2 -translate-y-1/2"
3484
+ top: "composer-tooltip--top",
3485
+ bottom: "composer-tooltip--bottom",
3486
+ left: "composer-tooltip--left",
3487
+ right: "composer-tooltip--right"
3533
3488
  };
3534
3489
  function Tooltip({
3535
3490
  children,
@@ -3567,18 +3522,14 @@ function Tooltip({
3567
3522
  children
3568
3523
  }
3569
3524
  );
3570
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative inline-flex", children: [
3525
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "composer-tooltip-wrap", children: [
3571
3526
  trigger,
3572
3527
  open && /* @__PURE__ */ jsxRuntime.jsx(
3573
3528
  "span",
3574
3529
  {
3575
3530
  id,
3576
3531
  role: "tooltip",
3577
- className: cn(
3578
- "absolute z-50 whitespace-nowrap rounded-md bg-foreground px-2 py-1 text-xs text-background shadow-md",
3579
- sideClasses[side],
3580
- className
3581
- ),
3532
+ className: cn("composer-tooltip", sideClasses[side], className),
3582
3533
  children: content
3583
3534
  }
3584
3535
  )
@@ -3728,7 +3679,7 @@ function VoiceButton() {
3728
3679
  }
3729
3680
  };
3730
3681
  const isRecording = state === "recording" || state === "starting";
3731
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
3682
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "composer-voice", children: [
3732
3683
  /* @__PURE__ */ jsxRuntime.jsx(
3733
3684
  Tooltip,
3734
3685
  {
@@ -3742,17 +3693,16 @@ function VoiceButton() {
3742
3693
  "aria-pressed": isRecording,
3743
3694
  onClick: () => isRecording ? stop() : void start(),
3744
3695
  className: cn(
3745
- "flex h-8 w-8 items-center justify-center rounded-full transition-colors",
3746
- isRecording ? "bg-destructive/10 text-destructive ring-1 ring-destructive/40" : "text-muted-foreground hover:bg-accent hover:text-foreground",
3696
+ "composer-toolbar-btn composer-voice-btn",
3747
3697
  classNames?.toolbarButton
3748
3698
  ),
3749
- children: state === "transcribing" ? /* @__PURE__ */ jsxRuntime.jsx(VoiceRecordingIcon, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(VoiceIcon, { className: cn("h-4 w-4", isRecording && "animate-pulse") })
3699
+ children: state === "transcribing" ? /* @__PURE__ */ jsxRuntime.jsx(VoiceRecordingIcon, { className: "composer-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(VoiceIcon, { className: cn(isRecording && "composer-pulse") })
3750
3700
  }
3751
3701
  )
3752
3702
  }
3753
3703
  ),
3754
- isRecording && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 rounded-full bg-destructive/10 px-2 py-0.5 text-[11px] font-mono font-medium tabular-nums text-destructive", children: [
3755
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 animate-pulse rounded-full bg-destructive" }),
3704
+ isRecording && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "composer-voice-timer", children: [
3705
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-voice-dot composer-pulse" }),
3756
3706
  formatSeconds(elapsed)
3757
3707
  ] })
3758
3708
  ] });
@@ -3850,7 +3800,7 @@ function AttachmentTypePicker({
3850
3800
  react.useEffect(() => {
3851
3801
  if (open) setActiveIndex(0);
3852
3802
  }, [open]);
3853
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
3803
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "composer-attach-picker", children: [
3854
3804
  /* @__PURE__ */ jsxRuntime.jsx(
3855
3805
  "input",
3856
3806
  {
@@ -3877,7 +3827,7 @@ function AttachmentTypePicker({
3877
3827
  onClick: () => setOpen((o) => !o),
3878
3828
  className: triggerClassName,
3879
3829
  style: triggerStyle,
3880
- children: /* @__PURE__ */ jsxRuntime.jsx(TriggerIcon, { className: "h-4 w-4" })
3830
+ children: /* @__PURE__ */ jsxRuntime.jsx(TriggerIcon, {})
3881
3831
  }
3882
3832
  ),
3883
3833
  open && /* @__PURE__ */ jsxRuntime.jsx(
@@ -3888,11 +3838,7 @@ function AttachmentTypePicker({
3888
3838
  role: "menu",
3889
3839
  "aria-label": "Attachment types",
3890
3840
  "data-composer-popover": "open",
3891
- className: cn(
3892
- "composer-popover-in absolute bottom-full start-0 z-30 mb-2 min-w-[200px] overflow-hidden",
3893
- "rounded-xl border border-border bg-popover p-1 text-popover-foreground",
3894
- "shadow-soft"
3895
- ),
3841
+ className: "composer-popover-in composer-attach-menu",
3896
3842
  children: types.map((type, index) => {
3897
3843
  const active = index === activeIndex;
3898
3844
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -3904,16 +3850,14 @@ function AttachmentTypePicker({
3904
3850
  role: "menuitem",
3905
3851
  type: "button",
3906
3852
  tabIndex: active ? 0 : -1,
3853
+ "data-active": active ? "" : void 0,
3907
3854
  onMouseEnter: () => setActiveIndex(index),
3908
3855
  onClick: () => pick(index),
3909
- className: cn(
3910
- "flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-start text-sm transition-colors",
3911
- active ? "bg-accent text-accent-foreground" : "text-foreground hover:bg-accent/60"
3912
- ),
3856
+ className: "composer-attach-item",
3913
3857
  children: [
3914
- type.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center text-muted-foreground", children: type.icon }) : null,
3915
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate font-medium", children: type.label }),
3916
- type.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 font-mono text-[11px] text-muted-foreground", children: type.description }) : null
3858
+ type.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-attach-item-icon", children: type.icon }) : null,
3859
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-attach-item-label", children: type.label }),
3860
+ type.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-attach-item-desc", children: type.description }) : null
3917
3861
  ]
3918
3862
  },
3919
3863
  type.id
@@ -3923,7 +3867,7 @@ function AttachmentTypePicker({
3923
3867
  )
3924
3868
  ] });
3925
3869
  }
3926
- var TOOLBAR_BTN_BASE = "flex h-8 w-8 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground";
3870
+ var TOOLBAR_BTN_BASE = "composer-toolbar-btn";
3927
3871
  function Toolbar({ extras }) {
3928
3872
  const {
3929
3873
  features,
@@ -3942,7 +3886,7 @@ function Toolbar({ extras }) {
3942
3886
  const showFileBtn = attachmentsEnabled && attachmentsConfig.file !== false;
3943
3887
  const showImageBtn = attachmentsEnabled && attachmentsConfig.image !== false;
3944
3888
  const hasTypePicker = showFileBtn && Array.isArray(attachmentsConfig.types) && attachmentsConfig.types.length > 0;
3945
- const toolbar = slotProps("toolbar", "flex items-center gap-1", classNames, sx);
3889
+ const toolbar = slotProps("toolbar", "composer-toolbar", classNames, sx);
3946
3890
  const toolbarBtn = slotProps("toolbarButton", TOOLBAR_BTN_BASE, classNames, sx);
3947
3891
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...toolbar, children: [
3948
3892
  showFileBtn && !hasTypePicker && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -3968,7 +3912,7 @@ function Toolbar({ extras }) {
3968
3912
  "aria-label": "Attach file",
3969
3913
  onClick: () => fileInputRef.current?.click(),
3970
3914
  ...toolbarBtn,
3971
- children: /* @__PURE__ */ jsxRuntime.jsx(AttachIcon, { className: "h-4 w-4" })
3915
+ children: /* @__PURE__ */ jsxRuntime.jsx(AttachIcon, {})
3972
3916
  }
3973
3917
  ) })
3974
3918
  ] }),
@@ -4005,7 +3949,7 @@ function Toolbar({ extras }) {
4005
3949
  "aria-label": "Add image",
4006
3950
  onClick: () => imageInputRef.current?.click(),
4007
3951
  ...toolbarBtn,
4008
- children: /* @__PURE__ */ jsxRuntime.jsx(ImageIcon, { className: "h-4 w-4" })
3952
+ children: /* @__PURE__ */ jsxRuntime.jsx(ImageIcon, {})
4009
3953
  }
4010
3954
  ) })
4011
3955
  ] }),
@@ -4016,13 +3960,9 @@ function Toolbar({ extras }) {
4016
3960
  type: "button",
4017
3961
  onClick: toggleWeb,
4018
3962
  "aria-pressed": webEnabled,
4019
- className: cn(
4020
- "ms-0.5 inline-flex h-8 items-center gap-1.5 rounded-full px-2.5 text-xs font-medium transition-colors",
4021
- webEnabled ? "bg-primary/10 text-primary" : "text-muted-foreground hover:bg-accent hover:text-foreground",
4022
- classNames?.toolbarButton
4023
- ),
3963
+ className: cn("composer-web-btn", classNames?.toolbarButton),
4024
3964
  children: [
4025
- /* @__PURE__ */ jsxRuntime.jsx(WebIcon, { className: "h-3.5 w-3.5" }),
3965
+ /* @__PURE__ */ jsxRuntime.jsx(WebIcon, {}),
4026
3966
  "Web"
4027
3967
  ]
4028
3968
  }
@@ -4036,7 +3976,7 @@ function SendButton({ canSend, isStreaming, onSend, onStop }) {
4036
3976
  if (isStreaming) {
4037
3977
  const stop = slotProps(
4038
3978
  "stopButton",
4039
- "inline-flex h-9 w-9 items-center justify-center rounded-full bg-foreground text-background transition-transform hover:scale-105",
3979
+ "composer-send-btn composer-send-btn--stop",
4040
3980
  classNames,
4041
3981
  sx
4042
3982
  );
@@ -4051,17 +3991,9 @@ function SendButton({ canSend, isStreaming, onSend, onStop }) {
4051
3991
  }
4052
3992
  );
4053
3993
  }
4054
- return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onStop, "aria-label": "Stop generating", ...stop, children: /* @__PURE__ */ jsxRuntime.jsx(StopIcon, { className: "h-3.5 w-3.5 fill-current" }) });
3994
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: onStop, "aria-label": "Stop generating", ...stop, children: /* @__PURE__ */ jsxRuntime.jsx(StopIcon, {}) });
4055
3995
  }
4056
- const send = slotProps(
4057
- "sendButton",
4058
- [
4059
- "inline-flex h-9 w-9 items-center justify-center rounded-full transition-all",
4060
- canSend ? "bg-foreground text-background shadow-sm hover:scale-105" : "bg-muted text-muted-foreground/60"
4061
- ],
4062
- classNames,
4063
- sx
4064
- );
3996
+ const send = slotProps("sendButton", "composer-send-btn", classNames, sx);
4065
3997
  if (slots.sendButton) {
4066
3998
  const Slot = slots.sendButton;
4067
3999
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -4082,14 +4014,14 @@ function SendButton({ canSend, isStreaming, onSend, onStop }) {
4082
4014
  disabled: !canSend,
4083
4015
  "aria-label": "Send message",
4084
4016
  ...send,
4085
- children: /* @__PURE__ */ jsxRuntime.jsx(SendIcon, { className: "h-4 w-4", strokeWidth: 2.5 })
4017
+ children: /* @__PURE__ */ jsxRuntime.jsx(SendIcon, { strokeWidth: 2.5 })
4086
4018
  }
4087
4019
  );
4088
4020
  }
4089
4021
  function noop() {
4090
4022
  }
4091
4023
  function Key({ children }) {
4092
- return /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "rounded border border-border bg-card px-1 py-0.5 font-mono text-[10px]", children });
4024
+ return /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "composer-kbd", children });
4093
4025
  }
4094
4026
  function formatShortcut(spec) {
4095
4027
  const parts = spec.split("+").map((s) => s.trim().toLowerCase()).filter(Boolean);
@@ -4180,19 +4112,14 @@ function HintBar({ hint }) {
4180
4112
  ] });
4181
4113
  }, [focusShortcut]);
4182
4114
  if (!hint) return null;
4183
- const hintProps = slotProps(
4184
- "hint",
4185
- "text-center text-[11px] text-muted-foreground",
4186
- classNames,
4187
- sx
4188
- );
4115
+ const hintProps = slotProps("hint", "composer-hint", classNames, sx);
4189
4116
  return /* @__PURE__ */ jsxRuntime.jsx("p", { ...hintProps, children: hint === true ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4190
4117
  "AI can make mistakes \u2014 verify important info.",
4191
- defaultShortcuts ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden sm:inline", children: [
4118
+ defaultShortcuts ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "composer-hint-sm", children: [
4192
4119
  " ",
4193
4120
  defaultShortcuts
4194
4121
  ] }) : null,
4195
- focusHint ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: focusHint }) : null
4122
+ focusHint ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-hint-md", children: focusHint }) : null
4196
4123
  ] }) : hint });
4197
4124
  }
4198
4125
  var DEFAULT_MAX = 3;
@@ -4223,35 +4150,20 @@ function QuickPrompts({ prompts }) {
4223
4150
  prompts.onSelect?.(prompt);
4224
4151
  runPrompt(prompt, behavior);
4225
4152
  };
4226
- return /* @__PURE__ */ jsxRuntime.jsx(
4227
- "div",
4153
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "group", "aria-label": "Quick prompts", className: "composer-prompts", children: display.map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
4154
+ "button",
4228
4155
  {
4229
- role: "group",
4230
- "aria-label": "Quick prompts",
4231
- className: "flex flex-wrap items-center gap-2 px-1 pb-1",
4232
- children: display.map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
4233
- "button",
4234
- {
4235
- type: "button",
4236
- onClick: () => handleClick(p),
4237
- title: p,
4238
- className: cn(
4239
- "group inline-flex max-w-full items-center gap-1.5 rounded-full",
4240
- "border border-border bg-card/60 px-3 py-1.5 text-xs",
4241
- "text-muted-foreground backdrop-blur transition-all",
4242
- "hover:-translate-y-px hover:border-primary/40 hover:bg-card",
4243
- "hover:text-foreground hover:shadow-sm",
4244
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"
4245
- ),
4246
- children: [
4247
- /* @__PURE__ */ jsxRuntime.jsx(SparkleIcon, { className: "h-3 w-3 shrink-0 text-primary opacity-70 group-hover:opacity-100" }),
4248
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", style: { maxWidth: "32ch" }, children: p })
4249
- ]
4250
- },
4251
- p
4252
- ))
4253
- }
4254
- );
4156
+ type: "button",
4157
+ onClick: () => handleClick(p),
4158
+ title: p,
4159
+ className: "composer-prompt",
4160
+ children: [
4161
+ /* @__PURE__ */ jsxRuntime.jsx(SparkleIcon, {}),
4162
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "composer-prompt-text", style: { maxWidth: "32ch" }, children: p })
4163
+ ]
4164
+ },
4165
+ p
4166
+ )) });
4255
4167
  }
4256
4168
  function useComposerHandle(ref, onSubmit) {
4257
4169
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
@@ -4401,7 +4313,7 @@ var Composer = react.forwardRef(function Composer2(props, ref) {
4401
4313
  if (!derived && !tokens) return void 0;
4402
4314
  return tokensToStyle({ ...derived, ...tokens });
4403
4315
  }, [color, tokens]);
4404
- const root = slotProps("root", "space-y-2", classNames, sx);
4316
+ const root = slotProps("root", "composer-root", classNames, sx);
4405
4317
  const rootStyle = react.useMemo(
4406
4318
  () => ({ ...tokenStyle, ...root.style, ...style }),
4407
4319
  [tokenStyle, root.style, style]
@@ -4429,6 +4341,7 @@ var Composer = react.forwardRef(function Composer2(props, ref) {
4429
4341
  "div",
4430
4342
  {
4431
4343
  dir,
4344
+ "data-composer-scope": "",
4432
4345
  className: cn(root.className, className),
4433
4346
  style: Object.keys(rootStyle).length ? rootStyle : void 0,
4434
4347
  children: [
@@ -4485,16 +4398,7 @@ function ComposerCard({
4485
4398
  multiline
4486
4399
  }) {
4487
4400
  const { webEnabled, isDraggingFiles, classNames, sx } = useComposerContext();
4488
- const card = slotProps(
4489
- "card",
4490
- [
4491
- "group relative border border-border bg-card shadow-soft transition-all focus-within:border-primary/40 focus-within:shadow-glow",
4492
- webEnabled && "ring-1 ring-primary/20",
4493
- isDraggingFiles && "ring-2 ring-primary/60"
4494
- ],
4495
- classNames,
4496
- sx
4497
- );
4401
+ const card = slotProps("card", "composer-card", classNames, sx);
4498
4402
  const initialConfig = react.useMemo(
4499
4403
  () => ({
4500
4404
  namespace: "composeai",
@@ -4512,6 +4416,8 @@ function ComposerCard({
4512
4416
  {
4513
4417
  "data-composer-root": "",
4514
4418
  "data-composer-inline": multiline ? void 0 : "",
4419
+ "data-composer-web": webEnabled ? "" : void 0,
4420
+ "data-composer-dragging": isDraggingFiles ? "" : void 0,
4515
4421
  ...card,
4516
4422
  children: [
4517
4423
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4519,7 +4425,7 @@ function ComposerCard({
4519
4425
  {
4520
4426
  "aria-hidden": true,
4521
4427
  "data-composer-overlay": "",
4522
- className: "pointer-events-none absolute inset-0 opacity-0 transition-opacity group-focus-within:opacity-100",
4428
+ className: "composer-overlay-glow",
4523
4429
  style: {
4524
4430
  background: "linear-gradient(135deg, hsl(var(--primary)/0.08) 0%, transparent 40%, hsl(var(--primary)/0.06) 100%)"
4525
4431
  }
@@ -4530,7 +4436,7 @@ function ComposerCard({
4530
4436
  {
4531
4437
  "aria-hidden": true,
4532
4438
  "data-composer-overlay": "",
4533
- className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center bg-primary/5 text-sm font-medium text-primary backdrop-blur-[1px]",
4439
+ className: "composer-overlay-drop",
4534
4440
  children: "Drop to attach"
4535
4441
  }
4536
4442
  ),
@@ -4729,14 +4635,14 @@ function MermaidSlot() {
4729
4635
  function SuggestionRow({ items, onSelect, className }) {
4730
4636
  const { icons } = useComposerContext();
4731
4637
  const { sparkle: SparkleIcon } = icons;
4732
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-wrap justify-center gap-2", className), children: items.map((s) => /* @__PURE__ */ jsxRuntime.jsxs(
4638
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("composer-suggestions", className), children: items.map((s) => /* @__PURE__ */ jsxRuntime.jsxs(
4733
4639
  "button",
4734
4640
  {
4735
4641
  type: "button",
4736
4642
  onClick: () => onSelect(s),
4737
- className: "group inline-flex items-center gap-1.5 rounded-full border border-border bg-card/60 px-3.5 py-1.5 text-xs text-muted-foreground backdrop-blur transition-all hover:-translate-y-px hover:border-primary/40 hover:bg-card hover:text-foreground hover:shadow-sm",
4643
+ className: "composer-suggestion",
4738
4644
  children: [
4739
- /* @__PURE__ */ jsxRuntime.jsx(SparkleIcon, { className: "h-3 w-3 text-primary opacity-70 group-hover:opacity-100" }),
4645
+ /* @__PURE__ */ jsxRuntime.jsx(SparkleIcon, {}),
4740
4646
  s
4741
4647
  ]
4742
4648
  },