@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 +682 -304
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +238 -8
- package/dist/index.d.ts +238 -8
- package/dist/index.js +675 -308
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/components/badge/badge.stories.tsx +25 -0
- package/src/components/badge/badge.test.tsx +22 -0
- package/src/components/badge/badge.tsx +41 -10
- package/src/components/badge-multi-select/badge-multi-select.tsx +16 -11
- package/src/components/conversation-brief-card/conversation-brief-card.stories.tsx +81 -0
- package/src/components/conversation-brief-card/conversation-brief-card.tsx +102 -0
- package/src/components/conversation-brief-card/conversation-brief-preview.tsx +193 -0
- package/src/components/conversation-brief-card/conversation-brief-review.test.tsx +250 -0
- package/src/components/conversation-brief-card/conversation-brief-review.tsx +196 -0
- package/src/components/conversation-brief-card/create-conversation-brief-client.ts +18 -0
- package/src/components/conversation-brief-card/index.ts +24 -0
- package/src/components/conversation-brief-card/types.ts +50 -0
- package/src/components/data-table/data-table.test.tsx +62 -0
- package/src/components/data-table/data-table.tsx +75 -7
- package/src/components/record-filter/chip-value.tsx +2 -0
- package/src/index.ts +1 -0
- package/src/styles.css +1 -0
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
|
|
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
|
-
|
|
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
|
-
|
|
680
|
-
|
|
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
|
|
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({
|
|
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(
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
)
|
|
2433
|
+
)
|
|
1912
2434
|
] });
|
|
1913
2435
|
}
|
|
1914
|
-
|
|
1915
|
-
|
|
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
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
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
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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:
|
|
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
|
|
2894
|
-
if (!
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
3444
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className:
|
|
3445
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className:
|
|
3446
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className:
|
|
3447
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className:
|
|
3448
|
-
recipients && recipients.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className:
|
|
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:
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
4515
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className:
|
|
4516
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className:
|
|
4517
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className:
|
|
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:
|
|
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:
|
|
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
|
|
4821
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkMWAXK66H_cjs.cn(
|
|
4822
|
-
icon ? /* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
4823
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
4824
|
-
description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
4825
|
-
action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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
|
-
|
|
7580
|
-
|
|
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
|
|
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
|
-
|
|
7618
|
-
|
|
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;
|