@snksergio/design-system 0.1.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.
Files changed (73) hide show
  1. package/README.md +260 -0
  2. package/dist-lib/chunks/app-shell-BNTvOETJ.mjs +2681 -0
  3. package/dist-lib/chunks/app-shell-BNTvOETJ.mjs.map +1 -0
  4. package/dist-lib/chunks/app-shell-CDy42aNI.mjs +2663 -0
  5. package/dist-lib/chunks/app-shell-CDy42aNI.mjs.map +1 -0
  6. package/dist-lib/chunks/app-shell-mocks-kWIVSzLs.mjs +208 -0
  7. package/dist-lib/chunks/app-shell-mocks-kWIVSzLs.mjs.map +1 -0
  8. package/dist-lib/chunks/app-shell-mocks-oO_IV3Gw.mjs +207 -0
  9. package/dist-lib/chunks/app-shell-mocks-oO_IV3Gw.mjs.map +1 -0
  10. package/dist-lib/chunks/badge-B_2Zt52o.mjs +797 -0
  11. package/dist-lib/chunks/badge-B_2Zt52o.mjs.map +1 -0
  12. package/dist-lib/chunks/badge-DKpXURa1.mjs +813 -0
  13. package/dist-lib/chunks/badge-DKpXURa1.mjs.map +1 -0
  14. package/dist-lib/chunks/chat-v2-mocks-BV9Wha_Z.mjs +192 -0
  15. package/dist-lib/chunks/chat-v2-mocks-BV9Wha_Z.mjs.map +1 -0
  16. package/dist-lib/chunks/chat-v2-mocks-DvZRkhmz.mjs +193 -0
  17. package/dist-lib/chunks/chat-v2-mocks-DvZRkhmz.mjs.map +1 -0
  18. package/dist-lib/chunks/chip-group-CsKBBHW2.mjs +796 -0
  19. package/dist-lib/chunks/chip-group-CsKBBHW2.mjs.map +1 -0
  20. package/dist-lib/chunks/chip-group-D3D0i72q.mjs +780 -0
  21. package/dist-lib/chunks/chip-group-D3D0i72q.mjs.map +1 -0
  22. package/dist-lib/chunks/clientes-showcase-mocks-BMfbNNJh.mjs +185 -0
  23. package/dist-lib/chunks/clientes-showcase-mocks-BMfbNNJh.mjs.map +1 -0
  24. package/dist-lib/chunks/clientes-showcase-mocks-Cq9u3nGZ.mjs +169 -0
  25. package/dist-lib/chunks/clientes-showcase-mocks-Cq9u3nGZ.mjs.map +1 -0
  26. package/dist-lib/chunks/input-374MpdBL.mjs +72 -0
  27. package/dist-lib/chunks/input-374MpdBL.mjs.map +1 -0
  28. package/dist-lib/chunks/input-DF4XAWmr.mjs +56 -0
  29. package/dist-lib/chunks/input-DF4XAWmr.mjs.map +1 -0
  30. package/dist-lib/chunks/page-header-Dw-3wqAG.mjs +75 -0
  31. package/dist-lib/chunks/page-header-Dw-3wqAG.mjs.map +1 -0
  32. package/dist-lib/chunks/page-header-mC1gGtOI.mjs +76 -0
  33. package/dist-lib/chunks/page-header-mC1gGtOI.mjs.map +1 -0
  34. package/dist-lib/chunks/panel-Ds15whqp.mjs +9717 -0
  35. package/dist-lib/chunks/panel-Ds15whqp.mjs.map +1 -0
  36. package/dist-lib/chunks/panel-bzNmFlEZ.mjs +9737 -0
  37. package/dist-lib/chunks/panel-bzNmFlEZ.mjs.map +1 -0
  38. package/dist-lib/chunks/useTheme-BUPLZBMs.mjs +66 -0
  39. package/dist-lib/chunks/useTheme-BUPLZBMs.mjs.map +1 -0
  40. package/dist-lib/chunks/useTheme-Dee4mo-A.mjs +65 -0
  41. package/dist-lib/chunks/useTheme-Dee4mo-A.mjs.map +1 -0
  42. package/dist-lib/index.cjs +1207 -0
  43. package/dist-lib/index.cjs.map +1 -0
  44. package/dist-lib/index.d.ts +2 -0
  45. package/dist-lib/index.mjs +1209 -0
  46. package/dist-lib/index.mjs.map +1 -0
  47. package/dist-lib/preview/chat.cjs +1120 -0
  48. package/dist-lib/preview/chat.cjs.map +1 -0
  49. package/dist-lib/preview/chat.d.ts +6 -0
  50. package/dist-lib/preview/chat.mjs +1120 -0
  51. package/dist-lib/preview/chat.mjs.map +1 -0
  52. package/dist-lib/preview/clientes.cjs +897 -0
  53. package/dist-lib/preview/clientes.cjs.map +1 -0
  54. package/dist-lib/preview/clientes.d.ts +6 -0
  55. package/dist-lib/preview/clientes.mjs +897 -0
  56. package/dist-lib/preview/clientes.mjs.map +1 -0
  57. package/dist-lib/preview/dashboard.cjs +733 -0
  58. package/dist-lib/preview/dashboard.cjs.map +1 -0
  59. package/dist-lib/preview/dashboard.d.ts +4 -0
  60. package/dist-lib/preview/dashboard.mjs +733 -0
  61. package/dist-lib/preview/dashboard.mjs.map +1 -0
  62. package/dist-lib/preview/mocks.cjs +15 -0
  63. package/dist-lib/preview/mocks.cjs.map +1 -0
  64. package/dist-lib/preview/mocks.d.ts +2 -0
  65. package/dist-lib/preview/mocks.mjs +15 -0
  66. package/dist-lib/preview/mocks.mjs.map +1 -0
  67. package/dist-lib/theme.css +668 -0
  68. package/dist-lib/tokens.cjs +915 -0
  69. package/dist-lib/tokens.cjs.map +1 -0
  70. package/dist-lib/tokens.d.ts +2 -0
  71. package/dist-lib/tokens.mjs +915 -0
  72. package/dist-lib/tokens.mjs.map +1 -0
  73. package/package.json +142 -0
