@proteos/ui 0.50.1 → 0.51.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -610,7 +610,7 @@ function IconPicker({
610
610
  const [query, setQuery] = react.useState("");
611
611
  const [limit, setLimit] = react.useState(GRID_PAGE);
612
612
  const triggerRef = react.useRef(null);
613
- const styles3 = fieldControlStyles({ size, invalid: isInvalid, appearance });
613
+ const styles4 = fieldControlStyles({ size, invalid: isInvalid, appearance });
614
614
  const selectedName = resolveLucideIconName(value);
615
615
  const SelectedIcon = selectedName ? lucideReact.icons[selectedName] : null;
616
616
  const matches2 = react.useMemo(() => {
@@ -655,7 +655,7 @@ function IconPicker({
655
655
  onClick: () => open(!isOpen),
656
656
  "data-invalid": isInvalid || void 0,
657
657
  className: chunkMWAXK66H_cjs.cn(
658
- styles3.box(),
658
+ styles4.box(),
659
659
  "flex shrink-0 items-center justify-center cursor-pointer",
660
660
  appearance === "cell" ? "size-[29px]" : COMPACT_SIZE[size],
661
661
  "disabled:cursor-not-allowed disabled:opacity-45"
@@ -676,8 +676,8 @@ function IconPicker({
676
676
  className: chunkMWAXK66H_cjs.cn(
677
677
  // box carries no padding by contract — content is what gives a
678
678
  // single-element control its interior (padding, font, text-size).
679
- styles3.box(),
680
- styles3.content(),
679
+ styles4.box(),
680
+ styles4.content(),
681
681
  "flex w-full items-center gap-2 text-left cursor-pointer",
682
682
  "disabled:cursor-not-allowed disabled:opacity-45"
683
683
  ),
@@ -809,9 +809,7 @@ var badgeStyles = tailwindVariants.tv({
809
809
  base: [
810
810
  "inline-flex items-center gap-1.5",
811
811
  "font-mono text-[11.5px] tracking-[-0.005em]",
812
- "px-2.5 py-0.5 rounded-pill border",
813
- // Leading dot
814
- 'before:content-[""] before:block before:size-1.5 before:rounded-full'
812
+ "px-2.5 py-0.5 border"
815
813
  ],
816
814
  variants: {
817
815
  variant: {
@@ -845,9 +843,18 @@ var badgeStyles = tailwindVariants.tv({
845
843
  "border-[color-mix(in_oklab,var(--badge-color)_35%,var(--color-rule))]",
846
844
  "bg-[color-mix(in_oklab,var(--badge-color)_12%,var(--color-surface))]"
847
845
  ]
846
+ },
847
+ shape: {
848
+ pill: "rounded-pill",
849
+ rounded: "rounded-chip"
850
+ },
851
+ // Leading dot — its color comes from the register's `before:bg-*`.
852
+ hasDot: {
853
+ true: 'before:content-[""] before:block before:size-1.5 before:rounded-full',
854
+ false: ""
848
855
  }
849
856
  },
850
- defaultVariants: { variant: "default" }
857
+ defaultVariants: { variant: "default", shape: "pill", hasDot: true }
851
858
  });
852
859
  var ICON_TONE = {
853
860
  default: "text-ink-4",
@@ -858,16 +865,31 @@ var ICON_TONE = {
858
865
  danger: "text-danger",
859
866
  custom: "text-[var(--badge-color)]"
860
867
  };
861
- function Badge({ variant, color, icon, className, style, children, ...props }) {
868
+ function Badge({
869
+ variant,
870
+ shape,
871
+ hasDot,
872
+ color,
873
+ icon,
874
+ className,
875
+ style,
876
+ children,
877
+ ...props
878
+ }) {
862
879
  const Icon = icon ? resolveLucideIcon(icon) : null;
863
880
  const register2 = color ? "custom" : variant ?? "default";
864
881
  const mergedStyle = color ? { ...style, "--badge-color": color } : style;
882
+ const showDot = hasDot !== false && !Icon;
865
883
  return /* @__PURE__ */ jsxRuntime.jsxs(
866
884
  "span",
867
885
  {
868
886
  ...props,
869
887
  style: mergedStyle,
870
- className: chunkMWAXK66H_cjs.cn(badgeStyles({ variant: register2 }), Icon ? "before:hidden" : null, className),
888
+ className: chunkMWAXK66H_cjs.cn(
889
+ badgeStyles({ variant: register2, shape, hasDot }),
890
+ showDot ? null : "before:hidden",
891
+ className
892
+ ),
871
893
  children: [
872
894
  Icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { "aria-hidden": true, className: chunkMWAXK66H_cjs.cn("size-3 shrink-0", ICON_TONE[register2]) }) : null,
873
895
  children
@@ -878,6 +900,8 @@ function Badge({ variant, color, icon, className, style, children, ...props }) {
878
900
  function badgeChrome(option) {
879
901
  return {
880
902
  ...option.variant ? { variant: option.variant } : {},
903
+ ...option.shape ? { shape: option.shape } : {},
904
+ ...option.hasDot !== void 0 ? { hasDot: option.hasDot } : {},
881
905
  ...option.color ? { color: option.color } : {},
882
906
  ...option.icon ? { icon: option.icon } : {}
883
907
  };
@@ -898,7 +922,7 @@ function BadgeMultiSelect({
898
922
  autoFocus = false,
899
923
  className
900
924
  }) {
901
- const styles3 = fieldControlStyles({ size, invalid: isInvalid, appearance });
925
+ const styles4 = fieldControlStyles({ size, invalid: isInvalid, appearance });
902
926
  const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
903
927
  const minHeight = appearance === "cell" ? "min-h-[29px]" : fieldMinHeight[size];
904
928
  const [isOpen, setIsOpen] = react.useState(false);
@@ -938,7 +962,7 @@ function BadgeMultiSelect({
938
962
  "data-invalid": isInvalid || void 0,
939
963
  "data-disabled": isDisabled || void 0,
940
964
  className: chunkMWAXK66H_cjs.cn(
941
- styles3.box(),
965
+ styles4.box(),
942
966
  "flex flex-wrap items-center gap-1.5 cursor-pointer",
943
967
  minHeight,
944
968
  fieldChipPadding[size],
@@ -1024,13 +1048,11 @@ function BadgeMultiSelect({
1024
1048
  }
1025
1049
  function RemovableBadge({
1026
1050
  children,
1027
- variant,
1028
- color,
1029
- icon,
1030
1051
  onRemove,
1031
- isDisabled
1052
+ isDisabled,
1053
+ ...chrome
1032
1054
  }) {
1033
- return /* @__PURE__ */ jsxRuntime.jsxs(Badge, { ...badgeChrome({ variant, color, icon }), children: [
1055
+ return /* @__PURE__ */ jsxRuntime.jsxs(Badge, { ...badgeChrome(chrome), children: [
1034
1056
  /* @__PURE__ */ jsxRuntime.jsx("span", { children }),
1035
1057
  /* @__PURE__ */ jsxRuntime.jsx(
1036
1058
  "button",
@@ -1384,7 +1406,7 @@ function ColorInput({
1384
1406
  }, [committed]);
1385
1407
  const isDraftInvalid = draft.trim() !== "" && normalizeHexColor(draft) === null;
1386
1408
  const invalid = isInvalid || isDraftInvalid;
1387
- const styles3 = fieldControlStyles({ size, invalid, appearance });
1409
+ const styles4 = fieldControlStyles({ size, invalid, appearance });
1388
1410
  const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
1389
1411
  const edit = (next) => {
1390
1412
  setDraft(next);
@@ -1425,7 +1447,7 @@ function ColorInput({
1425
1447
  {
1426
1448
  "data-disabled": isDisabled || void 0,
1427
1449
  className: chunkMWAXK66H_cjs.cn(
1428
- styles3.box(),
1450
+ styles4.box(),
1429
1451
  "flex items-center gap-2",
1430
1452
  size === "sm" ? "pl-2" : "pl-2.5",
1431
1453
  focusWithin
@@ -1472,7 +1494,7 @@ function ColorInput({
1472
1494
  spellCheck: false,
1473
1495
  autoComplete: "off",
1474
1496
  className: chunkMWAXK66H_cjs.cn(
1475
- styles3.content(),
1497
+ styles4.content(),
1476
1498
  "min-w-0 flex-1 bg-transparent font-mono outline-none",
1477
1499
  "pl-0",
1478
1500
  fieldTextStyles[size]
@@ -1505,7 +1527,7 @@ function Combobox({
1505
1527
  allowsEmptyCollection = true,
1506
1528
  ...props
1507
1529
  }) {
1508
- const styles3 = fieldControlStyles({ size, appearance });
1530
+ const styles4 = fieldControlStyles({ size, appearance });
1509
1531
  const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
1510
1532
  return /* @__PURE__ */ jsxRuntime.jsxs(
1511
1533
  reactAriaComponents.ComboBox,
@@ -1524,7 +1546,7 @@ function Combobox({
1524
1546
  className: chunkMWAXK66H_cjs.cn(
1525
1547
  // Box chrome on the wrapper; the inner <input> carries the padding
1526
1548
  // + font so the chevron button sits inside the same border + ring.
1527
- styles3.box(),
1549
+ styles4.box(),
1528
1550
  "flex items-center gap-1 pr-2",
1529
1551
  focusWithin,
1530
1552
  inputWrapperClassName
@@ -1536,7 +1558,7 @@ function Combobox({
1536
1558
  placeholder,
1537
1559
  className: chunkMWAXK66H_cjs.cn(
1538
1560
  "flex-1 min-w-0 bg-transparent outline-none",
1539
- styles3.content(),
1561
+ styles4.content(),
1540
1562
  inputClassName
1541
1563
  )
1542
1564
  }
@@ -1904,46 +1926,532 @@ function Command({ combo, target, className, children }) {
1904
1926
  discoveryActive ? /* @__PURE__ */ jsxRuntime.jsx(
1905
1927
  "div",
1906
1928
  {
1907
- "aria-hidden": true,
1908
- className: "absolute -inset-2 rounded-md bg-[color-mix(in_oklab,var(--color-ink)_28%,transparent)] pointer-events-none transition-opacity z-40",
1909
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-2.5 -left-2 pointer-events-none z-50", children: /* @__PURE__ */ jsxRuntime.jsx(CommandHint, { combo, tone: "prominent" }) })
1929
+ "aria-hidden": true,
1930
+ className: "absolute -inset-2 rounded-md bg-[color-mix(in_oklab,var(--color-ink)_28%,transparent)] pointer-events-none transition-opacity z-40",
1931
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -top-2.5 -left-2 pointer-events-none z-50", children: /* @__PURE__ */ jsxRuntime.jsx(CommandHint, { combo, tone: "prominent" }) })
1932
+ }
1933
+ ) : null
1934
+ ] });
1935
+ }
1936
+ var stack = [];
1937
+ var listenerInstalled2 = false;
1938
+ function onWindowKeyDown2(event) {
1939
+ if (event.key !== "Escape") return;
1940
+ if (isEditableTarget(event.target)) return;
1941
+ const top = stack[stack.length - 1];
1942
+ if (!top) return;
1943
+ top.handler(event);
1944
+ }
1945
+ function ensureListener2() {
1946
+ if (listenerInstalled2) return;
1947
+ if (typeof window === "undefined") return;
1948
+ window.addEventListener("keydown", onWindowKeyDown2, { capture: true });
1949
+ listenerInstalled2 = true;
1950
+ }
1951
+ function useEscapeKey(handler, options) {
1952
+ const enabled = options?.enabled ?? true;
1953
+ const handlerRef = react.useRef(handler);
1954
+ react.useEffect(() => {
1955
+ handlerRef.current = handler;
1956
+ });
1957
+ react.useEffect(() => {
1958
+ if (!enabled) return void 0;
1959
+ ensureListener2();
1960
+ const entry = {
1961
+ handler: (event) => handlerRef.current(event)
1962
+ };
1963
+ stack.push(entry);
1964
+ return () => {
1965
+ const idx = stack.lastIndexOf(entry);
1966
+ if (idx >= 0) stack.splice(idx, 1);
1967
+ };
1968
+ }, [enabled]);
1969
+ }
1970
+ var conversationBriefCardStyles = tailwindVariants.tv({
1971
+ slots: {
1972
+ root: [
1973
+ "flex items-center gap-2.5 rounded-md border border-accent/40 px-3 py-2",
1974
+ "bg-[color-mix(in_oklab,var(--color-accent)_6%,var(--color-surface))]"
1975
+ ],
1976
+ icon: [
1977
+ "grid size-8 shrink-0 place-items-center rounded-full text-accent",
1978
+ "bg-[color-mix(in_oklab,var(--color-accent)_12%,transparent)]"
1979
+ ],
1980
+ body: "min-w-0 flex-1",
1981
+ eyebrow: "font-mono text-[10px] uppercase tracking-[0.08em] text-accent",
1982
+ title: "truncate text-[13px] font-medium text-ink",
1983
+ summary: "truncate text-[12px] text-ink-3",
1984
+ action: [
1985
+ "shrink-0 cursor-pointer rounded-sm border border-accent/50 px-2.5 py-1",
1986
+ "font-mono text-[11px] text-accent outline-none",
1987
+ "hover:bg-[color-mix(in_oklab,var(--color-accent)_12%,transparent)]",
1988
+ "focus-visible:shadow-[var(--shadow-focus)]",
1989
+ "disabled:cursor-default disabled:opacity-50"
1990
+ ],
1991
+ outcome: "shrink-0 font-mono text-[11px] text-ink-3"
1992
+ }
1993
+ });
1994
+ var styles = conversationBriefCardStyles();
1995
+ var CONVERSATION_BRIEF_OUTCOME_LABEL = {
1996
+ used: "Call held",
1997
+ discarded: "Discarded"
1998
+ };
1999
+ function ConversationBriefCard({
2000
+ title,
2001
+ summary,
2002
+ eyebrow = "Conversation brief \u2014 prepared",
2003
+ openLabel = "Open Brief",
2004
+ outcome,
2005
+ onOpen,
2006
+ isOpenDisabled = false,
2007
+ className
2008
+ }) {
2009
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(styles.root(), className), children: [
2010
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.icon(), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, { className: "size-4", "aria-hidden": true }) }),
2011
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.body(), children: [
2012
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles.eyebrow(), children: eyebrow }),
2013
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles.title(), children: title }),
2014
+ summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles.summary(), children: summary }) : null
2015
+ ] }),
2016
+ outcome ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.outcome(), children: CONVERSATION_BRIEF_OUTCOME_LABEL[outcome] }) : /* @__PURE__ */ jsxRuntime.jsx(
2017
+ reactAriaComponents.Button,
2018
+ {
2019
+ onPress: onOpen ?? (() => {
2020
+ }),
2021
+ isDisabled: isOpenDisabled,
2022
+ className: styles.action(),
2023
+ children: openLabel
2024
+ }
2025
+ )
2026
+ ] });
2027
+ }
2028
+ function Select({
2029
+ label,
2030
+ description,
2031
+ errorMessage,
2032
+ placeholder = "Select\u2026",
2033
+ options,
2034
+ renderItem,
2035
+ size,
2036
+ appearance,
2037
+ triggerClassName,
2038
+ popoverClassName,
2039
+ className,
2040
+ ...props
2041
+ }) {
2042
+ const styles4 = fieldControlStyles({ size, appearance });
2043
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2044
+ reactAriaComponents.Select,
2045
+ {
2046
+ ...props,
2047
+ className: (renderProps) => chunkMWAXK66H_cjs.cn(
2048
+ "grid grid-cols-1 gap-1.5",
2049
+ typeof className === "function" ? className(renderProps) : className
2050
+ ),
2051
+ children: [
2052
+ label ? /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Label, { className: fieldLabelStyles, children: label }) : null,
2053
+ /* @__PURE__ */ jsxRuntime.jsxs(
2054
+ reactAriaComponents.Button,
2055
+ {
2056
+ className: chunkMWAXK66H_cjs.cn(
2057
+ styles4.box(),
2058
+ styles4.content(),
2059
+ "flex items-center justify-between gap-3 text-left cursor-pointer",
2060
+ triggerClassName
2061
+ ),
2062
+ children: [
2063
+ /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.SelectValue, { className: "truncate", children: ({ defaultChildren, isPlaceholder }) => isPlaceholder ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ink-4", children: placeholder }) : defaultChildren }),
2064
+ /* @__PURE__ */ jsxRuntime.jsx(FieldCaret, {})
2065
+ ]
2066
+ }
2067
+ ),
2068
+ description ? /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Text, { slot: "description", className: fieldHintStyles, children: description }) : null,
2069
+ errorMessage && appearance !== "cell" ? /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.FieldError, { className: fieldErrorStyles, children: errorMessage }) : null,
2070
+ /* @__PURE__ */ jsxRuntime.jsxs(
2071
+ reactAriaComponents.Popover,
2072
+ {
2073
+ offset: 6,
2074
+ className: chunkMWAXK66H_cjs.cn(
2075
+ // Match the trigger width exactly (RAC exposes --trigger-width on
2076
+ // the Popover when anchored to a Select button).
2077
+ "w-[var(--trigger-width)]",
2078
+ // Float above modals + full-screen editors (e.g. agent-studio's
2079
+ // .as-editor z-1000 / a raised modal overlay), matching Menu's z-[1200].
2080
+ "z-[1300]",
2081
+ "rounded-md border border-rule bg-surface p-1",
2082
+ "shadow-[var(--shadow-raised)]",
2083
+ "entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1",
2084
+ "exiting:animate-out exiting:fade-out-0 exiting:slide-out-to-top-1",
2085
+ popoverClassName
2086
+ ),
2087
+ children: [
2088
+ /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.ListBox, { className: "outline-none max-h-72 overflow-auto", children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
2089
+ SelectItem,
2090
+ {
2091
+ id: option.id,
2092
+ ...option.textValue ? { textValue: option.textValue } : {},
2093
+ ...option.isDisabled ? { isDisabled: true } : {},
2094
+ children: renderItem ? renderItem(option) : option.label
2095
+ },
2096
+ option.id
2097
+ )) }),
2098
+ options.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkMWAXK66H_cjs.cn("px-3 py-2", fieldHintStyles), children: placeholder }) : null
2099
+ ]
2100
+ }
2101
+ )
2102
+ ]
2103
+ }
2104
+ );
2105
+ }
2106
+ function SelectItem(props) {
2107
+ return /* @__PURE__ */ jsxRuntime.jsx(
2108
+ reactAriaComponents.ListBoxItem,
2109
+ {
2110
+ ...props,
2111
+ className: chunkMWAXK66H_cjs.cn(
2112
+ "flex items-center justify-between gap-3",
2113
+ "rounded-[6px] px-3 py-2 text-[14px] text-ink-2",
2114
+ "cursor-pointer outline-none select-none",
2115
+ "data-[hovered]:bg-surface-2 data-[hovered]:text-ink",
2116
+ "data-[focused]:bg-surface-2 data-[focused]:text-ink",
2117
+ "data-[selected]:bg-surface-3 data-[selected]:text-ink",
2118
+ "data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed"
2119
+ )
2120
+ }
2121
+ );
2122
+ }
2123
+
2124
+ // src/components/conversation-brief-card/types.ts
2125
+ function conversationBriefOutcomeFor(status) {
2126
+ if (status === "used" || status === "discarded") return status;
2127
+ return null;
2128
+ }
2129
+ function isDialableConversationBrief(brief) {
2130
+ return !brief.channel || brief.channel === "phone";
2131
+ }
2132
+ function contactPhoneNumbers(contact) {
2133
+ const numbers = [];
2134
+ for (const address of contact?.addresses ?? []) {
2135
+ if (address.kind !== "phone" || !address.value) continue;
2136
+ if (!numbers.includes(address.value)) numbers.push(address.value);
2137
+ }
2138
+ return numbers;
2139
+ }
2140
+ function ConversationBriefPreview({
2141
+ brief,
2142
+ contacts,
2143
+ onCall,
2144
+ isCallDisabled = false,
2145
+ callDisabledReason,
2146
+ controls,
2147
+ isCallButtonHidden = false,
2148
+ onSelectionChange,
2149
+ callLabel = "Call",
2150
+ className,
2151
+ contentClassName,
2152
+ renderContent,
2153
+ onEdit,
2154
+ editor
2155
+ }) {
2156
+ const [pickedContactId, setPickedContactId] = react.useState("");
2157
+ const contact = contacts.find((entry) => entry.id === pickedContactId) ?? contacts[0] ?? null;
2158
+ const numbers = react.useMemo(() => contactPhoneNumbers(contact), [contact]);
2159
+ const [pickedNumber, setPickedNumber] = react.useState("");
2160
+ const phoneNumber = numbers.includes(pickedNumber) ? pickedNumber : numbers[0] || "";
2161
+ const isOpen = brief.status === "prepared";
2162
+ const names = contacts.map((entry) => entry.name).filter(Boolean).join(", ");
2163
+ const onSelectionChangeRef = react.useRef(onSelectionChange);
2164
+ onSelectionChangeRef.current = onSelectionChange;
2165
+ react.useEffect(() => {
2166
+ onSelectionChangeRef.current?.(contact, phoneNumber);
2167
+ }, [contact, phoneNumber]);
2168
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn("flex flex-col gap-3", className), children: [
2169
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
2170
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-[14px] font-semibold text-ink", children: brief.subject || names || "Prepared conversation" }),
2171
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-[10.5px] text-ink-4", children: [
2172
+ brief.subject ? names : "",
2173
+ brief.channel ? `Channel ${brief.channel}` : "Any channel",
2174
+ brief.type_key ? `Type ${brief.type_key}` : "",
2175
+ brief.status === "prepared" ? "Prepared" : brief.status === "used" ? "Call held" : "Discarded"
2176
+ ].filter(Boolean).join(" \xB7 ") })
2177
+ ] }),
2178
+ editor ?? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/brief-content relative", children: [
2179
+ /* @__PURE__ */ jsxRuntime.jsx(
2180
+ "div",
2181
+ {
2182
+ className: chunkMWAXK66H_cjs.cn(
2183
+ "rounded-md border border-rule-2 bg-surface-2/60 px-3 py-2.5",
2184
+ "text-[13px] leading-relaxed text-ink-2 overflow-y-auto [scrollbar-width:thin]",
2185
+ renderContent ? null : "whitespace-pre-wrap",
2186
+ contentClassName
2187
+ ),
2188
+ children: renderContent ? renderContent(brief.content) : brief.content
2189
+ }
2190
+ ),
2191
+ onEdit ? /* @__PURE__ */ jsxRuntime.jsx(
2192
+ reactAriaComponents.Button,
2193
+ {
2194
+ "aria-label": "Edit brief",
2195
+ onPress: onEdit,
2196
+ className: chunkMWAXK66H_cjs.cn(
2197
+ "absolute right-1.5 top-1.5 inline-flex size-7 cursor-pointer items-center justify-center",
2198
+ "rounded-md bg-surface/80 text-ink-3 outline-none transition-opacity",
2199
+ "opacity-0 group-hover/brief-content:opacity-100 focus-visible:opacity-100",
2200
+ "data-[hovered]:bg-surface-3 data-[hovered]:text-ink",
2201
+ "focus-visible:shadow-[var(--shadow-focus)]"
2202
+ ),
2203
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "size-3.5", "aria-hidden": true })
2204
+ }
2205
+ ) : null
2206
+ ] }),
2207
+ onCall ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 border-t border-rule-2 pt-3", children: [
2208
+ contacts.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(
2209
+ Select,
2210
+ {
2211
+ "aria-label": "Who to call",
2212
+ selectedKey: contact?.id ?? "",
2213
+ onSelectionChange: (key) => {
2214
+ setPickedContactId(String(key));
2215
+ setPickedNumber("");
2216
+ },
2217
+ options: contacts.map((entry) => ({ id: entry.id, label: entry.name || entry.id }))
2218
+ }
2219
+ ) : null,
2220
+ numbers.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(
2221
+ Select,
2222
+ {
2223
+ "aria-label": "Number to call",
2224
+ selectedKey: phoneNumber,
2225
+ onSelectionChange: (key) => setPickedNumber(String(key)),
2226
+ options: numbers.map((number) => ({ id: number, label: number }))
2227
+ }
2228
+ ) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-[12px] text-ink-3", children: phoneNumber || (contact ? "This contact has no phone number on file." : "No contact to call.") }),
2229
+ controls,
2230
+ callDisabledReason ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[12px] text-warning", children: callDisabledReason }) : null,
2231
+ isCallButtonHidden ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsxs(
2232
+ chunkMWAXK66H_cjs.Button,
2233
+ {
2234
+ isDisabled: isCallDisabled || !isOpen || phoneNumber === "" || !contact,
2235
+ onPress: () => contact && onCall(contact, phoneNumber),
2236
+ children: [
2237
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, { className: "size-3.5", "aria-hidden": true }),
2238
+ callLabel
2239
+ ]
2240
+ }
2241
+ ) })
2242
+ ] }) : null
2243
+ ] });
2244
+ }
2245
+ function Modal(props) {
2246
+ return /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.DialogTrigger, { ...props });
2247
+ }
2248
+ function ModalContent({
2249
+ children,
2250
+ className,
2251
+ modalClassName,
2252
+ isDismissable = true,
2253
+ ...props
2254
+ }) {
2255
+ return /* @__PURE__ */ jsxRuntime.jsx(
2256
+ reactAriaComponents.ModalOverlay,
2257
+ {
2258
+ isDismissable,
2259
+ ...props,
2260
+ className: (renderProps) => chunkMWAXK66H_cjs.cn(
2261
+ "fixed inset-0 z-50 flex items-center justify-center p-4",
2262
+ // Warm ink scrim — stays in the Proteos palette (no pure black).
2263
+ "bg-[color-mix(in_oklab,var(--color-ink)_40%,transparent)]",
2264
+ "entering:animate-in entering:fade-in-0 entering:duration-150",
2265
+ "exiting:animate-out exiting:fade-out-0 exiting:duration-100",
2266
+ typeof className === "function" ? className(renderProps) : className
2267
+ ),
2268
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2269
+ reactAriaComponents.Modal,
2270
+ {
2271
+ className: chunkMWAXK66H_cjs.cn(
2272
+ "w-full max-w-lg",
2273
+ // Cap the panel at the viewport (minus the overlay's p-4) and lay it
2274
+ // out as a column so a tall body scrolls instead of overflowing the
2275
+ // screen. Short modals are unaffected — height still tracks content.
2276
+ "flex flex-col max-h-[calc(100dvh-2rem)]",
2277
+ "bg-surface border border-rule rounded-lg",
2278
+ "shadow-[var(--shadow-float)]",
2279
+ "entering:animate-in entering:zoom-in-95 entering:slide-in-from-top-2 entering:duration-150",
2280
+ "exiting:animate-out exiting:zoom-out-95 exiting:duration-100",
2281
+ modalClassName
2282
+ ),
2283
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Dialog, { className: "outline-none flex flex-col min-h-0 overflow-hidden", children })
2284
+ }
2285
+ )
2286
+ }
2287
+ );
2288
+ }
2289
+ function ModalHeader({ className, ...props }) {
2290
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, className: chunkMWAXK66H_cjs.cn("shrink-0 px-5 pt-5 pb-3 flex flex-col gap-1.5", className) });
2291
+ }
2292
+ function ModalTitle({ className, ...props }) {
2293
+ return /* @__PURE__ */ jsxRuntime.jsx(
2294
+ reactAriaComponents.Heading,
2295
+ {
2296
+ slot: "title",
2297
+ ...props,
2298
+ className: chunkMWAXK66H_cjs.cn(
2299
+ "font-sans font-medium text-[20px] leading-[1.25] tracking-[-0.015em] text-ink",
2300
+ className
2301
+ )
2302
+ }
2303
+ );
2304
+ }
2305
+ function ModalDescription({ className, ...props }) {
2306
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { ...props, className: chunkMWAXK66H_cjs.cn("text-[14px] leading-[1.55] text-ink-3", className) });
2307
+ }
2308
+ function ModalBody({ className, ...props }) {
2309
+ return /* @__PURE__ */ jsxRuntime.jsx(
2310
+ "div",
2311
+ {
2312
+ ...props,
2313
+ className: chunkMWAXK66H_cjs.cn(
2314
+ // The scroll region: caps at the panel's spare height and scrolls when
2315
+ // the content is taller, leaving header + footer pinned.
2316
+ "min-h-0 overflow-y-auto px-5 py-3 flex flex-col gap-3 text-[14px] text-ink-2",
2317
+ className
2318
+ )
2319
+ }
2320
+ );
2321
+ }
2322
+ function ModalFooter({ className, ...props }) {
2323
+ return /* @__PURE__ */ jsxRuntime.jsx(
2324
+ "div",
2325
+ {
2326
+ ...props,
2327
+ className: chunkMWAXK66H_cjs.cn("shrink-0 flex justify-end items-center gap-2", "px-5 pt-3 pb-5", className)
2328
+ }
2329
+ );
2330
+ }
2331
+ function ConversationBriefReview({
2332
+ conversationBriefId,
2333
+ client,
2334
+ onOpenCall,
2335
+ onCall,
2336
+ isCallDisabled = false,
2337
+ callDisabledReason,
2338
+ onOutcome,
2339
+ onLoadError,
2340
+ modalTitle = "Prepared conversation",
2341
+ modalClassName = "max-w-2xl",
2342
+ overlayClassName,
2343
+ openLabel,
2344
+ className,
2345
+ renderContent
2346
+ }) {
2347
+ const [brief, setBrief] = react.useState(null);
2348
+ const [contacts, setContacts] = react.useState([]);
2349
+ const [isOpen, setIsOpen] = react.useState(false);
2350
+ const [outcome, setOutcome] = react.useState(null);
2351
+ const onOutcomeRef = react.useRef(onOutcome);
2352
+ onOutcomeRef.current = onOutcome;
2353
+ const onLoadErrorRef = react.useRef(onLoadError);
2354
+ onLoadErrorRef.current = onLoadError;
2355
+ const hasSettledRef = react.useRef(false);
2356
+ const settle = react.useCallback((next, settled) => {
2357
+ setOutcome(next);
2358
+ setIsOpen(false);
2359
+ if (hasSettledRef.current) return;
2360
+ hasSettledRef.current = true;
2361
+ onOutcomeRef.current?.(next, settled);
2362
+ }, []);
2363
+ react.useEffect(() => {
2364
+ let cancelled = false;
2365
+ void (async () => {
2366
+ try {
2367
+ const loaded = await client.getConversationBrief(conversationBriefId);
2368
+ if (cancelled) return;
2369
+ setBrief(loaded);
2370
+ const terminal = conversationBriefOutcomeFor(loaded.status);
2371
+ if (terminal) settle(terminal, loaded);
2372
+ const people = await Promise.all(
2373
+ loaded.contact_ids.map((contactId) => client.getContact(contactId).catch(() => null))
2374
+ );
2375
+ if (!cancelled) setContacts(people.filter((person) => person !== null));
2376
+ } catch (error) {
2377
+ if (cancelled) return;
2378
+ onLoadErrorRef.current?.(error instanceof Error ? error : new Error(String(error)));
2379
+ }
2380
+ })();
2381
+ return () => {
2382
+ cancelled = true;
2383
+ };
2384
+ }, [client, conversationBriefId, settle]);
2385
+ const open = () => {
2386
+ if (onOpenCall) {
2387
+ onOpenCall(conversationBriefId);
2388
+ return;
2389
+ }
2390
+ setIsOpen(true);
2391
+ };
2392
+ if (!brief) return null;
2393
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2394
+ /* @__PURE__ */ jsxRuntime.jsx(
2395
+ ConversationBriefCard,
2396
+ {
2397
+ title: brief.subject || namesOf(contacts) || "Prepared conversation",
2398
+ summary: summaryFor(brief, contacts),
2399
+ outcome,
2400
+ onOpen: open,
2401
+ ...openLabel !== void 0 ? { openLabel } : {},
2402
+ ...className !== void 0 ? { className } : {}
2403
+ }
2404
+ ),
2405
+ onOpenCall ? null : /* @__PURE__ */ jsxRuntime.jsxs(
2406
+ ModalContent,
2407
+ {
2408
+ isOpen,
2409
+ onOpenChange: setIsOpen,
2410
+ modalClassName,
2411
+ ...overlayClassName !== void 0 ? { className: overlayClassName } : {},
2412
+ children: [
2413
+ /* @__PURE__ */ jsxRuntime.jsx(ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { children: modalTitle }) }),
2414
+ /* @__PURE__ */ jsxRuntime.jsx(ModalBody, { className: "min-h-0 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
2415
+ ConversationBriefPreview,
2416
+ {
2417
+ brief,
2418
+ contacts,
2419
+ contentClassName: "max-h-[50dvh]",
2420
+ isCallDisabled,
2421
+ ...callDisabledReason !== void 0 ? { callDisabledReason } : {},
2422
+ ...renderContent !== void 0 ? { renderContent } : {},
2423
+ ...onCall && isDialableConversationBrief(brief) ? {
2424
+ onCall: (contact, phoneNumber) => {
2425
+ setIsOpen(false);
2426
+ onCall(brief, contact, phoneNumber);
2427
+ }
2428
+ } : {}
2429
+ }
2430
+ ) })
2431
+ ]
1910
2432
  }
