@snksergio/design-system 0.1.0 → 0.4.0
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/README.md +34 -1
- package/dist-lib/chunks/{app-shell-BNTvOETJ.mjs → app-shell-BdVam01i.cjs} +55 -55
- package/dist-lib/chunks/app-shell-BdVam01i.cjs.map +1 -0
- package/dist-lib/chunks/{app-shell-CDy42aNI.mjs → app-shell-C_enrPD8.mjs} +86 -86
- package/dist-lib/chunks/app-shell-C_enrPD8.mjs.map +1 -0
- package/dist-lib/chunks/{app-shell-mocks-oO_IV3Gw.mjs → app-shell-mocks-oO_IV3Gw.cjs} +1 -1
- package/dist-lib/chunks/{app-shell-mocks-oO_IV3Gw.mjs.map → app-shell-mocks-oO_IV3Gw.cjs.map} +1 -1
- package/dist-lib/chunks/{badge-B_2Zt52o.mjs → badge-B0D_PRxn.mjs} +10 -10
- package/dist-lib/chunks/badge-B0D_PRxn.mjs.map +1 -0
- package/dist-lib/chunks/{badge-DKpXURa1.mjs → badge-CUttkO1X.cjs} +10 -10
- package/dist-lib/chunks/badge-CUttkO1X.cjs.map +1 -0
- package/dist-lib/chunks/{chat-v2-mocks-BV9Wha_Z.mjs → chat-v2-mocks-BV9Wha_Z.cjs} +1 -1
- package/dist-lib/chunks/{chat-v2-mocks-BV9Wha_Z.mjs.map → chat-v2-mocks-BV9Wha_Z.cjs.map} +1 -1
- package/dist-lib/chunks/{chip-group-CsKBBHW2.mjs → chip-group-2-f_Yo7Y.cjs} +31 -64
- package/dist-lib/chunks/chip-group-2-f_Yo7Y.cjs.map +1 -0
- package/dist-lib/chunks/{chip-group-D3D0i72q.mjs → chip-group-_e-yh1Zq.mjs} +31 -64
- package/dist-lib/chunks/chip-group-_e-yh1Zq.mjs.map +1 -0
- package/dist-lib/chunks/{clientes-showcase-mocks-BMfbNNJh.mjs → clientes-showcase-mocks-CPNOhx1G.cjs} +3 -3
- package/dist-lib/chunks/clientes-showcase-mocks-CPNOhx1G.cjs.map +1 -0
- package/dist-lib/chunks/{clientes-showcase-mocks-Cq9u3nGZ.mjs → clientes-showcase-mocks-DEHCKxMK.mjs} +3 -3
- package/dist-lib/chunks/clientes-showcase-mocks-DEHCKxMK.mjs.map +1 -0
- package/dist-lib/chunks/{input-374MpdBL.mjs → input-BWevV7up.cjs} +3 -3
- package/dist-lib/chunks/input-BWevV7up.cjs.map +1 -0
- package/dist-lib/chunks/{input-DF4XAWmr.mjs → input-C9eKSSEb.mjs} +3 -3
- package/dist-lib/chunks/input-C9eKSSEb.mjs.map +1 -0
- package/dist-lib/chunks/{page-header-mC1gGtOI.mjs → page-header-DM2G1mdi.mjs} +3 -3
- package/dist-lib/chunks/page-header-DM2G1mdi.mjs.map +1 -0
- package/dist-lib/chunks/{page-header-Dw-3wqAG.mjs → page-header-qOywgRWy.cjs} +3 -3
- package/dist-lib/chunks/page-header-qOywgRWy.cjs.map +1 -0
- package/dist-lib/chunks/{panel-bzNmFlEZ.mjs → panel-CjfnpA-4.cjs} +532 -244
- package/dist-lib/chunks/panel-CjfnpA-4.cjs.map +1 -0
- package/dist-lib/chunks/{panel-Ds15whqp.mjs → panel-DZ7X1NZV.mjs} +547 -259
- package/dist-lib/chunks/panel-DZ7X1NZV.mjs.map +1 -0
- package/dist-lib/chunks/{useTheme-Dee4mo-A.mjs → useTheme-Dee4mo-A.cjs} +1 -1
- package/dist-lib/chunks/{useTheme-Dee4mo-A.mjs.map → useTheme-Dee4mo-A.cjs.map} +1 -1
- package/dist-lib/index.cjs +23 -76
- package/dist-lib/index.cjs.map +1 -1
- package/dist-lib/index.mjs +89 -142
- package/dist-lib/index.mjs.map +1 -1
- package/dist-lib/preview/chat.cjs +38 -39
- package/dist-lib/preview/chat.cjs.map +1 -1
- package/dist-lib/preview/chat.mjs +35 -36
- package/dist-lib/preview/chat.mjs.map +1 -1
- package/dist-lib/preview/clientes.cjs +22 -22
- package/dist-lib/preview/clientes.cjs.map +1 -1
- package/dist-lib/preview/clientes.mjs +20 -20
- package/dist-lib/preview/clientes.mjs.map +1 -1
- package/dist-lib/preview/dashboard.cjs +40 -40
- package/dist-lib/preview/dashboard.cjs.map +1 -1
- package/dist-lib/preview/dashboard.mjs +38 -38
- package/dist-lib/preview/dashboard.mjs.map +1 -1
- package/dist-lib/preview/mocks.cjs +3 -3
- package/dist-lib/preview/mocks.mjs +1 -1
- package/dist-lib/theme.css +18 -122
- package/dist-lib/tokens.cjs +24 -160
- package/dist-lib/tokens.cjs.map +1 -1
- package/dist-lib/tokens.mjs +24 -160
- package/dist-lib/tokens.mjs.map +1 -1
- package/package.json +142 -142
- package/dist-lib/chunks/app-shell-BNTvOETJ.mjs.map +0 -1
- package/dist-lib/chunks/app-shell-CDy42aNI.mjs.map +0 -1
- package/dist-lib/chunks/badge-B_2Zt52o.mjs.map +0 -1
- package/dist-lib/chunks/badge-DKpXURa1.mjs.map +0 -1
- package/dist-lib/chunks/chip-group-CsKBBHW2.mjs.map +0 -1
- package/dist-lib/chunks/chip-group-D3D0i72q.mjs.map +0 -1
- package/dist-lib/chunks/clientes-showcase-mocks-BMfbNNJh.mjs.map +0 -1
- package/dist-lib/chunks/clientes-showcase-mocks-Cq9u3nGZ.mjs.map +0 -1
- package/dist-lib/chunks/input-374MpdBL.mjs.map +0 -1
- package/dist-lib/chunks/input-DF4XAWmr.mjs.map +0 -1
- package/dist-lib/chunks/page-header-Dw-3wqAG.mjs.map +0 -1
- package/dist-lib/chunks/page-header-mC1gGtOI.mjs.map +0 -1
- package/dist-lib/chunks/panel-Ds15whqp.mjs.map +0 -1
- package/dist-lib/chunks/panel-bzNmFlEZ.mjs.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useRef, useEffect, useCallback, useMemo } from "react";
|
|
3
|
-
import { t as tv, B as Button, C as Chip, c as cn, a as ChipGroup, b as ChipGroupItem } from "../chunks/chip-group-
|
|
3
|
+
import { t as tv, B as Button, C as Chip, c as cn, a as ChipGroup, b as ChipGroupItem } from "../chunks/chip-group-_e-yh1Zq.mjs";
|
|
4
4
|
import { u as useTheme } from "../chunks/useTheme-BUPLZBMs.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { E as DropdownMenu, F as DropdownMenuTrigger, G as DropdownMenuContent, p as DropdownMenuItem, t as DropdownMenuSeparator, a as Avatar, b as AvatarFallback, A as AppShell } from "../chunks/app-shell-C_enrPD8.mjs";
|
|
6
6
|
import { MoreVertical, CheckCircle2, Phone, Video, Tag, UserPlus, Archive, CheckCheck, Check, ArrowLeft, PanelRightClose, PanelRightOpen, Paperclip, Smile, Send, Mic, ChevronDown, X, Plus, Menu, Search } from "lucide-react";
|
|
7
7
|
import { e as APP_SHELL_THEME_OPTIONS, c as APP_SHELL_MESSAGES, d as APP_SHELL_NOTIFICATIONS, A as APP_SHELL_COMMANDS, a as APP_SHELL_CONTEXTS } from "../chunks/app-shell-mocks-kWIVSzLs.mjs";
|
|
8
8
|
import { C as CHANNEL_LABEL, a as CHANNEL_HEX, S as SAMPLE_MESSAGES, b as STATUS_DOT, F as FILTER_GROUPS, d as CONVERSATIONS, e as CONVERSATION_DETAILS, D as DEFAULT_DETAIL } from "../chunks/chat-v2-mocks-DvZRkhmz.mjs";
|
|
9
|
-
import { I as Input } from "../chunks/input-
|
|
9
|
+
import { I as Input } from "../chunks/input-C9eKSSEb.mjs";
|
|
10
10
|
const chatV2Styles = tv({
|
|
11
11
|
slots: {
|
|
12
12
|
/** Body do AppShell — flex row com gap entre colunas. `relative` pra mobile overlays. */
|
|
@@ -73,7 +73,7 @@ function ChannelDot({ channel, dotOnly = false }) {
|
|
|
73
73
|
return /* @__PURE__ */ jsxs(
|
|
74
74
|
"span",
|
|
75
75
|
{
|
|
76
|
-
className: "inline-flex items-center gap-[4px] text-
|
|
76
|
+
className: "inline-flex items-center gap-[4px] text-caption-sm text-fg-muted",
|
|
77
77
|
title: CHANNEL_LABEL[channel],
|
|
78
78
|
children: [
|
|
79
79
|
/* @__PURE__ */ jsx(
|
|
@@ -142,7 +142,7 @@ function ConversationActionsMenu({
|
|
|
142
142
|
] });
|
|
143
143
|
}
|
|
144
144
|
function DateSeparator({ label }) {
|
|
145
|
-
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center my-pad-md", children: /* @__PURE__ */ jsx("span", { className: "px-pad-lg py-pad-2xs rounded-radius-full bg-bg-muted text-
|
|
145
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center my-pad-md", children: /* @__PURE__ */ jsx("span", { className: "px-pad-lg py-pad-2xs rounded-radius-full bg-bg-muted text-caption-sm text-fg-muted [font-variant-numeric:tabular-nums]", children: label }) });
|
|
146
146
|
}
|
|
147
147
|
const messageBubbleStyles = tv({
|
|
148
148
|
slots: {
|
|
@@ -151,9 +151,9 @@ const messageBubbleStyles = tv({
|
|
|
151
151
|
/** Balão em si — variants definem cor + corner pointer. */
|
|
152
152
|
bubble: "max-w-[70%] px-pad-xl py-pad-md rounded-radius-xl shadow-sh-sm",
|
|
153
153
|
/** Texto da mensagem. */
|
|
154
|
-
text: "text-
|
|
154
|
+
text: "text-body-md leading-[1.45] whitespace-pre-wrap break-words",
|
|
155
155
|
/** Footer com horário + status icon. */
|
|
156
|
-
meta: "flex items-center justify-end gap-[4px] mt-[2px] text-
|
|
156
|
+
meta: "flex items-center justify-end gap-[4px] mt-[2px] text-caption-xs",
|
|
157
157
|
/** Span do horário (tabular-nums pra alinhar). */
|
|
158
158
|
time: "[font-variant-numeric:tabular-nums]"
|
|
159
159
|
},
|
|
@@ -187,9 +187,9 @@ function MessageBubble({ msg }) {
|
|
|
187
187
|
] }) });
|
|
188
188
|
}
|
|
189
189
|
const SIZE_CLASSES = {
|
|
190
|
-
sm: "size-[28px] text-
|
|
191
|
-
md: "size-[36px] text-
|
|
192
|
-
lg: "size-[40px] text-
|
|
190
|
+
sm: "size-[28px] text-caption-sm",
|
|
191
|
+
md: "size-[36px] text-body-sm font-normal",
|
|
192
|
+
lg: "size-[40px] text-body-md"
|
|
193
193
|
};
|
|
194
194
|
function PersonAvatar({ initials, hex, size = "md" }) {
|
|
195
195
|
return /* @__PURE__ */ jsx(Avatar, { className: SIZE_CLASSES[size], style: { background: hex }, children: /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-transparent text-white font-bold", children: initials }) });
|
|
@@ -201,7 +201,7 @@ const conversationColumnStyles = tv({
|
|
|
201
201
|
headerInfo: "flex-1 min-w-0 flex flex-col gap-[2px]",
|
|
202
202
|
headerTitleRow: "flex items-center gap-gp-sm",
|
|
203
203
|
headerName: "text-title-md text-fg-default whitespace-nowrap overflow-hidden text-ellipsis",
|
|
204
|
-
headerMetaRow: "flex flex-wrap items-center gap-x-gp-sm gap-y-[2px] text-
|
|
204
|
+
headerMetaRow: "flex flex-wrap items-center gap-x-gp-sm gap-y-[2px] text-caption-sm text-fg-muted min-w-0",
|
|
205
205
|
headerActions: "flex items-center gap-gp-sm shrink-0",
|
|
206
206
|
statusInner: "inline-flex items-center gap-[4px]",
|
|
207
207
|
statusDot: "size-[6px] rounded-radius-full shrink-0",
|
|
@@ -384,8 +384,8 @@ function ConversationColumn({
|
|
|
384
384
|
}
|
|
385
385
|
function DetailField({ label, value }) {
|
|
386
386
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-gp-md py-pad-2xs", children: [
|
|
387
|
-
/* @__PURE__ */ jsx("span", { className: "text-
|
|
388
|
-
/* @__PURE__ */ jsx("span", { className: "text-
|
|
387
|
+
/* @__PURE__ */ jsx("span", { className: "text-body-xs font-normal text-fg-muted shrink-0", children: label }),
|
|
388
|
+
/* @__PURE__ */ jsx("span", { className: "text-body-xs font-normal text-fg-default text-right break-words min-w-0", children: value || "—" })
|
|
389
389
|
] });
|
|
390
390
|
}
|
|
391
391
|
function DetailSection({
|
|
@@ -403,7 +403,7 @@ function DetailSection({
|
|
|
403
403
|
"aria-expanded": open,
|
|
404
404
|
className: "flex items-center justify-between w-full px-pad-sm py-pad-sm -mx-pad-sm rounded-radius-md cursor-pointer text-left transition-colors duration-150 hover:bg-bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring-brand",
|
|
405
405
|
children: [
|
|
406
|
-
/* @__PURE__ */ jsx("span", { className: "text-
|
|
406
|
+
/* @__PURE__ */ jsx("span", { className: "text-body-sm font-semibold text-fg-default", children: title }),
|
|
407
407
|
/* @__PURE__ */ jsx(
|
|
408
408
|
ChevronDown,
|
|
409
409
|
{
|
|
@@ -429,18 +429,18 @@ const detailsColumnStyles = tv({
|
|
|
429
429
|
title: "m-0 text-title-md text-fg-default flex-1",
|
|
430
430
|
body: "flex-1 min-h-0 overflow-y-auto px-pad-2xl py-pad-md flex flex-col gap-gp-2xl",
|
|
431
431
|
contactHead: "flex flex-col items-center gap-gp-md pb-pad-md",
|
|
432
|
-
contactName: "text-
|
|
432
|
+
contactName: "text-body-md font-semibold text-fg-default text-center",
|
|
433
433
|
tagsRow: "flex flex-col gap-gp-sm pt-pad-xs",
|
|
434
|
-
tagsLabel: "text-
|
|
434
|
+
tagsLabel: "text-body-xs font-normal text-fg-muted",
|
|
435
435
|
tagsChips: "flex items-center gap-gp-xs flex-wrap",
|
|
436
|
-
tagAddBtn: "inline-flex items-center gap-[3px] px-pad-md h-[22px] rounded-radius-full border border-dashed border-border-input text-
|
|
437
|
-
historyEmpty: "text-
|
|
436
|
+
tagAddBtn: "inline-flex items-center gap-[3px] px-pad-md h-[22px] rounded-radius-full border border-dashed border-border-input text-caption-sm font-medium text-fg-muted hover:bg-bg-muted hover:text-fg-default transition-colors",
|
|
437
|
+
historyEmpty: "text-body-xs font-normal text-fg-subtle text-center py-pad-md",
|
|
438
438
|
historyList: "m-0 p-0 list-none flex flex-col gap-gp-sm",
|
|
439
439
|
historyItem: "flex gap-gp-md p-pad-md rounded-radius-md bg-bg-muted border border-border-subtle",
|
|
440
|
-
historyId: "text-
|
|
440
|
+
historyId: "text-caption-sm text-fg-muted shrink-0 [font-variant-numeric:tabular-nums] pt-[1px]",
|
|
441
441
|
historyBody: "flex-1 min-w-0 flex flex-col gap-[1px]",
|
|
442
|
-
historySubject: "text-
|
|
443
|
-
historyMeta: "text-
|
|
442
|
+
historySubject: "text-body-xs text-fg-default",
|
|
443
|
+
historyMeta: "text-caption-sm text-fg-muted"
|
|
444
444
|
}
|
|
445
445
|
});
|
|
446
446
|
function DetailsColumn({
|
|
@@ -582,11 +582,11 @@ const filterRowStyles = tv({
|
|
|
582
582
|
/** Leading slot (icon ou dot fallback). */
|
|
583
583
|
leading: "shrink-0 inline-flex items-center justify-center size-[18px]",
|
|
584
584
|
/** Label do filtro (ellipsis). */
|
|
585
|
-
label: "flex-1 min-w-0 text-
|
|
585
|
+
label: "flex-1 min-w-0 text-body-xs whitespace-nowrap overflow-hidden text-ellipsis",
|
|
586
586
|
/** Dot brand 6px pra "tem novidades". */
|
|
587
587
|
unreadDot: "size-[6px] rounded-radius-full bg-bg-brand shrink-0",
|
|
588
588
|
/** Contador à direita. */
|
|
589
|
-
count: "text-
|
|
589
|
+
count: "text-caption-sm text-fg-muted shrink-0 [font-variant-numeric:tabular-nums]",
|
|
590
590
|
/** Dot fallback (quando item não tem icon). */
|
|
591
591
|
fallbackDot: "size-[8px] rounded-radius-full"
|
|
592
592
|
},
|
|
@@ -649,9 +649,9 @@ const filtersColumnStyles = tv({
|
|
|
649
649
|
railScroll: "flex-1 min-h-0 overflow-y-auto py-pad-md flex flex-col items-center gap-gp-sm",
|
|
650
650
|
/** Section wrapper (expandida). */
|
|
651
651
|
section: "flex flex-col gap-gp-2xs",
|
|
652
|
-
/** Header de section (título all-caps).
|
|
653
|
-
|
|
654
|
-
sectionTitle: "px-pad-md pt-pad-2xs pb-pad-2xs text-
|
|
652
|
+
/** Header de section (título all-caps). Combo: `caption-xs` (10/400)
|
|
653
|
+
+ override `font-bold uppercase tracking-[0.06em]` pra pattern strong. */
|
|
654
|
+
sectionTitle: "px-pad-md pt-pad-2xs pb-pad-2xs text-caption-xs font-bold tracking-[0.06em] text-fg-subtle uppercase",
|
|
655
655
|
/** Group wrapper (rail) — divider entre grupos. */
|
|
656
656
|
railGroup: "w-full flex flex-col items-center gap-gp-xs px-pad-md",
|
|
657
657
|
/** Modifier de divisor pros grupos não-primeiros (rail). */
|
|
@@ -794,22 +794,21 @@ const conversationListItemStyles = tv({
|
|
|
794
794
|
/** Row 1 — nome + horário. */
|
|
795
795
|
rowTop: "flex items-center gap-gp-sm",
|
|
796
796
|
/** Nome (ellipsis). */
|
|
797
|
-
name: "text-
|
|
797
|
+
name: "text-body-sm font-semibold text-fg-default whitespace-nowrap overflow-hidden text-ellipsis flex-1 min-w-0",
|
|
798
798
|
/** Horário. */
|
|
799
|
-
time: "text-
|
|
799
|
+
time: "text-caption-sm text-fg-muted shrink-0 [font-variant-numeric:tabular-nums]",
|
|
800
800
|
/** Row 2 — preview + badge unread. */
|
|
801
801
|
rowMid: "flex items-center gap-gp-sm",
|
|
802
802
|
/** Preview da última mensagem (ellipsis). */
|
|
803
|
-
preview: "text-
|
|
804
|
-
/** Badge contador de não lidas —
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
unread: "inline-flex items-center justify-center min-w-[18px] h-[18px] px-[5px] rounded-radius-full bg-bg-brand text-fg-on-brand text-[10.5px] font-bold leading-none shrink-0 [font-variant-numeric:tabular-nums]",
|
|
803
|
+
preview: "text-body-xs font-normal text-fg-muted whitespace-nowrap overflow-hidden text-ellipsis flex-1 min-w-0",
|
|
804
|
+
/** Badge contador de não lidas — `caption-xs` (10/400) + override
|
|
805
|
+
`font-bold leading-none` pra centralizar o número dentro do círculo.
|
|
806
|
+
Tabular-nums alinha dígitos verticalmente em badges com counters dinâmicos. */
|
|
807
|
+
unread: "inline-flex items-center justify-center min-w-[18px] h-[18px] px-[5px] rounded-radius-full bg-bg-brand text-fg-on-brand text-caption-xs font-bold leading-none shrink-0 [font-variant-numeric:tabular-nums]",
|
|
809
808
|
/** Row 3 — canal + tag + ID. */
|
|
810
809
|
rowBot: "flex items-center gap-gp-sm",
|
|
811
810
|
/** ID da conversa (canto inferior direito). */
|
|
812
|
-
id: "ml-auto text-
|
|
811
|
+
id: "ml-auto text-caption-xs text-fg-subtle shrink-0 [font-variant-numeric:tabular-nums]"
|
|
813
812
|
},
|
|
814
813
|
variants: {
|
|
815
814
|
isActive: {
|
|
@@ -875,7 +874,7 @@ const queueColumnStyles = tv({
|
|
|
875
874
|
searchClear: "absolute right-pad-md top-1/2 -translate-y-1/2 grid place-items-center size-[20px] rounded-radius-md text-fg-muted hover:bg-bg-muted hover:text-fg-default transition-colors",
|
|
876
875
|
chipsWrap: "px-pad-md pb-pad-2xl",
|
|
877
876
|
list: "flex-1 min-h-0 overflow-y-auto px-pad-md pb-pad-md flex flex-col gap-gp-xs",
|
|
878
|
-
empty: "py-pad-4xl px-pad-xl text-center text-
|
|
877
|
+
empty: "py-pad-4xl px-pad-xl text-center text-body-xs font-normal text-fg-subtle"
|
|
879
878
|
}
|
|
880
879
|
});
|
|
881
880
|
function QueueColumn({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.mjs","sources":["../../src/preview/pages/ChatV2/chat-v2.styles.ts","../../src/preview/pages/ChatV2/hooks/use-resizable.ts","../../src/preview/pages/ChatV2/components/ChannelDot/channel-dot.tsx","../../src/preview/pages/ChatV2/components/ConversationActionsMenu/conversation-actions-menu.tsx","../../src/preview/pages/ChatV2/components/DateSeparator/date-separator.tsx","../../src/preview/pages/ChatV2/components/MessageBubble/message-bubble.styles.ts","../../src/preview/pages/ChatV2/components/MessageBubble/message-bubble.tsx","../../src/preview/pages/ChatV2/components/PersonAvatar/person-avatar.tsx","../../src/preview/pages/ChatV2/components/ConversationColumn/conversation-column.styles.ts","../../src/preview/pages/ChatV2/components/ConversationColumn/conversation-column.tsx","../../src/preview/pages/ChatV2/components/DetailField/detail-field.tsx","../../src/preview/pages/ChatV2/components/DetailSection/detail-section.tsx","../../src/preview/pages/ChatV2/components/DetailsColumn/details-column.styles.ts","../../src/preview/pages/ChatV2/components/DetailsColumn/details-column.tsx","../../src/preview/pages/ChatV2/components/FilterRow/filter-row.styles.ts","../../src/preview/pages/ChatV2/components/FilterRow/filter-row.tsx","../../src/preview/pages/ChatV2/components/FiltersColumn/filters-column.styles.ts","../../src/preview/pages/ChatV2/components/FiltersColumn/filters-column.tsx","../../src/preview/pages/ChatV2/components/RailItem/rail-item.styles.ts","../../src/preview/pages/ChatV2/components/RailItem/rail-item.tsx","../../src/preview/pages/ChatV2/components/FiltersColumn/filters-rail.tsx","../../src/preview/pages/ChatV2/components/ConversationListItem/conversation-list-item.styles.ts","../../src/preview/pages/ChatV2/components/ConversationListItem/conversation-list-item.tsx","../../src/preview/pages/ChatV2/components/QueueColumn/queue-column.styles.ts","../../src/preview/pages/ChatV2/components/QueueColumn/queue-column.tsx","../../src/preview/pages/ChatV2/ChatV2.tsx"],"sourcesContent":["import { tv } from \"@/utils/tv\";\n\n/**\n * Layout root da página Chat V2 — 4 colunas side-by-side em desktop,\n * fullscreen overlays em mobile (<md), controladas por `mobileView`.\n */\nexport const chatV2Styles = tv({\n slots: {\n /** Body do AppShell — flex row com gap entre colunas. `relative` pra mobile overlays. */\n root: \"flex flex-1 min-h-0 gap-gp-2xl relative\",\n /** Wrapper dos filtros (col 1) — escondido em mobile. */\n filtersWrap: \"hidden md:contents\",\n },\n});\n\n/**\n * Helpers de className pros 3 estados de mobile view (list/chat/details).\n * Cada coluna recebe a classe correspondente; em desktop ficam sem efeito.\n */\nexport const mobileOverlay = {\n active: \"max-md:absolute max-md:inset-0 max-md:w-full max-md:rounded-radius-none max-md:border-0\",\n hidden: \"max-md:hidden\",\n} as const;\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport type UseResizableOptions = {\n /** Largura inicial (em px) antes do localStorage hidratar. */\n initial: number;\n /** Largura mínima permitida (em px). */\n min: number;\n /** Largura máxima permitida (em px). */\n max: number;\n /** Chave no localStorage pra persistir o último valor entre sessões. */\n storageKey: string;\n};\n\nexport type UseResizableResult = {\n /** Largura atual em px (controlada pelo drag + hidratação localStorage). */\n width: number;\n /** Handler pra começar o drag — atribuir em `onMouseDown` do handle. */\n onResizeStart: (e: React.MouseEvent) => void;\n};\n\n/**\n * Hook de drag-resize horizontal pra split-panes com persist em localStorage.\n *\n * Comportamento: o handle é assumido como estando no **left edge** do painel —\n * arrastar pra esquerda (delta negativo em X) **aumenta** a largura. Reverter o\n * sinal de `delta` no handler caso o handle esteja no right edge.\n *\n * Hidratação:\n * - No mount, tenta ler `localStorage[storageKey]` e validar dentro de\n * [min, max]. Se válido, usa esse valor; senão, usa `initial`.\n * - Após hidratação, qualquer mudança de `width` é salva (com check de\n * `hydrated.current` pra evitar overwrite do valor persistido com o\n * `initial` no primeiro paint).\n *\n * Cleanup:\n * - `mousemove`/`mouseup` são listeners globais durante o drag. `mouseup`\n * remove os 2 + restaura `cursor` e `user-select` do `<body>`.\n */\nexport function useResizable({\n initial,\n min,\n max,\n storageKey,\n}: UseResizableOptions): UseResizableResult {\n const [width, setWidth] = useState<number>(initial);\n const hydrated = useRef(false);\n\n // Hidrata do localStorage no mount\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n try {\n const raw = window.localStorage.getItem(storageKey);\n const n = raw ? Number(raw) : NaN;\n if (!Number.isNaN(n) && n >= min && n <= max) setWidth(n);\n } catch {\n /* ignore */\n }\n hydrated.current = true;\n }, [min, max, storageKey]);\n\n // Salva quando muda (após hidratação)\n useEffect(() => {\n if (!hydrated.current || typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(storageKey, String(width));\n } catch {\n /* ignore */\n }\n }, [width, storageKey]);\n\n const onResizeStart = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n const startX = e.clientX;\n const startWidth = width;\n\n const onMove = (ev: MouseEvent) => {\n // Handle no left edge: drag pra ESQUERDA (delta < 0 em X) AUMENTA o width\n const delta = startX - ev.clientX;\n const next = Math.max(min, Math.min(max, startWidth + delta));\n setWidth(next);\n };\n const onUp = () => {\n document.removeEventListener(\"mousemove\", onMove);\n document.removeEventListener(\"mouseup\", onUp);\n document.body.style.cursor = \"\";\n document.body.style.userSelect = \"\";\n };\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n document.body.style.cursor = \"col-resize\";\n document.body.style.userSelect = \"none\";\n },\n [width, min, max],\n );\n\n return { width, onResizeStart };\n}\n","import type { ChannelId } from \"../../chat-v2.types\";\nimport { CHANNEL_HEX, CHANNEL_LABEL } from \"../../chat-v2-mocks\";\n\nexport type ChannelDotProps = {\n channel: ChannelId;\n /** Quando true, mostra apenas o dot (sem label). Default: false. */\n dotOnly?: boolean;\n};\n\n/**\n * Dot 8px + label do canal. Cor vem de `CHANNEL_HEX`. Usado em\n * `ConversationListItem`, header de `ConversationColumn` e tooltips.\n */\nexport function ChannelDot({ channel, dotOnly = false }: ChannelDotProps) {\n return (\n <span\n className=\"inline-flex items-center gap-[4px] text-[11px] text-fg-muted\"\n title={CHANNEL_LABEL[channel]}\n >\n <span\n className=\"size-[8px] rounded-radius-full shrink-0\"\n style={{ background: CHANNEL_HEX[channel] }}\n aria-hidden\n />\n {!dotOnly && CHANNEL_LABEL[channel]}\n </span>\n );\n}\n","import {\n Archive,\n CheckCircle2,\n MoreVertical,\n Phone,\n Tag,\n UserPlus,\n Video,\n} from \"lucide-react\";\nimport { Button } from \"@/components/ui/Button/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/components/shadcn/dropdown-menu\";\n\nexport type ConversationActionsMenuProps = {\n /** Quando true, adiciona \"Resolver\" no topo do dropdown (mobile compact). */\n showResolveInMenu?: boolean;\n onResolve?: () => void;\n onCall?: () => void;\n onVideo?: () => void;\n onAddTag?: () => void;\n onAssign?: () => void;\n onArchive?: () => void;\n};\n\n/**\n * Dropdown \"...\" do header da conversa com 5–6 ações (Ligar, Vídeo, Tag,\n * Atribuir, Arquivar; opcionalmente Resolver no topo pra mobile).\n */\nexport function ConversationActionsMenu({\n showResolveInMenu = false,\n onResolve,\n onCall,\n onVideo,\n onAddTag,\n onAssign,\n onArchive,\n}: ConversationActionsMenuProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n color=\"secondary\"\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label=\"Mais opções\"\n >\n <MoreVertical />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" sideOffset={6} className=\"min-w-[200px]\">\n {showResolveInMenu && (\n <>\n <DropdownMenuItem onSelect={onResolve}>\n <CheckCircle2 /> Resolver\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n </>\n )}\n <DropdownMenuItem onSelect={onCall}>\n <Phone /> Ligar\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={onVideo}>\n <Video /> Vídeo chamada\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={onAddTag}>\n <Tag /> Adicionar tag\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={onAssign}>\n <UserPlus /> Atribuir\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\" onSelect={onArchive}>\n <Archive /> Arquivar\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","export type DateSeparatorProps = {\n /** Texto exibido — ex: \"Hoje\", \"Ontem\", \"12 mar 2024\". */\n label: string;\n};\n\n/**\n * Pílula centralizada com label de data entre grupos de mensagens.\n * Visual: chip arredondado com `bg-bg-muted`, tipografia tabular.\n */\nexport function DateSeparator({ label }: DateSeparatorProps) {\n return (\n <div className=\"flex items-center justify-center my-pad-md\">\n <span className=\"px-pad-lg py-pad-2xs rounded-radius-full bg-bg-muted text-[11px] text-fg-muted [font-variant-numeric:tabular-nums]\">\n {label}\n </span>\n </div>\n );\n}\n","import { tv, type VariantProps } from \"@/utils/tv\";\n\nexport const messageBubbleStyles = tv({\n slots: {\n /** Wrapper que controla o alinhamento horizontal (esquerda/direita). */\n row: \"flex\",\n /** Balão em si — variants definem cor + corner pointer. */\n bubble:\n \"max-w-[70%] px-pad-xl py-pad-md rounded-radius-xl shadow-sh-sm\",\n /** Texto da mensagem. */\n text: \"text-[13.5px] leading-[1.45] whitespace-pre-wrap break-words\",\n /** Footer com horário + status icon. */\n meta: \"flex items-center justify-end gap-[4px] mt-[2px] text-[10.5px]\",\n /** Span do horário (tabular-nums pra alinhar). */\n time: \"[font-variant-numeric:tabular-nums]\",\n },\n variants: {\n from: {\n me: {\n row: \"justify-end\",\n bubble: \"bg-bg-brand text-fg-on-brand rounded-br-[4px]\",\n meta: \"text-fg-on-brand opacity-80\",\n },\n them: {\n row: \"justify-start\",\n bubble:\n \"bg-bg-surface text-fg-default border border-border-subtle rounded-bl-[4px]\",\n meta: \"text-fg-muted\",\n },\n },\n },\n defaultVariants: {\n from: \"them\",\n },\n});\n\nexport type MessageBubbleVariants = VariantProps<typeof messageBubbleStyles>;\n","import { Check, CheckCheck } from \"lucide-react\";\nimport { messageBubbleStyles } from \"./message-bubble.styles\";\nimport type { MessageBubbleProps } from \"./message-bubble.types\";\n\n/**\n * Balão de mensagem. Variant `from` (me|them) controla cor + alinhamento.\n * Status icons (Check / CheckCheck) renderizam apenas pra `from=\"me\"`.\n */\nexport function MessageBubble({ msg }: MessageBubbleProps) {\n const from = msg.from === \"me\" ? \"me\" : \"them\";\n const { row, bubble, text, meta, time } = messageBubbleStyles({ from });\n\n return (\n <div className={row()}>\n <div className={bubble()}>\n <div className={text()}>{msg.text}</div>\n <div className={meta()}>\n <span className={time()}>{msg.time}</span>\n {from === \"me\" &&\n (msg.status === \"read\" ? (\n <CheckCheck size={12} strokeWidth={2} />\n ) : (\n <Check size={12} strokeWidth={2} />\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import { Avatar, AvatarFallback } from \"@/components/shadcn/avatar\";\n\nexport type PersonAvatarSize = \"sm\" | \"md\" | \"lg\";\n\nexport type PersonAvatarProps = {\n initials: string;\n /** Cor de fundo do avatar — hex/rgb/CSS color (vem do mock do contato). */\n hex: string;\n /** sm=28px / md=36px / lg=40px. Default: md. */\n size?: PersonAvatarSize;\n};\n\nconst SIZE_CLASSES: Record<PersonAvatarSize, string> = {\n sm: \"size-[28px] text-[11px]\",\n md: \"size-[36px] text-[13px]\",\n lg: \"size-[40px] text-[14px]\",\n};\n\n/**\n * Avatar circular com `initials` em branco bold sobre `hex` como background.\n * Usado em ConversationListItem, header de ConversationColumn e DetailsColumn.\n */\nexport function PersonAvatar({ initials, hex, size = \"md\" }: PersonAvatarProps) {\n return (\n <Avatar className={SIZE_CLASSES[size]} style={{ background: hex }}>\n <AvatarFallback className=\"bg-transparent text-white font-bold\">\n {initials}\n </AvatarFallback>\n </Avatar>\n );\n}\n","import { tv } from \"@/utils/tv\";\n\nexport const conversationColumnStyles = tv({\n slots: {\n root: \"flex flex-col flex-1 min-w-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\n header:\n \"flex items-center gap-gp-lg px-pad-2xl py-pad-md border-b border-border-subtle shrink-0\",\n headerInfo: \"flex-1 min-w-0 flex flex-col gap-[2px]\",\n headerTitleRow: \"flex items-center gap-gp-sm\",\n headerName:\n \"text-title-md text-fg-default whitespace-nowrap overflow-hidden text-ellipsis\",\n headerMetaRow:\n \"flex flex-wrap items-center gap-x-gp-sm gap-y-[2px] text-[11.5px] text-fg-muted min-w-0\",\n headerActions: \"flex items-center gap-gp-sm shrink-0\",\n statusInner: \"inline-flex items-center gap-[4px]\",\n statusDot: \"size-[6px] rounded-radius-full shrink-0\",\n thread:\n \"flex-1 min-h-0 overflow-y-auto bg-bg-muted dark:bg-bg-canvas px-pad-3xl py-pad-2xl flex flex-col gap-gp-md\",\n composer:\n \"flex items-center gap-gp-sm px-pad-2xl py-pad-md border-t border-border-subtle shrink-0 bg-bg-surface\",\n },\n});\n","import { useState } from \"react\";\nimport {\n ArrowLeft,\n CheckCircle2,\n Mic,\n PanelRightClose,\n PanelRightOpen,\n Paperclip,\n Send,\n Smile,\n} from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/Button/button\";\nimport { Chip } from \"@/components/ui/Chip\";\nimport { Input } from \"@/components/shadcn/input\";\nimport { SAMPLE_MESSAGES, STATUS_DOT } from \"../../chat-v2-mocks\";\nimport type { Message } from \"../../chat-v2.types\";\nimport { ChannelDot } from \"../ChannelDot/channel-dot\";\nimport { ConversationActionsMenu } from \"../ConversationActionsMenu\";\nimport { DateSeparator } from \"../DateSeparator/date-separator\";\nimport { MessageBubble } from \"../MessageBubble\";\nimport { PersonAvatar } from \"../PersonAvatar\";\nimport { conversationColumnStyles } from \"./conversation-column.styles\";\nimport type { ConversationColumnProps } from \"./conversation-column.types\";\n\n/**\n * Coluna central. Header com avatar + nome + meta (id/canal/status) + ações,\n * thread scrollável com `DateSeparator` + `MessageBubble`, composer com Input\n * + botões. Estado local: texto digitado + lista de mensagens.\n */\nexport function ConversationColumn({\n conversation,\n detailsOpen,\n onToggleDetails,\n onBackToList,\n className,\n}: ConversationColumnProps) {\n const s = conversationColumnStyles();\n const [text, setText] = useState(\"\");\n const [msgs, setMsgs] = useState<Message[]>(SAMPLE_MESSAGES);\n\n const send = (e?: React.FormEvent) => {\n e?.preventDefault();\n if (!text.trim()) return;\n setMsgs((m) => [\n ...m,\n {\n id: Date.now(),\n from: \"me\",\n text: text.trim(),\n time: new Date().toLocaleTimeString(\"pt-BR\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n }),\n status: \"sent\",\n },\n ]);\n setText(\"\");\n };\n\n return (\n <section aria-label=\"Conversa\" className={cn(s.root(), className)}>\n {/* Header da conversa */}\n <header className={s.header()}>\n {onBackToList && (\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Voltar pra lista\"\n onClick={onBackToList}\n className=\"md:hidden\"\n >\n <ArrowLeft />\n </Button>\n )}\n <div className=\"max-md:hidden\">\n <PersonAvatar\n initials={conversation.initials}\n hex={conversation.avatarHex}\n size=\"md\"\n />\n </div>\n\n <div className={s.headerInfo()}>\n <div className={s.headerTitleRow()}>\n <span className={s.headerName()}>{conversation.name}</span>\n <Chip color={conversation.tagKind} variant=\"soft\" size=\"sm\" shape=\"pill\">\n {conversation.tag}\n </Chip>\n </div>\n\n <div className={s.headerMetaRow()}>\n <span className=\"[font-variant-numeric:tabular-nums]\">\n {conversation.id}\n </span>\n <span aria-hidden>·</span>\n <ChannelDot channel={conversation.channel} />\n <span aria-hidden>·</span>\n <span className={s.statusInner()}>\n <span\n className={s.statusDot()}\n style={{ background: STATUS_DOT[conversation.status] }}\n aria-hidden\n />\n {conversation.statusLabel}\n </span>\n </div>\n </div>\n\n <div className={s.headerActions()}>\n <Button\n color=\"primary\"\n variant=\"filled\"\n size=\"sm\"\n iconLeft={<CheckCircle2 />}\n className=\"max-md:hidden\"\n >\n Resolver\n </Button>\n <ConversationActionsMenu\n showResolveInMenu\n onResolve={() => console.log(\"resolver\")}\n onCall={() => console.log(\"ligar\")}\n onVideo={() => console.log(\"video\")}\n onAddTag={() => console.log(\"tag\")}\n onAssign={() => console.log(\"atribuir\")}\n onArchive={() => console.log(\"arquivar\")}\n />\n <Button\n color=\"secondary\"\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={detailsOpen ? \"Ocultar detalhes\" : \"Mostrar detalhes\"}\n aria-pressed={detailsOpen}\n onClick={onToggleDetails}\n >\n {detailsOpen ? <PanelRightClose /> : <PanelRightOpen />}\n </Button>\n </div>\n </header>\n\n {/* Thread */}\n <div className={s.thread()} aria-live=\"polite\">\n <DateSeparator label=\"Hoje\" />\n {msgs.map((m) => (\n <MessageBubble key={m.id} msg={m} />\n ))}\n </div>\n\n {/* Composer */}\n <form onSubmit={send} className={s.composer()}>\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Anexar\"\n type=\"button\"\n >\n <Paperclip />\n </Button>\n <Input\n type=\"text\"\n value={text}\n onChange={(e) => setText(e.target.value)}\n placeholder=\"Digite uma mensagem...\"\n aria-label=\"Mensagem\"\n className=\"flex-1\"\n />\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Emoji\"\n type=\"button\"\n >\n <Smile />\n </Button>\n {text.trim() ? (\n <Button\n color=\"primary\"\n variant=\"filled\"\n size=\"icon-sm\"\n aria-label=\"Enviar\"\n type=\"submit\"\n >\n <Send strokeWidth={2.2} />\n </Button>\n ) : (\n <Button\n color=\"primary\"\n variant=\"filled\"\n size=\"icon-sm\"\n aria-label=\"Gravar áudio\"\n type=\"button\"\n >\n <Mic strokeWidth={2.2} />\n </Button>\n )}\n </form>\n </section>\n );\n}\n","import type { ReactNode } from \"react\";\n\nexport type DetailFieldProps = {\n /** Label à esquerda (text-fg-muted). */\n label: string;\n /** Valor à direita — string, número ou ReactNode (Chip, link, etc). */\n value: ReactNode;\n};\n\n/**\n * Row label : value usada nas seções de detalhes (Contato, Atendimento).\n * Layout flex baseline justify-between, quebra de palavra no valor.\n */\nexport function DetailField({ label, value }: DetailFieldProps) {\n return (\n <div className=\"flex items-baseline justify-between gap-gp-md py-pad-2xs\">\n <span className=\"text-[12px] text-fg-muted shrink-0\">{label}</span>\n <span className=\"text-[12.5px] text-fg-default text-right break-words min-w-0\">\n {value || \"—\"}\n </span>\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { ChevronDown } from \"lucide-react\";\n\nexport type DetailSectionProps = {\n title: string;\n open: boolean;\n onToggle: () => void;\n children: ReactNode;\n};\n\n/**\n * Seção colapsável da `DetailsColumn` (Contato / Atendimento / Histórico).\n * Header clicável com chevron rotativo + corpo só monta quando `open`.\n */\nexport function DetailSection({\n title,\n open,\n onToggle,\n children,\n}: DetailSectionProps) {\n return (\n <section className=\"flex flex-col border-b border-border-subtle pb-pad-xl last:border-b-0 last:pb-0\">\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={open}\n className=\"flex items-center justify-between w-full px-pad-sm py-pad-sm -mx-pad-sm rounded-radius-md cursor-pointer text-left transition-colors duration-150 hover:bg-bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring-brand\"\n >\n <span className=\"text-[13px] font-semibold text-fg-default\">{title}</span>\n <ChevronDown\n size={14}\n className={[\n \"text-fg-muted transition-transform duration-150\",\n open ? \"\" : \"-rotate-90\",\n ].join(\" \")}\n />\n </button>\n {open && <div className=\"flex flex-col gap-gp-sm pt-pad-xs\">{children}</div>}\n </section>\n );\n}\n","import { tv } from \"@/utils/tv\";\n\nexport const detailsColumnStyles = tv({\n slots: {\n root: \"relative flex flex-col shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\n /** Resize handle no left edge — 4px. */\n handle:\n \"absolute left-0 top-0 bottom-0 w-[4px] z-[1] bg-transparent cursor-col-resize hover:bg-bg-brand active:bg-bg-brand transition-colors duration-150 focus-visible:outline-none focus-visible:bg-bg-brand\",\n header:\n \"flex items-center gap-gp-md px-pad-2xl py-pad-lg border-b border-border-subtle shrink-0\",\n title: \"m-0 text-title-md text-fg-default flex-1\",\n body: \"flex-1 min-h-0 overflow-y-auto px-pad-2xl py-pad-md flex flex-col gap-gp-2xl\",\n contactHead: \"flex flex-col items-center gap-gp-md pb-pad-md\",\n contactName: \"text-[14px] font-semibold text-fg-default text-center\",\n tagsRow: \"flex flex-col gap-gp-sm pt-pad-xs\",\n tagsLabel: \"text-[12px] text-fg-muted\",\n tagsChips: \"flex items-center gap-gp-xs flex-wrap\",\n tagAddBtn:\n \"inline-flex items-center gap-[3px] px-pad-md h-[22px] rounded-radius-full border border-dashed border-border-input text-[11px] font-medium text-fg-muted hover:bg-bg-muted hover:text-fg-default transition-colors\",\n historyEmpty: \"text-[12px] text-fg-subtle text-center py-pad-md\",\n historyList: \"m-0 p-0 list-none flex flex-col gap-gp-sm\",\n historyItem:\n \"flex gap-gp-md p-pad-md rounded-radius-md bg-bg-muted border border-border-subtle\",\n historyId:\n \"text-[11px] text-fg-muted shrink-0 [font-variant-numeric:tabular-nums] pt-[1px]\",\n historyBody: \"flex-1 min-w-0 flex flex-col gap-[1px]\",\n historySubject: \"text-[12.5px] font-medium text-fg-default\",\n historyMeta: \"text-[11px] text-fg-muted\",\n },\n});\n","import { ArrowLeft, Plus, X } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/Button/button\";\nimport { Chip } from \"@/components/ui/Chip\";\nimport { CHANNEL_LABEL } from \"../../chat-v2-mocks\";\nimport { DetailField } from \"../DetailField/detail-field\";\nimport { DetailSection } from \"../DetailSection\";\nimport { PersonAvatar } from \"../PersonAvatar\";\nimport { detailsColumnStyles } from \"./details-column.styles\";\nimport type { DetailsColumnProps } from \"./details-column.types\";\n\n/**\n * Coluna direita: header com título + close, resize handle no left edge (4px),\n * body scrollável com 3 accordions (Contato, Atendimento, Histórico).\n * Width controlado pelo hook `useResizable` no parent.\n */\nexport function DetailsColumn({\n conversation,\n detail,\n openSections,\n onToggleSection,\n onClose,\n width,\n onResizeStart,\n onBackToChat,\n className,\n}: DetailsColumnProps) {\n const s = detailsColumnStyles();\n\n return (\n <aside\n aria-label=\"Detalhes do contato\"\n style={{ width }}\n className={cn(s.root(), className)}\n >\n <button\n type=\"button\"\n onMouseDown={onResizeStart}\n aria-label=\"Redimensionar painel de detalhes\"\n className={s.handle()}\n />\n\n <header className={s.header()}>\n {onBackToChat && (\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Voltar pra conversa\"\n onClick={onBackToChat}\n className=\"md:hidden\"\n >\n <ArrowLeft />\n </Button>\n )}\n <h3 className={s.title()}>Detalhes</h3>\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Fechar painel\"\n onClick={onClose}\n >\n <X />\n </Button>\n </header>\n\n <div className={s.body()}>\n <DetailSection\n title=\"Contato\"\n open={openSections.contact}\n onToggle={() => onToggleSection(\"contact\")}\n >\n <div className={s.contactHead()}>\n <PersonAvatar\n initials={conversation.initials}\n hex={conversation.avatarHex}\n size=\"lg\"\n />\n <div className={s.contactName()}>{conversation.name}</div>\n </div>\n <DetailField label=\"Telefone\" value={detail.phone} />\n <DetailField label=\"Email\" value={detail.email} />\n <DetailField label=\"Primeiro contato\" value={detail.firstContact} />\n </DetailSection>\n\n <DetailSection\n title=\"Atendimento\"\n open={openSections.ticket}\n onToggle={() => onToggleSection(\"ticket\")}\n >\n <DetailField label=\"ID\" value={conversation.id} />\n <DetailField label=\"Status\" value={conversation.statusLabel} />\n <DetailField label=\"Atribuído a\" value={detail.assignedTo} />\n <DetailField label=\"Canal\" value={CHANNEL_LABEL[conversation.channel]} />\n <DetailField label=\"Criado em\" value={detail.createdAt} />\n\n <div className={s.tagsRow()}>\n <span className={s.tagsLabel()}>Tags</span>\n <div className={s.tagsChips()}>\n <Chip color={conversation.tagKind} variant=\"soft\" size=\"sm\" shape=\"pill\">\n {conversation.tag}\n </Chip>\n {detail.extraTags.map((t) => (\n <Chip key={t} color=\"info\" variant=\"soft\" size=\"sm\" shape=\"pill\">\n {t}\n </Chip>\n ))}\n <button type=\"button\" className={s.tagAddBtn()}>\n <Plus size={11} strokeWidth={2.2} /> tag\n </button>\n </div>\n </div>\n </DetailSection>\n\n <DetailSection\n title=\"Histórico\"\n open={openSections.history}\n onToggle={() => onToggleSection(\"history\")}\n >\n {detail.history.length === 0 ? (\n <div className={s.historyEmpty()}>Nenhum atendimento anterior.</div>\n ) : (\n <ul className={s.historyList()}>\n {detail.history.map((h) => (\n <li key={h.id} className={s.historyItem()}>\n <span className={s.historyId()}>{h.id}</span>\n <div className={s.historyBody()}>\n <span className={s.historySubject()}>{h.subject}</span>\n <span className={s.historyMeta()}>\n {h.date} · {h.status}\n </span>\n </div>\n </li>\n ))}\n </ul>\n )}\n </DetailSection>\n </div>\n </aside>\n );\n}\n","import { tv, type VariantProps } from \"@/utils/tv\";\n\nexport const filterRowStyles = tv({\n slots: {\n button: [\n \"flex items-center gap-gp-md w-full\",\n \"px-pad-md py-pad-sm rounded-radius-md text-left\",\n \"transition-colors duration-150 cursor-pointer\",\n ].join(\" \"),\n /** Leading slot (icon ou dot fallback). */\n leading: \"shrink-0 inline-flex items-center justify-center size-[18px]\",\n /** Label do filtro (ellipsis). */\n label:\n \"flex-1 min-w-0 text-[12.5px] font-medium whitespace-nowrap overflow-hidden text-ellipsis\",\n /** Dot brand 6px pra \"tem novidades\". */\n unreadDot: \"size-[6px] rounded-radius-full bg-bg-brand shrink-0\",\n /** Contador à direita. */\n count: \"text-[11px] text-fg-muted shrink-0 [font-variant-numeric:tabular-nums]\",\n /** Dot fallback (quando item não tem icon). */\n fallbackDot: \"size-[8px] rounded-radius-full\",\n },\n variants: {\n isActive: {\n true: {\n button: \"bg-bg-muted dark:bg-bg-emphasis text-fg-default font-semibold\",\n },\n false: {\n button: \"text-fg-muted hover:bg-bg-muted hover:text-fg-default\",\n },\n },\n },\n defaultVariants: {\n isActive: false,\n },\n});\n\nexport type FilterRowVariants = VariantProps<typeof filterRowStyles>;\n","import type { FilterItem } from \"../../chat-v2.types\";\nimport { filterRowStyles } from \"./filter-row.styles\";\n\nexport type FilterRowProps = {\n item: FilterItem;\n isActive: boolean;\n onClick: () => void;\n};\n\n/**\n * Row clicável da `FiltersColumn` expandida. Layout: leading (icon ou dot) +\n * label (ellipsis) + dot unread opcional + count tabular.\n */\nexport function FilterRow({ item, isActive, onClick }: FilterRowProps) {\n const Icon = item.icon;\n const s = filterRowStyles({ isActive });\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={isActive}\n className={s.button()}\n >\n <span className={s.leading()}>\n {Icon ? (\n <Icon\n size={15}\n strokeWidth={1.8}\n style={{ color: item.color ?? \"var(--color-fg-muted)\" }}\n />\n ) : (\n <span\n className={s.fallbackDot()}\n style={{ background: item.color ?? \"var(--color-fg-muted)\" }}\n aria-hidden\n />\n )}\n </span>\n <span className={s.label()}>{item.name}</span>\n {item.hasUnread && <span className={s.unreadDot()} aria-label=\"tem novidades\" />}\n <span className={s.count()}>{item.count}</span>\n </button>\n );\n}\n","import { tv } from \"@/utils/tv\";\n\nexport const filtersColumnStyles = tv({\n slots: {\n /** Aside raiz da versão expandida (280px). */\n root: \"flex flex-col w-[280px] shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\n /** Aside raiz da versão rail (64px). */\n rail: \"flex flex-col w-[64px] shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\n /** Container scrollável das seções (expandida). */\n scroll: \"flex-1 min-h-0 overflow-y-auto px-pad-md py-pad-md flex flex-col gap-gp-lg\",\n /** Container scrollável (rail). */\n railScroll:\n \"flex-1 min-h-0 overflow-y-auto py-pad-md flex flex-col items-center gap-gp-sm\",\n /** Section wrapper (expandida). */\n section: \"flex flex-col gap-gp-2xs\",\n /** Header de section (título all-caps). Usa `subheading-strong-sm` —\n token DS criado especificamente pra este caso (10px/700/+0.06em). */\n sectionTitle:\n \"px-pad-md pt-pad-2xs pb-pad-2xs text-[10px] font-bold tracking-[0.06em] text-fg-subtle uppercase\",\n /** Group wrapper (rail) — divider entre grupos. */\n railGroup: \"w-full flex flex-col items-center gap-gp-xs px-pad-md\",\n /** Modifier de divisor pros grupos não-primeiros (rail). */\n railGroupDivider: \"pt-pad-sm border-t border-border-subtle\",\n /** Modifier de divisor pras sections não-primeiras (expandida). */\n sectionDivider: \"pt-pad-lg border-t border-border-subtle\",\n },\n});\n","import { cn } from \"@/lib/utils\";\nimport { FILTER_GROUPS } from \"../../chat-v2-mocks\";\nimport type { FilterGroupKey, FilterItem } from \"../../chat-v2.types\";\nimport { FilterRow } from \"../FilterRow\";\nimport { filtersColumnStyles } from \"./filters-column.styles\";\nimport type { FiltersColumnProps, FiltersState } from \"./filters-column.types\";\n\n/**\n * Coluna esquerda expandida (280px) com as 4 seções de filtros definidas\n * em `FILTER_GROUPS` (mocks).\n */\nexport function FiltersColumn({\n filters,\n onToggleFilter,\n className,\n}: FiltersColumnProps) {\n const s = filtersColumnStyles();\n return (\n <aside aria-label=\"Filtros\" className={cn(s.root(), className)}>\n <div className={s.scroll()}>\n {FILTER_GROUPS.map((sec, i) => (\n <FilterSection\n key={sec.group}\n title={sec.title}\n group={sec.group}\n items={sec.items}\n filters={filters}\n onToggle={onToggleFilter}\n isFirst={i === 0}\n />\n ))}\n </div>\n </aside>\n );\n}\n\nfunction FilterSection({\n title,\n group,\n items,\n filters,\n onToggle,\n isFirst,\n}: {\n title: string;\n group: FilterGroupKey;\n items: FilterItem[];\n filters: FiltersState;\n onToggle: (group: FilterGroupKey, id: string) => void;\n isFirst?: boolean;\n}) {\n const s = filtersColumnStyles();\n return (\n <section className={cn(s.section(), !isFirst && s.sectionDivider())}>\n <div className={s.sectionTitle()}>{title}</div>\n {items.map((item) => (\n <FilterRow\n key={item.id}\n item={item}\n isActive={filters[group].has(item.id)}\n onClick={() => onToggle(group, item.id)}\n />\n ))}\n </section>\n );\n}\n","import { tv, type VariantProps } from \"@/utils/tv\";\n\nexport const railItemStyles = tv({\n slots: {\n button: [\n \"relative grid place-items-center size-form-md rounded-radius-md cursor-pointer\",\n \"transition-colors duration-150\",\n ].join(\" \"),\n /** Badge dot 6px (top-right) pra \"tem novidades\". */\n unreadDot:\n \"absolute top-[2px] right-[2px] size-[6px] rounded-radius-full bg-bg-brand\",\n /** Fallback dot (quando item não tem icon). */\n fallbackDot: \"size-[10px] rounded-radius-full\",\n },\n variants: {\n isActive: {\n true: {\n button: \"bg-bg-muted dark:bg-bg-emphasis text-fg-default\",\n },\n false: {\n button: \"text-fg-muted hover:bg-bg-muted hover:text-fg-default\",\n },\n },\n },\n defaultVariants: {\n isActive: false,\n },\n});\n\nexport type RailItemVariants = VariantProps<typeof railItemStyles>;\n","import type { FilterItem } from \"../../chat-v2.types\";\nimport { railItemStyles } from \"./rail-item.styles\";\n\nexport type RailItemProps = {\n item: FilterItem;\n isActive: boolean;\n onClick: () => void;\n};\n\n/**\n * Botão ícone compacto (32px) usado na `FiltersRail`. Suporta cor por\n * `item.color`, ícone Lucide ou fallback dot, e badge \"tem novidades\".\n */\nexport function RailItem({ item, isActive, onClick }: RailItemProps) {\n const Icon = item.icon;\n const s = railItemStyles({ isActive });\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={isActive}\n title={`${item.name} (${item.count})`}\n className={s.button()}\n >\n {Icon ? (\n <Icon\n size={16}\n strokeWidth={1.8}\n style={{ color: item.color ?? \"currentColor\" }}\n />\n ) : (\n <span\n className={s.fallbackDot()}\n style={{ background: item.color ?? \"var(--color-fg-muted)\" }}\n aria-hidden\n />\n )}\n {item.hasUnread && <span className={s.unreadDot()} aria-label=\"tem novidades\" />}\n </button>\n );\n}\n","import { cn } from \"@/lib/utils\";\nimport { FILTER_GROUPS } from \"../../chat-v2-mocks\";\nimport { RailItem } from \"../RailItem\";\nimport { filtersColumnStyles } from \"./filters-column.styles\";\nimport type { FiltersColumnProps } from \"./filters-column.types\";\n\n/**\n * Coluna esquerda compacta (64px) — só ícones, divididos por grupo\n * com divider top entre grupos. Consome `FILTER_GROUPS` (mocks).\n */\nexport function FiltersRail({\n filters,\n onToggleFilter,\n className,\n}: FiltersColumnProps) {\n const s = filtersColumnStyles();\n return (\n <aside aria-label=\"Filtros (compactos)\" className={cn(s.rail(), className)}>\n <div className={s.railScroll()}>\n {FILTER_GROUPS.map(({ group, items }, gi) => (\n <div\n key={group}\n className={cn(s.railGroup(), gi > 0 && s.railGroupDivider())}\n >\n {items.map((item) => (\n <RailItem\n key={item.id}\n item={item}\n isActive={filters[group].has(item.id)}\n onClick={() => onToggleFilter(group, item.id)}\n />\n ))}\n </div>\n ))}\n </div>\n </aside>\n );\n}\n","import { tv, type VariantProps } from \"@/utils/tv\";\n\nexport const conversationListItemStyles = tv({\n slots: {\n /** Card raiz (button) — flex horizontal com avatar + conteúdo. */\n root: [\n \"group/conv text-left relative\",\n \"flex gap-gp-md p-pad-md rounded-radius-md\",\n \"cursor-pointer transition-colors duration-150\",\n ].join(\" \"),\n /** Coluna direita (3 rows). */\n content: \"flex-1 min-w-0 flex flex-col gap-[3px]\",\n /** Row 1 — nome + horário. */\n rowTop: \"flex items-center gap-gp-sm\",\n /** Nome (ellipsis). */\n name: \"text-[13px] font-semibold text-fg-default whitespace-nowrap overflow-hidden text-ellipsis flex-1 min-w-0\",\n /** Horário. */\n time: \"text-[11px] text-fg-muted shrink-0 [font-variant-numeric:tabular-nums]\",\n /** Row 2 — preview + badge unread. */\n rowMid: \"flex items-center gap-gp-sm\",\n /** Preview da última mensagem (ellipsis). */\n preview:\n \"text-[12px] text-fg-muted whitespace-nowrap overflow-hidden text-ellipsis flex-1 min-w-0\",\n /** Badge contador de não lidas — usa `subheading-strong-md` (11px/700) como\n base e força `font-bold` + `leading-none` inline pra preservar o weight\n e a centralização vertical do número dentro do círculo (preset DS sozinho\n usa lineHeight 0.875rem, que descentraliza o conteúdo). */\n unread:\n \"inline-flex items-center justify-center min-w-[18px] h-[18px] px-[5px] rounded-radius-full bg-bg-brand text-fg-on-brand text-[10.5px] font-bold leading-none shrink-0 [font-variant-numeric:tabular-nums]\",\n /** Row 3 — canal + tag + ID. */\n rowBot: \"flex items-center gap-gp-sm\",\n /** ID da conversa (canto inferior direito). */\n id: \"ml-auto text-[10.5px] text-fg-subtle shrink-0 [font-variant-numeric:tabular-nums]\",\n },\n variants: {\n isActive: {\n true: {\n root: [\n \"bg-bg-muted dark:bg-bg-emphasis\",\n \"before:content-[''] before:absolute before:left-0 before:top-[10px] before:bottom-[10px]\",\n \"before:w-[3px] before:bg-bg-brand before:rounded-r-[2px] before:pointer-events-none\",\n ].join(\" \"),\n },\n false: {\n root: \"hover:bg-bg-muted\",\n },\n },\n },\n defaultVariants: {\n isActive: false,\n },\n});\n\nexport type ConversationListItemVariants = VariantProps<\n typeof conversationListItemStyles\n>;\n","import { Chip } from \"@/components/ui/Chip\";\nimport { ChannelDot } from \"../ChannelDot/channel-dot\";\nimport { PersonAvatar } from \"../PersonAvatar\";\nimport { conversationListItemStyles } from \"./conversation-list-item.styles\";\nimport type { ConversationListItemProps } from \"./conversation-list-item.types\";\n\n/**\n * Item da fila de conversas. Avatar (36px) à esquerda + 3 rows de info à direita.\n * Variant `isActive` adiciona strip lateral brand de 3px + bg muted.\n */\nexport function ConversationListItem({\n conv,\n isActive,\n onSelect,\n}: ConversationListItemProps) {\n const s = conversationListItemStyles({ isActive });\n\n return (\n <button\n type=\"button\"\n onClick={() => onSelect(conv.id)}\n className={s.root()}\n aria-pressed={isActive}\n >\n <PersonAvatar initials={conv.initials} hex={conv.avatarHex} size=\"md\" />\n\n <div className={s.content()}>\n <div className={s.rowTop()}>\n <span className={s.name()}>{conv.name}</span>\n <span className={s.time()}>{conv.time}</span>\n </div>\n\n <div className={s.rowMid()}>\n <span className={s.preview()}>{conv.last}</span>\n {conv.unread > 0 && (\n <span className={s.unread()} aria-label={`${conv.unread} não lidas`}>\n {conv.unread}\n </span>\n )}\n </div>\n\n <div className={s.rowBot()}>\n <ChannelDot channel={conv.channel} />\n <Chip color={conv.tagKind} variant=\"soft\" size=\"sm\" shape=\"pill\">\n {conv.tag}\n </Chip>\n <span className={s.id()}>{conv.id}</span>\n </div>\n </div>\n </button>\n );\n}\n","import { tv } from \"@/utils/tv\";\n\nexport const queueColumnStyles = tv({\n slots: {\n root: \"flex flex-col w-[340px] shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\n header: \"flex items-center gap-gp-sm px-pad-md pt-pad-md pb-pad-md\",\n title: \"m-0 text-title-md text-fg-default flex-1 min-w-0\",\n searchWrap: \"px-pad-md pb-pad-lg\",\n searchInner: \"relative\",\n searchIcon:\n \"absolute left-pad-lg top-1/2 -translate-y-1/2 text-fg-muted pointer-events-none\",\n searchInput: \"pl-[34px] pr-[30px]\",\n searchClear:\n \"absolute right-pad-md top-1/2 -translate-y-1/2 grid place-items-center size-[20px] rounded-radius-md text-fg-muted hover:bg-bg-muted hover:text-fg-default transition-colors\",\n chipsWrap: \"px-pad-md pb-pad-2xl\",\n list: \"flex-1 min-h-0 overflow-y-auto px-pad-md pb-pad-md flex flex-col gap-gp-xs\",\n empty: \"py-pad-4xl px-pad-xl text-center text-[12px] text-fg-subtle\",\n },\n});\n","import { useMemo } from \"react\";\nimport { Menu as MenuIcon, Search, X } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/Button/button\";\nimport { Chip, ChipGroup, ChipGroupItem } from \"@/components/ui/Chip\";\nimport { Input } from \"@/components/shadcn/input\";\nimport { CONVERSATIONS } from \"../../chat-v2-mocks\";\nimport type { QueueFilter } from \"../../chat-v2.types\";\nimport { ConversationListItem } from \"../ConversationListItem\";\nimport { queueColumnStyles } from \"./queue-column.styles\";\nimport type { QueueColumnProps } from \"./queue-column.types\";\n\n/**\n * Coluna da fila de conversas (340px). Header com toggle de filtros + título +\n * badge de contagem; Search + chips Todas/Não lidas/Lidas; lista scrollável.\n */\nexport function QueueColumn({\n activeId,\n onSelect,\n searchQuery,\n onSearchChange,\n queueFilter,\n onQueueFilterChange,\n filtersCollapsed,\n onToggleFilters,\n className,\n}: QueueColumnProps) {\n const s = queueColumnStyles();\n\n const filtered = useMemo(() => {\n const q = searchQuery.trim().toLowerCase();\n const bySearch = q\n ? CONVERSATIONS.filter(\n (c) =>\n c.name.toLowerCase().includes(q) ||\n c.id.toLowerCase().includes(q) ||\n c.last.toLowerCase().includes(q),\n )\n : CONVERSATIONS;\n if (queueFilter === \"unread\") return bySearch.filter((c) => c.unread > 0);\n if (queueFilter === \"read\") return bySearch.filter((c) => c.unread === 0);\n return bySearch;\n }, [searchQuery, queueFilter]);\n\n const counts = useMemo(() => {\n const q = searchQuery.trim().toLowerCase();\n const bySearch = q\n ? CONVERSATIONS.filter(\n (c) =>\n c.name.toLowerCase().includes(q) ||\n c.id.toLowerCase().includes(q) ||\n c.last.toLowerCase().includes(q),\n )\n : CONVERSATIONS;\n return {\n all: bySearch.length,\n unread: bySearch.filter((c) => c.unread > 0).length,\n read: bySearch.filter((c) => c.unread === 0).length,\n };\n }, [searchQuery]);\n\n return (\n <aside aria-label=\"Fila de conversas\" className={cn(s.root(), className)}>\n <header className={s.header()}>\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onToggleFilters}\n aria-label={filtersCollapsed ? \"Expandir filtros\" : \"Colapsar filtros\"}\n aria-pressed={!filtersCollapsed}\n >\n <MenuIcon />\n </Button>\n <h2 className={s.title()}>Conversas</h2>\n <Chip color=\"primary\" variant=\"soft\" size=\"sm\" shape=\"rounded\">\n {filtered.length}\n </Chip>\n </header>\n\n <div className={s.searchWrap()}>\n <div className={s.searchInner()}>\n <Search size={14} strokeWidth={1.8} className={s.searchIcon()} />\n <Input\n type=\"text\"\n placeholder=\"Buscar conversa, ID ou nome...\"\n value={searchQuery}\n onChange={(e) => onSearchChange(e.target.value)}\n className={s.searchInput()}\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => onSearchChange(\"\")}\n className={s.searchClear()}\n aria-label=\"Limpar busca\"\n >\n <X size={12} />\n </button>\n )}\n </div>\n </div>\n\n <div className={s.chipsWrap()}>\n <ChipGroup\n type=\"single\"\n value={queueFilter}\n onValueChange={(v) => onQueueFilterChange((v || \"all\") as QueueFilter)}\n size=\"md\"\n ariaLabel=\"Filtrar conversas\"\n >\n <ChipGroupItem value=\"all\">\n Todas{counts.all > 0 && ` (${counts.all})`}\n </ChipGroupItem>\n <ChipGroupItem value=\"unread\">\n Não lidas{counts.unread > 0 && ` (${counts.unread})`}\n </ChipGroupItem>\n <ChipGroupItem value=\"read\">\n Lidas{counts.read > 0 && ` (${counts.read})`}\n </ChipGroupItem>\n </ChipGroup>\n </div>\n\n <div className={s.list()}>\n {filtered.length === 0 ? (\n <div className={s.empty()}>Nenhuma conversa encontrada.</div>\n ) : (\n filtered.map((c) => (\n <ConversationListItem\n key={c.id}\n conv={c}\n isActive={c.id === activeId}\n onSelect={onSelect}\n />\n ))\n )}\n </div>\n </aside>\n );\n}\n","import { useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { useTheme, type Theme } from \"@/hooks/useTheme\";\nimport { AppShell } from \"@/components/ui/AppShell\";\nimport {\n APP_SHELL_CONTEXTS,\n APP_SHELL_COMMANDS,\n APP_SHELL_NOTIFICATIONS,\n APP_SHELL_MESSAGES,\n APP_SHELL_THEME_OPTIONS,\n} from \"../../mocks/app-shell-mocks\";\nimport { chatV2Styles, mobileOverlay } from \"./chat-v2.styles\";\nimport { CONVERSATIONS, CONVERSATION_DETAILS, DEFAULT_DETAIL } from \"./chat-v2-mocks\";\nimport type { FilterGroupKey, QueueFilter } from \"./chat-v2.types\";\nimport { useResizable } from \"./hooks/use-resizable\";\nimport { ConversationColumn } from \"./components/ConversationColumn\";\nimport { DetailsColumn, type SectionsState } from \"./components/DetailsColumn\";\nimport { FiltersColumn, FiltersRail, type FiltersState } from \"./components/FiltersColumn\";\nimport { QueueColumn } from \"./components/QueueColumn\";\n\n/** Em mobile (<md) só uma view fica visível por vez. */\ntype MobileView = \"list\" | \"chat\" | \"details\";\n\nexport default function ChatV2() {\n const s = chatV2Styles();\n\n const [activeId, setActiveId] = useState<string>(CONVERSATIONS[0].id);\n const [searchQuery, setSearchQuery] = useState(\"\");\n const { theme, setTheme } = useTheme();\n const [mobileView, setMobileView] = useState<MobileView>(\"list\");\n\n const handleSelectConversation = (id: string) => {\n setActiveId(id);\n setMobileView(\"chat\");\n };\n\n // Toggle de detalhes:\n // - Desktop: alterna o painel lateral (detailsOpen).\n // - Mobile (<md): navega entre \"chat\" ↔ \"details\" SEM fechar o painel.\n const handleToggleDetails = () => {\n const isMobile =\n typeof window !== \"undefined\" &&\n window.matchMedia(\"(max-width: 767px)\").matches;\n if (isMobile) {\n setDetailsOpen(true);\n setMobileView((v) => (v === \"details\" ? \"chat\" : \"details\"));\n } else {\n setDetailsOpen((o) => !o);\n }\n };\n\n // Filtros multi-seleção (Set por grupo)\n const [filters, setFilters] = useState<FiltersState>({\n status: new Set([\"open\"]),\n channels: new Set(),\n categories: new Set(),\n innerStatus: new Set(),\n });\n const toggleFilter = (group: FilterGroupKey, id: string) => {\n setFilters((prev) => {\n const next = new Set(prev[group]);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return { ...prev, [group]: next };\n });\n };\n\n const [filtersCollapsed, setFiltersCollapsed] = useState(false);\n const [queueFilter, setQueueFilter] = useState<QueueFilter>(\"all\");\n\n const [detailsOpen, setDetailsOpen] = useState(true);\n const [openSections, setOpenSections] = useState<SectionsState>({\n contact: true,\n ticket: true,\n history: true,\n });\n const toggleSection = (id: keyof SectionsState) =>\n setOpenSections((m) => ({ ...m, [id]: !m[id] }));\n\n const detailsResize = useResizable({\n initial: 360,\n min: 280,\n max: 520,\n // Mantém storageKey diferente da ChatShowcase pra não conflitar valores entre as 2 páginas.\n storageKey: \"chat-v2.detailsWidth\",\n });\n\n const activeConversation =\n CONVERSATIONS.find((c) => c.id === activeId) ?? CONVERSATIONS[0];\n const activeDetail =\n CONVERSATION_DETAILS[activeConversation.id] ?? DEFAULT_DETAIL;\n\n return (\n <AppShell\n contexts={APP_SHELL_CONTEXTS}\n defaultActiveContextId=\"inbox\"\n defaultActiveItemHref=\"#chat-v2\"\n breadcrumb={[{ label: \"Atendimentos\" }]}\n commandGroups={APP_SHELL_COMMANDS}\n notifications={{\n items: APP_SHELL_NOTIFICATIONS,\n onMarkAllRead: () => alert(\"Marcar todas como lidas\"),\n onMoreActions: () => alert(\"Mais ações\"),\n onViewAll: () => alert(\"Ver todas\"),\n }}\n messages={{\n items: APP_SHELL_MESSAGES,\n onNewMessage: () => alert(\"Nova mensagem\"),\n onExpand: () => alert(\"Expandir\"),\n onViewAll: () => alert(\"Ver todas\"),\n }}\n theme={theme}\n onThemeChange={(id) => setTheme(id as Theme)}\n themeOptions={APP_SHELL_THEME_OPTIONS}\n mobileEdgeToEdge\n >\n {/* Body — desktop: 4 colunas lado a lado.\n Mobile (<md): só uma view visível por vez, fullscreen, controlada por\n `mobileView` (list → chat → details). Simula navegação de app. */}\n <div className={s.root()}>\n {/* Filters: escondido em mobile. `md:contents` mantém a coluna no flex parent. */}\n <div className={s.filtersWrap()}>\n {filtersCollapsed ? (\n <FiltersRail filters={filters} onToggleFilter={toggleFilter} />\n ) : (\n <FiltersColumn filters={filters} onToggleFilter={toggleFilter} />\n )}\n </div>\n\n <QueueColumn\n activeId={activeId}\n onSelect={handleSelectConversation}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n queueFilter={queueFilter}\n onQueueFilterChange={setQueueFilter}\n filtersCollapsed={filtersCollapsed}\n onToggleFilters={() => setFiltersCollapsed((c) => !c)}\n className={cn(\n mobileView === \"list\"\n ? `${mobileOverlay.active} max-md:z-[1]`\n : mobileOverlay.hidden,\n )}\n />\n\n <ConversationColumn\n conversation={activeConversation}\n detailsOpen={detailsOpen}\n onToggleDetails={handleToggleDetails}\n onBackToList={() => setMobileView(\"list\")}\n className={cn(\n mobileView === \"chat\"\n ? `${mobileOverlay.active} max-md:z-[2]`\n : mobileOverlay.hidden,\n )}\n />\n\n {detailsOpen && (\n <DetailsColumn\n conversation={activeConversation}\n detail={activeDetail}\n openSections={openSections}\n onToggleSection={toggleSection}\n onClose={() => {\n setDetailsOpen(false);\n setMobileView(\"chat\");\n }}\n onBackToChat={() => setMobileView(\"chat\")}\n width={detailsResize.width}\n onResizeStart={detailsResize.onResizeStart}\n className={cn(\n mobileView === \"details\"\n ? `${mobileOverlay.active} max-md:!w-full max-md:z-[3]`\n : mobileOverlay.hidden,\n )}\n />\n )}\n </div>\n </AppShell>\n );\n}\n"],"names":["MenuIcon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chat.mjs","sources":["../../src/preview/pages/ChatV2/chat-v2.styles.ts","../../src/preview/pages/ChatV2/hooks/use-resizable.ts","../../src/preview/pages/ChatV2/components/ChannelDot/channel-dot.tsx","../../src/preview/pages/ChatV2/components/ConversationActionsMenu/conversation-actions-menu.tsx","../../src/preview/pages/ChatV2/components/DateSeparator/date-separator.tsx","../../src/preview/pages/ChatV2/components/MessageBubble/message-bubble.styles.ts","../../src/preview/pages/ChatV2/components/MessageBubble/message-bubble.tsx","../../src/preview/pages/ChatV2/components/PersonAvatar/person-avatar.tsx","../../src/preview/pages/ChatV2/components/ConversationColumn/conversation-column.styles.ts","../../src/preview/pages/ChatV2/components/ConversationColumn/conversation-column.tsx","../../src/preview/pages/ChatV2/components/DetailField/detail-field.tsx","../../src/preview/pages/ChatV2/components/DetailSection/detail-section.tsx","../../src/preview/pages/ChatV2/components/DetailsColumn/details-column.styles.ts","../../src/preview/pages/ChatV2/components/DetailsColumn/details-column.tsx","../../src/preview/pages/ChatV2/components/FilterRow/filter-row.styles.ts","../../src/preview/pages/ChatV2/components/FilterRow/filter-row.tsx","../../src/preview/pages/ChatV2/components/FiltersColumn/filters-column.styles.ts","../../src/preview/pages/ChatV2/components/FiltersColumn/filters-column.tsx","../../src/preview/pages/ChatV2/components/RailItem/rail-item.styles.ts","../../src/preview/pages/ChatV2/components/RailItem/rail-item.tsx","../../src/preview/pages/ChatV2/components/FiltersColumn/filters-rail.tsx","../../src/preview/pages/ChatV2/components/ConversationListItem/conversation-list-item.styles.ts","../../src/preview/pages/ChatV2/components/ConversationListItem/conversation-list-item.tsx","../../src/preview/pages/ChatV2/components/QueueColumn/queue-column.styles.ts","../../src/preview/pages/ChatV2/components/QueueColumn/queue-column.tsx","../../src/preview/pages/ChatV2/ChatV2.tsx"],"sourcesContent":["import { tv } from \"@/utils/tv\";\n\n/**\n * Layout root da página Chat V2 — 4 colunas side-by-side em desktop,\n * fullscreen overlays em mobile (<md), controladas por `mobileView`.\n */\nexport const chatV2Styles = tv({\n slots: {\n /** Body do AppShell — flex row com gap entre colunas. `relative` pra mobile overlays. */\n root: \"flex flex-1 min-h-0 gap-gp-2xl relative\",\n /** Wrapper dos filtros (col 1) — escondido em mobile. */\n filtersWrap: \"hidden md:contents\",\n },\n});\n\n/**\n * Helpers de className pros 3 estados de mobile view (list/chat/details).\n * Cada coluna recebe a classe correspondente; em desktop ficam sem efeito.\n */\nexport const mobileOverlay = {\n active: \"max-md:absolute max-md:inset-0 max-md:w-full max-md:rounded-radius-none max-md:border-0\",\n hidden: \"max-md:hidden\",\n} as const;\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport type UseResizableOptions = {\n /** Largura inicial (em px) antes do localStorage hidratar. */\n initial: number;\n /** Largura mínima permitida (em px). */\n min: number;\n /** Largura máxima permitida (em px). */\n max: number;\n /** Chave no localStorage pra persistir o último valor entre sessões. */\n storageKey: string;\n};\n\nexport type UseResizableResult = {\n /** Largura atual em px (controlada pelo drag + hidratação localStorage). */\n width: number;\n /** Handler pra começar o drag — atribuir em `onMouseDown` do handle. */\n onResizeStart: (e: React.MouseEvent) => void;\n};\n\n/**\n * Hook de drag-resize horizontal pra split-panes com persist em localStorage.\n *\n * Comportamento: o handle é assumido como estando no **left edge** do painel —\n * arrastar pra esquerda (delta negativo em X) **aumenta** a largura. Reverter o\n * sinal de `delta` no handler caso o handle esteja no right edge.\n *\n * Hidratação:\n * - No mount, tenta ler `localStorage[storageKey]` e validar dentro de\n * [min, max]. Se válido, usa esse valor; senão, usa `initial`.\n * - Após hidratação, qualquer mudança de `width` é salva (com check de\n * `hydrated.current` pra evitar overwrite do valor persistido com o\n * `initial` no primeiro paint).\n *\n * Cleanup:\n * - `mousemove`/`mouseup` são listeners globais durante o drag. `mouseup`\n * remove os 2 + restaura `cursor` e `user-select` do `<body>`.\n */\nexport function useResizable({\n initial,\n min,\n max,\n storageKey,\n}: UseResizableOptions): UseResizableResult {\n const [width, setWidth] = useState<number>(initial);\n const hydrated = useRef(false);\n\n // Hidrata do localStorage no mount\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n try {\n const raw = window.localStorage.getItem(storageKey);\n const n = raw ? Number(raw) : NaN;\n if (!Number.isNaN(n) && n >= min && n <= max) setWidth(n);\n } catch {\n /* ignore */\n }\n hydrated.current = true;\n }, [min, max, storageKey]);\n\n // Salva quando muda (após hidratação)\n useEffect(() => {\n if (!hydrated.current || typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(storageKey, String(width));\n } catch {\n /* ignore */\n }\n }, [width, storageKey]);\n\n const onResizeStart = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n const startX = e.clientX;\n const startWidth = width;\n\n const onMove = (ev: MouseEvent) => {\n // Handle no left edge: drag pra ESQUERDA (delta < 0 em X) AUMENTA o width\n const delta = startX - ev.clientX;\n const next = Math.max(min, Math.min(max, startWidth + delta));\n setWidth(next);\n };\n const onUp = () => {\n document.removeEventListener(\"mousemove\", onMove);\n document.removeEventListener(\"mouseup\", onUp);\n document.body.style.cursor = \"\";\n document.body.style.userSelect = \"\";\n };\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n document.body.style.cursor = \"col-resize\";\n document.body.style.userSelect = \"none\";\n },\n [width, min, max],\n );\n\n return { width, onResizeStart };\n}\n","import type { ChannelId } from \"../../chat-v2.types\";\r\nimport { CHANNEL_HEX, CHANNEL_LABEL } from \"../../chat-v2-mocks\";\r\n\r\nexport type ChannelDotProps = {\r\n channel: ChannelId;\r\n /** Quando true, mostra apenas o dot (sem label). Default: false. */\r\n dotOnly?: boolean;\r\n};\r\n\r\n/**\r\n * Dot 8px + label do canal. Cor vem de `CHANNEL_HEX`. Usado em\r\n * `ConversationListItem`, header de `ConversationColumn` e tooltips.\r\n */\r\nexport function ChannelDot({ channel, dotOnly = false }: ChannelDotProps) {\r\n return (\r\n <span\r\n className=\"inline-flex items-center gap-[4px] text-caption-sm text-fg-muted\"\r\n title={CHANNEL_LABEL[channel]}\r\n >\r\n <span\r\n className=\"size-[8px] rounded-radius-full shrink-0\"\r\n style={{ background: CHANNEL_HEX[channel] }}\r\n aria-hidden\r\n />\r\n {!dotOnly && CHANNEL_LABEL[channel]}\r\n </span>\r\n );\r\n}\r\n","import {\n Archive,\n CheckCircle2,\n MoreVertical,\n Phone,\n Tag,\n UserPlus,\n Video,\n} from \"lucide-react\";\nimport { Button } from \"@/components/ui/Button/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/components/shadcn/dropdown-menu\";\n\nexport type ConversationActionsMenuProps = {\n /** Quando true, adiciona \"Resolver\" no topo do dropdown (mobile compact). */\n showResolveInMenu?: boolean;\n onResolve?: () => void;\n onCall?: () => void;\n onVideo?: () => void;\n onAddTag?: () => void;\n onAssign?: () => void;\n onArchive?: () => void;\n};\n\n/**\n * Dropdown \"...\" do header da conversa com 5–6 ações (Ligar, Vídeo, Tag,\n * Atribuir, Arquivar; opcionalmente Resolver no topo pra mobile).\n */\nexport function ConversationActionsMenu({\n showResolveInMenu = false,\n onResolve,\n onCall,\n onVideo,\n onAddTag,\n onAssign,\n onArchive,\n}: ConversationActionsMenuProps) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n color=\"secondary\"\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label=\"Mais opções\"\n >\n <MoreVertical />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" sideOffset={6} className=\"min-w-[200px]\">\n {showResolveInMenu && (\n <>\n <DropdownMenuItem onSelect={onResolve}>\n <CheckCircle2 /> Resolver\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n </>\n )}\n <DropdownMenuItem onSelect={onCall}>\n <Phone /> Ligar\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={onVideo}>\n <Video /> Vídeo chamada\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={onAddTag}>\n <Tag /> Adicionar tag\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={onAssign}>\n <UserPlus /> Atribuir\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem variant=\"destructive\" onSelect={onArchive}>\n <Archive /> Arquivar\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","export type DateSeparatorProps = {\r\n /** Texto exibido — ex: \"Hoje\", \"Ontem\", \"12 mar 2024\". */\r\n label: string;\r\n};\r\n\r\n/**\r\n * Pílula centralizada com label de data entre grupos de mensagens.\r\n * Visual: chip arredondado com `bg-bg-muted`, tipografia tabular.\r\n */\r\nexport function DateSeparator({ label }: DateSeparatorProps) {\r\n return (\r\n <div className=\"flex items-center justify-center my-pad-md\">\r\n <span className=\"px-pad-lg py-pad-2xs rounded-radius-full bg-bg-muted text-caption-sm text-fg-muted [font-variant-numeric:tabular-nums]\">\r\n {label}\r\n </span>\r\n </div>\r\n );\r\n}\r\n","import { tv, type VariantProps } from \"@/utils/tv\";\r\n\r\nexport const messageBubbleStyles = tv({\r\n slots: {\r\n /** Wrapper que controla o alinhamento horizontal (esquerda/direita). */\r\n row: \"flex\",\r\n /** Balão em si — variants definem cor + corner pointer. */\r\n bubble:\r\n \"max-w-[70%] px-pad-xl py-pad-md rounded-radius-xl shadow-sh-sm\",\r\n /** Texto da mensagem. */\r\n text: \"text-body-md leading-[1.45] whitespace-pre-wrap break-words\",\r\n /** Footer com horário + status icon. */\r\n meta: \"flex items-center justify-end gap-[4px] mt-[2px] text-caption-xs\",\r\n /** Span do horário (tabular-nums pra alinhar). */\r\n time: \"[font-variant-numeric:tabular-nums]\",\r\n },\r\n variants: {\r\n from: {\r\n me: {\r\n row: \"justify-end\",\r\n bubble: \"bg-bg-brand text-fg-on-brand rounded-br-[4px]\",\r\n meta: \"text-fg-on-brand opacity-80\",\r\n },\r\n them: {\r\n row: \"justify-start\",\r\n bubble:\r\n \"bg-bg-surface text-fg-default border border-border-subtle rounded-bl-[4px]\",\r\n meta: \"text-fg-muted\",\r\n },\r\n },\r\n },\r\n defaultVariants: {\r\n from: \"them\",\r\n },\r\n});\r\n\r\nexport type MessageBubbleVariants = VariantProps<typeof messageBubbleStyles>;\r\n","import { Check, CheckCheck } from \"lucide-react\";\nimport { messageBubbleStyles } from \"./message-bubble.styles\";\nimport type { MessageBubbleProps } from \"./message-bubble.types\";\n\n/**\n * Balão de mensagem. Variant `from` (me|them) controla cor + alinhamento.\n * Status icons (Check / CheckCheck) renderizam apenas pra `from=\"me\"`.\n */\nexport function MessageBubble({ msg }: MessageBubbleProps) {\n const from = msg.from === \"me\" ? \"me\" : \"them\";\n const { row, bubble, text, meta, time } = messageBubbleStyles({ from });\n\n return (\n <div className={row()}>\n <div className={bubble()}>\n <div className={text()}>{msg.text}</div>\n <div className={meta()}>\n <span className={time()}>{msg.time}</span>\n {from === \"me\" &&\n (msg.status === \"read\" ? (\n <CheckCheck size={12} strokeWidth={2} />\n ) : (\n <Check size={12} strokeWidth={2} />\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import { Avatar, AvatarFallback } from \"@/components/shadcn/avatar\";\r\n\r\nexport type PersonAvatarSize = \"sm\" | \"md\" | \"lg\";\r\n\r\nexport type PersonAvatarProps = {\r\n initials: string;\r\n /** Cor de fundo do avatar — hex/rgb/CSS color (vem do mock do contato). */\r\n hex: string;\r\n /** sm=28px / md=36px / lg=40px. Default: md. */\r\n size?: PersonAvatarSize;\r\n};\r\n\r\nconst SIZE_CLASSES: Record<PersonAvatarSize, string> = {\r\n sm: \"size-[28px] text-caption-sm\",\r\n md: \"size-[36px] text-body-sm font-normal\",\r\n lg: \"size-[40px] text-body-md\",\r\n};\r\n\r\n/**\r\n * Avatar circular com `initials` em branco bold sobre `hex` como background.\r\n * Usado em ConversationListItem, header de ConversationColumn e DetailsColumn.\r\n */\r\nexport function PersonAvatar({ initials, hex, size = \"md\" }: PersonAvatarProps) {\r\n return (\r\n <Avatar className={SIZE_CLASSES[size]} style={{ background: hex }}>\r\n <AvatarFallback className=\"bg-transparent text-white font-bold\">\r\n {initials}\r\n </AvatarFallback>\r\n </Avatar>\r\n );\r\n}\r\n","import { tv } from \"@/utils/tv\";\r\n\r\nexport const conversationColumnStyles = tv({\r\n slots: {\r\n root: \"flex flex-col flex-1 min-w-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\r\n header:\r\n \"flex items-center gap-gp-lg px-pad-2xl py-pad-md border-b border-border-subtle shrink-0\",\r\n headerInfo: \"flex-1 min-w-0 flex flex-col gap-[2px]\",\r\n headerTitleRow: \"flex items-center gap-gp-sm\",\r\n headerName:\r\n \"text-title-md text-fg-default whitespace-nowrap overflow-hidden text-ellipsis\",\r\n headerMetaRow:\r\n \"flex flex-wrap items-center gap-x-gp-sm gap-y-[2px] text-caption-sm text-fg-muted min-w-0\",\r\n headerActions: \"flex items-center gap-gp-sm shrink-0\",\r\n statusInner: \"inline-flex items-center gap-[4px]\",\r\n statusDot: \"size-[6px] rounded-radius-full shrink-0\",\r\n thread:\r\n \"flex-1 min-h-0 overflow-y-auto bg-bg-muted dark:bg-bg-canvas px-pad-3xl py-pad-2xl flex flex-col gap-gp-md\",\r\n composer:\r\n \"flex items-center gap-gp-sm px-pad-2xl py-pad-md border-t border-border-subtle shrink-0 bg-bg-surface\",\r\n },\r\n});\r\n","import { useState } from \"react\";\nimport {\n ArrowLeft,\n CheckCircle2,\n Mic,\n PanelRightClose,\n PanelRightOpen,\n Paperclip,\n Send,\n Smile,\n} from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/Button/button\";\nimport { Chip } from \"@/components/ui/Chip\";\nimport { Input } from \"@/components/shadcn/input\";\nimport { SAMPLE_MESSAGES, STATUS_DOT } from \"../../chat-v2-mocks\";\nimport type { Message } from \"../../chat-v2.types\";\nimport { ChannelDot } from \"../ChannelDot/channel-dot\";\nimport { ConversationActionsMenu } from \"../ConversationActionsMenu\";\nimport { DateSeparator } from \"../DateSeparator/date-separator\";\nimport { MessageBubble } from \"../MessageBubble\";\nimport { PersonAvatar } from \"../PersonAvatar\";\nimport { conversationColumnStyles } from \"./conversation-column.styles\";\nimport type { ConversationColumnProps } from \"./conversation-column.types\";\n\n/**\n * Coluna central. Header com avatar + nome + meta (id/canal/status) + ações,\n * thread scrollável com `DateSeparator` + `MessageBubble`, composer com Input\n * + botões. Estado local: texto digitado + lista de mensagens.\n */\nexport function ConversationColumn({\n conversation,\n detailsOpen,\n onToggleDetails,\n onBackToList,\n className,\n}: ConversationColumnProps) {\n const s = conversationColumnStyles();\n const [text, setText] = useState(\"\");\n const [msgs, setMsgs] = useState<Message[]>(SAMPLE_MESSAGES);\n\n const send = (e?: React.FormEvent) => {\n e?.preventDefault();\n if (!text.trim()) return;\n setMsgs((m) => [\n ...m,\n {\n id: Date.now(),\n from: \"me\",\n text: text.trim(),\n time: new Date().toLocaleTimeString(\"pt-BR\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n }),\n status: \"sent\",\n },\n ]);\n setText(\"\");\n };\n\n return (\n <section aria-label=\"Conversa\" className={cn(s.root(), className)}>\n {/* Header da conversa */}\n <header className={s.header()}>\n {onBackToList && (\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Voltar pra lista\"\n onClick={onBackToList}\n className=\"md:hidden\"\n >\n <ArrowLeft />\n </Button>\n )}\n <div className=\"max-md:hidden\">\n <PersonAvatar\n initials={conversation.initials}\n hex={conversation.avatarHex}\n size=\"md\"\n />\n </div>\n\n <div className={s.headerInfo()}>\n <div className={s.headerTitleRow()}>\n <span className={s.headerName()}>{conversation.name}</span>\n <Chip color={conversation.tagKind} variant=\"soft\" size=\"sm\" shape=\"pill\">\n {conversation.tag}\n </Chip>\n </div>\n\n <div className={s.headerMetaRow()}>\n <span className=\"[font-variant-numeric:tabular-nums]\">\n {conversation.id}\n </span>\n <span aria-hidden>·</span>\n <ChannelDot channel={conversation.channel} />\n <span aria-hidden>·</span>\n <span className={s.statusInner()}>\n <span\n className={s.statusDot()}\n style={{ background: STATUS_DOT[conversation.status] }}\n aria-hidden\n />\n {conversation.statusLabel}\n </span>\n </div>\n </div>\n\n <div className={s.headerActions()}>\n <Button\n color=\"primary\"\n variant=\"filled\"\n size=\"sm\"\n iconLeft={<CheckCircle2 />}\n className=\"max-md:hidden\"\n >\n Resolver\n </Button>\n <ConversationActionsMenu\n showResolveInMenu\n onResolve={() => console.log(\"resolver\")}\n onCall={() => console.log(\"ligar\")}\n onVideo={() => console.log(\"video\")}\n onAddTag={() => console.log(\"tag\")}\n onAssign={() => console.log(\"atribuir\")}\n onArchive={() => console.log(\"arquivar\")}\n />\n <Button\n color=\"secondary\"\n variant=\"outline\"\n size=\"icon-sm\"\n aria-label={detailsOpen ? \"Ocultar detalhes\" : \"Mostrar detalhes\"}\n aria-pressed={detailsOpen}\n onClick={onToggleDetails}\n >\n {detailsOpen ? <PanelRightClose /> : <PanelRightOpen />}\n </Button>\n </div>\n </header>\n\n {/* Thread */}\n <div className={s.thread()} aria-live=\"polite\">\n <DateSeparator label=\"Hoje\" />\n {msgs.map((m) => (\n <MessageBubble key={m.id} msg={m} />\n ))}\n </div>\n\n {/* Composer */}\n <form onSubmit={send} className={s.composer()}>\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Anexar\"\n type=\"button\"\n >\n <Paperclip />\n </Button>\n <Input\n type=\"text\"\n value={text}\n onChange={(e) => setText(e.target.value)}\n placeholder=\"Digite uma mensagem...\"\n aria-label=\"Mensagem\"\n className=\"flex-1\"\n />\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Emoji\"\n type=\"button\"\n >\n <Smile />\n </Button>\n {text.trim() ? (\n <Button\n color=\"primary\"\n variant=\"filled\"\n size=\"icon-sm\"\n aria-label=\"Enviar\"\n type=\"submit\"\n >\n <Send strokeWidth={2.2} />\n </Button>\n ) : (\n <Button\n color=\"primary\"\n variant=\"filled\"\n size=\"icon-sm\"\n aria-label=\"Gravar áudio\"\n type=\"button\"\n >\n <Mic strokeWidth={2.2} />\n </Button>\n )}\n </form>\n </section>\n );\n}\n","import type { ReactNode } from \"react\";\r\n\r\nexport type DetailFieldProps = {\r\n /** Label à esquerda (text-fg-muted). */\r\n label: string;\r\n /** Valor à direita — string, número ou ReactNode (Chip, link, etc). */\r\n value: ReactNode;\r\n};\r\n\r\n/**\r\n * Row label : value usada nas seções de detalhes (Contato, Atendimento).\r\n * Layout flex baseline justify-between, quebra de palavra no valor.\r\n */\r\nexport function DetailField({ label, value }: DetailFieldProps) {\r\n return (\r\n <div className=\"flex items-baseline justify-between gap-gp-md py-pad-2xs\">\r\n <span className=\"text-body-xs font-normal text-fg-muted shrink-0\">{label}</span>\r\n <span className=\"text-body-xs font-normal text-fg-default text-right break-words min-w-0\">\r\n {value || \"—\"}\r\n </span>\r\n </div>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\nimport { ChevronDown } from \"lucide-react\";\r\n\r\nexport type DetailSectionProps = {\r\n title: string;\r\n open: boolean;\r\n onToggle: () => void;\r\n children: ReactNode;\r\n};\r\n\r\n/**\r\n * Seção colapsável da `DetailsColumn` (Contato / Atendimento / Histórico).\r\n * Header clicável com chevron rotativo + corpo só monta quando `open`.\r\n */\r\nexport function DetailSection({\r\n title,\r\n open,\r\n onToggle,\r\n children,\r\n}: DetailSectionProps) {\r\n return (\r\n <section className=\"flex flex-col border-b border-border-subtle pb-pad-xl last:border-b-0 last:pb-0\">\r\n <button\r\n type=\"button\"\r\n onClick={onToggle}\r\n aria-expanded={open}\r\n className=\"flex items-center justify-between w-full px-pad-sm py-pad-sm -mx-pad-sm rounded-radius-md cursor-pointer text-left transition-colors duration-150 hover:bg-bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring-brand\"\r\n >\r\n <span className=\"text-body-sm font-semibold text-fg-default\">{title}</span>\r\n <ChevronDown\r\n size={14}\r\n className={[\r\n \"text-fg-muted transition-transform duration-150\",\r\n open ? \"\" : \"-rotate-90\",\r\n ].join(\" \")}\r\n />\r\n </button>\r\n {open && <div className=\"flex flex-col gap-gp-sm pt-pad-xs\">{children}</div>}\r\n </section>\r\n );\r\n}\r\n","import { tv } from \"@/utils/tv\";\r\n\r\nexport const detailsColumnStyles = tv({\r\n slots: {\r\n root: \"relative flex flex-col shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\r\n /** Resize handle no left edge — 4px. */\r\n handle:\r\n \"absolute left-0 top-0 bottom-0 w-[4px] z-[1] bg-transparent cursor-col-resize hover:bg-bg-brand active:bg-bg-brand transition-colors duration-150 focus-visible:outline-none focus-visible:bg-bg-brand\",\r\n header:\r\n \"flex items-center gap-gp-md px-pad-2xl py-pad-lg border-b border-border-subtle shrink-0\",\r\n title: \"m-0 text-title-md text-fg-default flex-1\",\r\n body: \"flex-1 min-h-0 overflow-y-auto px-pad-2xl py-pad-md flex flex-col gap-gp-2xl\",\r\n contactHead: \"flex flex-col items-center gap-gp-md pb-pad-md\",\r\n contactName: \"text-body-md font-semibold text-fg-default text-center\",\r\n tagsRow: \"flex flex-col gap-gp-sm pt-pad-xs\",\r\n tagsLabel: \"text-body-xs font-normal text-fg-muted\",\r\n tagsChips: \"flex items-center gap-gp-xs flex-wrap\",\r\n tagAddBtn:\r\n \"inline-flex items-center gap-[3px] px-pad-md h-[22px] rounded-radius-full border border-dashed border-border-input text-caption-sm font-medium text-fg-muted hover:bg-bg-muted hover:text-fg-default transition-colors\",\r\n historyEmpty: \"text-body-xs font-normal text-fg-subtle text-center py-pad-md\",\r\n historyList: \"m-0 p-0 list-none flex flex-col gap-gp-sm\",\r\n historyItem:\r\n \"flex gap-gp-md p-pad-md rounded-radius-md bg-bg-muted border border-border-subtle\",\r\n historyId:\r\n \"text-caption-sm text-fg-muted shrink-0 [font-variant-numeric:tabular-nums] pt-[1px]\",\r\n historyBody: \"flex-1 min-w-0 flex flex-col gap-[1px]\",\r\n historySubject: \"text-body-xs text-fg-default\",\r\n historyMeta: \"text-caption-sm text-fg-muted\",\r\n },\r\n});\r\n","import { ArrowLeft, Plus, X } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/Button/button\";\nimport { Chip } from \"@/components/ui/Chip\";\nimport { CHANNEL_LABEL } from \"../../chat-v2-mocks\";\nimport { DetailField } from \"../DetailField/detail-field\";\nimport { DetailSection } from \"../DetailSection\";\nimport { PersonAvatar } from \"../PersonAvatar\";\nimport { detailsColumnStyles } from \"./details-column.styles\";\nimport type { DetailsColumnProps } from \"./details-column.types\";\n\n/**\n * Coluna direita: header com título + close, resize handle no left edge (4px),\n * body scrollável com 3 accordions (Contato, Atendimento, Histórico).\n * Width controlado pelo hook `useResizable` no parent.\n */\nexport function DetailsColumn({\n conversation,\n detail,\n openSections,\n onToggleSection,\n onClose,\n width,\n onResizeStart,\n onBackToChat,\n className,\n}: DetailsColumnProps) {\n const s = detailsColumnStyles();\n\n return (\n <aside\n aria-label=\"Detalhes do contato\"\n style={{ width }}\n className={cn(s.root(), className)}\n >\n <button\n type=\"button\"\n onMouseDown={onResizeStart}\n aria-label=\"Redimensionar painel de detalhes\"\n className={s.handle()}\n />\n\n <header className={s.header()}>\n {onBackToChat && (\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Voltar pra conversa\"\n onClick={onBackToChat}\n className=\"md:hidden\"\n >\n <ArrowLeft />\n </Button>\n )}\n <h3 className={s.title()}>Detalhes</h3>\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Fechar painel\"\n onClick={onClose}\n >\n <X />\n </Button>\n </header>\n\n <div className={s.body()}>\n <DetailSection\n title=\"Contato\"\n open={openSections.contact}\n onToggle={() => onToggleSection(\"contact\")}\n >\n <div className={s.contactHead()}>\n <PersonAvatar\n initials={conversation.initials}\n hex={conversation.avatarHex}\n size=\"lg\"\n />\n <div className={s.contactName()}>{conversation.name}</div>\n </div>\n <DetailField label=\"Telefone\" value={detail.phone} />\n <DetailField label=\"Email\" value={detail.email} />\n <DetailField label=\"Primeiro contato\" value={detail.firstContact} />\n </DetailSection>\n\n <DetailSection\n title=\"Atendimento\"\n open={openSections.ticket}\n onToggle={() => onToggleSection(\"ticket\")}\n >\n <DetailField label=\"ID\" value={conversation.id} />\n <DetailField label=\"Status\" value={conversation.statusLabel} />\n <DetailField label=\"Atribuído a\" value={detail.assignedTo} />\n <DetailField label=\"Canal\" value={CHANNEL_LABEL[conversation.channel]} />\n <DetailField label=\"Criado em\" value={detail.createdAt} />\n\n <div className={s.tagsRow()}>\n <span className={s.tagsLabel()}>Tags</span>\n <div className={s.tagsChips()}>\n <Chip color={conversation.tagKind} variant=\"soft\" size=\"sm\" shape=\"pill\">\n {conversation.tag}\n </Chip>\n {detail.extraTags.map((t) => (\n <Chip key={t} color=\"info\" variant=\"soft\" size=\"sm\" shape=\"pill\">\n {t}\n </Chip>\n ))}\n <button type=\"button\" className={s.tagAddBtn()}>\n <Plus size={11} strokeWidth={2.2} /> tag\n </button>\n </div>\n </div>\n </DetailSection>\n\n <DetailSection\n title=\"Histórico\"\n open={openSections.history}\n onToggle={() => onToggleSection(\"history\")}\n >\n {detail.history.length === 0 ? (\n <div className={s.historyEmpty()}>Nenhum atendimento anterior.</div>\n ) : (\n <ul className={s.historyList()}>\n {detail.history.map((h) => (\n <li key={h.id} className={s.historyItem()}>\n <span className={s.historyId()}>{h.id}</span>\n <div className={s.historyBody()}>\n <span className={s.historySubject()}>{h.subject}</span>\n <span className={s.historyMeta()}>\n {h.date} · {h.status}\n </span>\n </div>\n </li>\n ))}\n </ul>\n )}\n </DetailSection>\n </div>\n </aside>\n );\n}\n","import { tv, type VariantProps } from \"@/utils/tv\";\r\n\r\nexport const filterRowStyles = tv({\r\n slots: {\r\n button: [\r\n \"flex items-center gap-gp-md w-full\",\r\n \"px-pad-md py-pad-sm rounded-radius-md text-left\",\r\n \"transition-colors duration-150 cursor-pointer\",\r\n ].join(\" \"),\r\n /** Leading slot (icon ou dot fallback). */\r\n leading: \"shrink-0 inline-flex items-center justify-center size-[18px]\",\r\n /** Label do filtro (ellipsis). */\r\n label:\r\n \"flex-1 min-w-0 text-body-xs whitespace-nowrap overflow-hidden text-ellipsis\",\r\n /** Dot brand 6px pra \"tem novidades\". */\r\n unreadDot: \"size-[6px] rounded-radius-full bg-bg-brand shrink-0\",\r\n /** Contador à direita. */\r\n count: \"text-caption-sm text-fg-muted shrink-0 [font-variant-numeric:tabular-nums]\",\r\n /** Dot fallback (quando item não tem icon). */\r\n fallbackDot: \"size-[8px] rounded-radius-full\",\r\n },\r\n variants: {\r\n isActive: {\r\n true: {\r\n button: \"bg-bg-muted dark:bg-bg-emphasis text-fg-default font-semibold\",\r\n },\r\n false: {\r\n button: \"text-fg-muted hover:bg-bg-muted hover:text-fg-default\",\r\n },\r\n },\r\n },\r\n defaultVariants: {\r\n isActive: false,\r\n },\r\n});\r\n\r\nexport type FilterRowVariants = VariantProps<typeof filterRowStyles>;\r\n","import type { FilterItem } from \"../../chat-v2.types\";\nimport { filterRowStyles } from \"./filter-row.styles\";\n\nexport type FilterRowProps = {\n item: FilterItem;\n isActive: boolean;\n onClick: () => void;\n};\n\n/**\n * Row clicável da `FiltersColumn` expandida. Layout: leading (icon ou dot) +\n * label (ellipsis) + dot unread opcional + count tabular.\n */\nexport function FilterRow({ item, isActive, onClick }: FilterRowProps) {\n const Icon = item.icon;\n const s = filterRowStyles({ isActive });\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={isActive}\n className={s.button()}\n >\n <span className={s.leading()}>\n {Icon ? (\n <Icon\n size={15}\n strokeWidth={1.8}\n style={{ color: item.color ?? \"var(--color-fg-muted)\" }}\n />\n ) : (\n <span\n className={s.fallbackDot()}\n style={{ background: item.color ?? \"var(--color-fg-muted)\" }}\n aria-hidden\n />\n )}\n </span>\n <span className={s.label()}>{item.name}</span>\n {item.hasUnread && <span className={s.unreadDot()} aria-label=\"tem novidades\" />}\n <span className={s.count()}>{item.count}</span>\n </button>\n );\n}\n","import { tv } from \"@/utils/tv\";\r\n\r\nexport const filtersColumnStyles = tv({\r\n slots: {\r\n /** Aside raiz da versão expandida (280px). */\r\n root: \"flex flex-col w-[280px] shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\r\n /** Aside raiz da versão rail (64px). */\r\n rail: \"flex flex-col w-[64px] shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\r\n /** Container scrollável das seções (expandida). */\r\n scroll: \"flex-1 min-h-0 overflow-y-auto px-pad-md py-pad-md flex flex-col gap-gp-lg\",\r\n /** Container scrollável (rail). */\r\n railScroll:\r\n \"flex-1 min-h-0 overflow-y-auto py-pad-md flex flex-col items-center gap-gp-sm\",\r\n /** Section wrapper (expandida). */\r\n section: \"flex flex-col gap-gp-2xs\",\r\n /** Header de section (título all-caps). Combo: `caption-xs` (10/400)\r\n + override `font-bold uppercase tracking-[0.06em]` pra pattern strong. */\r\n sectionTitle:\r\n \"px-pad-md pt-pad-2xs pb-pad-2xs text-caption-xs font-bold tracking-[0.06em] text-fg-subtle uppercase\",\r\n /** Group wrapper (rail) — divider entre grupos. */\r\n railGroup: \"w-full flex flex-col items-center gap-gp-xs px-pad-md\",\r\n /** Modifier de divisor pros grupos não-primeiros (rail). */\r\n railGroupDivider: \"pt-pad-sm border-t border-border-subtle\",\r\n /** Modifier de divisor pras sections não-primeiras (expandida). */\r\n sectionDivider: \"pt-pad-lg border-t border-border-subtle\",\r\n },\r\n});\r\n","import { cn } from \"@/lib/utils\";\nimport { FILTER_GROUPS } from \"../../chat-v2-mocks\";\nimport type { FilterGroupKey, FilterItem } from \"../../chat-v2.types\";\nimport { FilterRow } from \"../FilterRow\";\nimport { filtersColumnStyles } from \"./filters-column.styles\";\nimport type { FiltersColumnProps, FiltersState } from \"./filters-column.types\";\n\n/**\n * Coluna esquerda expandida (280px) com as 4 seções de filtros definidas\n * em `FILTER_GROUPS` (mocks).\n */\nexport function FiltersColumn({\n filters,\n onToggleFilter,\n className,\n}: FiltersColumnProps) {\n const s = filtersColumnStyles();\n return (\n <aside aria-label=\"Filtros\" className={cn(s.root(), className)}>\n <div className={s.scroll()}>\n {FILTER_GROUPS.map((sec, i) => (\n <FilterSection\n key={sec.group}\n title={sec.title}\n group={sec.group}\n items={sec.items}\n filters={filters}\n onToggle={onToggleFilter}\n isFirst={i === 0}\n />\n ))}\n </div>\n </aside>\n );\n}\n\nfunction FilterSection({\n title,\n group,\n items,\n filters,\n onToggle,\n isFirst,\n}: {\n title: string;\n group: FilterGroupKey;\n items: FilterItem[];\n filters: FiltersState;\n onToggle: (group: FilterGroupKey, id: string) => void;\n isFirst?: boolean;\n}) {\n const s = filtersColumnStyles();\n return (\n <section className={cn(s.section(), !isFirst && s.sectionDivider())}>\n <div className={s.sectionTitle()}>{title}</div>\n {items.map((item) => (\n <FilterRow\n key={item.id}\n item={item}\n isActive={filters[group].has(item.id)}\n onClick={() => onToggle(group, item.id)}\n />\n ))}\n </section>\n );\n}\n","import { tv, type VariantProps } from \"@/utils/tv\";\n\nexport const railItemStyles = tv({\n slots: {\n button: [\n \"relative grid place-items-center size-form-md rounded-radius-md cursor-pointer\",\n \"transition-colors duration-150\",\n ].join(\" \"),\n /** Badge dot 6px (top-right) pra \"tem novidades\". */\n unreadDot:\n \"absolute top-[2px] right-[2px] size-[6px] rounded-radius-full bg-bg-brand\",\n /** Fallback dot (quando item não tem icon). */\n fallbackDot: \"size-[10px] rounded-radius-full\",\n },\n variants: {\n isActive: {\n true: {\n button: \"bg-bg-muted dark:bg-bg-emphasis text-fg-default\",\n },\n false: {\n button: \"text-fg-muted hover:bg-bg-muted hover:text-fg-default\",\n },\n },\n },\n defaultVariants: {\n isActive: false,\n },\n});\n\nexport type RailItemVariants = VariantProps<typeof railItemStyles>;\n","import type { FilterItem } from \"../../chat-v2.types\";\nimport { railItemStyles } from \"./rail-item.styles\";\n\nexport type RailItemProps = {\n item: FilterItem;\n isActive: boolean;\n onClick: () => void;\n};\n\n/**\n * Botão ícone compacto (32px) usado na `FiltersRail`. Suporta cor por\n * `item.color`, ícone Lucide ou fallback dot, e badge \"tem novidades\".\n */\nexport function RailItem({ item, isActive, onClick }: RailItemProps) {\n const Icon = item.icon;\n const s = railItemStyles({ isActive });\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={isActive}\n title={`${item.name} (${item.count})`}\n className={s.button()}\n >\n {Icon ? (\n <Icon\n size={16}\n strokeWidth={1.8}\n style={{ color: item.color ?? \"currentColor\" }}\n />\n ) : (\n <span\n className={s.fallbackDot()}\n style={{ background: item.color ?? \"var(--color-fg-muted)\" }}\n aria-hidden\n />\n )}\n {item.hasUnread && <span className={s.unreadDot()} aria-label=\"tem novidades\" />}\n </button>\n );\n}\n","import { cn } from \"@/lib/utils\";\nimport { FILTER_GROUPS } from \"../../chat-v2-mocks\";\nimport { RailItem } from \"../RailItem\";\nimport { filtersColumnStyles } from \"./filters-column.styles\";\nimport type { FiltersColumnProps } from \"./filters-column.types\";\n\n/**\n * Coluna esquerda compacta (64px) — só ícones, divididos por grupo\n * com divider top entre grupos. Consome `FILTER_GROUPS` (mocks).\n */\nexport function FiltersRail({\n filters,\n onToggleFilter,\n className,\n}: FiltersColumnProps) {\n const s = filtersColumnStyles();\n return (\n <aside aria-label=\"Filtros (compactos)\" className={cn(s.rail(), className)}>\n <div className={s.railScroll()}>\n {FILTER_GROUPS.map(({ group, items }, gi) => (\n <div\n key={group}\n className={cn(s.railGroup(), gi > 0 && s.railGroupDivider())}\n >\n {items.map((item) => (\n <RailItem\n key={item.id}\n item={item}\n isActive={filters[group].has(item.id)}\n onClick={() => onToggleFilter(group, item.id)}\n />\n ))}\n </div>\n ))}\n </div>\n </aside>\n );\n}\n","import { tv, type VariantProps } from \"@/utils/tv\";\r\n\r\nexport const conversationListItemStyles = tv({\r\n slots: {\r\n /** Card raiz (button) — flex horizontal com avatar + conteúdo. */\r\n root: [\r\n \"group/conv text-left relative\",\r\n \"flex gap-gp-md p-pad-md rounded-radius-md\",\r\n \"cursor-pointer transition-colors duration-150\",\r\n ].join(\" \"),\r\n /** Coluna direita (3 rows). */\r\n content: \"flex-1 min-w-0 flex flex-col gap-[3px]\",\r\n /** Row 1 — nome + horário. */\r\n rowTop: \"flex items-center gap-gp-sm\",\r\n /** Nome (ellipsis). */\r\n name: \"text-body-sm font-semibold text-fg-default whitespace-nowrap overflow-hidden text-ellipsis flex-1 min-w-0\",\r\n /** Horário. */\r\n time: \"text-caption-sm text-fg-muted shrink-0 [font-variant-numeric:tabular-nums]\",\r\n /** Row 2 — preview + badge unread. */\r\n rowMid: \"flex items-center gap-gp-sm\",\r\n /** Preview da última mensagem (ellipsis). */\r\n preview:\r\n \"text-body-xs font-normal text-fg-muted whitespace-nowrap overflow-hidden text-ellipsis flex-1 min-w-0\",\r\n /** Badge contador de não lidas — `caption-xs` (10/400) + override\r\n `font-bold leading-none` pra centralizar o número dentro do círculo.\r\n Tabular-nums alinha dígitos verticalmente em badges com counters dinâmicos. */\r\n unread:\r\n \"inline-flex items-center justify-center min-w-[18px] h-[18px] px-[5px] rounded-radius-full bg-bg-brand text-fg-on-brand text-caption-xs font-bold leading-none shrink-0 [font-variant-numeric:tabular-nums]\",\r\n /** Row 3 — canal + tag + ID. */\r\n rowBot: \"flex items-center gap-gp-sm\",\r\n /** ID da conversa (canto inferior direito). */\r\n id: \"ml-auto text-caption-xs text-fg-subtle shrink-0 [font-variant-numeric:tabular-nums]\",\r\n },\r\n variants: {\r\n isActive: {\r\n true: {\r\n root: [\r\n \"bg-bg-muted dark:bg-bg-emphasis\",\r\n \"before:content-[''] before:absolute before:left-0 before:top-[10px] before:bottom-[10px]\",\r\n \"before:w-[3px] before:bg-bg-brand before:rounded-r-[2px] before:pointer-events-none\",\r\n ].join(\" \"),\r\n },\r\n false: {\r\n root: \"hover:bg-bg-muted\",\r\n },\r\n },\r\n },\r\n defaultVariants: {\r\n isActive: false,\r\n },\r\n});\r\n\r\nexport type ConversationListItemVariants = VariantProps<\r\n typeof conversationListItemStyles\r\n>;\r\n","import { Chip } from \"@/components/ui/Chip\";\nimport { ChannelDot } from \"../ChannelDot/channel-dot\";\nimport { PersonAvatar } from \"../PersonAvatar\";\nimport { conversationListItemStyles } from \"./conversation-list-item.styles\";\nimport type { ConversationListItemProps } from \"./conversation-list-item.types\";\n\n/**\n * Item da fila de conversas. Avatar (36px) à esquerda + 3 rows de info à direita.\n * Variant `isActive` adiciona strip lateral brand de 3px + bg muted.\n */\nexport function ConversationListItem({\n conv,\n isActive,\n onSelect,\n}: ConversationListItemProps) {\n const s = conversationListItemStyles({ isActive });\n\n return (\n <button\n type=\"button\"\n onClick={() => onSelect(conv.id)}\n className={s.root()}\n aria-pressed={isActive}\n >\n <PersonAvatar initials={conv.initials} hex={conv.avatarHex} size=\"md\" />\n\n <div className={s.content()}>\n <div className={s.rowTop()}>\n <span className={s.name()}>{conv.name}</span>\n <span className={s.time()}>{conv.time}</span>\n </div>\n\n <div className={s.rowMid()}>\n <span className={s.preview()}>{conv.last}</span>\n {conv.unread > 0 && (\n <span className={s.unread()} aria-label={`${conv.unread} não lidas`}>\n {conv.unread}\n </span>\n )}\n </div>\n\n <div className={s.rowBot()}>\n <ChannelDot channel={conv.channel} />\n <Chip color={conv.tagKind} variant=\"soft\" size=\"sm\" shape=\"pill\">\n {conv.tag}\n </Chip>\n <span className={s.id()}>{conv.id}</span>\n </div>\n </div>\n </button>\n );\n}\n","import { tv } from \"@/utils/tv\";\r\n\r\nexport const queueColumnStyles = tv({\r\n slots: {\r\n root: \"flex flex-col w-[340px] shrink-0 bg-bg-surface border border-border-subtle rounded-radius-xl overflow-hidden\",\r\n header: \"flex items-center gap-gp-sm px-pad-md pt-pad-md pb-pad-md\",\r\n title: \"m-0 text-title-md text-fg-default flex-1 min-w-0\",\r\n searchWrap: \"px-pad-md pb-pad-lg\",\r\n searchInner: \"relative\",\r\n searchIcon:\r\n \"absolute left-pad-lg top-1/2 -translate-y-1/2 text-fg-muted pointer-events-none\",\r\n searchInput: \"pl-[34px] pr-[30px]\",\r\n searchClear:\r\n \"absolute right-pad-md top-1/2 -translate-y-1/2 grid place-items-center size-[20px] rounded-radius-md text-fg-muted hover:bg-bg-muted hover:text-fg-default transition-colors\",\r\n chipsWrap: \"px-pad-md pb-pad-2xl\",\r\n list: \"flex-1 min-h-0 overflow-y-auto px-pad-md pb-pad-md flex flex-col gap-gp-xs\",\r\n empty: \"py-pad-4xl px-pad-xl text-center text-body-xs font-normal text-fg-subtle\",\r\n },\r\n});\r\n","import { useMemo } from \"react\";\nimport { Menu as MenuIcon, Search, X } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/Button/button\";\nimport { Chip, ChipGroup, ChipGroupItem } from \"@/components/ui/Chip\";\nimport { Input } from \"@/components/shadcn/input\";\nimport { CONVERSATIONS } from \"../../chat-v2-mocks\";\nimport type { QueueFilter } from \"../../chat-v2.types\";\nimport { ConversationListItem } from \"../ConversationListItem\";\nimport { queueColumnStyles } from \"./queue-column.styles\";\nimport type { QueueColumnProps } from \"./queue-column.types\";\n\n/**\n * Coluna da fila de conversas (340px). Header com toggle de filtros + título +\n * badge de contagem; Search + chips Todas/Não lidas/Lidas; lista scrollável.\n */\nexport function QueueColumn({\n activeId,\n onSelect,\n searchQuery,\n onSearchChange,\n queueFilter,\n onQueueFilterChange,\n filtersCollapsed,\n onToggleFilters,\n className,\n}: QueueColumnProps) {\n const s = queueColumnStyles();\n\n const filtered = useMemo(() => {\n const q = searchQuery.trim().toLowerCase();\n const bySearch = q\n ? CONVERSATIONS.filter(\n (c) =>\n c.name.toLowerCase().includes(q) ||\n c.id.toLowerCase().includes(q) ||\n c.last.toLowerCase().includes(q),\n )\n : CONVERSATIONS;\n if (queueFilter === \"unread\") return bySearch.filter((c) => c.unread > 0);\n if (queueFilter === \"read\") return bySearch.filter((c) => c.unread === 0);\n return bySearch;\n }, [searchQuery, queueFilter]);\n\n const counts = useMemo(() => {\n const q = searchQuery.trim().toLowerCase();\n const bySearch = q\n ? CONVERSATIONS.filter(\n (c) =>\n c.name.toLowerCase().includes(q) ||\n c.id.toLowerCase().includes(q) ||\n c.last.toLowerCase().includes(q),\n )\n : CONVERSATIONS;\n return {\n all: bySearch.length,\n unread: bySearch.filter((c) => c.unread > 0).length,\n read: bySearch.filter((c) => c.unread === 0).length,\n };\n }, [searchQuery]);\n\n return (\n <aside aria-label=\"Fila de conversas\" className={cn(s.root(), className)}>\n <header className={s.header()}>\n <Button\n color=\"secondary\"\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onToggleFilters}\n aria-label={filtersCollapsed ? \"Expandir filtros\" : \"Colapsar filtros\"}\n aria-pressed={!filtersCollapsed}\n >\n <MenuIcon />\n </Button>\n <h2 className={s.title()}>Conversas</h2>\n <Chip color=\"primary\" variant=\"soft\" size=\"sm\" shape=\"rounded\">\n {filtered.length}\n </Chip>\n </header>\n\n <div className={s.searchWrap()}>\n <div className={s.searchInner()}>\n <Search size={14} strokeWidth={1.8} className={s.searchIcon()} />\n <Input\n type=\"text\"\n placeholder=\"Buscar conversa, ID ou nome...\"\n value={searchQuery}\n onChange={(e) => onSearchChange(e.target.value)}\n className={s.searchInput()}\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => onSearchChange(\"\")}\n className={s.searchClear()}\n aria-label=\"Limpar busca\"\n >\n <X size={12} />\n </button>\n )}\n </div>\n </div>\n\n <div className={s.chipsWrap()}>\n <ChipGroup\n type=\"single\"\n value={queueFilter}\n onValueChange={(v) => onQueueFilterChange((v || \"all\") as QueueFilter)}\n size=\"md\"\n ariaLabel=\"Filtrar conversas\"\n >\n <ChipGroupItem value=\"all\">\n Todas{counts.all > 0 && ` (${counts.all})`}\n </ChipGroupItem>\n <ChipGroupItem value=\"unread\">\n Não lidas{counts.unread > 0 && ` (${counts.unread})`}\n </ChipGroupItem>\n <ChipGroupItem value=\"read\">\n Lidas{counts.read > 0 && ` (${counts.read})`}\n </ChipGroupItem>\n </ChipGroup>\n </div>\n\n <div className={s.list()}>\n {filtered.length === 0 ? (\n <div className={s.empty()}>Nenhuma conversa encontrada.</div>\n ) : (\n filtered.map((c) => (\n <ConversationListItem\n key={c.id}\n conv={c}\n isActive={c.id === activeId}\n onSelect={onSelect}\n />\n ))\n )}\n </div>\n </aside>\n );\n}\n","import { useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { useTheme, type Theme } from \"@/hooks/useTheme\";\nimport { AppShell } from \"@/components/ui/AppShell\";\nimport {\n APP_SHELL_CONTEXTS,\n APP_SHELL_COMMANDS,\n APP_SHELL_NOTIFICATIONS,\n APP_SHELL_MESSAGES,\n APP_SHELL_THEME_OPTIONS,\n} from \"../../mocks/app-shell-mocks\";\nimport { chatV2Styles, mobileOverlay } from \"./chat-v2.styles\";\nimport { CONVERSATIONS, CONVERSATION_DETAILS, DEFAULT_DETAIL } from \"./chat-v2-mocks\";\nimport type { FilterGroupKey, QueueFilter } from \"./chat-v2.types\";\nimport { useResizable } from \"./hooks/use-resizable\";\nimport { ConversationColumn } from \"./components/ConversationColumn\";\nimport { DetailsColumn, type SectionsState } from \"./components/DetailsColumn\";\nimport { FiltersColumn, FiltersRail, type FiltersState } from \"./components/FiltersColumn\";\nimport { QueueColumn } from \"./components/QueueColumn\";\n\n/** Em mobile (<md) só uma view fica visível por vez. */\ntype MobileView = \"list\" | \"chat\" | \"details\";\n\nexport default function ChatV2() {\n const s = chatV2Styles();\n\n const [activeId, setActiveId] = useState<string>(CONVERSATIONS[0].id);\n const [searchQuery, setSearchQuery] = useState(\"\");\n const { theme, setTheme } = useTheme();\n const [mobileView, setMobileView] = useState<MobileView>(\"list\");\n\n const handleSelectConversation = (id: string) => {\n setActiveId(id);\n setMobileView(\"chat\");\n };\n\n // Toggle de detalhes:\n // - Desktop: alterna o painel lateral (detailsOpen).\n // - Mobile (<md): navega entre \"chat\" ↔ \"details\" SEM fechar o painel.\n const handleToggleDetails = () => {\n const isMobile =\n typeof window !== \"undefined\" &&\n window.matchMedia(\"(max-width: 767px)\").matches;\n if (isMobile) {\n setDetailsOpen(true);\n setMobileView((v) => (v === \"details\" ? \"chat\" : \"details\"));\n } else {\n setDetailsOpen((o) => !o);\n }\n };\n\n // Filtros multi-seleção (Set por grupo)\n const [filters, setFilters] = useState<FiltersState>({\n status: new Set([\"open\"]),\n channels: new Set(),\n categories: new Set(),\n innerStatus: new Set(),\n });\n const toggleFilter = (group: FilterGroupKey, id: string) => {\n setFilters((prev) => {\n const next = new Set(prev[group]);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return { ...prev, [group]: next };\n });\n };\n\n const [filtersCollapsed, setFiltersCollapsed] = useState(false);\n const [queueFilter, setQueueFilter] = useState<QueueFilter>(\"all\");\n\n const [detailsOpen, setDetailsOpen] = useState(true);\n const [openSections, setOpenSections] = useState<SectionsState>({\n contact: true,\n ticket: true,\n history: true,\n });\n const toggleSection = (id: keyof SectionsState) =>\n setOpenSections((m) => ({ ...m, [id]: !m[id] }));\n\n const detailsResize = useResizable({\n initial: 360,\n min: 280,\n max: 520,\n // Mantém storageKey diferente da ChatShowcase pra não conflitar valores entre as 2 páginas.\n storageKey: \"chat-v2.detailsWidth\",\n });\n\n const activeConversation =\n CONVERSATIONS.find((c) => c.id === activeId) ?? CONVERSATIONS[0];\n const activeDetail =\n CONVERSATION_DETAILS[activeConversation.id] ?? DEFAULT_DETAIL;\n\n return (\n <AppShell\n contexts={APP_SHELL_CONTEXTS}\n defaultActiveContextId=\"inbox\"\n defaultActiveItemHref=\"#chat-v2\"\n breadcrumb={[{ label: \"Atendimentos\" }]}\n commandGroups={APP_SHELL_COMMANDS}\n notifications={{\n items: APP_SHELL_NOTIFICATIONS,\n onMarkAllRead: () => alert(\"Marcar todas como lidas\"),\n onMoreActions: () => alert(\"Mais ações\"),\n onViewAll: () => alert(\"Ver todas\"),\n }}\n messages={{\n items: APP_SHELL_MESSAGES,\n onNewMessage: () => alert(\"Nova mensagem\"),\n onExpand: () => alert(\"Expandir\"),\n onViewAll: () => alert(\"Ver todas\"),\n }}\n theme={theme}\n onThemeChange={(id) => setTheme(id as Theme)}\n themeOptions={APP_SHELL_THEME_OPTIONS}\n mobileEdgeToEdge\n >\n {/* Body — desktop: 4 colunas lado a lado.\n Mobile (<md): só uma view visível por vez, fullscreen, controlada por\n `mobileView` (list → chat → details). Simula navegação de app. */}\n <div className={s.root()}>\n {/* Filters: escondido em mobile. `md:contents` mantém a coluna no flex parent. */}\n <div className={s.filtersWrap()}>\n {filtersCollapsed ? (\n <FiltersRail filters={filters} onToggleFilter={toggleFilter} />\n ) : (\n <FiltersColumn filters={filters} onToggleFilter={toggleFilter} />\n )}\n </div>\n\n <QueueColumn\n activeId={activeId}\n onSelect={handleSelectConversation}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n queueFilter={queueFilter}\n onQueueFilterChange={setQueueFilter}\n filtersCollapsed={filtersCollapsed}\n onToggleFilters={() => setFiltersCollapsed((c) => !c)}\n className={cn(\n mobileView === \"list\"\n ? `${mobileOverlay.active} max-md:z-[1]`\n : mobileOverlay.hidden,\n )}\n />\n\n <ConversationColumn\n conversation={activeConversation}\n detailsOpen={detailsOpen}\n onToggleDetails={handleToggleDetails}\n onBackToList={() => setMobileView(\"list\")}\n className={cn(\n mobileView === \"chat\"\n ? `${mobileOverlay.active} max-md:z-[2]`\n : mobileOverlay.hidden,\n )}\n />\n\n {detailsOpen && (\n <DetailsColumn\n conversation={activeConversation}\n detail={activeDetail}\n openSections={openSections}\n onToggleSection={toggleSection}\n onClose={() => {\n setDetailsOpen(false);\n setMobileView(\"chat\");\n }}\n onBackToChat={() => setMobileView(\"chat\")}\n width={detailsResize.width}\n onResizeStart={detailsResize.onResizeStart}\n className={cn(\n mobileView === \"details\"\n ? `${mobileOverlay.active} max-md:!w-full max-md:z-[3]`\n : mobileOverlay.hidden,\n )}\n />\n )}\n </div>\n </AppShell>\n );\n}\n"],"names":["MenuIcon"],"mappings":"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"}
|