@@ -0,0 +1,1207 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const panel = require("./chunks/panel-bzNmFlEZ.mjs");
4
+ const appShell = require("./chunks/app-shell-BNTvOETJ.mjs");
5
+ const chipGroup = require("./chunks/chip-group-CsKBBHW2.mjs");
6
+ const jsxRuntime = require("react/jsx-runtime");
7
+ const lucideReact = require("lucide-react");
8
+ const pageHeader = require("./chunks/page-header-Dw-3wqAG.mjs");
9
+ const badge = require("./chunks/badge-DKpXURa1.mjs");
10
+ const React = require("react");
11
+ const input = require("./chunks/input-374MpdBL.mjs");
12
+ function ToolbarMobileDialog({
13
+ children,
14
+ trigger,
15
+ title: title2 = "Filtros e ações",
16
+ open: openProp,
17
+ onOpenChange,
18
+ className,
19
+ contentClassName
20
+ }) {
21
+ const [internalOpen, setInternalOpen] = React.useState(false);
22
+ const open = openProp ?? internalOpen;
23
+ const setOpen = onOpenChange ?? setInternalOpen;
24
+ const titleId = React.useId();
25
+ return /* @__PURE__ */ jsxRuntime.jsxs(appShell.Dialog, { open, onOpenChange: setOpen, children: [
26
+ /* @__PURE__ */ jsxRuntime.jsx(appShell.DialogTrigger, { asChild: true, children: trigger ?? /* @__PURE__ */ jsxRuntime.jsx(
27
+ chipGroup.Button,
28
+ {
29
+ color: "secondary",
30
+ variant: "outline",
31
+ size: "icon-md",
32
+ "aria-label": "Mais opções",
33
+ className: chipGroup.cn("md:hidden", className),
34
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, {})
35
+ }
36
+ ) }),
37
+ /* @__PURE__ */ jsxRuntime.jsxs(
38
+ appShell.DialogContent,
39
+ {
40
+ hideClose: true,
41
+ "aria-labelledby": titleId,
42
+ className: chipGroup.cn(
43
+ // Visual alinhado com CommandDialog
44
+ "overflow-hidden p-0 gap-0 sm:max-w-[384px]",
45
+ "rounded-[12px] border border-border-default outline-float",
46
+ contentClassName
47
+ ),
48
+ children: [
49
+ /* @__PURE__ */ jsxRuntime.jsx(appShell.DialogTitle, { id: titleId, className: "sr-only", children: title2 }),
50
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-gp-3xl p-pad-2xl max-h-[85vh] overflow-y-auto", children })
51
+ ]
52
+ }
53
+ )
54
+ ] });
55
+ }
56
+ const ToolbarMobileSheet = ToolbarMobileDialog;
57
+ function ToolbarMobileSection({
58
+ title: title2,
59
+ children,
60
+ className
61
+ }) {
62
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: chipGroup.cn("flex flex-col gap-gp-md", className), children: [
63
+ title2 && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[12px] font-medium text-fg-muted", children: title2 }),
64
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-gp-md", children })
65
+ ] });
66
+ }
67
+ function defaultId() {
68
+ if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
69
+ return crypto.randomUUID();
70
+ }
71
+ return `f_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
72
+ }
73
+ function useToolbarFilters(options) {
74
+ const { initial = [], generateId = defaultId } = options ?? {};
75
+ const [list, setList] = React.useState(initial);
76
+ const add = React.useCallback(
77
+ (entry) => {
78
+ setList((prev) => [
79
+ ...prev,
80
+ { ...entry, id: entry.id ?? generateId() }
81
+ ]);
82
+ },
83
+ [generateId]
84
+ );
85
+ const remove = React.useCallback((id) => {
86
+ setList((prev) => prev.filter((f) => f.id !== id));
87
+ }, []);
88
+ const update = React.useCallback((id, patch) => {
89
+ setList(
90
+ (prev) => prev.map((f) => f.id === id ? { ...f, ...patch } : f)
91
+ );
92
+ }, []);
93
+ const clear = React.useCallback(() => setList([]), []);
94
+ const replaceAll = React.useCallback((next) => setList(next), []);
95
+ const count = React.useMemo(
96
+ () => list.filter((f) => {
97
+ if (f.value === null || f.value === void 0) return false;
98
+ if (typeof f.value === "string") return f.value.length > 0;
99
+ if (Array.isArray(f.value)) return f.value.length > 0;
100
+ return true;
101
+ }).length,
102
+ [list]
103
+ );
104
+ return { list, add, remove, update, clear, replaceAll, count };
105
+ }
106
+ function useToolbarSort(options) {
107
+ const { initial = [], maxColumns = Infinity } = options ?? {};
108
+ const [list, setList] = React.useState(initial);
109
+ const toggle = React.useCallback(
110
+ (columnKey) => {
111
+ setList((prev) => {
112
+ const idx = prev.findIndex((s) => s.columnKey === columnKey);
113
+ if (idx === -1) {
114
+ const next = [...prev, { columnKey, direction: "asc" }];
115
+ if (next.length > maxColumns) next.shift();
116
+ return next;
117
+ }
118
+ const current = prev[idx];
119
+ if (current.direction === "asc") {
120
+ const next = [...prev];
121
+ next[idx] = { ...current, direction: "desc" };
122
+ return next;
123
+ }
124
+ return prev.filter((_, i) => i !== idx);
125
+ });
126
+ },
127
+ [maxColumns]
128
+ );
129
+ const set = React.useCallback(
130
+ (columnKey, direction) => {
131
+ setList((prev) => {
132
+ const idx = prev.findIndex((s) => s.columnKey === columnKey);
133
+ if (idx === -1) {
134
+ const next2 = [...prev, { columnKey, direction }];
135
+ if (next2.length > maxColumns) next2.shift();
136
+ return next2;
137
+ }
138
+ const next = [...prev];
139
+ next[idx] = { columnKey, direction };
140
+ return next;
141
+ });
142
+ },
143
+ [maxColumns]
144
+ );
145
+ const remove = React.useCallback((columnKey) => {
146
+ setList((prev) => prev.filter((s) => s.columnKey !== columnKey));
147
+ }, []);
148
+ const clear = React.useCallback(() => setList([]), []);
149
+ const replaceAll = React.useCallback(
150
+ (next) => setList(next),
151
+ []
152
+ );
153
+ const directionOf = React.useCallback(
154
+ (columnKey) => list.find((s) => s.columnKey === columnKey)?.direction,
155
+ [list]
156
+ );
157
+ return {
158
+ list,
159
+ toggle,
160
+ set,
161
+ remove,
162
+ clear,
163
+ replaceAll,
164
+ count: list.length,
165
+ directionOf
166
+ };
167
+ }
168
+ function textColumn(field, headerName, overrides) {
169
+ return { field, headerName, type: "text", ...overrides };
170
+ }
171
+ function numberColumn(field, headerName, overrides) {
172
+ return { field, headerName, type: "number", sortable: true, ...overrides };
173
+ }
174
+ function currencyColumn(field, headerName, overrides) {
175
+ const { currency, locale, ...rest } = overrides ?? {};
176
+ return {
177
+ field,
178
+ headerName,
179
+ type: "currency",
180
+ sortable: true,
181
+ ...currency || locale ? { typeOptions: { currency, locale } } : {},
182
+ ...rest
183
+ };
184
+ }
185
+ function emailColumn(field, headerName = "Email", overrides) {
186
+ return { field, headerName, type: "email", ...overrides };
187
+ }
188
+ function phoneColumn(field, headerName = "Telefone", overrides) {
189
+ return { field, headerName, type: "phone", ...overrides };
190
+ }
191
+ function dateColumn(field, headerName, overrides) {
192
+ return { field, headerName, type: "date", sortable: true, ...overrides };
193
+ }
194
+ function statusColumn(field, headerName, options, overrides) {
195
+ return {
196
+ field,
197
+ headerName,
198
+ type: "status",
199
+ filterType: "select",
200
+ filterOptions: options,
201
+ enableColumnFilter: true,
202
+ ...overrides
203
+ };
204
+ }
205
+ function actionColumn(opts) {
206
+ return {
207
+ field: "_actions",
208
+ headerName: "",
209
+ type: "actions",
210
+ width: opts.width ?? 120,
211
+ pinned: "right",
212
+ getActions: opts.getActions
213
+ };
214
+ }
215
+ function customColumn(field, headerName, render, overrides) {
216
+ return { field, headerName, render, ...overrides };
217
+ }
218
+ const dialog = chipGroup.tv({
219
+ base: [
220
+ // Override do DialogContent default (grid + p-pad-4xl + rounded-radius-base + shadow-sh-xl)
221
+ "!gap-0 !p-0",
222
+ "border border-border-default",
223
+ "!rounded-radius-2xl !shadow-sh-2xl",
224
+ "outline-float",
225
+ "flex flex-col overflow-hidden",
226
+ "w-[calc(100%-32px)]"
227
+ ],
228
+ variants: {
229
+ size: {
230
+ sm: "!max-w-[440px]",
231
+ md: "!max-w-[540px]",
232
+ lg: "!max-w-[720px]"
233
+ }
234
+ },
235
+ defaultVariants: { size: "md" }
236
+ });
237
+ const closeBtn = chipGroup.tv({
238
+ base: [
239
+ "absolute top-[14px] right-[14px] z-[1]",
240
+ "grid place-items-center size-[28px]",
241
+ "rounded-radius-md bg-transparent border-0 cursor-pointer",
242
+ "text-fg-muted opacity-55",
243
+ "transition-[background-color,color,opacity] duration-150",
244
+ "hover:bg-bg-muted hover:text-fg-default hover:opacity-100",
245
+ "focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-ring-brand",
246
+ "dark:hover:bg-bg-muted-hover"
247
+ ]
248
+ });
249
+ const head = chipGroup.tv({
250
+ base: [
251
+ "flex items-center gap-[14px]",
252
+ "px-pad-4xl pt-pad-4xl pb-pad-3xl",
253
+ // 24/24/20
254
+ "border-b border-border-default"
255
+ ],
256
+ variants: {
257
+ // Sem icon — alinha texto à esquerda direto
258
+ withIcon: { false: "", true: "" }
259
+ }
260
+ });
261
+ const headIcon = chipGroup.tv({
262
+ base: [
263
+ "shrink-0 grid place-items-center size-form-lg",
264
+ // 40×40
265
+ "bg-bg-muted border border-border-input rounded-radius-lg",
266
+ // radius-lg=10px
267
+ "text-fg-default",
268
+ "dark:bg-bg-accent dark:border-border-subtle"
269
+ ]
270
+ });
271
+ const headTitleWrap = chipGroup.tv({
272
+ base: [
273
+ "flex-1 min-w-0",
274
+ "pr-pad-3xl"
275
+ // reserva espaço pro X close (right-14 + 28px) — evita overlap
276
+ ]
277
+ });
278
+ const title = chipGroup.tv({
279
+ base: [
280
+ "m-0 mb-[2px]",
281
+ "text-[17px] font-bold leading-[1.3]",
282
+ "text-fg-default",
283
+ "tracking-[-0.01em]"
284
+ ]
285
+ });
286
+ const description = chipGroup.tv({
287
+ base: "m-0 text-[12.5px] text-fg-muted leading-[1.45]"
288
+ });
289
+ const body = chipGroup.tv({
290
+ base: "flex flex-col gap-[18px] px-pad-4xl py-[22px]"
291
+ });
292
+ const foot = chipGroup.tv({
293
+ base: [
294
+ "flex items-center gap-gp-lg",
295
+ // gap 10px
296
+ "px-pad-4xl pt-pad-md pb-[22px]"
297
+ // 24/8/22
298
+ ],
299
+ variants: {
300
+ layout: {
301
+ end: "justify-end",
302
+ between: "justify-between"
303
+ }
304
+ },
305
+ defaultVariants: { layout: "end" }
306
+ });
307
+ const footRight = chipGroup.tv({
308
+ base: "flex items-center gap-gp-lg"
309
+ });
310
+ function Modal({
311
+ open,
312
+ onClose,
313
+ icon,
314
+ title: title$1,
315
+ description: description$1,
316
+ children,
317
+ primaryAction,
318
+ secondaryAction,
319
+ tertiaryAction,
320
+ footer,
321
+ size = "md",
322
+ hideClose = false,
323
+ closeOnOverlay = true,
324
+ className
325
+ }) {
326
+ const hasHeader = Boolean(icon || title$1 || description$1);
327
+ const hasStructuredFooter = Boolean(primaryAction || secondaryAction || tertiaryAction);
328
+ const showFooter = Boolean(footer) || hasStructuredFooter;
329
+ const handleOpenChange = (next) => {
330
+ if (next) return;
331
+ if (!closeOnOverlay) return;
332
+ onClose();
333
+ };
334
+ return /* @__PURE__ */ jsxRuntime.jsx(appShell.Dialog, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(
335
+ appShell.DialogContent,
336
+ {
337
+ className: dialog({ size, className }),
338
+ hideClose: true,
339
+ "aria-labelledby": title$1 ? "modal-title" : void 0,
340
+ "aria-describedby": description$1 ? "modal-description" : void 0,
341
+ children: [
342
+ !hideClose && /* @__PURE__ */ jsxRuntime.jsx(appShell.DialogClose, { className: closeBtn(), "aria-label": "Fechar", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-icon-sm" }) }),
343
+ hasHeader && /* @__PURE__ */ jsxRuntime.jsxs("header", { className: head(), children: [
344
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: headIcon(), "aria-hidden": "true", children: icon }),
345
+ (title$1 || description$1) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: headTitleWrap(), children: [
346
+ title$1 && /* @__PURE__ */ jsxRuntime.jsx("h3", { id: "modal-title", className: title(), children: title$1 }),
347
+ description$1 && /* @__PURE__ */ jsxRuntime.jsx("p", { id: "modal-description", className: description(), children: description$1 })
348
+ ] })
349
+ ] }),
350
+ children !== void 0 && children !== null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: body(), children }),
351
+ showFooter && /* @__PURE__ */ jsxRuntime.jsx(
352
+ "footer",
353
+ {
354
+ className: foot({
355
+ layout: tertiaryAction ? "between" : "end"
356
+ }),
357
+ children: footer ?? /* @__PURE__ */ jsxRuntime.jsx(
358
+ StructuredActions,
359
+ {
360
+ primary: primaryAction,
361
+ secondary: secondaryAction,
362
+ tertiary: tertiaryAction,
363
+ onClose
364
+ }
365
+ )
366
+ }
367
+ )
368
+ ]
369
+ }
370
+ ) });
371
+ }
372
+ function StructuredActions({
373
+ primary,
374
+ secondary,
375
+ tertiary,
376
+ onClose
377
+ }) {
378
+ const renderTertiary = tertiary && /* @__PURE__ */ jsxRuntime.jsx(
379
+ chipGroup.Button,
380
+ {
381
+ color: tertiary.danger ? "critical" : "secondary",
382
+ variant: "ghost",
383
+ size: "md",
384
+ onClick: tertiary.onClick,
385
+ disabled: tertiary.disabled,
386
+ loading: tertiary.loading,
387
+ children: tertiary.label
388
+ }
389
+ );
390
+ const renderSecondary = secondary && /* @__PURE__ */ jsxRuntime.jsx(
391
+ chipGroup.Button,
392
+ {
393
+ color: "secondary",
394
+ variant: "outline",
395
+ size: "md",
396
+ onClick: secondary.onClick ?? onClose,
397
+ disabled: secondary.disabled,
398
+ loading: secondary.loading,
399
+ children: secondary.label
400
+ }
401
+ );
402
+ const renderPrimary = primary && /* @__PURE__ */ jsxRuntime.jsx(
403
+ chipGroup.Button,
404
+ {
405
+ color: primary.danger ? "critical" : "primary",
406
+ variant: "filled",
407
+ size: "md",
408
+ onClick: primary.onClick,
409
+ disabled: primary.disabled,
410
+ loading: primary.loading,
411
+ children: primary.label
412
+ }
413
+ );
414
+ if (tertiary) {
415
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
416
+ renderTertiary,
417
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: footRight(), children: [
418
+ renderSecondary,
419
+ renderPrimary
420
+ ] })
421
+ ] });
422
+ }
423
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
424
+ renderSecondary,
425
+ renderPrimary
426
+ ] });
427
+ }
428
+ const COLUMNS = [
429
+ { key: "select", width: 44, type: "select" },
430
+ { key: "id", width: 120, label: "ID", type: "id", icon: lucideReact.Hash },
431
+ { key: "name", minWidth: 220, label: "Nome", type: "person", icon: lucideReact.User, sorted: true },
432
+ { key: "email", minWidth: 240, label: "Email", type: "email", icon: lucideReact.AtSign },
433
+ { key: "phone", minWidth: 170, label: "Telefone", type: "phone", icon: lucideReact.Phone },
434
+ { key: "status", minWidth: 140, label: "Status", type: "status", icon: lucideReact.CheckCircle2 },
435
+ { key: "category", minWidth: 130, label: "Categoria", type: "category", icon: lucideReact.Tag },
436
+ { key: "agent", minWidth: 170, label: "Atribuído", type: "agent", icon: lucideReact.Users },
437
+ { key: "value", width: 130, label: "Valor", type: "currency", icon: lucideReact.DollarSign },
438
+ { key: "createdAt", width: 130, label: "Criado em", type: "date", icon: lucideReact.Calendar },
439
+ { key: "lastContact", width: 150, label: "Último contato", type: "date", icon: lucideReact.Calendar },
440
+ { key: "location", minWidth: 150, label: "Localização", type: "text", icon: lucideReact.Type },
441
+ { key: "actions", width: 44, type: "actions" }
442
+ ];
443
+ function getColCellStyle(col) {
444
+ if (col.width) return { width: col.width, flex: `0 0 ${col.width}px` };
445
+ if (col.minWidth) return { minWidth: col.minWidth, flex: `1 0 ${col.minWidth}px` };
446
+ return {};
447
+ }
448
+ const STATUSES = {
449
+ active: { label: "Ativo", color: "var(--color-fg-success)" },
450
+ pending: { label: "Pendente", color: "var(--color-fg-warning)" },
451
+ paused: { label: "Pausado", color: "var(--color-fg-info)" },
452
+ inactive: { label: "Inativo", color: "var(--color-fg-muted)" }
453
+ };
454
+ const CATEGORIES = {
455
+ royal: { label: "Royal", kind: "warning" },
456
+ licenciado: { label: "Licenciado", kind: "info" },
457
+ lead: { label: "Lead", kind: "success" }
458
+ };
459
+ const AGENTS = {
460
+ you: { name: "Você", initials: "VC", color: "#0a3a2e" },
461
+ aline: { name: "Aline Castro", initials: "AC", color: "#f59e0b" },
462
+ carlos: { name: "Carlos Souza", initials: "CS", color: "#8754ec" },
463
+ maria: { name: "Maria Lima", initials: "ML", color: "#ef4444" }
464
+ };
465
+ const BASE_DATE = (/* @__PURE__ */ new Date("2026-04-15T12:00:00Z")).getTime();
466
+ const DAY_MS = 864e5;
467
+ const ROWS_BASE = [
468
+ { id: "CLI-2401", name: "Maria Silva", initials: "MS", avatarColor: "#f59e0b", email: "maria.silva@example.com", phone: "+55 11 91234-5678", statusId: "active", categoryId: "royal", location: "São Paulo, SP", value: 4800, agentId: "you", createdAt: BASE_DATE - 65 * DAY_MS, lastContact: BASE_DATE - 2 * DAY_MS },
469
+ { id: "CLI-2402", name: "João Santos", initials: "JS", avatarColor: "#0a3a2e", email: "joao.santos@example.com", phone: "+55 11 92345-6789", statusId: "pending", categoryId: "licenciado", location: "Rio de Janeiro, RJ", value: 12300, agentId: "aline", createdAt: BASE_DATE - 58 * DAY_MS, lastContact: BASE_DATE - 5 * DAY_MS },
470
+ { id: "CLI-2403", name: "Carlos Oliveira", initials: "CO", avatarColor: "#8754ec", email: "carlos.oliveira@example.com", phone: "+55 11 93456-7890", statusId: "active", categoryId: "lead", location: "Belo Horizonte, MG", value: 2150, agentId: "carlos", createdAt: BASE_DATE - 51 * DAY_MS, lastContact: BASE_DATE - 1 * DAY_MS },
471
+ { id: "CLI-2404", name: "Ana Costa", initials: "AC", avatarColor: "#1cb280", email: "ana.costa@example.com", phone: "+55 11 94567-8901", statusId: "paused", categoryId: "royal", location: "Porto Alegre, RS", value: 8900, agentId: "maria", createdAt: BASE_DATE - 44 * DAY_MS, lastContact: BASE_DATE - 12 * DAY_MS },
472
+ { id: "CLI-2405", name: "Pedro Pereira", initials: "PP", avatarColor: "#ef4444", email: "pedro.pereira@example.com", phone: "+55 11 95678-9012", statusId: "inactive", categoryId: "lead", location: "Curitiba, PR", value: 1100, agentId: "you", createdAt: BASE_DATE - 37 * DAY_MS, lastContact: BASE_DATE - 30 * DAY_MS },
473
+ { id: "CLI-2406", name: "Lúcia Almeida", initials: "LA", avatarColor: "#f9a47a", email: "lucia.almeida@example.com", phone: "+55 11 96789-0123", statusId: "active", categoryId: "licenciado", location: "Recife, PE", value: 6750, agentId: "aline", createdAt: BASE_DATE - 30 * DAY_MS, lastContact: BASE_DATE - 3 * DAY_MS },
474
+ { id: "CLI-2407", name: "Roberto Souza", initials: "RS", avatarColor: "#0088cc", email: "roberto.souza@example.com", phone: "+55 11 97890-1234", statusId: "pending", categoryId: "royal", location: "São Paulo, SP", value: 15200, agentId: "carlos", createdAt: BASE_DATE - 23 * DAY_MS, lastContact: BASE_DATE - 7 * DAY_MS },
475
+ { id: "CLI-2408", name: "Fernanda Lima", initials: "FL", avatarColor: "#e1306c", email: "fernanda.lima@example.com", phone: "+55 11 98901-2345", statusId: "active", categoryId: "lead", location: "Rio de Janeiro, RJ", value: 3400, agentId: "maria", createdAt: BASE_DATE - 16 * DAY_MS, lastContact: BASE_DATE - 1 * DAY_MS },
476
+ { id: "CLI-2409", name: "Bruno Rodrigues", initials: "BR", avatarColor: "#70c748", email: "bruno.rodrigues@example.com", phone: "+55 11 99012-3456", statusId: "paused", categoryId: "licenciado", location: "Belo Horizonte, MG", value: 5600, agentId: "you", createdAt: BASE_DATE - 9 * DAY_MS, lastContact: BASE_DATE - 6 * DAY_MS },
477
+ { id: "CLI-2410", name: "Camila Ribeiro", initials: "CR", avatarColor: "#8754ec", email: "camila.ribeiro@example.com", phone: "+55 11 90123-4567", statusId: "active", categoryId: "royal", location: "Porto Alegre, RS", value: 9800, agentId: "aline", createdAt: BASE_DATE - 2 * DAY_MS, lastContact: BASE_DATE }
478
+ ];
479
+ const NAME_SUFFIXES = ["", " Jr", " Filho", " Neto", " II"];
480
+ const CITY_OVERRIDES = ["Salvador, BA", "Fortaleza, CE", "Manaus, AM", "Brasília, DF", "Vitória, ES"];
481
+ const ROWS_MOCK = Array.from({ length: 50 }, (_, i) => {
482
+ const base = ROWS_BASE[i % ROWS_BASE.length];
483
+ const cycle = Math.floor(i / ROWS_BASE.length);
484
+ const seq = 2401 + i;
485
+ const nameSuffix = NAME_SUFFIXES[cycle];
486
+ return {
487
+ ...base,
488
+ id: `CLI-${seq}`,
489
+ name: `${base.name}${nameSuffix}`,
490
+ location: cycle === 0 ? base.location : CITY_OVERRIDES[cycle - 1] ?? base.location,
491
+ value: base.value + cycle * 175,
492
+ createdAt: base.createdAt - cycle * 7 * DAY_MS,
493
+ lastContact: base.lastContact - cycle * 3 * DAY_MS
494
+ };
495
+ });
496
+ function formatCurrency(value) {
497
+ return value.toLocaleString("pt-BR", { style: "currency", currency: "BRL", minimumFractionDigits: 2 });
498
+ }
499
+ const MONTHS_SHORT = ["jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez"];
500
+ function formatDateShort(value) {
501
+ if (!value) return "—";
502
+ const d = new Date(value);
503
+ const day = d.getDate().toString().padStart(2, "0");
504
+ return `${day} de ${MONTHS_SHORT[d.getMonth()]}`;
505
+ }
506
+ const tabelaStyles = {
507
+ /* ── Wrap (container externo) ─────────────────────────────────────── */
508
+ wrap: chipGroup.tv({
509
+ base: [
510
+ "flex-1 overflow-auto min-h-0",
511
+ "bg-bg-table border border-border-table rounded-radius-xl",
512
+ "scrollbar-default"
513
+ ]
514
+ }),
515
+ /* tbl-table — inner container, min-width: max-content pra scroll horizontal */
516
+ table: chipGroup.tv({
517
+ base: "block min-w-max"
518
+ }),
519
+ /* ── Head ─────────────────────────────────────────────────────────── */
520
+ thead: chipGroup.tv({
521
+ base: [
522
+ "sticky top-0 z-[5]",
523
+ "bg-bg-table-head",
524
+ "border-b border-border-table"
525
+ ]
526
+ }),
527
+ trHead: chipGroup.tv({
528
+ base: "flex bg-bg-table-head"
529
+ }),
530
+ /* tbl-th base — 42px sempre, padding-right reserva espaço pro menu absoluto */
531
+ th: chipGroup.tv({
532
+ base: [
533
+ "relative flex items-center gap-gp-sm",
534
+ "py-0 pl-[14px] pr-[38px]",
535
+ "h-[42px] text-[13px] font-semibold leading-none",
536
+ "text-fg-muted cursor-pointer select-none",
537
+ "[flex:1_0_auto]",
538
+ "hover:text-fg-default"
539
+ // hover do th faz menu aparecer (ver thMenu)
540
+ // hover do th faz sort-hint aparecer (ver sortHint)
541
+ ],
542
+ variants: {
543
+ sorted: { true: "text-fg-default" }
544
+ },
545
+ defaultVariants: { sorted: false }
546
+ }),
547
+ /* Coluna select — 44px, sem hover, justify-center, sem padding right pro menu */
548
+ thSelect: chipGroup.tv({
549
+ base: [
550
+ "relative flex items-center justify-center",
551
+ "w-[44px] [flex:0_0_44px] px-[12px] py-0",
552
+ "h-[42px] cursor-default select-none",
553
+ "bg-bg-table-head"
554
+ ]
555
+ }),
556
+ /* Coluna actions — 44px sticky right */
557
+ thActions: chipGroup.tv({
558
+ base: [
559
+ "relative flex items-center justify-center",
560
+ "w-[44px] [flex:0_0_44px] p-0",
561
+ "h-[42px] cursor-default select-none",
562
+ "sticky right-0 z-[3]",
563
+ "bg-bg-table-head"
564
+ ]
565
+ }),
566
+ /* Label da coluna — elipsa */
567
+ thLabel: chipGroup.tv({
568
+ base: "flex-1 min-w-0 whitespace-nowrap overflow-hidden text-ellipsis text-left"
569
+ }),
570
+ /* Ícone de tipo — opacity 0.7 rest, 1 no hover do th OU quando sorted */
571
+ thTypeIcon: chipGroup.tv({
572
+ base: [
573
+ "shrink-0 size-[13px] text-fg-muted opacity-70",
574
+ "group-hover/th:opacity-100"
575
+ ],
576
+ variants: {
577
+ sorted: { true: "opacity-100" }
578
+ },
579
+ defaultVariants: { sorted: false }
580
+ }),
581
+ /* Sort badge "1" (chip brand) + arrow */
582
+ thSort: chipGroup.tv({
583
+ base: "inline-flex items-center gap-[4px] shrink-0 text-fg-default"
584
+ }),
585
+ thSortIndex: chipGroup.tv({
586
+ base: [
587
+ "grid place-items-center",
588
+ "min-w-[18px] h-[18px] px-[5px]",
589
+ "rounded-radius-sm",
590
+ "bg-bg-brand text-fg-on-brand",
591
+ "text-[10.5px] font-bold leading-none",
592
+ "[font-variant-numeric:tabular-nums]"
593
+ ]
594
+ }),
595
+ /* Hint atenuado em hover de col não-sorted (sinaliza clicável) */
596
+ thSortHint: chipGroup.tv({
597
+ base: [
598
+ "inline-flex items-center shrink-0 text-fg-muted",
599
+ "opacity-0 transition-opacity duration-150",
600
+ "group-hover/th:opacity-50"
601
+ ]
602
+ }),
603
+ /* Menu "..." absolute, aparece só no hover */
604
+ thMenu: chipGroup.tv({
605
+ base: [
606
+ "absolute right-[6px] top-1/2 -translate-y-1/2 z-[1]",
607
+ "grid place-items-center size-[28px]",
608
+ "border-0 bg-transparent text-fg-muted rounded-radius-md cursor-pointer",
609
+ "opacity-0 transition-all duration-150",
610
+ "group-hover/th:opacity-100",
611
+ "hover:bg-bg-muted hover:text-fg-default"
612
+ ]
613
+ }),
614
+ /* Resize handle (6px) — linha que vira brand e projeta pra baixo no hover */
615
+ thResize: chipGroup.tv({
616
+ base: [
617
+ "absolute right-0 top-0 bottom-0 w-[6px] z-[2]",
618
+ "bg-transparent cursor-col-resize",
619
+ // ::before linha vertical dentro do header
620
+ "before:content-[''] before:absolute before:left-1/2 before:-translate-x-1/2",
621
+ "before:top-[8px] before:bottom-[8px] before:w-px before:bg-transparent",
622
+ "before:transition-all before:duration-150",
623
+ "group-hover/th:before:bg-fg-muted",
624
+ // hover direto no handle → brand 2px + altura total
625
+ "hover:before:bg-bg-brand hover:before:w-[2px] hover:before:top-0 hover:before:bottom-0",
626
+ // ::after projeção 100vh pra baixo cobrindo body
627
+ "after:content-[''] after:absolute after:left-1/2 after:-translate-x-1/2",
628
+ "after:top-full after:w-[2px] after:h-screen after:bg-transparent after:pointer-events-none",
629
+ "after:transition-colors after:duration-150",
630
+ "hover:after:bg-bg-brand"
631
+ ]
632
+ }),
633
+ /* ── Body ─────────────────────────────────────────────────────────── */
634
+ tbody: chipGroup.tv({
635
+ base: "bg-bg-surface"
636
+ }),
637
+ /* tbl-tr — flex row, altura por densidade. Default comfortable (56px). */
638
+ tr: chipGroup.tv({
639
+ base: [
640
+ "relative flex",
641
+ "border-b border-border-table bg-bg-surface",
642
+ "cursor-pointer transition-colors duration-150",
643
+ "hover:bg-bg-table-row-hover",
644
+ "focus-visible:outline-2 focus-visible:outline-bg-brand focus-visible:-outline-offset-2"
645
+ ],
646
+ variants: {
647
+ density: {
648
+ compact: "h-[40px]",
649
+ comfortable: "h-[56px]",
650
+ spacious: "h-[64px]"
651
+ },
652
+ // Selected (checkbox) e Open (detail panel) — mesmo visual brand-tinted
653
+ // + strip lateral 3px brand via ::before
654
+ selected: {
655
+ true: [
656
+ "bg-bg-table-row-selected hover:bg-bg-table-row-selected-hover",
657
+ "before:content-[''] before:absolute before:left-0 before:top-0 before:bottom-0",
658
+ "before:w-[3px] before:bg-bg-brand before:z-[5] before:pointer-events-none"
659
+ ].join(" ")
660
+ }
661
+ },
662
+ defaultVariants: { density: "comfortable", selected: false }
663
+ }),
664
+ /* Cells base — height/font-size variam por densidade */
665
+ td: chipGroup.tv({
666
+ base: [
667
+ "flex items-center px-[14px] py-0",
668
+ "text-fg-default",
669
+ "[flex:1_0_auto] overflow-hidden whitespace-nowrap"
670
+ ],
671
+ variants: {
672
+ density: {
673
+ compact: "h-[40px] text-[12px]",
674
+ comfortable: "h-[56px] text-[13px]",
675
+ spacious: "h-[64px] text-[13px]"
676
+ }
677
+ },
678
+ defaultVariants: { density: "comfortable" }
679
+ }),
680
+ tdSelect: chipGroup.tv({
681
+ base: [
682
+ "flex items-center justify-center",
683
+ "w-[44px] [flex:0_0_44px] px-[12px] py-0"
684
+ ],
685
+ variants: {
686
+ density: {
687
+ compact: "h-[40px]",
688
+ comfortable: "h-[56px]",
689
+ spacious: "h-[64px]"
690
+ }
691
+ },
692
+ defaultVariants: { density: "comfortable" }
693
+ }),
694
+ /* tdActions — sticky right, bg adapta ao estado da row */
695
+ tdActions: chipGroup.tv({
696
+ base: [
697
+ "flex items-center justify-center",
698
+ "w-[44px] [flex:0_0_44px] p-0",
699
+ "sticky right-0 z-[2]",
700
+ "bg-bg-surface",
701
+ // bg adapta ao estado da row pai
702
+ "group-hover/tr:bg-bg-table-row-hover"
703
+ ],
704
+ variants: {
705
+ density: {
706
+ compact: "h-[40px]",
707
+ comfortable: "h-[56px]",
708
+ spacious: "h-[64px]"
709
+ },
710
+ selected: {
711
+ true: "!bg-bg-table-row-selected group-hover/tr:!bg-bg-table-row-selected-hover"
712
+ }
713
+ },
714
+ defaultVariants: { density: "comfortable", selected: false }
715
+ }),
716
+ /* Botão "..." da row — opacity 0 → 1 no hover */
717
+ rowMenuBtn: chipGroup.tv({
718
+ base: [
719
+ "grid place-items-center size-[28px]",
720
+ "border-0 bg-transparent text-fg-muted rounded-radius-md cursor-pointer",
721
+ "opacity-0 transition-all duration-150",
722
+ "group-hover/tr:opacity-100",
723
+ "hover:bg-bg-muted hover:text-fg-default"
724
+ ]
725
+ }),
726
+ /* ── Cell borders verticais (sempre on neste componente) ──────────── */
727
+ cellBorderTh: chipGroup.tv({
728
+ base: "border-r border-border-table"
729
+ }),
730
+ cellBorderTd: chipGroup.tv({
731
+ base: "border-r border-border-table"
732
+ }),
733
+ /* ── Cells específicas ────────────────────────────────────────────── */
734
+ cellId: chipGroup.tv({
735
+ base: "text-[13px] text-fg-muted [font-variant-numeric:tabular-nums]"
736
+ }),
737
+ cellCurrency: chipGroup.tv({
738
+ base: "[font-variant-numeric:tabular-nums] font-semibold"
739
+ }),
740
+ cellDate: chipGroup.tv({
741
+ base: "[font-variant-numeric:tabular-nums] text-fg-muted"
742
+ }),
743
+ cellStatus: chipGroup.tv({
744
+ base: "inline-flex items-center gap-gp-md text-[13px] text-fg-default dark:text-fg-muted"
745
+ }),
746
+ dot: chipGroup.tv({
747
+ base: "size-[8px] rounded-radius-full shrink-0"
748
+ }),
749
+ cellPerson: chipGroup.tv({
750
+ base: "inline-flex items-center gap-gp-md whitespace-nowrap overflow-hidden"
751
+ }),
752
+ cellPersonName: chipGroup.tv({
753
+ base: "whitespace-nowrap overflow-hidden text-ellipsis font-medium"
754
+ }),
755
+ cellAgent: chipGroup.tv({
756
+ base: "inline-flex items-center gap-gp-md whitespace-nowrap overflow-hidden"
757
+ }),
758
+ /* Avatar 28px (sm 22px) — bg via inline style (cor por entidade) */
759
+ avatar: chipGroup.tv({
760
+ base: [
761
+ "grid place-items-center shrink-0",
762
+ "size-[28px] rounded-radius-full",
763
+ "text-white text-[11px] font-bold"
764
+ ]
765
+ }),
766
+ avatarSm: chipGroup.tv({
767
+ base: [
768
+ "grid place-items-center shrink-0",
769
+ "size-[22px] rounded-radius-full",
770
+ "text-white text-[10px] font-bold"
771
+ ]
772
+ }),
773
+ cellLink: chipGroup.tv({
774
+ base: "text-fg-brand no-underline hover:underline"
775
+ }),
776
+ cellMuted: chipGroup.tv({
777
+ base: "text-fg-muted"
778
+ }),
779
+ /* ── Checkbox custom (16px com check rotacionado) ─────────────────── */
780
+ checkbox: chipGroup.tv({
781
+ base: [
782
+ "appearance-none size-[16px] cursor-pointer relative",
783
+ "border-[1.5px] border-border-input bg-bg-input rounded-radius-sm",
784
+ "transition-[background,border-color] duration-100",
785
+ "checked:bg-bg-brand checked:border-border-brand",
786
+ "indeterminate:bg-bg-brand indeterminate:border-border-brand",
787
+ // Check mark via ::after — retângulo rotacionado 45deg
788
+ "checked:after:content-[''] checked:after:absolute",
789
+ "checked:after:left-1/2 checked:after:top-1/2",
790
+ "checked:after:w-[4px] checked:after:h-[8px]",
791
+ "checked:after:border-solid checked:after:border-fg-on-brand",
792
+ "checked:after:[border-width:0_2px_2px_0]",
793
+ "checked:after:[transform:translate(-50%,-55%)_rotate(45deg)]",
794
+ // Barra indeterminate
795
+ "indeterminate:after:content-[''] indeterminate:after:absolute",
796
+ "indeterminate:after:left-1/2 indeterminate:after:top-1/2",
797
+ "indeterminate:after:w-[8px] indeterminate:after:h-[2px]",
798
+ "indeterminate:after:bg-fg-on-brand indeterminate:after:rounded-[1px]",
799
+ "indeterminate:after:[transform:translate(-50%,-50%)]"
800
+ ]
801
+ }),
802
+ /* ── Chip de categoria (pílula soft com kind) ─────────────────────── */
803
+ chip: chipGroup.tv({
804
+ base: [
805
+ "inline-flex items-center gap-[4px]",
806
+ "h-[22px] px-[8px] rounded-radius-full",
807
+ "text-[11px] font-semibold leading-none whitespace-nowrap"
808
+ ],
809
+ variants: {
810
+ kind: {
811
+ success: "bg-bg-success-muted text-fg-success",
812
+ warning: "bg-bg-warning-muted text-fg-warning",
813
+ info: "bg-bg-info-muted text-fg-info",
814
+ danger: "bg-bg-danger-muted text-fg-danger"
815
+ }
816
+ },
817
+ defaultVariants: { kind: "info" }
818
+ })
819
+ };
820
+ function TabelaTeste() {
821
+ const [selectedIds, setSelectedIds] = React.useState(/* @__PURE__ */ new Set());
822
+ const [openRowId, setOpenRowId] = React.useState(null);
823
+ const allSelected = selectedIds.size === ROWS_MOCK.length;
824
+ const someSelected = selectedIds.size > 0 && !allSelected;
825
+ const toggleSelect = (id) => {
826
+ setSelectedIds((prev) => {
827
+ const next = new Set(prev);
828
+ if (next.has(id)) next.delete(id);
829
+ else next.add(id);
830
+ return next;
831
+ });
832
+ };
833
+ const toggleAll = () => {
834
+ if (selectedIds.size > 0) setSelectedIds(/* @__PURE__ */ new Set());
835
+ else setSelectedIds(new Set(ROWS_MOCK.map((r) => r.id)));
836
+ };
837
+ return /* @__PURE__ */ jsxRuntime.jsx(
838
+ "div",
839
+ {
840
+ role: "region",
841
+ "aria-label": "Tabela de clientes (referência)",
842
+ className: tabelaStyles.wrap(),
843
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tabelaStyles.table(), children: [
844
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: tabelaStyles.thead(), role: "rowgroup", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: tabelaStyles.trHead(), role: "row", children: COLUMNS.map((col) => renderHeadCell(col, {
845
+ allSelected,
846
+ someSelected,
847
+ onToggleAll: toggleAll
848
+ })) }) }),
849
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: tabelaStyles.tbody(), role: "rowgroup", children: ROWS_MOCK.map((row) => {
850
+ const isSelected = selectedIds.has(row.id);
851
+ const isOpen = openRowId === row.id;
852
+ const isHighlighted = isSelected || isOpen;
853
+ return /* @__PURE__ */ jsxRuntime.jsx(
854
+ "div",
855
+ {
856
+ role: "row",
857
+ tabIndex: 0,
858
+ onClick: () => setOpenRowId((cur) => cur === row.id ? null : row.id),
859
+ className: `group/tr ${tabelaStyles.tr({ selected: isHighlighted })}`,
860
+ children: COLUMNS.map(
861
+ (col) => renderBodyCell(col, row, {
862
+ isSelected,
863
+ isHighlighted,
864
+ onToggle: () => toggleSelect(row.id)
865
+ })
866
+ )
867
+ },
868
+ row.id
869
+ );
870
+ }) })
871
+ ] })
872
+ }
873
+ );
874
+ }
875
+ function renderHeadCell(col, ctx) {
876
+ const cellStyle = getColCellStyle(col);
877
+ if (col.type === "select") {
878
+ return /* @__PURE__ */ jsxRuntime.jsx(
879
+ "div",
880
+ {
881
+ role: "columnheader",
882
+ className: `${tabelaStyles.thSelect()} ${tabelaStyles.cellBorderTh()}`,
883
+ style: cellStyle,
884
+ children: /* @__PURE__ */ jsxRuntime.jsx(
885
+ "input",
886
+ {
887
+ type: "checkbox",
888
+ className: tabelaStyles.checkbox(),
889
+ checked: ctx.allSelected,
890
+ ref: (el) => {
891
+ if (el) el.indeterminate = ctx.someSelected;
892
+ },
893
+ onChange: ctx.onToggleAll,
894
+ "aria-label": "Selecionar todas"
895
+ }
896
+ )
897
+ },
898
+ col.key
899
+ );
900
+ }
901
+ if (col.type === "actions") {
902
+ return /* @__PURE__ */ jsxRuntime.jsx(
903
+ "div",
904
+ {
905
+ role: "columnheader",
906
+ "aria-label": "Ações",
907
+ className: tabelaStyles.thActions(),
908
+ style: cellStyle
909
+ },
910
+ col.key
911
+ );
912
+ }
913
+ const isBeforeActions = COLUMNS[COLUMNS.indexOf(col) + 1]?.type === "actions";
914
+ const borderCls = isBeforeActions ? "" : tabelaStyles.cellBorderTh();
915
+ const TypeIcon = col.icon;
916
+ const sorted = Boolean(col.sorted);
917
+ return /* @__PURE__ */ jsxRuntime.jsxs(
918
+ "div",
919
+ {
920
+ role: "columnheader",
921
+ style: cellStyle,
922
+ className: `group/th ${tabelaStyles.th({ sorted })} ${borderCls}`,
923
+ children: [
924
+ TypeIcon && /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { strokeWidth: 1.7, className: tabelaStyles.thTypeIcon({ sorted }), "aria-hidden": "true" }),
925
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.thLabel(), children: col.label }),
926
+ sorted ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: tabelaStyles.thSort(), children: [
927
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.thSortIndex(), children: "1" }),
928
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpDown, { size: 12, strokeWidth: 1.8 })
929
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.thSortHint(), "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpDown, { size: 11, strokeWidth: 1.8 }) }),
930
+ /* @__PURE__ */ jsxRuntime.jsx(
931
+ "button",
932
+ {
933
+ type: "button",
934
+ className: tabelaStyles.thMenu(),
935
+ onClick: (e) => e.stopPropagation(),
936
+ "aria-label": `Menu da coluna ${col.label}`,
937
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, { size: 15, strokeWidth: 1.7 })
938
+ }
939
+ ),
940
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.thResize(), "aria-hidden": "true" })
941
+ ]
942
+ },
943
+ col.key
944
+ );
945
+ }
946
+ function renderBodyCell(col, row, ctx) {
947
+ const cellStyle = getColCellStyle(col);
948
+ if (col.type === "select") {
949
+ return /* @__PURE__ */ jsxRuntime.jsx(
950
+ "div",
951
+ {
952
+ role: "cell",
953
+ className: `${tabelaStyles.tdSelect()} ${tabelaStyles.cellBorderTd()}`,
954
+ style: cellStyle,
955
+ onClick: (e) => e.stopPropagation(),
956
+ children: /* @__PURE__ */ jsxRuntime.jsx(
957
+ "input",
958
+ {
959
+ type: "checkbox",
960
+ className: tabelaStyles.checkbox(),
961
+ checked: ctx.isSelected,
962
+ onChange: ctx.onToggle,
963
+ "aria-label": `Selecionar ${row.name}`
964
+ }
965
+ )
966
+ },
967
+ col.key
968
+ );
969
+ }
970
+ if (col.type === "actions") {
971
+ return /* @__PURE__ */ jsxRuntime.jsx(
972
+ "div",
973
+ {
974
+ role: "cell",
975
+ className: tabelaStyles.tdActions({ selected: ctx.isHighlighted }),
976
+ style: cellStyle,
977
+ onClick: (e) => e.stopPropagation(),
978
+ children: /* @__PURE__ */ jsxRuntime.jsx(
979
+ "button",
980
+ {
981
+ type: "button",
982
+ className: tabelaStyles.rowMenuBtn(),
983
+ "aria-label": "Ações da linha",
984
+ onClick: (e) => e.stopPropagation(),
985
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { size: 16 })
986
+ }
987
+ )
988
+ },
989
+ col.key
990
+ );
991
+ }
992
+ const isBeforeActions = COLUMNS[COLUMNS.indexOf(col) + 1]?.type === "actions";
993
+ const borderCls = isBeforeActions ? "" : tabelaStyles.cellBorderTd();
994
+ return /* @__PURE__ */ jsxRuntime.jsx(
995
+ "div",
996
+ {
997
+ role: "cell",
998
+ style: cellStyle,
999
+ className: `${tabelaStyles.td()} ${borderCls}`,
1000
+ children: renderCellContent(col, row)
1001
+ },
1002
+ col.key
1003
+ );
1004
+ }
1005
+ function renderCellContent(col, row) {
1006
+ switch (col.type) {
1007
+ case "id":
1008
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.cellId(), children: row.id });
1009
+ case "person":
1010
+ return /* @__PURE__ */ jsxRuntime.jsx(PersonCell, { row });
1011
+ case "email":
1012
+ return /* @__PURE__ */ jsxRuntime.jsx(
1013
+ "a",
1014
+ {
1015
+ href: `mailto:${row.email}`,
1016
+ className: tabelaStyles.cellLink(),
1017
+ onClick: (e) => e.stopPropagation(),
1018
+ children: row.email
1019
+ }
1020
+ );
1021
+ case "phone":
1022
+ return /* @__PURE__ */ jsxRuntime.jsx(PhoneCell, { value: row.phone });
1023
+ case "status":
1024
+ return /* @__PURE__ */ jsxRuntime.jsx(StatusCell, { statusId: row.statusId });
1025
+ case "category":
1026
+ return /* @__PURE__ */ jsxRuntime.jsx(CategoryCell, { categoryId: row.categoryId });
1027
+ case "agent":
1028
+ return /* @__PURE__ */ jsxRuntime.jsx(AgentCell, { agentId: row.agentId });
1029
+ case "currency":
1030
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.cellCurrency(), children: formatCurrency(row.value) });
1031
+ case "date":
1032
+ return /* @__PURE__ */ jsxRuntime.jsx(DateCell, { value: row[col.key] });
1033
+ case "text":
1034
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: row[col.key] });
1035
+ default:
1036
+ return null;
1037
+ }
1038
+ }
1039
+ function PersonCell({ row }) {
1040
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: tabelaStyles.cellPerson(), title: row.name, children: [
1041
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.avatar(), style: { background: row.avatarColor }, children: row.initials }),
1042
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.cellPersonName(), children: row.name })
1043
+ ] });
1044
+ }
1045
+ function StatusCell({ statusId }) {
1046
+ const st = STATUSES[statusId];
1047
+ if (!st) return null;
1048
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: tabelaStyles.cellStatus(), children: [
1049
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.dot(), style: { background: st.color }, "aria-hidden": true }),
1050
+ st.label
1051
+ ] });
1052
+ }
1053
+ function CategoryCell({ categoryId }) {
1054
+ const c = CATEGORIES[categoryId];
1055
+ if (!c) return null;
1056
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.chip({ kind: c.kind }), children: c.label });
1057
+ }
1058
+ function AgentCell({ agentId }) {
1059
+ const a = AGENTS[agentId];
1060
+ if (!a) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.cellMuted(), children: "—" });
1061
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: tabelaStyles.cellAgent(), title: a.name, children: [
1062
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.avatarSm(), style: { background: a.color }, children: a.initials }),
1063
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: a.name })
1064
+ ] });
1065
+ }
1066
+ function PhoneCell({ value }) {
1067
+ if (!value) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.cellMuted(), children: "—" });
1068
+ return /* @__PURE__ */ jsxRuntime.jsx(
1069
+ "a",
1070
+ {
1071
+ href: `tel:${value.replace(/\D/g, "")}`,
1072
+ className: tabelaStyles.cellLink(),
1073
+ onClick: (e) => e.stopPropagation(),
1074
+ children: value
1075
+ }
1076
+ );
1077
+ }
1078
+ function DateCell({ value }) {
1079
+ if (!value) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.cellMuted(), children: "—" });
1080
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: tabelaStyles.cellDate(), children: formatDateShort(value) });
1081
+ }
1082
+ exports.AddViewModal = panel.AddViewModal;
1083
+ exports.AlertModal = panel.AlertModal;
1084
+ exports.Avatar = panel.Avatar;
1085
+ exports.BulkActionButton = panel.BulkActionButton;
1086
+ exports.BulkActionsBar = panel.BulkActionsBar;
1087
+ exports.ColsPopover = panel.ColsPopover;
1088
+ exports.DEFAULT_FILTER_OPERATORS = panel.DEFAULT_FILTER_OPERATORS;
1089
+ exports.DataTable = panel.DataTable;
1090
+ exports.DataTableActionsCell = panel.DataTableActionsCell;
1091
+ exports.DataTableEditCell = panel.DataTableEditCell;
1092
+ exports.DataTableEmpty = panel.DataTableEmpty;
1093
+ exports.DataTableFloatingBulkBar = panel.DataTableFloatingBulkBar;
1094
+ exports.DataTableLoading = panel.DataTableLoading;
1095
+ exports.DataTableNoResults = panel.DataTableNoResults;
1096
+ exports.DataTableTotalizerRow = panel.DataTableTotalizerRow;
1097
+ exports.FLOATING_PANEL_SIZE_PX = panel.FLOATING_PANEL_SIZE_PX;
1098
+ exports.FilterPopover = panel.FilterPopover;
1099
+ exports.FloatingPanel = panel.FloatingPanel;
1100
+ exports.FooterTable = panel.FooterTable;
1101
+ exports.FooterTableSkeleton = panel.FooterTableSkeleton;
1102
+ exports.FormField = panel.FormField;
1103
+ exports.FormFieldCheckbox = panel.FormFieldCheckbox;
1104
+ exports.FormFieldInput = panel.FormFieldInput;
1105
+ exports.FormFieldSelect = panel.FormFieldSelect;
1106
+ exports.FormFieldSwitch = panel.FormFieldSwitch;
1107
+ exports.FormFieldTextarea = panel.FormFieldTextarea;
1108
+ exports.Kanban = panel.Kanban;
1109
+ exports.MoreMenu = panel.MoreMenu;
1110
+ exports.Panel = panel.Panel;
1111
+ exports.PanelBody = panel.PanelBody;
1112
+ exports.PanelCloseAction = panel.SheetClose;
1113
+ exports.PanelContent = panel.SheetContent;
1114
+ exports.PanelFooter = panel.PanelFooter;
1115
+ exports.PanelHeader = panel.PanelHeader;
1116
+ exports.PanelRoot = panel.Sheet;
1117
+ exports.PanelTrigger = panel.SheetTrigger;
1118
+ exports.SELECTION_COLUMN_WIDTH = panel.SELECTION_COLUMN_WIDTH;
1119
+ exports.SortPopover = panel.SortPopover;
1120
+ exports.TABLE_HEADER_HEIGHT = panel.TABLE_HEADER_HEIGHT;
1121
+ exports.TableToolbar = panel.TableToolbar;
1122
+ exports.TableToolbarViews = panel.TableToolbarViews;
1123
+ exports.ToolbarApplied = panel.ToolbarApplied;
1124
+ exports.ToolbarDivider = panel.ToolbarDivider;
1125
+ exports.ToolbarSaveButton = panel.ToolbarSaveButton;
1126
+ exports.ToolbarSearch = panel.ToolbarSearch;
1127
+ exports.ToolbarSegmented = panel.ToolbarSegmented;
1128
+ exports.ToolbarTabs = panel.ToolbarTabs;
1129
+ exports.ToolbarToolButton = panel.ToolbarToolButton;
1130
+ exports.ViewsPopover = panel.ViewsPopover;
1131
+ exports.avatarVariants = panel.avatarVariants;
1132
+ exports.columnTypeRegistry = panel.columnTypeRegistry;
1133
+ exports.floatingPanelStyles = panel.floatingPanelStyles;
1134
+ exports.panelContainer = panel.panelContainer;
1135
+ exports.presetView = panel.presetView;
1136
+ exports.savedViewsMockService = panel.savedViewsMockService;
1137
+ exports.useColumnWidths = panel.useColumnWidths;
1138
+ exports.useDataTableContext = panel.useDataTableContext;
1139
+ exports.useFloatingPanelResize = panel.useFloatingPanelResize;
1140
+ exports.AppShell = appShell.AppShell;
1141
+ exports.Header = appShell.Header;
1142
+ exports.HeaderBreadcrumb = appShell.HeaderBreadcrumb;
1143
+ exports.HeaderMessages = appShell.HeaderMessages;
1144
+ exports.HeaderNotifications = appShell.HeaderNotifications;
1145
+ exports.HeaderSearch = appShell.HeaderSearch;
1146
+ exports.HeaderThemeSwitcher = appShell.HeaderThemeSwitcher;
1147
+ exports.InputGroup = appShell.InputGroup;
1148
+ exports.InputGroupAddon = appShell.InputGroupAddon;
1149
+ exports.InputGroupButton = appShell.InputGroupButton;
1150
+ exports.InputGroupInput = appShell.InputGroupInput;
1151
+ exports.InputGroupText = appShell.InputGroupText;
1152
+ exports.InputGroupTextarea = appShell.InputGroupTextarea;
1153
+ exports.MenuSidebar = appShell.MenuSidebar;
1154
+ exports.MoreMenuCheckboxItem = appShell.DropdownMenuCheckboxItem;
1155
+ exports.MoreMenuItem = appShell.DropdownMenuItem;
1156
+ exports.MoreMenuLabel = appShell.DropdownMenuLabel;
1157
+ exports.MoreMenuRadioGroup = appShell.DropdownMenuRadioGroup;
1158
+ exports.MoreMenuRadioItem = appShell.DropdownMenuRadioItem;
1159
+ exports.MoreMenuSeparator = appShell.DropdownMenuSeparator;
1160
+ exports.SidebarBrandIcon = appShell.SidebarBrandIcon;
1161
+ exports.SidebarItem = appShell.SidebarItem;
1162
+ exports.SidebarPanel = appShell.SidebarPanel;
1163
+ exports.SidebarPill = appShell.SidebarPill;
1164
+ exports.SidebarRail = appShell.SidebarRail;
1165
+ exports.SidebarSection = appShell.SidebarSection;
1166
+ exports.SidebarSubgroup = appShell.SidebarSubgroup;
1167
+ exports.UserMenu = appShell.UserMenu;
1168
+ exports.useControllable = appShell.useControllable;
1169
+ exports.useMediaQuery = appShell.useMediaQuery;
1170
+ exports.Button = chipGroup.Button;
1171
+ exports.Chip = chipGroup.Chip;
1172
+ exports.ChipGroup = chipGroup.ChipGroup;
1173
+ exports.ChipGroupItem = chipGroup.ChipGroupItem;
1174
+ exports.buttonVariants = chipGroup.buttonVariants;
1175
+ exports.chipCount = chipGroup.chipCount;
1176
+ exports.chipVariants = chipGroup.chipVariants;
1177
+ exports.PageHeader = pageHeader.PageHeader;
1178
+ exports.pageHeaderStyles = pageHeader.pageHeaderStyles;
1179
+ exports.Badge = badge.Badge;
1180
+ exports.Table = badge.Table;
1181
+ exports.TableBody = badge.TableBody;
1182
+ exports.TableCardRow = badge.TableCardRow;
1183
+ exports.TableCell = badge.TableCell;
1184
+ exports.TableHead = badge.TableHead;
1185
+ exports.TableHeadCell = badge.TableHeadCell;
1186
+ exports.TableRow = badge.TableRow;
1187
+ exports.badgeVariants = badge.badgeVariants;
1188
+ exports.useColumnResize = badge.useColumnResize;
1189
+ exports.Input = input.Input;
1190
+ exports.inputVariants = input.inputVariants;
1191
+ exports.Modal = Modal;
1192
+ exports.TabelaTeste = TabelaTeste;
1193
+ exports.ToolbarMobileDialog = ToolbarMobileDialog;
1194
+ exports.ToolbarMobileSection = ToolbarMobileSection;
1195
+ exports.ToolbarMobileSheet = ToolbarMobileSheet;
1196
+ exports.actionColumn = actionColumn;
1197
+ exports.currencyColumn = currencyColumn;
1198
+ exports.customColumn = customColumn;
1199
+ exports.dateColumn = dateColumn;
1200
+ exports.emailColumn = emailColumn;
1201
+ exports.numberColumn = numberColumn;
1202
+ exports.phoneColumn = phoneColumn;
1203
+ exports.statusColumn = statusColumn;
1204
+ exports.textColumn = textColumn;
1205
+ exports.useToolbarFilters = useToolbarFilters;
1206
+ exports.useToolbarSort = useToolbarSort;
1207
+ //# sourceMappingURL=index.cjs.map