1911
- ) : null
2433
+ )
1912
2434
  ] });
1913
2435
  }
1914
- var stack = [];
1915
- var listenerInstalled2 = false;
1916
- function onWindowKeyDown2(event) {
1917
- if (event.key !== "Escape") return;
1918
- if (isEditableTarget(event.target)) return;
1919
- const top = stack[stack.length - 1];
1920
- if (!top) return;
1921
- top.handler(event);
2436
+ function namesOf(contacts) {
2437
+ return contacts.map((contact) => contact.name).filter(Boolean).join(", ");
1922
2438
  }
1923
- function ensureListener2() {
1924
- if (listenerInstalled2) return;
1925
- if (typeof window === "undefined") return;
1926
- window.addEventListener("keydown", onWindowKeyDown2, { capture: true });
1927
- listenerInstalled2 = true;
2439
+ function summaryFor(brief, contacts) {
2440
+ const firstLine = brief.content.split("\n").find((line) => line.trim() !== "")?.trim() ?? "";
2441
+ return [
2442
+ brief.subject ? namesOf(contacts) : "",
2443
+ brief.channel ?? "",
2444
+ brief.type_key ?? "",
2445
+ firstLine
2446
+ ].filter(Boolean).join(" \xB7 ");
1928
2447
  }
1929
- function useEscapeKey(handler, options) {
1930
- const enabled = options?.enabled ?? true;
1931
- const handlerRef = react.useRef(handler);
1932
- react.useEffect(() => {
1933
- handlerRef.current = handler;
1934
- });
1935
- react.useEffect(() => {
1936
- if (!enabled) return void 0;
1937
- ensureListener2();
1938
- const entry = {
1939
- handler: (event) => handlerRef.current(event)
1940
- };
1941
- stack.push(entry);
1942
- return () => {
1943
- const idx = stack.lastIndexOf(entry);
1944
- if (idx >= 0) stack.splice(idx, 1);
1945
- };
1946
- }, [enabled]);
2448
+
2449
+ // src/components/conversation-brief-card/create-conversation-brief-client.ts
2450
+ function createConversationBriefClient(conversation) {
2451
+ return {
2452
+ getConversationBrief: (conversationBriefId) => conversation.conversationBriefs.get(conversationBriefId),
2453
+ getContact: (contactId) => conversation.contacts.get(contactId)
2454
+ };
1947
2455
  }
1948
2456
  function CurrencyInput({
1949
2457
  value,
@@ -1976,16 +2484,16 @@ function CurrencyInput({
1976
2484
  onChange({ amount: nextAmount, currency_code: nextCode });
1977
2485
  };
1978
2486
  const selectedSymbol = currencyOptions.find((option) => option.code === code)?.symbol ?? code;
1979
- const styles3 = fieldControlStyles({ size, appearance, ...isInvalid ? { invalid: true } : {} });
2487
+ const styles4 = fieldControlStyles({ size, appearance, ...isInvalid ? { invalid: true } : {} });
1980
2488
  const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
1981
2489
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn("grid grid-cols-1 gap-1.5", className), children: [
1982
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(styles3.box(), "flex items-center gap-1 pr-1", focusWithin), children: [
2490
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(styles4.box(), "flex items-center gap-1 pr-1", focusWithin), children: [
1983
2491
  /* @__PURE__ */ jsxRuntime.jsx(
1984
2492
  "input",
1985
2493
  {
1986
2494
  className: chunkMWAXK66H_cjs.cn(
1987
2495
  "min-w-0 flex-1 bg-transparent text-ink outline-none tabular-nums",
1988
- styles3.content(),
2496
+ styles4.content(),
1989
2497
  // Sit a touch lower than a standard field by trimming the vertical
1990
2498
  // padding (cell mode keeps the fixed 29px row-editor height).
1991
2499
  appearance === "cell" ? "" : size === "sm" ? "py-1" : "py-1.5"
@@ -2651,7 +3159,9 @@ function DataTable({
2651
3159
  selectionMode = "none",
2652
3160
  selectedIds,
2653
3161
  onSelectionChange,
2654
- columnBorders = false
3162
+ columnBorders = false,
3163
+ groupBy,
3164
+ groupHeaderHeight
2655
3165
  }) {
2656
3166
  const rows = react.useMemo(() => {
2657
3167
  const pages = query.data?.pages;
@@ -2770,6 +3280,24 @@ function DataTable({
2770
3280
  });
2771
3281
  const tableRows = table.getRowModel().rows;
2772
3282
  const tableRowCount = tableRows.length;
3283
+ const listItems = react.useMemo(() => {
3284
+ if (!groupBy) {
3285
+ return tableRows.map((row, dataIndex) => ({ kind: "row", row, dataIndex }));
3286
+ }
3287
+ const items = [];
3288
+ let currentGroupId = null;
3289
+ tableRows.forEach((row, dataIndex) => {
3290
+ const group = groupBy(row.original);
3291
+ if (group && group.id !== currentGroupId) {
3292
+ currentGroupId = group.id;
3293
+ items.push({ kind: "group", id: group.id, label: group.label });
3294
+ } else if (!group) {
3295
+ currentGroupId = null;
3296
+ }
3297
+ items.push({ kind: "row", row, dataIndex });
3298
+ });
3299
+ return items;
3300
+ }, [tableRows, groupBy]);
2773
3301
  const scrollerRef = react.useRef(null);
2774
3302
  react.useEffect(() => {
2775
3303
  scrollerRef.current?.scrollTo({ top: 0 });
@@ -2780,10 +3308,11 @@ function DataTable({
2780
3308
  const top = listRef.current?.offsetTop ?? 0;
2781
3309
  setListOffset((prev) => prev === top ? prev : top);
2782
3310
  });
3311
+ const headingHeight = groupHeaderHeight ?? rowHeight;
2783
3312
  const virtualizer = reactVirtual.useVirtualizer({
2784
- count: tableRowCount,
3313
+ count: listItems.length,
2785
3314
  getScrollElement: () => scrollerRef.current,
2786
- estimateSize: () => rowHeight,
3315
+ estimateSize: (index) => listItems[index]?.kind === "group" ? headingHeight : rowHeight,
2787
3316
  overscan,
2788
3317
  scrollMargin: listOffset
2789
3318
  });
@@ -2890,8 +3419,8 @@ function DataTable({
2890
3419
  role: "presentation",
2891
3420
  style: { height: totalSize, position: "relative", width: "100%" },
2892
3421
  children: virtualItems.map((vRow) => {
2893
- const row = tableRows[vRow.index];
2894
- if (!row) return null;
3422
+ const item = listItems[vRow.index];
3423
+ if (!item) return null;
2895
3424
  const rowStyle = {
2896
3425
  // Items' `start` includes the virtualizer's scrollMargin
2897
3426
  // (the list's offset below the sticky header); subtract
@@ -2899,18 +3428,21 @@ function DataTable({
2899
3428
  transform: `translateY(${vRow.start - listOffset}px)`,
2900
3429
  height: vRow.size
2901
3430
  };
3431
+ if (item.kind === "group") {
3432
+ return /* @__PURE__ */ jsxRuntime.jsx(GroupHeaderRow, { style: rowStyle, children: item.label }, `group:${item.id}`);
3433
+ }
2902
3434
  return /* @__PURE__ */ jsxRuntime.jsx(
2903
3435
  DataRow,
2904
3436
  {
2905
- row,
2906
- index: vRow.index,
3437
+ row: item.row,
3438
+ index: item.dataIndex,
2907
3439
  zebra,
2908
3440
  onRowClick,
2909
3441
  style: rowStyle,
2910
3442
  columnBorders,
2911
3443
  ...rowWrapper ? { rowWrapper } : {}
2912
3444
  },
2913
- row.id
3445
+ item.row.id
2914
3446
  );
2915
3447
  })
2916
3448
  }
@@ -2924,6 +3456,20 @@ function DataTable({
2924
3456
  }
2925
3457
  );
2926
3458
  }
3459
+ function GroupHeaderRow({ style, children }) {
3460
+ return /* @__PURE__ */ jsxRuntime.jsx(
3461
+ TableRow,
3462
+ {
3463
+ absolute: true,
3464
+ style,
3465
+ className: chunkMWAXK66H_cjs.cn(
3466
+ "bg-surface-2 border-b border-rule",
3467
+ "font-mono text-[11px] uppercase tracking-[0.06em] text-ink-3"
3468
+ ),
3469
+ children: /* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "gap-2 text-inherit", children })
3470
+ }
3471
+ );
3472
+ }
2927
3473
  function DataRow({
2928
3474
  row,
2929
3475
  index,
@@ -3156,7 +3702,7 @@ function DatePicker({
3156
3702
  className,
3157
3703
  ...props
3158
3704
  }) {
3159
- const styles3 = fieldControlStyles({ size, appearance });
3705
+ const styles4 = fieldControlStyles({ size, appearance });
3160
3706
  const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
3161
3707
  return /* @__PURE__ */ jsxRuntime.jsxs(
3162
3708
  reactAriaComponents.DatePicker,
@@ -3174,7 +3720,7 @@ function DatePicker({
3174
3720
  className: chunkMWAXK66H_cjs.cn(
3175
3721
  // Box chrome on the wrapper; the DateInput inside carries padding +
3176
3722
  // font so the calendar trigger sits inside the same border + ring.
3177
- styles3.box(),
3723
+ styles4.box(),
3178
3724
  "flex items-center gap-1 pr-1",
3179
3725
  focusWithin
3180
3726
  ),
@@ -3184,7 +3730,7 @@ function DatePicker({
3184
3730
  {
3185
3731
  className: chunkMWAXK66H_cjs.cn(
3186
3732
  "flex-1 flex items-center min-w-0 text-ink",
3187
- styles3.content(),
3733
+ styles4.content(),
3188
3734
  // Tabular alignment for date segments — overrides content's
3189
3735
  // font-sans on purpose.
3190
3736
  "font-mono"
@@ -3306,7 +3852,7 @@ function DateTimePicker({
3306
3852
  shouldCloseOnSelect = false,
3307
3853
  ...props
3308
3854
  }) {
3309
- const styles3 = fieldControlStyles({ size, appearance });
3855
+ const styles4 = fieldControlStyles({ size, appearance });
3310
3856
  const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
3311
3857
  const timeGranularity = granularity === "day" ? "minute" : granularity;
3312
3858
  const { hourCycle } = props;
@@ -3329,7 +3875,7 @@ function DateTimePicker({
3329
3875
  className: chunkMWAXK66H_cjs.cn(
3330
3876
  // Box chrome on the wrapper; the DateInput inside carries padding +
3331
3877
  // font so the calendar trigger sits inside the same border + ring.
3332
- styles3.box(),
3878
+ styles4.box(),
3333
3879
  "flex items-center gap-1 pr-1",
3334
3880
  focusWithin
3335
3881
  ),
@@ -3339,7 +3885,7 @@ function DateTimePicker({
3339
3885
  {
3340
3886
  className: chunkMWAXK66H_cjs.cn(
3341
3887
  "flex-1 flex items-center min-w-0 text-ink",
3342
- styles3.content(),
3888
+ styles4.content(),
3343
3889
  // Tabular alignment for date/time segments — overrides content's
3344
3890
  // font-sans on purpose.
3345
3891
  "font-mono"
@@ -3423,7 +3969,7 @@ var draftMessageCardStyles = tailwindVariants.tv({
3423
3969
  outcome: "shrink-0 font-mono text-[11px] text-ink-3"
3424
3970
  }
3425
3971
  });
3426
- var styles = draftMessageCardStyles();
3972
+ var styles2 = draftMessageCardStyles();
3427
3973
  var DRAFT_OUTCOME_LABEL = {
3428
3974
  sent: "Sent",
3429
3975
  rejected: "Rejected",
@@ -3440,23 +3986,23 @@ function DraftMessageCard({
3440
3986
  isPreviewDisabled = false,
3441
3987
  className
3442
3988
  }) {
3443
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(styles.root(), className), children: [
3444
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.icon(), children: /* @__PURE__ */ jsxRuntime.jsx(ChannelIcon, { channel }) }),
3445
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.body(), children: [
3446
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles.eyebrow(), children: eyebrow }),
3447
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles.title(), children: title }),
3448
- recipients && recipients.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: styles.recipients(), children: [
3989
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(styles2.root(), className), children: [
3990
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles2.icon(), children: /* @__PURE__ */ jsxRuntime.jsx(ChannelIcon, { channel }) }),
3991
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles2.body(), children: [
3992
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles2.eyebrow(), children: eyebrow }),
3993
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles2.title(), children: title }),
3994
+ recipients && recipients.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: styles2.recipients(), children: [
3449
3995
  "To ",
3450
3996
  recipients.join(", ")
3451
3997
  ] }) : null
3452
3998
  ] }),
3453
- outcome ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.outcome(), children: DRAFT_OUTCOME_LABEL[outcome] }) : /* @__PURE__ */ jsxRuntime.jsx(
3999
+ outcome ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles2.outcome(), children: DRAFT_OUTCOME_LABEL[outcome] }) : /* @__PURE__ */ jsxRuntime.jsx(
3454
4000
  reactAriaComponents.Button,
3455
4001
  {
3456
4002
  onPress: onPreview ?? (() => {
3457
4003
  }),
3458
4004
  isDisabled: isPreviewDisabled,
3459
- className: styles.action(),
4005
+ className: styles2.action(),
3460
4006
  children: previewLabel
3461
4007
  }
3462
4008
  )
@@ -3531,7 +4077,7 @@ function MultiSelect({
3531
4077
  appearance,
3532
4078
  className
3533
4079
  }) {
3534
- const styles3 = fieldControlStyles({ size, invalid: isInvalid, appearance });
4080
+ const styles4 = fieldControlStyles({ size, invalid: isInvalid, appearance });
3535
4081
  const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
3536
4082
  const minHeight = appearance === "cell" ? "min-h-[29px]" : fieldMinHeight[size];
3537
4083
  const [isOpen, setIsOpen] = react.useState(false);
@@ -3578,7 +4124,7 @@ function MultiSelect({
3578
4124
  "data-invalid": isInvalid || void 0,
3579
4125
  "data-disabled": isDisabled || void 0,
3580
4126
  className: chunkMWAXK66H_cjs.cn(
3581
- styles3.box(),
4127
+ styles4.box(),
3582
4128
  "flex flex-wrap items-center gap-1.5 cursor-pointer",
3583
4129
  minHeight,
3584
4130
  fieldChipPadding[size],
@@ -3814,101 +4360,6 @@ function RecipientSelect({
3814
4360
  }
3815
4361
  );
3816
4362
  }
3817
- function Select({
3818
- label,
3819
- description,
3820
- errorMessage,
3821
- placeholder = "Select\u2026",
3822
- options,
3823
- renderItem,
3824
- size,
3825
- appearance,
3826
- triggerClassName,
3827
- popoverClassName,
3828
- className,
3829
- ...props
3830
- }) {
3831
- const styles3 = fieldControlStyles({ size, appearance });
3832
- return /* @__PURE__ */ jsxRuntime.jsxs(
3833
- reactAriaComponents.Select,
3834
- {
3835
- ...props,
3836
- className: (renderProps) => chunkMWAXK66H_cjs.cn(
3837
- "grid grid-cols-1 gap-1.5",
3838
- typeof className === "function" ? className(renderProps) : className
3839
- ),
3840
- children: [
3841
- label ? /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Label, { className: fieldLabelStyles, children: label }) : null,
3842
- /* @__PURE__ */ jsxRuntime.jsxs(
3843
- reactAriaComponents.Button,
3844
- {
3845
- className: chunkMWAXK66H_cjs.cn(
3846
- styles3.box(),
3847
- styles3.content(),
3848
- "flex items-center justify-between gap-3 text-left cursor-pointer",
3849
- triggerClassName
3850
- ),
3851
- children: [
3852
- /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.SelectValue, { className: "truncate", children: ({ defaultChildren, isPlaceholder }) => isPlaceholder ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ink-4", children: placeholder }) : defaultChildren }),
3853
- /* @__PURE__ */ jsxRuntime.jsx(FieldCaret, {})
3854
- ]
3855
- }
3856
- ),
3857
- description ? /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Text, { slot: "description", className: fieldHintStyles, children: description }) : null,
3858
- errorMessage && appearance !== "cell" ? /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.FieldError, { className: fieldErrorStyles, children: errorMessage }) : null,
3859
- /* @__PURE__ */ jsxRuntime.jsxs(
3860
- reactAriaComponents.Popover,
3861
- {
3862
- offset: 6,
3863
- className: chunkMWAXK66H_cjs.cn(
3864
- // Match the trigger width exactly (RAC exposes --trigger-width on
3865
- // the Popover when anchored to a Select button).
3866
- "w-[var(--trigger-width)]",
3867
- // Float above modals + full-screen editors (e.g. agent-studio's
3868
- // .as-editor z-1000 / a raised modal overlay), matching Menu's z-[1200].
3869
- "z-[1300]",
3870
- "rounded-md border border-rule bg-surface p-1",
3871
- "shadow-[var(--shadow-raised)]",
3872
- "entering:animate-in entering:fade-in-0 entering:slide-in-from-top-1",
3873
- "exiting:animate-out exiting:fade-out-0 exiting:slide-out-to-top-1",
3874
- popoverClassName
3875
- ),
3876
- children: [
3877
- /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.ListBox, { className: "outline-none max-h-72 overflow-auto", children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
3878
- SelectItem,
3879
- {
3880
- id: option.id,
3881
- ...option.textValue ? { textValue: option.textValue } : {},
3882
- ...option.isDisabled ? { isDisabled: true } : {},
3883
- children: renderItem ? renderItem(option) : option.label
3884
- },
3885
- option.id
3886
- )) }),
3887
- options.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkMWAXK66H_cjs.cn("px-3 py-2", fieldHintStyles), children: placeholder }) : null
3888
- ]
3889
- }
3890
- )
3891
- ]
3892
- }
3893
- );
3894
- }
3895
- function SelectItem(props) {
3896
- return /* @__PURE__ */ jsxRuntime.jsx(
3897
- reactAriaComponents.ListBoxItem,
3898
- {
3899
- ...props,
3900
- className: chunkMWAXK66H_cjs.cn(
3901
- "flex items-center justify-between gap-3",
3902
- "rounded-[6px] px-3 py-2 text-[14px] text-ink-2",
3903
- "cursor-pointer outline-none select-none",
3904
- "data-[hovered]:bg-surface-2 data-[hovered]:text-ink",
3905
- "data-[focused]:bg-surface-2 data-[focused]:text-ink",
3906
- "data-[selected]:bg-surface-3 data-[selected]:text-ink",
3907
- "data-[disabled]:opacity-45 data-[disabled]:cursor-not-allowed"
3908
- )
3909
- }
3910
- );
3911
- }
3912
4363
  var MAX_COMPOSER_ATTACHMENT_BYTES = 25 * 1024 * 1024;
3913
4364
  var messageComposerStyles = tailwindVariants.tv({
3914
4365
  base: [
@@ -4275,7 +4726,7 @@ var draftMessageComposerStyles = tailwindVariants.tv({
4275
4726
  error: "px-[18px] font-mono text-[11px] text-danger"
4276
4727
  }
4277
4728
  });
4278
- var styles2 = draftMessageComposerStyles();
4729
+ var styles3 = draftMessageComposerStyles();
4279
4730
  function sendRecipientsFromMessage(message, role) {
4280
4731
  return (message.recipients ?? []).filter((recipient) => recipient.role === role && !!recipient.external_id).map((recipient) => ({
4281
4732
  kind: "contact-address",
@@ -4491,10 +4942,10 @@ function DraftMessageComposer({
4491
4942
  [message?.attachments]
4492
4943
  );
4493
4944
  if (phase === "loading") {
4494
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkMWAXK66H_cjs.cn(styles2.root(), className), children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles2.terminal(), children: "Loading draft\u2026" }) });
4945
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkMWAXK66H_cjs.cn(styles3.root(), className), children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles3.terminal(), children: "Loading draft\u2026" }) });
4495
4946
  }
4496
4947
  if (phase === "load-error") {
4497
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkMWAXK66H_cjs.cn(styles2.root(), className), children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: styles2.terminal(), children: [
4948
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkMWAXK66H_cjs.cn(styles3.root(), className), children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: styles3.terminal(), children: [
4498
4949
  loadError ?? "Loading the draft failed.",
4499
4950
  " ",
4500
4951
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4509,12 +4960,12 @@ function DraftMessageComposer({
4509
4960
  }
4510
4961
  if (phase === "terminal" || !message) {
4511
4962
  const line = terminalKind === "sent" ? "This draft was sent." : terminalKind === "rejected" ? "This draft was rejected." : terminalKind === "failed" ? `Sending failed${message?.error ? ` \u2014 ${message.error}` : ""}.` : "This message is not a reviewable draft.";
4512
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkMWAXK66H_cjs.cn(styles2.root(), className), "data-draft-terminal": terminalKind, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles2.terminal(), children: line }) });
4963
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkMWAXK66H_cjs.cn(styles3.root(), className), "data-draft-terminal": terminalKind, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles3.terminal(), children: line }) });
4513
4964
  }
4514
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(styles2.root(), className), children: [
4515
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles2.header(), children: [
4516
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles2.badge(), children: "Draft \xB7 awaiting review" }),
4517
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles2.sender(), children: [
4965
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(styles3.root(), className), children: [
4966
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles3.header(), children: [
4967
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles3.badge(), children: "Draft \xB7 awaiting review" }),
4968
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles3.sender(), children: [
4518
4969
  "from ",
4519
4970
  message.sender.name
4520
4971
  ] })
@@ -4545,11 +4996,11 @@ function DraftMessageComposer({
4545
4996
  showSendButton: showActions
4546
4997
  }
4547
4998
  ),
4548
- actionError ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: styles2.error(), children: [
4999
+ actionError ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: styles3.error(), children: [
4549
5000
  actionError,
4550
5001
  " \u2014 your edits are kept."
4551
5002
  ] }) : null,
4552
- showActions ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles2.actions(), children: [
5003
+ showActions ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles3.actions(), children: [
4553
5004
  isConfirmingReject ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
4554
5005
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12.5px] text-ink-3", children: "Reject draft?" }),
4555
5006
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4586,92 +5037,6 @@ function DraftMessageComposer({
4586
5037
  ] }) : null
4587
5038
  ] });
4588
5039
  }
4589
- function Modal(props) {
4590
- return /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.DialogTrigger, { ...props });
4591
- }
4592
- function ModalContent({
4593
- children,
4594
- className,
4595
- modalClassName,
4596
- isDismissable = true,
4597
- ...props
4598
- }) {
4599
- return /* @__PURE__ */ jsxRuntime.jsx(
4600
- reactAriaComponents.ModalOverlay,
4601
- {
4602
- isDismissable,
4603
- ...props,
4604
- className: (renderProps) => chunkMWAXK66H_cjs.cn(
4605
- "fixed inset-0 z-50 flex items-center justify-center p-4",
4606
- // Warm ink scrim — stays in the Proteos palette (no pure black).
4607
- "bg-[color-mix(in_oklab,var(--color-ink)_40%,transparent)]",
4608
- "entering:animate-in entering:fade-in-0 entering:duration-150",
4609
- "exiting:animate-out exiting:fade-out-0 exiting:duration-100",
4610
- typeof className === "function" ? className(renderProps) : className
4611
- ),
4612
- children: /* @__PURE__ */ jsxRuntime.jsx(
4613
- reactAriaComponents.Modal,
4614
- {
4615
- className: chunkMWAXK66H_cjs.cn(
4616
- "w-full max-w-lg",
4617
- // Cap the panel at the viewport (minus the overlay's p-4) and lay it
4618
- // out as a column so a tall body scrolls instead of overflowing the
4619
- // screen. Short modals are unaffected — height still tracks content.
4620
- "flex flex-col max-h-[calc(100dvh-2rem)]",
4621
- "bg-surface border border-rule rounded-lg",
4622
- "shadow-[var(--shadow-float)]",
4623
- "entering:animate-in entering:zoom-in-95 entering:slide-in-from-top-2 entering:duration-150",
4624
- "exiting:animate-out exiting:zoom-out-95 exiting:duration-100",
4625
- modalClassName
4626
- ),
4627
- children: /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Dialog, { className: "outline-none flex flex-col min-h-0 overflow-hidden", children })
4628
- }
4629
- )
4630
- }
4631
- );
4632
- }
4633
- function ModalHeader({ className, ...props }) {
4634
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, className: chunkMWAXK66H_cjs.cn("shrink-0 px-5 pt-5 pb-3 flex flex-col gap-1.5", className) });
4635
- }
4636
- function ModalTitle({ className, ...props }) {
4637
- return /* @__PURE__ */ jsxRuntime.jsx(
4638
- reactAriaComponents.Heading,
4639
- {
4640
- slot: "title",
4641
- ...props,
4642
- className: chunkMWAXK66H_cjs.cn(
4643
- "font-sans font-medium text-[20px] leading-[1.25] tracking-[-0.015em] text-ink",
4644
- className
4645
- )
4646
- }
4647
- );
4648
- }
4649
- function ModalDescription({ className, ...props }) {
4650
- return /* @__PURE__ */ jsxRuntime.jsx("p", { ...props, className: chunkMWAXK66H_cjs.cn("text-[14px] leading-[1.55] text-ink-3", className) });
4651
- }
4652
- function ModalBody({ className, ...props }) {
4653
- return /* @__PURE__ */ jsxRuntime.jsx(
4654
- "div",
4655
- {
4656
- ...props,
4657
- className: chunkMWAXK66H_cjs.cn(
4658
- // The scroll region: caps at the panel's spare height and scrolls when
4659
- // the content is taller, leaving header + footer pinned.
4660
- "min-h-0 overflow-y-auto px-5 py-3 flex flex-col gap-3 text-[14px] text-ink-2",
4661
- className
4662
- )
4663
- }
4664
- );
4665
- }
4666
- function ModalFooter({ className, ...props }) {
4667
- return /* @__PURE__ */ jsxRuntime.jsx(
4668
- "div",
4669
- {
4670
- ...props,
4671
- className: chunkMWAXK66H_cjs.cn("shrink-0 flex justify-end items-center gap-2", "px-5 pt-3 pb-5", className)
4672
- }
4673
- );
4674
- }
4675
5040
  function DraftMessageReview({
4676
5041
  messageId,
4677
5042
  client,
@@ -4817,12 +5182,12 @@ function EmptyState({
4817
5182
  size,
4818
5183
  className
4819
5184
  }) {
4820
- const styles3 = emptyStateStyles({ size });
4821
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(styles3.root(), className), children: [
4822
- icon ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles3.art(), children: icon }) : null,
4823
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles3.title(), children: title }),
4824
- description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles3.description(), children: description }) : null,
4825
- action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles3.actions(), children: action }) : null
5185
+ const styles4 = emptyStateStyles({ size });
5186
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(styles4.root(), className), children: [
5187
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles4.art(), children: icon }) : null,
5188
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles4.title(), children: title }),
5189
+ description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles4.description(), children: description }) : null,
5190
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles4.actions(), children: action }) : null
4826
5191
  ] });
4827
5192
  }
4828
5193
  function ErrorAnimation({ className }) {
@@ -5063,7 +5428,7 @@ function Input({
5063
5428
  className,
5064
5429
  ...props
5065
5430
  }) {
5066
- const styles3 = fieldControlStyles({ size, appearance, hasFocusRing });
5431
+ const styles4 = fieldControlStyles({ size, appearance, hasFocusRing });
5067
5432
  return /* @__PURE__ */ jsxRuntime.jsxs(
5068
5433
  reactAriaComponents.TextField,
5069
5434
  {
@@ -5079,7 +5444,7 @@ function Input({
5079
5444
  {
5080
5445
  ...inputProps,
5081
5446
  placeholder: placeholder ?? "",
5082
- className: chunkMWAXK66H_cjs.cn(styles3.box(), styles3.content(), inputClassName)
5447
+ className: chunkMWAXK66H_cjs.cn(styles4.box(), styles4.content(), inputClassName)
5083
5448
  }
5084
5449
  ),
5085
5450
  description ? /* @__PURE__ */ jsxRuntime.jsx(reactAriaComponents.Text, { slot: "description", className: fieldHintStyles, children: description }) : null,
@@ -5589,6 +5954,8 @@ function ChipItem({
5589
5954
  Badge,
5590
5955
  {
5591
5956
  variant: option?.variant,
5957
+ shape: "rounded",
5958
+ hasDot: false,
5592
5959
  ...option?.color ? { color: option.color } : {},
5593
5960
  ...option?.icon ? { icon: option.icon } : {},
5594
5961
  children: option?.label ?? value
@@ -5665,7 +6032,7 @@ function SegmentedControl({
5665
6032
  orientation = "horizontal",
5666
6033
  ...props
5667
6034
  }) {
5668
- const styles3 = segmentedControlStyles({ size });
6035
+ const styles4 = segmentedControlStyles({ size });
5669
6036
  return /* @__PURE__ */ jsxRuntime.jsx(
5670
6037
  reactAriaComponents.RadioGroup,
5671
6038
  {
@@ -5673,14 +6040,14 @@ function SegmentedControl({
5673
6040
  orientation,
5674
6041
  value: String(value),
5675
6042
  onChange: (next) => onChange(next),
5676
- className: chunkMWAXK66H_cjs.cn(styles3.group(), className),
6043
+ className: chunkMWAXK66H_cjs.cn(styles4.group(), className),
5677
6044
  children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
5678
6045
  reactAriaComponents.Radio,
5679
6046
  {
5680
6047
  value: String(option.id),
5681
6048
  ...option.isDisabled ? { isDisabled: true } : {},
5682
6049
  ...autoFocus && option.id === value ? { autoFocus: true } : {},
5683
- className: styles3.segment(),
6050
+ className: styles4.segment(),
5684
6051
  children: option.label
5685
6052
  },
5686
6053
  String(option.id)
@@ -5703,7 +6070,7 @@ function TagInput({
5703
6070
  autoFocus = false,
5704
6071
  className
5705
6072
  }) {
5706
- const styles3 = fieldControlStyles({ size, invalid: isInvalid, appearance });
6073
+ const styles4 = fieldControlStyles({ size, invalid: isInvalid, appearance });
5707
6074
  const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
5708
6075
  const minHeight = appearance === "cell" ? "min-h-[29px]" : fieldMinHeight[size];
5709
6076
  const inputRef = react.useRef(null);
@@ -5744,7 +6111,7 @@ function TagInput({
5744
6111
  "data-invalid": isInvalid || void 0,
5745
6112
  "data-disabled": isDisabled || void 0,
5746
6113
  className: chunkMWAXK66H_cjs.cn(
5747
- styles3.box(),
6114
+ styles4.box(),
5748
6115
  "flex flex-wrap items-center gap-1",
5749
6116
  minHeight,
5750
6117
  fieldChipPadding[size],
@@ -7494,45 +7861,45 @@ var tabsStyles = tailwindVariants.tv({
7494
7861
  defaultVariants: { size: "md" }
7495
7862
  });
7496
7863
  function Root({ size, className, children, ...props }) {
7497
- const styles3 = tabsStyles({ size });
7864
+ const styles4 = tabsStyles({ size });
7498
7865
  return /* @__PURE__ */ jsxRuntime.jsx(
7499
7866
  reactAriaComponents.Tabs,
7500
7867
  {
7501
7868
  ...props,
7502
- className: (rp) => chunkMWAXK66H_cjs.cn(styles3.root(), typeof className === "function" ? className(rp) : className),
7869
+ className: (rp) => chunkMWAXK66H_cjs.cn(styles4.root(), typeof className === "function" ? className(rp) : className),
7503
7870
  children
7504
7871
  }
7505
7872
  );
7506
7873
  }
7507
7874
  function List({ size, className, children, ...props }) {
7508
- const styles3 = tabsStyles({ size });
7875
+ const styles4 = tabsStyles({ size });
7509
7876
  return /* @__PURE__ */ jsxRuntime.jsx(
7510
7877
  reactAriaComponents.TabList,
7511
7878
  {
7512
7879
  ...props,
7513
- className: (rp) => chunkMWAXK66H_cjs.cn(styles3.list(), typeof className === "function" ? className(rp) : className),
7880
+ className: (rp) => chunkMWAXK66H_cjs.cn(styles4.list(), typeof className === "function" ? className(rp) : className),
7514
7881
  children
7515
7882
  }
7516
7883
  );
7517
7884
  }
7518
7885
  function Trigger({ size, className, children, ...props }) {
7519
- const styles3 = tabsStyles({ size });
7886
+ const styles4 = tabsStyles({ size });
7520
7887
  return /* @__PURE__ */ jsxRuntime.jsx(
7521
7888
  reactAriaComponents.Tab,
7522
7889
  {
7523
7890
  ...props,
7524
- className: (rp) => chunkMWAXK66H_cjs.cn(styles3.trigger(), typeof className === "function" ? className(rp) : className),
7891
+ className: (rp) => chunkMWAXK66H_cjs.cn(styles4.trigger(), typeof className === "function" ? className(rp) : className),
7525
7892
  children
7526
7893
  }
7527
7894
  );
7528
7895
  }
7529
7896
  function Panel({ className, children, ...props }) {
7530
- const styles3 = tabsStyles({});
7897
+ const styles4 = tabsStyles({});
7531
7898
  return /* @__PURE__ */ jsxRuntime.jsx(
7532
7899
  reactAriaComponents.TabPanel,
7533
7900
  {
7534
7901
  ...props,
7535
- className: (rp) => chunkMWAXK66H_cjs.cn(styles3.panel(), typeof className === "function" ? className(rp) : className),
7902
+ className: (rp) => chunkMWAXK66H_cjs.cn(styles4.panel(), typeof className === "function" ? className(rp) : className),
7536
7903
  children
7537
7904
  }
7538
7905
  );
@@ -7556,7 +7923,7 @@ function Textarea({
7556
7923
  className,
7557
7924
  ...props
7558
7925
  }) {
7559
- const styles3 = fieldControlStyles({ size, appearance });
7926
+ const styles4 = fieldControlStyles({ size, appearance });
7560
7927
  return /* @__PURE__ */ jsxRuntime.jsxs(
7561
7928
  reactAriaComponents.TextField,
7562
7929
  {
@@ -7576,8 +7943,8 @@ function Textarea({
7576
7943
  className: chunkMWAXK66H_cjs.cn(
7577
7944
  // Same hairline chrome as Input, but allow vertical resize and set a
7578
7945
  // sensible minimum height so short content doesn't collapse.
7579
- styles3.box(),
7580
- styles3.content(),
7946
+ styles4.box(),
7947
+ styles4.content(),
7581
7948
  "min-h-[100px] resize-y",
7582
7949
  textareaClassName
7583
7950
  )
@@ -7598,7 +7965,7 @@ function TimeField({
7598
7965
  className,
7599
7966
  ...props
7600
7967
  }) {
7601
- const styles3 = fieldControlStyles({ size, appearance });
7968
+ const styles4 = fieldControlStyles({ size, appearance });
7602
7969
  const focusWithin = appearance === "cell" ? "focus-within:border-accent focus-within:shadow-none" : "focus-within:border-accent focus-within:shadow-[var(--shadow-focus)]";
7603
7970
  return /* @__PURE__ */ jsxRuntime.jsxs(
7604
7971
  reactAriaComponents.TimeField,
@@ -7614,8 +7981,8 @@ function TimeField({
7614
7981
  reactAriaComponents.DateInput,
7615
7982
  {
7616
7983
  className: chunkMWAXK66H_cjs.cn(
7617
- styles3.box(),
7618
- styles3.content(),
7984
+ styles4.box(),
7985
+ styles4.content(),
7619
7986
  "flex items-center min-w-0 text-ink",
7620
7987
  // Tabular alignment for time segments — overrides content's
7621
7988
  // font-sans on purpose.
@@ -7771,6 +8138,7 @@ exports.BadgeMultiSelect = BadgeMultiSelect;
7771
8138
  exports.BooleanCell = BooleanCell;
7772
8139
  exports.Breadcrumbs = Breadcrumbs;
7773
8140
  exports.COLUMN_DRAG_KIND = COLUMN_DRAG_KIND;
8141
+ exports.CONVERSATION_BRIEF_OUTCOME_LABEL = CONVERSATION_BRIEF_OUTCOME_LABEL;
7774
8142
  exports.Card = Card;
7775
8143
  exports.CardBody = CardBody;
7776
8144
  exports.CardContent = CardContent;
@@ -7787,6 +8155,9 @@ exports.ColorInput = ColorInput;
7787
8155
  exports.Combobox = Combobox;
7788
8156
  exports.Command = Command;
7789
8157
  exports.CommandHint = CommandHint;
8158
+ exports.ConversationBriefCard = ConversationBriefCard;
8159
+ exports.ConversationBriefPreview = ConversationBriefPreview;
8160
+ exports.ConversationBriefReview = ConversationBriefReview;
7790
8161
  exports.CurrencyInput = CurrencyInput;
7791
8162
  exports.DRAFT_OUTCOME_LABEL = DRAFT_OUTCOME_LABEL;
7792
8163
  exports.DataTable = DataTable;
@@ -7887,7 +8258,11 @@ exports.avatarStyles = avatarStyles;
7887
8258
  exports.badgeStyles = badgeStyles;
7888
8259
  exports.cardStyles = cardStyles2;
7889
8260
  exports.channelIcon = channelIcon;
8261
+ exports.contactPhoneNumbers = contactPhoneNumbers;
8262
+ exports.conversationBriefCardStyles = conversationBriefCardStyles;
8263
+ exports.conversationBriefOutcomeFor = conversationBriefOutcomeFor;
7890
8264
  exports.countLeaves = countLeaves;
8265
+ exports.createConversationBriefClient = createConversationBriefClient;
7891
8266
  exports.createDraftMessageClient = createDraftMessageClient;
7892
8267
  exports.createToastQueue = createToastQueue;
7893
8268
  exports.defaultValueFor = defaultValueFor;
@@ -7907,12 +8282,14 @@ exports.iconForContentType = iconForContentType;
7907
8282
  exports.imageAttachmentStyles = imageAttachmentStyles;
7908
8283
  exports.imageLightboxStyles = imageLightboxStyles;
7909
8284
  exports.isColumnDragData = isColumnDragData;
8285
+ exports.isDialableConversationBrief = isDialableConversationBrief;
7910
8286
  exports.isDraftReviewOutcome = isDraftReviewOutcome;
7911
8287
  exports.isEditableTarget = isEditableTarget;
7912
8288
  exports.isPreviewableImageName = isPreviewableImageName;
7913
8289
  exports.joinFieldLabel = joinFieldLabel;
7914
8290
  exports.makeActionsColumn = makeActionsColumn;
7915
8291
  exports.messageComposerStyles = messageComposerStyles;
8292
+ exports.namesOf = namesOf;
7916
8293
  exports.navItemStyles = navItemStyles;
7917
8294
  exports.normalizeHexColor = normalizeHexColor;
7918
8295
  exports.operatorById = operatorById;
@@ -7931,6 +8308,7 @@ exports.resolveLucideIconName = resolveLucideIconName;
7931
8308
  exports.segmentedControlStyles = segmentedControlStyles;
7932
8309
  exports.setJoiner = setJoiner;
7933
8310
  exports.subscribeDraftMessageOutcome = subscribeDraftMessageOutcome;
8311
+ exports.summaryFor = summaryFor;
7934
8312
  exports.tableCellStyles = tableCellStyles;
7935
8313
  exports.tableHeaderCellStyles = tableHeaderCellStyles;
7936
8314
  exports.tabsStyles = tabsStyles;