@rendra-ui/web 2.7.0 → 2.9.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 (64) hide show
  1. package/README.md +16 -16
  2. package/dist/base.css +1 -1
  3. package/dist/{button-DlzWwpZk.js → button-BcCBrlnt.js} +6 -6
  4. package/dist/{button-DlzWwpZk.js.map → button-BcCBrlnt.js.map} +1 -1
  5. package/dist/chart.js +7 -7
  6. package/dist/cli/auditar.js +1 -1
  7. package/dist/cli/codigos.js +2 -2
  8. package/dist/cli/executar-auditar.js +1 -1
  9. package/dist/cli/help.js +1 -1
  10. package/dist/cli/trocar.js +2 -2
  11. package/dist/cli/typescript-loader.js +1 -1
  12. package/dist/{cn-B0N3Pek0.js → cn-CpdCvlkP.js} +2 -2
  13. package/dist/{cn-B0N3Pek0.js.map → cn-CpdCvlkP.js.map} +1 -1
  14. package/dist/{components-CpQPMGfT.js → components-Bus_Jh2R.js} +9 -6
  15. package/dist/components-Bus_Jh2R.js.map +1 -0
  16. package/dist/components.css +85 -26
  17. package/dist/document-viewer.js +4 -4
  18. package/dist/{dropdown-menu-M8vs0byD.js → dropdown-menu-B3L1XSDf.js} +5 -5
  19. package/dist/{dropdown-menu-M8vs0byD.js.map → dropdown-menu-B3L1XSDf.js.map} +1 -1
  20. package/dist/{brand-feedback-icon-BYNcqBel.js → empty-state-Bcx4M0Me.js} +64 -4
  21. package/dist/empty-state-Bcx4M0Me.js.map +1 -0
  22. package/dist/{features-max-ScxV8gb3.js → features-max-CoyJ_kuK.js} +1 -1
  23. package/dist/flow.js +2818 -868
  24. package/dist/flow.js.map +1 -1
  25. package/dist/index.js +875 -681
  26. package/dist/index.js.map +1 -1
  27. package/dist/{motion-context-BUMPf0e9.js → motion-context-DWFl2xRr.js} +4 -4
  28. package/dist/{motion-context-BUMPf0e9.js.map → motion-context-DWFl2xRr.js.map} +1 -1
  29. package/dist/{motion-on-CNN6y8g-.js → motion-on-zwsBqYZL.js} +2 -2
  30. package/dist/{motion-on-CNN6y8g-.js.map → motion-on-zwsBqYZL.js.map} +1 -1
  31. package/dist/motion.js +2 -2
  32. package/dist/{rendra-provider-DEURIIL3.js → rendra-provider-DuIhBatD.js} +3 -3
  33. package/dist/{rendra-provider-DEURIIL3.js.map → rendra-provider-DuIhBatD.js.map} +1 -1
  34. package/dist/rich-text-editor.js +4 -4
  35. package/dist/router-bridge.js +2 -2
  36. package/dist/{timeline-BOh7gUdA.js → toast-C7qYslCp.js} +464 -80
  37. package/dist/toast-C7qYslCp.js.map +1 -0
  38. package/dist/tokens.css +9 -1
  39. package/dist/{tooltip-Ym9S4h9_.js → tooltip-BSPO-bH4.js} +5 -5
  40. package/dist/{tooltip-Ym9S4h9_.js.map → tooltip-BSPO-bH4.js.map} +1 -1
  41. package/dist/types/components/ui/data-toolbar.d.ts +6 -1
  42. package/dist/types/components/ui/flow-config-panels.d.ts +10 -0
  43. package/dist/types/components/ui/flow-editor.d.ts +5 -0
  44. package/dist/types/components/ui/flow-sidebar.d.ts +21 -0
  45. package/dist/types/components/ui/flow-simulation-panel.d.ts +20 -0
  46. package/dist/types/components/ui/flow-viewer.d.ts +27 -10
  47. package/dist/types/components/ui/kanban.d.ts +75 -6
  48. package/dist/types/flow.d.ts +1 -1
  49. package/dist/types/lib/flow-blocks.d.ts +122 -0
  50. package/dist/types/lib/flow-edit.d.ts +88 -0
  51. package/dist/types/lib/flow-layout.d.ts +3 -0
  52. package/dist/types/lib/flow-sim.d.ts +24 -0
  53. package/dist/types/lib/flow.d.ts +30 -80
  54. package/dist/{use-breakpoint-En17oXKY.js → use-breakpoint-BGmY3ir-.js} +2 -2
  55. package/dist/{use-breakpoint-En17oXKY.js.map → use-breakpoint-BGmY3ir-.js.map} +1 -1
  56. package/dist/{use-motion-presets-D3ww1oJX.js → use-motion-presets-CmMLBQLI.js} +3 -3
  57. package/dist/{use-motion-presets-D3ww1oJX.js.map → use-motion-presets-CmMLBQLI.js.map} +1 -1
  58. package/dist/widget-grid.js +2 -2
  59. package/package.json +3 -1
  60. package/dist/brand-feedback-icon-BYNcqBel.js.map +0 -1
  61. package/dist/components-CpQPMGfT.js.map +0 -1
  62. package/dist/empty-state-a47Kd_Ci.js +0 -67
  63. package/dist/empty-state-a47Kd_Ci.js.map +0 -1
  64. package/dist/timeline-BOh7gUdA.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,29 +1,27 @@
1
- /*! Rendra Design System v2.7.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
- import { t as cn } from "./cn-B0N3Pek0.js";
3
- import { a as useMotionMode, c as getReducedMotion, i as useMotionLib, l as subscribeReducedMotion, n as useLayoutReady, o as useMotionOn, r as useMotionAdopted, u as usePrefersReducedMotion } from "./motion-context-BUMPf0e9.js";
4
- import { t as useMotionPresets } from "./use-motion-presets-D3ww1oJX.js";
5
- import { A as lookupCnpj, B as ActionBar, C as toE164, D as controlInput, E as controlFrame, F as CardHeader, H as useShell, I as CardTitle, L as InfoHint, M as CardContent, N as CardDescription, O as useLookup, P as CardFooter, R as Modal, S as toCents, T as controlAdornmentSpace, V as ShellContext, _ as internationalPhoneMask, a as Label, b as percentMask, c as fieldGridClass, d as Drawer, f as PickerPanel, g as formatCurrency, h as formatCents, i as Field, j as Card, k as lookupCep, l as gapClass, m as DEFAULT_DDI, n as useFillHeight, o as useFieldControl, p as Input, r as Select, s as alignClass, t as Timeline, u as justifyClass, v as masks, w as controlAdornmentButton, x as phoneCountries, y as parseLocaleNumber, z as Alert } from "./timeline-BOh7gUdA.js";
6
- import { a as catalogByComponent, c as findComponentsWithoutDefault, d as findPresetCollisions, f as getCatalogEntry, i as assertCatalogIntegrity, l as findDuplicateCodes, n as CATALOG_EXCLUDED_FILES, o as filesMissingCatalogEntry, p as resolveCatalogCode, r as COMPONENT_CODE_PATTERN, s as findComponentsWithMultipleDefaults, t as CATALOG, u as findInvalidFormatCodes } from "./components-CpQPMGfT.js";
7
- import { n as buttonVariants, r as Spinner, t as Button } from "./button-DlzWwpZk.js";
8
- import { a as DropdownMenuItem, c as DropdownMenuRadioItem, d as DropdownMenuSubContent, f as DropdownMenuSubTrigger, i as DropdownMenuGroup, l as DropdownMenuSeparator, n as DropdownMenuCheckboxItem, o as DropdownMenuLabel, p as DropdownMenuTrigger, r as DropdownMenuContent, s as DropdownMenuRadioGroup, t as DropdownMenu, u as DropdownMenuSub } from "./dropdown-menu-M8vs0byD.js";
9
- import { i as BrandContext, n as feedbackLabels, r as useBrand, t as BrandFeedbackIcon } from "./brand-feedback-icon-BYNcqBel.js";
10
- import { a as useRendraNavigate, i as useRendraLink, n as useCurrentPath, r as useRendraBreadcrumbs, t as RendraProvider } from "./rendra-provider-DEURIIL3.js";
11
- import { n as useBreakpoint, t as breakpoints } from "./use-breakpoint-En17oXKY.js";
12
- import { t as EmptyState } from "./empty-state-a47Kd_Ci.js";
13
- import { n as TooltipProvider, t as Tooltip } from "./tooltip-Ym9S4h9_.js";
14
- import { ArrowDown, ArrowDownRight, ArrowLeft, ArrowRight, ArrowRightLeft, ArrowUp, ArrowUpRight, Bell, Bot, CalendarDays, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Clock, Columns3, Download, EllipsisVertical, FileText, Film, Filter, Globe, GripVertical, Home, ImageIcon, ImagePlus, LayoutTemplate, LogOut, Mail, MapPin, Menu, MessageCircle, MessagesSquare, Mic, Minus, Monitor, Moon, MoreHorizontal, Palette, PanelLeft, Paperclip, Pause, Pencil, Phone, Play, Plus, Reply, RotateCw, Search, Send, Smartphone, Smile, Star, Sun, Trash2, TriangleAlert, UploadCloud, User, VideoIcon, X, Zap } from "lucide-react";
15
- import { Accordion as Accordion$1, Avatar as Avatar$1, Checkbox as Checkbox$1, Collapsible, ContextMenu, Dialog, NavigationMenu, Popover as Popover$1, Progress as Progress$1, RadioGroup as RadioGroup$1, Slider as Slider$1, Slot, Switch as Switch$1, Tabs as Tabs$1, VisuallyHidden } from "radix-ui";
1
+ /*! Rendra Design System v2.9.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
+ import { t as cn } from "./cn-CpdCvlkP.js";
3
+ import { a as useMotionMode, c as getReducedMotion, i as useMotionLib, l as subscribeReducedMotion, n as useLayoutReady, o as useMotionOn, r as useMotionAdopted, u as usePrefersReducedMotion } from "./motion-context-DWFl2xRr.js";
4
+ import { t as useMotionPresets } from "./use-motion-presets-CmMLBQLI.js";
5
+ import { A as toE164, B as Alert, C as formatCurrency, D as percentMask, E as parseLocaleNumber, F as useLookup, H as ShellContext, I as lookupCep, L as lookupCnpj, M as controlAdornmentSpace, N as controlFrame, O as phoneCountries, P as controlInput, R as InfoHint, S as formatCents, T as masks, U as useShell, V as ActionBar, _ as PickerPanel, a as RadioGroup, b as Input, c as Select, d as useFieldControl, f as alignClass, g as Drawer, h as justifyClass, i as Textarea, j as controlAdornmentButton, k as toCents, l as Field, m as gapClass, n as toast, o as useFillHeight, p as fieldGridClass, r as Timeline, s as Tabs, t as Toaster, u as Label, v as Checkbox, w as internationalPhoneMask, x as DEFAULT_DDI, y as CheckboxGroup, z as Modal } from "./toast-C7qYslCp.js";
6
+ import { a as catalogByComponent, c as findComponentsWithoutDefault, d as findPresetCollisions, f as getCatalogEntry, i as assertCatalogIntegrity, l as findDuplicateCodes, n as CATALOG_EXCLUDED_FILES, o as filesMissingCatalogEntry, p as resolveCatalogCode, r as COMPONENT_CODE_PATTERN, s as findComponentsWithMultipleDefaults, t as CATALOG, u as findInvalidFormatCodes } from "./components-Bus_Jh2R.js";
7
+ import { n as buttonVariants, r as Spinner, t as Button } from "./button-BcCBrlnt.js";
8
+ import { a as DropdownMenuItem, c as DropdownMenuRadioItem, d as DropdownMenuSubContent, f as DropdownMenuSubTrigger, i as DropdownMenuGroup, l as DropdownMenuSeparator, n as DropdownMenuCheckboxItem, o as DropdownMenuLabel, p as DropdownMenuTrigger, r as DropdownMenuContent, s as DropdownMenuRadioGroup, t as DropdownMenu, u as DropdownMenuSub } from "./dropdown-menu-B3L1XSDf.js";
9
+ import { a as BrandContext, i as useBrand, n as BrandFeedbackIcon, r as feedbackLabels, t as EmptyState } from "./empty-state-Bcx4M0Me.js";
10
+ import { a as useRendraNavigate, i as useRendraLink, n as useCurrentPath, r as useRendraBreadcrumbs, t as RendraProvider } from "./rendra-provider-DuIhBatD.js";
11
+ import { n as useBreakpoint, t as breakpoints } from "./use-breakpoint-BGmY3ir-.js";
12
+ import { n as TooltipProvider, t as Tooltip } from "./tooltip-BSPO-bH4.js";
13
+ import { ArrowDown, ArrowDownRight, ArrowLeft, ArrowRight, ArrowRightLeft, ArrowUp, ArrowUpRight, Bell, Bot, CalendarClock, CalendarDays, CalendarX2, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Clock, Columns3, Download, EllipsisVertical, FileText, Film, Filter, Globe, GripVertical, Home, ImageIcon, ImagePlus, LayoutTemplate, LogOut, Mail, MapPin, Menu, MessageCircle, MessagesSquare, Mic, Minus, Monitor, Moon, MoreHorizontal, Palette, PanelLeft, Paperclip, Pause, Pencil, Phone, Play, Plus, Reply, RotateCw, Search, Send, Settings2, Smartphone, Smile, Star, Sun, Trash2, TriangleAlert, UploadCloud, User, VideoIcon, X, Zap } from "lucide-react";
14
+ import { Accordion as Accordion$1, Avatar as Avatar$1, Collapsible, ContextMenu, Dialog, NavigationMenu, Popover as Popover$1, Progress as Progress$1, Slider as Slider$1, Slot, Switch as Switch$1, VisuallyHidden } from "radix-ui";
16
15
  import { Fragment, createContext, forwardRef, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
17
16
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
18
17
  import { cva } from "class-variance-authority";
19
- import { addDays, addMonths, addWeeks, differenceInMinutes, endOfMonth, endOfWeek, format, isSameDay, isSameMonth, isToday, isYesterday, startOfDay, startOfMonth, startOfWeek } from "date-fns";
18
+ import { addDays, addMonths, addWeeks, differenceInCalendarDays, differenceInMinutes, endOfMonth, endOfWeek, format, isSameDay, isSameMonth, isToday, isYesterday, startOfDay, startOfMonth, startOfWeek } from "date-fns";
20
19
  import { ptBR } from "date-fns/locale";
21
20
  import { DayPicker } from "react-day-picker";
22
21
  import { ptBR as ptBR$1 } from "react-day-picker/locale";
23
22
  import { FormProvider, useController, useFormContext } from "react-hook-form";
24
23
  import { Command } from "cmdk";
25
24
  import { columnFilteringFeature, columnVisibilityFeature, createExpandedRowModel, createFilteredRowModel, createPaginatedRowModel, createSortedRowModel, filterFn_includesString, globalFilteringFeature, rowExpandingFeature, rowPaginationFeature, rowSelectionFeature, rowSortingFeature, sortFn_alphanumeric, sortFn_basic, tableFeatures, useTable } from "@tanstack/react-table";
26
- import { Toaster as Toaster$1, toast as toast$1 } from "sonner";
27
25
  import { z } from "zod";
28
26
  //#region src/lib/motion/reorder.ts
29
27
  function layoutEnabled({ mode, ready, dragging }) {
@@ -495,6 +493,73 @@ function ButtonGroup({ children, options, value, onChange, size = "md", fullWidt
495
493
  });
496
494
  }
497
495
  //#endregion
496
+ //#region src/components/ui/card.tsx
497
+ function Card({ className, "data-rendra": dataRendra, ...props }) {
498
+ return /* @__PURE__ */ jsx("div", {
499
+ "data-slot": "card",
500
+ "data-rendra": dataRendra ?? "CARD-001",
501
+ className: cn("flex min-w-0 flex-col rounded-surface border bg-card text-card-foreground", className),
502
+ ...props
503
+ });
504
+ }
505
+ function CardHeader({ className, actions, children, ...props }) {
506
+ if (!actions) return /* @__PURE__ */ jsx("div", {
507
+ "data-slot": "card-header",
508
+ className: cn("flex flex-col gap-1 p-4 md:p-6", className),
509
+ ...props,
510
+ children
511
+ });
512
+ return /* @__PURE__ */ jsxs("div", {
513
+ "data-slot": "card-header",
514
+ className: cn("flex flex-wrap items-start justify-between gap-x-4 gap-y-3 p-4 md:p-6", className),
515
+ ...props,
516
+ children: [/* @__PURE__ */ jsx("div", {
517
+ className: "flex min-w-0 flex-1 flex-col gap-1",
518
+ children
519
+ }), /* @__PURE__ */ jsx("div", {
520
+ className: "flex shrink-0 items-center gap-2",
521
+ children: actions
522
+ })]
523
+ });
524
+ }
525
+ function CardTitle({ className, children, help, ...props }) {
526
+ const heading = /* @__PURE__ */ jsx("h3", {
527
+ "data-slot": "card-title",
528
+ className: cn("text-lg font-semibold", className),
529
+ ...props,
530
+ children
531
+ });
532
+ if (!help) return heading;
533
+ return /* @__PURE__ */ jsxs("div", {
534
+ className: "flex min-w-0 items-center gap-1",
535
+ children: [heading, /* @__PURE__ */ jsx(InfoHint, {
536
+ title: typeof children === "string" ? children : "Sobre esta seção",
537
+ children: help
538
+ })]
539
+ });
540
+ }
541
+ function CardDescription({ className, ...props }) {
542
+ return /* @__PURE__ */ jsx("p", {
543
+ "data-slot": "card-description",
544
+ className: cn("text-sm text-muted-foreground", className),
545
+ ...props
546
+ });
547
+ }
548
+ function CardContent({ className, ...props }) {
549
+ return /* @__PURE__ */ jsx("div", {
550
+ "data-slot": "card-content",
551
+ className: cn("p-4 md:p-6 [[data-slot=card-header]+&]:pt-0", className),
552
+ ...props
553
+ });
554
+ }
555
+ function CardFooter({ className, ...props }) {
556
+ return /* @__PURE__ */ jsx("div", {
557
+ "data-slot": "card-footer",
558
+ className: cn("flex items-center gap-3 border-t px-4 py-3 md:px-6", className),
559
+ ...props
560
+ });
561
+ }
562
+ //#endregion
498
563
  //#region src/components/ui/calendar.tsx
499
564
  var viewLabels = {
500
565
  month: "Mês",
@@ -2071,124 +2136,6 @@ function QuickReplyList({ items, onPick }) {
2071
2136
  ] });
2072
2137
  }
2073
2138
  //#endregion
2074
- //#region src/components/ui/checkbox.tsx
2075
- /**
2076
- * Checkbox único, com estado indeterminado (checked="indeterminate").
2077
- * Com label, a linha inteira é área de toque de 44px no mobile.
2078
- */
2079
- function Checkbox({ checked, defaultChecked, onCheckedChange, label, description, disabled, invalid, id, name, className, ...aria }) {
2080
- const auto = useId();
2081
- const cid = id ?? `cb${auto}`;
2082
- const lib = useMotionLib();
2083
- const on = lib !== null;
2084
- const presets = useMotionPresets();
2085
- const [inner, setInner] = useState(defaultChecked ?? false);
2086
- const state = checked ?? inner;
2087
- const mark = checked === "indeterminate" ? /* @__PURE__ */ jsx(Minus, {
2088
- className: "size-3",
2089
- strokeWidth: 3,
2090
- "aria-hidden": true
2091
- }) : /* @__PURE__ */ jsx(Check, {
2092
- className: "size-3",
2093
- strokeWidth: 3,
2094
- "aria-hidden": true
2095
- });
2096
- const rootProps = {
2097
- id: cid,
2098
- name,
2099
- checked: on ? state : checked,
2100
- defaultChecked: on ? void 0 : defaultChecked,
2101
- onCheckedChange: (v) => {
2102
- if (on) setInner(v);
2103
- onCheckedChange?.(v === true);
2104
- },
2105
- disabled,
2106
- "aria-invalid": invalid || void 0,
2107
- "aria-label": aria["aria-label"],
2108
- "data-touch": label ? void 0 : "expanded",
2109
- className: cn("peer relative flex size-icon-md shrink-0 cursor-pointer items-center justify-center rounded-item border border-input bg-card transition-colors", "hover:border-primary data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground", "disabled:cursor-not-allowed disabled:opacity-50", invalid && "border-destructive", !label && "before:absolute before:-inset-3 md:before:hidden")
2110
- };
2111
- const box = on ? /* @__PURE__ */ jsx(Checkbox$1.Root, {
2112
- asChild: true,
2113
- ...rootProps,
2114
- children: /* @__PURE__ */ jsx(lib.m.button, {
2115
- type: "button",
2116
- whileTap: presets.press.whileTap,
2117
- transition: presets.press.transition,
2118
- children: /* @__PURE__ */ jsx(lib.AnimatePresence, {
2119
- initial: false,
2120
- children: state !== false && /* @__PURE__ */ jsx(Checkbox$1.Indicator, {
2121
- forceMount: true,
2122
- asChild: true,
2123
- children: /* @__PURE__ */ jsx(lib.m.span, {
2124
- className: "flex items-center justify-center",
2125
- ...presets.indicator,
2126
- children: mark
2127
- })
2128
- })
2129
- })
2130
- })
2131
- }) : /* @__PURE__ */ jsx(Checkbox$1.Root, {
2132
- ...rootProps,
2133
- children: /* @__PURE__ */ jsx(Checkbox$1.Indicator, {
2134
- className: "flex items-center justify-center data-[state=checked]:animate-in data-[state=checked]:duration-(--rendra-duration-fast) data-[state=checked]:zoom-in-90",
2135
- children: mark
2136
- })
2137
- });
2138
- if (!label) return /* @__PURE__ */ jsx("span", {
2139
- "data-rendra": "CHK-001",
2140
- className: cn("inline-flex", className),
2141
- children: box
2142
- });
2143
- return /* @__PURE__ */ jsxs("label", {
2144
- htmlFor: cid,
2145
- "data-rendra": "CHK-001",
2146
- className: cn("flex min-h-touch cursor-pointer items-start gap-3 py-3 md:min-h-0 md:py-1", disabled && "cursor-not-allowed opacity-60", className),
2147
- children: [/* @__PURE__ */ jsx("span", {
2148
- className: "flex pt-px",
2149
- children: box
2150
- }), /* @__PURE__ */ jsxs("span", {
2151
- className: "flex min-w-0 flex-col gap-1",
2152
- children: [/* @__PURE__ */ jsx("span", {
2153
- className: "text-sm font-medium",
2154
- children: label
2155
- }), description && /* @__PURE__ */ jsx("span", {
2156
- className: "text-sm text-muted-foreground",
2157
- children: description
2158
- })]
2159
- })]
2160
- });
2161
- }
2162
- function CheckboxGroup({ options, value = [], onChange, selectAll, orientation = "vertical", invalid, id, label, ...aria }) {
2163
- const enabled = options.filter((o) => !o.disabled);
2164
- const all = enabled.length > 0 && enabled.every((o) => value.includes(o.value));
2165
- const some = value.length > 0 && !all;
2166
- return /* @__PURE__ */ jsxs("div", {
2167
- id,
2168
- role: "group",
2169
- "aria-label": label,
2170
- "aria-describedby": aria["aria-describedby"],
2171
- "data-rendra": "CHK-002",
2172
- className: "flex flex-col",
2173
- children: [selectAll && /* @__PURE__ */ jsx(Checkbox, {
2174
- label: "Selecionar todos",
2175
- checked: all ? true : some ? "indeterminate" : false,
2176
- onCheckedChange: () => onChange?.(all ? [] : enabled.map((o) => o.value)),
2177
- className: "border-b"
2178
- }), /* @__PURE__ */ jsx("div", {
2179
- className: cn("flex", orientation === "vertical" ? "flex-col" : "flex-col sm:flex-row sm:flex-wrap sm:gap-x-6"),
2180
- children: options.map((o) => /* @__PURE__ */ jsx(Checkbox, {
2181
- label: o.label,
2182
- description: o.description,
2183
- disabled: o.disabled,
2184
- invalid,
2185
- checked: value.includes(o.value),
2186
- onCheckedChange: (c) => onChange?.(c ? [...value, o.value] : value.filter((v) => v !== o.value))
2187
- }, o.value))
2188
- })]
2189
- });
2190
- }
2191
- //#endregion
2192
2139
  //#region src/components/ui/checklist.tsx
2193
2140
  /** Uma lista de verificação por finalidade: itens de um checklist usam este componente. */
2194
2141
  function Checklist({ value, onChange, addLabel = "Adicionar item", disabled = false, id, className, ...aria }) {
@@ -2697,7 +2644,7 @@ function Switch({ checked, defaultChecked, onCheckedChange, label, description,
2697
2644
  }
2698
2645
  //#endregion
2699
2646
  //#region src/components/ui/data-toolbar.tsx
2700
- function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips = [], sort, columns, actions, primaryAction, selectionBar }) {
2647
+ function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips = [], sort, columns, actions, summary, primaryAction, selectionBar }) {
2701
2648
  const { isMobile } = useBreakpoint();
2702
2649
  const [drawer, setDrawer] = useState(false);
2703
2650
  const hasPanel = Boolean(filters || sort || columns?.length);
@@ -2735,49 +2682,57 @@ function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips =
2735
2682
  children: selectionBar
2736
2683
  }) : /* @__PURE__ */ jsxs("div", {
2737
2684
  className: "flex flex-col gap-3 md:flex-row md:items-center",
2738
- children: [search && /* @__PURE__ */ jsx(Input, {
2739
- icon: /* @__PURE__ */ jsx(Search, {}),
2740
- clearable: true,
2741
- value: search.value,
2742
- onChange: search.onChange,
2743
- placeholder: search.placeholder ?? "Buscar",
2744
- "aria-label": search.placeholder ?? "Buscar",
2745
- type: "search",
2746
- className: "md:w-3xs lg:w-sm"
2747
- }), isMobile ? /* @__PURE__ */ jsxs(Fragment$1, { children: [(hasPanel || primaryAction) && /* @__PURE__ */ jsxs("div", {
2748
- className: cn("grid gap-3", hasPanel && primaryAction ? "grid-actions-2" : "grid-cols-1"),
2749
- children: [hasPanel && filterButton(() => setDrawer(true)), primaryAction]
2750
- }), actions && /* @__PURE__ */ jsx("div", {
2751
- className: "flex flex-wrap gap-3 *:flex-1",
2752
- children: actions
2753
- })] }) : /* @__PURE__ */ jsxs("div", {
2754
- className: "flex flex-wrap items-center gap-2 md:ml-auto",
2755
- children: [
2756
- actions,
2757
- columnsMenu,
2758
- sort,
2759
- filters && /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
2760
- asChild: true,
2761
- children: filterButton()
2762
- }), /* @__PURE__ */ jsxs(PopoverContent, {
2763
- align: "end",
2764
- className: "flex flex-col",
2765
- children: [/* @__PURE__ */ jsx("div", {
2766
- className: "max-h-command overflow-y-auto p-4",
2767
- children: filters
2768
- }), onClearFilters && filterCount > 0 && /* @__PURE__ */ jsx("div", {
2769
- className: "border-t p-2",
2770
- children: /* @__PURE__ */ jsx(Button, {
2771
- variant: "ghost",
2772
- size: "sm",
2773
- onClick: onClearFilters,
2774
- children: "Limpar filtros"
2775
- })
2776
- })]
2777
- })] }),
2778
- primaryAction
2779
- ]
2780
- })]
2685
+ children: [
2686
+ search && /* @__PURE__ */ jsx(Input, {
2687
+ icon: /* @__PURE__ */ jsx(Search, {}),
2688
+ clearable: true,
2689
+ value: search.value,
2690
+ onChange: search.onChange,
2691
+ placeholder: search.placeholder ?? "Buscar",
2692
+ "aria-label": search.placeholder ?? "Buscar",
2693
+ type: "search",
2694
+ className: "md:w-3xs lg:w-sm"
2695
+ }),
2696
+ summary && /* @__PURE__ */ jsx("div", {
2697
+ "data-toolbar-summary": true,
2698
+ className: "flex flex-col gap-1 text-sm",
2699
+ children: summary
2700
+ }),
2701
+ isMobile ? /* @__PURE__ */ jsxs(Fragment$1, { children: [(hasPanel || primaryAction) && /* @__PURE__ */ jsxs("div", {
2702
+ className: cn("grid gap-3", hasPanel && primaryAction ? "grid-actions-2" : "grid-cols-1"),
2703
+ children: [hasPanel && filterButton(() => setDrawer(true)), primaryAction]
2704
+ }), actions && /* @__PURE__ */ jsx("div", {
2705
+ className: "flex flex-wrap gap-3 *:flex-1",
2706
+ children: actions
2707
+ })] }) : /* @__PURE__ */ jsxs("div", {
2708
+ className: "flex flex-wrap items-center gap-2 md:ml-auto",
2709
+ children: [
2710
+ actions,
2711
+ columnsMenu,
2712
+ sort,
2713
+ filters && /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
2714
+ asChild: true,
2715
+ children: filterButton()
2716
+ }), /* @__PURE__ */ jsxs(PopoverContent, {
2717
+ align: "end",
2718
+ className: "flex flex-col",
2719
+ children: [/* @__PURE__ */ jsx("div", {
2720
+ className: "max-h-command overflow-y-auto p-4",
2721
+ children: filters
2722
+ }), onClearFilters && filterCount > 0 && /* @__PURE__ */ jsx("div", {
2723
+ className: "border-t p-2",
2724
+ children: /* @__PURE__ */ jsx(Button, {
2725
+ variant: "ghost",
2726
+ size: "sm",
2727
+ onClick: onClearFilters,
2728
+ children: "Limpar filtros"
2729
+ })
2730
+ })]
2731
+ })] }),
2732
+ primaryAction
2733
+ ]
2734
+ })
2735
+ ]
2781
2736
  }),
2782
2737
  chips.length > 0 && /* @__PURE__ */ jsxs("div", {
2783
2738
  className: "flex flex-wrap items-center gap-2",
@@ -3230,139 +3185,6 @@ function Slider({ value, defaultValue = [50], onChange, min = 0, max = 100, step
3230
3185
  });
3231
3186
  }
3232
3187
  //#endregion
3233
- //#region src/components/ui/tabs.tsx
3234
- /** Contador de instâncias, só para o `layoutId` do indicador (ver `indicatorId`). */
3235
- var tabsCreated = 0;
3236
- /**
3237
- * Tabs único. Se as abas não couberem na largura, a mesma lista vira um Select
3238
- * (nunca rolagem lateral). A troca é medida no próprio contêiner, não na tela.
3239
- */
3240
- function Tabs({ items, value, defaultValue, onChange, variant = "line", className, ...aria }) {
3241
- const [inner, setInner] = useState(defaultValue ?? items[0]?.value ?? "");
3242
- const current = value ?? inner;
3243
- const set = (v) => {
3244
- setInner(v);
3245
- onChange?.(v);
3246
- };
3247
- const boxRef = useRef(null);
3248
- const measureRef = useRef(null);
3249
- const [overflow, setOverflow] = useState(false);
3250
- useLayoutEffect(() => {
3251
- const box = boxRef.current;
3252
- const measure = measureRef.current;
3253
- if (!box || !measure) return;
3254
- const check = () => setOverflow(measure.scrollWidth > box.clientWidth + 1);
3255
- check();
3256
- const ro = new ResizeObserver(check);
3257
- ro.observe(box);
3258
- return () => ro.disconnect();
3259
- }, [items, variant]);
3260
- const presets = useMotionPresets();
3261
- const on = useLayoutReady();
3262
- const lib = useMotionLib();
3263
- const listRef = useRef(null);
3264
- const [clip, setClip] = useState({
3265
- l: 0,
3266
- r: 0
3267
- });
3268
- useLayoutEffect(() => {
3269
- const list = listRef.current;
3270
- if (!on || !list) return;
3271
- const measure = () => {
3272
- const active = list.querySelector("[role=\"tab\"][data-state=\"active\"]");
3273
- if (!active) return;
3274
- const l = active.offsetLeft;
3275
- const r = list.offsetWidth - l - active.offsetWidth;
3276
- setClip((prev) => prev.l === l && prev.r === r ? prev : {
3277
- l,
3278
- r
3279
- });
3280
- };
3281
- measure();
3282
- const ro = new ResizeObserver(measure);
3283
- ro.observe(list);
3284
- return () => ro.disconnect();
3285
- }, [
3286
- on,
3287
- current,
3288
- items,
3289
- variant,
3290
- overflow
3291
- ]);
3292
- const [indicatorId] = useState(() => `rendra-tabs-${++tabsCreated}`);
3293
- const trigger = cn("inline-flex min-h-touch shrink-0 cursor-pointer items-center justify-center gap-2 px-3 text-sm font-medium whitespace-nowrap transition-colors outline-none disabled:cursor-not-allowed disabled:opacity-50 md:min-h-0 [&_svg]:size-icon-sm", variant === "line" ? on ? "relative -mb-px border-b-2 border-transparent py-3 text-muted-foreground hover:text-foreground" : "-mb-px border-b-2 border-transparent py-3 text-muted-foreground hover:text-foreground data-[state=active]:border-primary data-[state=active]:text-foreground" : on ? "relative isolate rounded-item py-2 text-muted-foreground hover:bg-card/60 hover:text-foreground" : "rounded-item py-2 text-muted-foreground hover:bg-card/60 hover:text-foreground data-[state=active]:bg-card data-[state=active]:text-foreground data-[state=active]:shadow-sm");
3294
- const indicator = lib && /* @__PURE__ */ jsx(lib.m.span, {
3295
- layoutId: indicatorId,
3296
- "data-indicator": "tabs",
3297
- "aria-hidden": true,
3298
- transition: presets.move,
3299
- className: variant === "line" ? "absolute inset-x-0 top-full border-b-2 border-primary" : "absolute inset-0 -z-10 rounded-item bg-card shadow-sm"
3300
- });
3301
- const list = cn("flex", variant === "line" ? "gap-2 border-b" : "gap-1 rounded-control bg-muted p-1");
3302
- const label = (it) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
3303
- it.icon,
3304
- it.label,
3305
- it.count !== void 0 && /* @__PURE__ */ jsx("span", {
3306
- className: "rounded-full bg-muted px-2 text-xs text-muted-foreground tabular-nums",
3307
- children: it.count
3308
- })
3309
- ] });
3310
- return /* @__PURE__ */ jsxs(Tabs$1.Root, {
3311
- value: current,
3312
- onValueChange: set,
3313
- "data-rendra": resolveCatalogCode("Tabs", { variant }),
3314
- className: cn("flex min-w-0 flex-col gap-6", className),
3315
- children: [/* @__PURE__ */ jsxs("div", {
3316
- ref: boxRef,
3317
- className: "relative min-w-0",
3318
- children: [/* @__PURE__ */ jsx("div", {
3319
- ref: measureRef,
3320
- "aria-hidden": true,
3321
- className: cn(list, "invisible absolute w-max"),
3322
- children: items.map((it) => /* @__PURE__ */ jsx("span", {
3323
- className: trigger,
3324
- children: label(it)
3325
- }, it.value))
3326
- }), overflow ? /* @__PURE__ */ jsx(Select, {
3327
- label: aria["aria-label"] ?? "Seção",
3328
- value: current,
3329
- onChange: (v) => v && set(v),
3330
- options: items.map((it) => ({
3331
- value: it.value,
3332
- label: it.count !== void 0 ? `${it.label} (${it.count})` : it.label,
3333
- disabled: it.disabled
3334
- }))
3335
- }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Tabs$1.List, {
3336
- ref: listRef,
3337
- "aria-label": aria["aria-label"],
3338
- className: list,
3339
- children: items.map((it) => /* @__PURE__ */ jsxs(Tabs$1.Trigger, {
3340
- value: it.value,
3341
- disabled: it.disabled,
3342
- className: trigger,
3343
- children: [on && current === it.value && indicator, label(it)]
3344
- }, it.value))
3345
- }), on && /* @__PURE__ */ jsx("div", {
3346
- "data-tabs-copy": true,
3347
- "aria-hidden": true,
3348
- className: cn(list, "pointer-events-none absolute inset-0 border-transparent bg-transparent text-foreground tabs-clip"),
3349
- style: {
3350
- "--tabs-l": `${clip.l}px`,
3351
- "--tabs-r": `${clip.r}px`
3352
- },
3353
- children: items.map((it) => /* @__PURE__ */ jsx("span", {
3354
- className: cn(trigger, "text-foreground"),
3355
- children: label(it)
3356
- }, it.value))
3357
- })] })]
3358
- }), items.map((it) => /* @__PURE__ */ jsx(Tabs$1.Content, {
3359
- value: it.value,
3360
- className: "min-w-0 outline-none",
3361
- children: it.content
3362
- }, it.value))]
3363
- });
3364
- }
3365
- //#endregion
3366
3188
  //#region src/lib/sortable.ts
3367
3189
  var DEFAULT_ATTR = "data-sortable-id";
3368
3190
  /**
@@ -3834,10 +3656,239 @@ var targetIconTone = {
3834
3656
  info: "text-info",
3835
3657
  outline: "text-foreground"
3836
3658
  };
3837
- function CardBody({ card, valueFields = [], formatValue, withHandle }) {
3838
- const shown = valueFields.slice(0, 2);
3659
+ /** Fundo claro de cada destino do rodapé flutuante, pela cor da ação. */
3660
+ var targetSoft = {
3661
+ neutral: "bg-muted",
3662
+ primary: "bg-primary-soft",
3663
+ success: "bg-success-soft",
3664
+ warning: "bg-warning-soft",
3665
+ error: "bg-destructive-soft",
3666
+ info: "bg-info-soft",
3667
+ outline: "bg-card"
3668
+ };
3669
+ /** Destino realçado (card por cima): fundo forte com o `-foreground` dele em tudo. */
3670
+ var targetStrong = {
3671
+ neutral: "bg-muted text-foreground",
3672
+ primary: "bg-primary text-primary-foreground",
3673
+ success: "bg-success text-success-foreground",
3674
+ warning: "bg-warning text-warning-foreground",
3675
+ error: "bg-destructive text-destructive-foreground",
3676
+ info: "bg-info text-info-foreground",
3677
+ outline: "bg-muted text-foreground"
3678
+ };
3679
+ /**
3680
+ * Situação do card a partir da próxima atividade e da cadência da etapa. Compara por dia de
3681
+ * calendário; `referenceDate` é o "hoje" (injetável para teste).
3682
+ */
3683
+ function getKanbanCardStatus(card, column, referenceDate) {
3684
+ const daysInColumn = card.enteredColumnAt ? differenceInCalendarDays(referenceDate, card.enteredColumnAt) : null;
3685
+ const cadenceOverdue = column?.cadenceDays !== void 0 && daysInColumn !== null && daysInColumn > column.cadenceDays;
3686
+ const ahead = card.activity ? differenceInCalendarDays(card.activity.at, referenceDate) : null;
3687
+ const activity = ahead === null ? "none" : ahead < 0 ? "late" : ahead === 0 ? "today" : "onTime";
3688
+ return {
3689
+ background: cadenceOverdue && (activity === "late" || activity === "none") ? "critical" : cadenceOverdue ? "cadenceOverdue" : activity === "none" ? "noActivity" : "normal",
3690
+ activity,
3691
+ daysInColumn,
3692
+ daysLate: ahead !== null && ahead < 0 ? -ahead : 0
3693
+ };
3694
+ }
3695
+ /** Classes literais completas (nada de classe montada por string). */
3696
+ var statusBackground = {
3697
+ critical: "bg-critical-soft",
3698
+ cadenceOverdue: "bg-destructive-soft",
3699
+ noActivity: "bg-warning-soft",
3700
+ normal: "bg-card"
3701
+ };
3702
+ var activityIcon = {
3703
+ onTime: {
3704
+ icon: CalendarDays,
3705
+ circle: "bg-info-soft text-info-soft-foreground"
3706
+ },
3707
+ today: {
3708
+ icon: CalendarClock,
3709
+ circle: "bg-warning-mid text-warning-mid-foreground"
3710
+ },
3711
+ late: {
3712
+ icon: CalendarX2,
3713
+ circle: "bg-destructive text-destructive-foreground"
3714
+ },
3715
+ none: {
3716
+ icon: CalendarDays,
3717
+ circle: "border border-dashed border-muted-foreground text-muted-foreground"
3718
+ }
3719
+ };
3720
+ function plural(n, one, many) {
3721
+ return `${n} ${n === 1 ? one : many}`;
3722
+ }
3723
+ function situationText(status) {
3724
+ if (status.activity === "onTime") return "Em dia";
3725
+ if (status.activity === "today") return "Vence hoje";
3726
+ if (status.activity === "late") return `Atrasada há ${plural(status.daysLate, "dia", "dias")}`;
3727
+ return "Sem atividade agendada";
3728
+ }
3729
+ /** Texto para o leitor de tela: a cor do fundo nunca é a única informação. */
3730
+ function backgroundLabel(status) {
3731
+ if (status.background === "critical") return `Situação: crítico, cadência vencida e ${status.activity === "late" ? "atividade atrasada" : "sem próxima atividade"}`;
3732
+ if (status.background === "cadenceOverdue") return "Situação: cadência vencida";
3733
+ if (status.background === "noActivity") return "Situação: sem atividade";
3734
+ return null;
3735
+ }
3736
+ function whenText(at, status) {
3737
+ return status.activity === "today" ? `Hoje às ${format(at, "HH:mm")}` : `${format(at, "dd/MM/yyyy")} às ${format(at, "HH:mm")}`;
3738
+ }
3739
+ var baseFields = [
3740
+ {
3741
+ id: "tags",
3742
+ label: "Tags"
3743
+ },
3744
+ {
3745
+ id: "document",
3746
+ label: "CNPJ ou CPF"
3747
+ },
3748
+ {
3749
+ id: "description",
3750
+ label: "Descrição"
3751
+ },
3752
+ {
3753
+ id: "contact",
3754
+ label: "Contato"
3755
+ },
3756
+ {
3757
+ id: "phone",
3758
+ label: "Telefone"
3759
+ },
3760
+ {
3761
+ id: "email",
3762
+ label: "E-mail"
3763
+ },
3764
+ {
3765
+ id: "activity",
3766
+ label: "Atividade"
3767
+ },
3768
+ {
3769
+ id: "assignee",
3770
+ label: "Responsável"
3771
+ }
3772
+ ];
3773
+ /** Lê os campos escondidos; qualquer falha do armazenamento cai no padrão (tudo visível). */
3774
+ function readHidden(storageKey) {
3775
+ if (!storageKey) return {};
3776
+ try {
3777
+ const raw = localStorage.getItem(storageKey);
3778
+ const list = raw ? JSON.parse(raw) : [];
3779
+ return Array.isArray(list) ? Object.fromEntries(list.filter((f) => typeof f === "string").map((f) => [f, true])) : {};
3780
+ } catch {
3781
+ return {};
3782
+ }
3783
+ }
3784
+ function writeHidden(storageKey, hidden) {
3785
+ if (!storageKey) return;
3786
+ try {
3787
+ localStorage.setItem(storageKey, JSON.stringify(Object.keys(hidden).filter((k) => hidden[k])));
3788
+ } catch {}
3789
+ }
3790
+ var HINT_CLOSE_DELAY = 150;
3791
+ /**
3792
+ * Calendário do card: ícone de situação, data ao lado e hint (tipo, quando, com quem,
3793
+ * responsável e situação). Abre por clique, toque, foco por teclado e mouse; o gatilho é um
3794
+ * botão fora do botão de clique do card.
3795
+ */
3796
+ function ActivityHint({ card, status }) {
3797
+ const [open, setOpen] = useState(false);
3798
+ const pressed = useRef(false);
3799
+ const holding = useRef(false);
3800
+ const triggerRef = useRef(null);
3801
+ const lastPointer = useRef("");
3802
+ const timer = useRef(void 0);
3803
+ const { icon: Icon, circle } = activityIcon[status.activity];
3804
+ const activity = card.activity;
3805
+ const visible = activity ? status.activity === "today" ? `Hoje ${format(activity.at, "HH:mm")}` : format(activity.at, "dd/MM/yyyy") : "Sem atividade";
3806
+ const cancelClose = () => clearTimeout(timer.current);
3807
+ const scheduleClose = () => {
3808
+ cancelClose();
3809
+ timer.current = setTimeout(() => {
3810
+ if (!holding.current) setOpen(false);
3811
+ }, HINT_CLOSE_DELAY);
3812
+ };
3813
+ useEffect(() => cancelClose, []);
3814
+ return /* @__PURE__ */ jsxs(Popover, {
3815
+ open,
3816
+ onOpenChange: (next) => !next && !holding.current && setOpen(false),
3817
+ children: [/* @__PURE__ */ jsx(PopoverAnchor, {
3818
+ asChild: true,
3819
+ children: /* @__PURE__ */ jsxs("button", {
3820
+ ref: triggerRef,
3821
+ type: "button",
3822
+ "aria-haspopup": "dialog",
3823
+ "aria-expanded": open,
3824
+ "aria-label": `${visible}. ${situationText(status)}`,
3825
+ className: "relative z-10 -ml-1 inline-flex cursor-pointer items-center gap-1 rounded-item px-1 tabular-nums outline-none focus-visible:ring-2 focus-visible:ring-ring max-md:min-h-touch",
3826
+ onPointerDown: (e) => {
3827
+ cancelClose();
3828
+ pressed.current = true;
3829
+ holding.current = true;
3830
+ window.addEventListener("pointerup", () => holding.current = false, { once: true });
3831
+ window.addEventListener("pointercancel", () => holding.current = false, { once: true });
3832
+ lastPointer.current = e.pointerType;
3833
+ },
3834
+ onPointerEnter: (e) => {
3835
+ if (e.pointerType !== "mouse") return;
3836
+ cancelClose();
3837
+ setOpen(true);
3838
+ },
3839
+ onPointerLeave: (e) => e.pointerType === "mouse" && scheduleClose(),
3840
+ onFocus: () => {
3841
+ if (!pressed.current) setOpen(true);
3842
+ },
3843
+ onBlur: () => {
3844
+ pressed.current = false;
3845
+ if (!holding.current) setOpen(false);
3846
+ },
3847
+ onClick: (e) => {
3848
+ e.preventDefault();
3849
+ e.stopPropagation();
3850
+ pressed.current = false;
3851
+ const byMouse = lastPointer.current === "mouse";
3852
+ lastPointer.current = "";
3853
+ setOpen((o) => byMouse || !o);
3854
+ },
3855
+ children: [/* @__PURE__ */ jsx("span", {
3856
+ "aria-hidden": true,
3857
+ className: cn("flex size-6 shrink-0 items-center justify-center rounded-full", circle),
3858
+ children: /* @__PURE__ */ jsx(Icon, { className: "size-3" })
3859
+ }), visible]
3860
+ })
3861
+ }), /* @__PURE__ */ jsxs(PopoverContent, {
3862
+ width: "sm",
3863
+ align: "start",
3864
+ className: "flex flex-col gap-1 p-3 text-xs",
3865
+ onOpenAutoFocus: (e) => e.preventDefault(),
3866
+ onInteractOutside: (e) => {
3867
+ if (triggerRef.current?.contains(e.target)) e.preventDefault();
3868
+ },
3869
+ onPointerEnter: cancelClose,
3870
+ onPointerLeave: scheduleClose,
3871
+ children: [
3872
+ activity ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("p", {
3873
+ className: "text-sm font-medium",
3874
+ children: [
3875
+ activity.type,
3876
+ " · ",
3877
+ whenText(activity.at, status)
3878
+ ]
3879
+ }), activity.with && /* @__PURE__ */ jsxs("p", { children: ["Com: ", activity.with] })] }) : null,
3880
+ card.assignee && /* @__PURE__ */ jsxs("p", { children: ["Responsável: ", card.assignee] }),
3881
+ /* @__PURE__ */ jsx("p", {
3882
+ className: "font-medium",
3883
+ children: situationText(status)
3884
+ })
3885
+ ]
3886
+ })]
3887
+ });
3888
+ }
3889
+ function CardBody({ card, show, withHandle }) {
3839
3890
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
3840
- card.tags && card.tags.length > 0 && /* @__PURE__ */ jsx("span", {
3891
+ show("tags") && card.tags && card.tags.length > 0 && /* @__PURE__ */ jsx("span", {
3841
3892
  className: "flex flex-wrap gap-1",
3842
3893
  children: card.tags.map((t) => /* @__PURE__ */ jsx(Badge, {
3843
3894
  tone: t.tone ?? "neutral",
@@ -3849,19 +3900,19 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
3849
3900
  children: [/* @__PURE__ */ jsx("span", {
3850
3901
  className: "line-clamp-2 text-sm font-medium",
3851
3902
  children: card.title
3852
- }), card.subtitle && /* @__PURE__ */ jsx("span", {
3903
+ }), show("document") && card.subtitle && /* @__PURE__ */ jsx("span", {
3853
3904
  className: "text-xs text-muted-foreground tabular-nums",
3854
3905
  children: card.subtitle
3855
3906
  })]
3856
3907
  }),
3857
- card.description && /* @__PURE__ */ jsx("span", {
3908
+ show("description") && card.description && /* @__PURE__ */ jsx("span", {
3858
3909
  className: "line-clamp-2 text-xs text-muted-foreground",
3859
3910
  children: card.description
3860
3911
  }),
3861
3912
  card.contact && /* @__PURE__ */ jsxs("span", {
3862
3913
  className: "flex flex-col gap-1 text-xs text-muted-foreground",
3863
3914
  children: [
3864
- card.contact.name && /* @__PURE__ */ jsxs("span", {
3915
+ show("contact") && card.contact.name && /* @__PURE__ */ jsxs("span", {
3865
3916
  className: "flex min-w-0 items-center gap-1 text-foreground",
3866
3917
  children: [/* @__PURE__ */ jsx(User, {
3867
3918
  className: "size-3 shrink-0",
@@ -3871,7 +3922,7 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
3871
3922
  children: card.contact.name
3872
3923
  })]
3873
3924
  }),
3874
- card.contact.phone && /* @__PURE__ */ jsxs("span", {
3925
+ show("phone") && card.contact.phone && /* @__PURE__ */ jsxs("span", {
3875
3926
  className: "flex min-w-0 items-center gap-1 tabular-nums",
3876
3927
  children: [/* @__PURE__ */ jsx(Phone, {
3877
3928
  className: "size-3 shrink-0",
@@ -3881,7 +3932,7 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
3881
3932
  children: card.contact.phone
3882
3933
  })]
3883
3934
  }),
3884
- card.contact.email && /* @__PURE__ */ jsxs("span", {
3935
+ show("email") && card.contact.email && /* @__PURE__ */ jsxs("span", {
3885
3936
  className: "flex min-w-0 items-center gap-1",
3886
3937
  children: [/* @__PURE__ */ jsx(Mail, {
3887
3938
  className: "size-3 shrink-0",
@@ -3892,50 +3943,96 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
3892
3943
  })]
3893
3944
  })
3894
3945
  ]
3895
- }),
3896
- shown.length > 0 && /* @__PURE__ */ jsx("span", {
3897
- className: "grid grid-cols-2 divide-x rounded-block bg-muted text-xs",
3898
- children: shown.map((f) => /* @__PURE__ */ jsxs("span", {
3899
- className: "flex min-w-0 flex-col px-2 py-1",
3900
- children: [/* @__PURE__ */ jsxs("span", {
3901
- className: "text-muted-foreground",
3902
- children: [f.label, ":"]
3903
- }), /* @__PURE__ */ jsx("span", {
3904
- className: "truncate font-semibold text-foreground tabular-nums",
3905
- children: formatValue(card.values?.[f.key] ?? 0)
3906
- })]
3907
- }, f.key))
3908
- }),
3909
- (card.assignee || card.dueDate || card.meta) && /* @__PURE__ */ jsxs("span", {
3910
- className: "flex items-center gap-2 border-t pt-2 text-xs text-muted-foreground",
3911
- children: [
3912
- card.dueDate && /* @__PURE__ */ jsxs("span", {
3913
- className: "inline-flex items-center gap-1 tabular-nums",
3914
- children: [/* @__PURE__ */ jsx(CalendarDays, {
3915
- className: "size-3",
3916
- "aria-hidden": true
3917
- }), format(card.dueDate, "dd/MM/yyyy")]
3918
- }),
3919
- card.meta && /* @__PURE__ */ jsx("span", {
3920
- className: "font-medium text-foreground tabular-nums",
3921
- children: card.meta
3922
- }),
3923
- card.assignee && /* @__PURE__ */ jsx("span", {
3924
- className: "ml-auto",
3925
- title: card.assignee,
3926
- children: /* @__PURE__ */ jsx(Avatar, {
3927
- name: card.assignee,
3928
- size: "sm"
3929
- })
3930
- })
3931
- ]
3932
3946
  })
3933
3947
  ] });
3934
3948
  }
3949
+ /**
3950
+ * Rodapé do card, fora do botão de clique: linha de calendário, meta e responsável e, depois
3951
+ * de uma divisória, os valores empilhados. Sem `renderCard` apenas.
3952
+ */
3953
+ function cardFooter({ card, status, show, valueFields, formatValue }) {
3954
+ const calendar = show("activity") ? status ? /* @__PURE__ */ jsx(ActivityHint, {
3955
+ card,
3956
+ status
3957
+ }) : card.dueDate && /* @__PURE__ */ jsxs("span", {
3958
+ className: "inline-flex items-center gap-1 tabular-nums",
3959
+ children: [/* @__PURE__ */ jsx(CalendarDays, {
3960
+ className: "size-3",
3961
+ "aria-hidden": true
3962
+ }), format(card.dueDate, "dd/MM/yyyy")]
3963
+ }) : null;
3964
+ const assignee = show("assignee") ? card.assignee : void 0;
3965
+ const values = valueFields.slice(0, 2).filter((f) => show(`value:${f.key}`));
3966
+ const hasRow = Boolean(calendar || assignee || card.meta);
3967
+ if (!hasRow && values.length === 0) return null;
3968
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [hasRow && /* @__PURE__ */ jsxs("span", {
3969
+ className: "flex items-center gap-2 border-t pt-2 text-xs text-muted-foreground",
3970
+ children: [
3971
+ calendar,
3972
+ card.meta && /* @__PURE__ */ jsx("span", {
3973
+ className: "font-medium text-foreground tabular-nums",
3974
+ children: card.meta
3975
+ }),
3976
+ assignee && /* @__PURE__ */ jsx("span", {
3977
+ className: "ml-auto",
3978
+ title: assignee,
3979
+ children: /* @__PURE__ */ jsx(Avatar, {
3980
+ name: assignee,
3981
+ size: "sm"
3982
+ })
3983
+ })
3984
+ ]
3985
+ }), values.length > 0 && /* @__PURE__ */ jsx("span", {
3986
+ className: "flex flex-col gap-1 border-t pt-2 text-xs",
3987
+ children: values.map((f) => /* @__PURE__ */ jsxs("span", {
3988
+ className: "flex items-baseline justify-between gap-2",
3989
+ children: [/* @__PURE__ */ jsxs("span", {
3990
+ className: "text-muted-foreground",
3991
+ children: [f.label, ":"]
3992
+ }), /* @__PURE__ */ jsx("span", {
3993
+ className: "truncate font-semibold text-foreground tabular-nums",
3994
+ children: formatValue(card.values?.[f.key] ?? 0)
3995
+ })]
3996
+ }, f.key))
3997
+ })] });
3998
+ }
3999
+ /** Sem acento e sem diferença de maiúscula, para a busca. */
4000
+ function normalize(text) {
4001
+ const marks = new RegExp(`[${String.fromCharCode(768)}-${String.fromCharCode(879)}]`, "g");
4002
+ return text.normalize("NFD").replace(marks, "").toLowerCase();
4003
+ }
4004
+ /**
4005
+ * Posição, na lista completa da coluna, de um índice da lista desenhada (que pode ser só uma
4006
+ * parte dela, por busca, filtro ou paginação). Fim da lista desenhada = logo depois do último
4007
+ * card desenhado; sem card desenhado = fim da lista completa.
4008
+ */
4009
+ function toFullIndex(full, drawn, drawnIndex) {
4010
+ if (drawn.length === 0) return full.length;
4011
+ if (drawnIndex < drawn.length) return full.indexOf(drawn[drawnIndex]);
4012
+ return full.indexOf(drawn[drawn.length - 1]) + 1;
4013
+ }
4014
+ var situationOptions = [
4015
+ {
4016
+ value: "critical",
4017
+ label: "Crítico"
4018
+ },
4019
+ {
4020
+ value: "cadenceOverdue",
4021
+ label: "Cadência vencida"
4022
+ },
4023
+ {
4024
+ value: "noActivity",
4025
+ label: "Sem atividade"
4026
+ },
4027
+ {
4028
+ value: "late",
4029
+ label: "Atividade atrasada"
4030
+ }
4031
+ ];
3935
4032
  function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard, valueFields, formatValue = (n) => n.toLocaleString("pt-BR", {
3936
4033
  style: "currency",
3937
4034
  currency: "BRL"
3938
- }), pageSize = 20, visibleColumns = 5, onLoadMore, hasMore, dropTargets, onDropTarget, className, ...aria }) {
4035
+ }), pageSize = 20, visibleColumns = 5, onLoadMore, hasMore, dropTargets, onDropTarget, referenceDate, toolbar, onNewCard, storageKey, className, ...aria }) {
3939
4036
  const code = resolveCatalogCode("Kanban", { hasDropTargets: Boolean(dropTargets?.length) });
3940
4037
  const { isMobile } = useBreakpoint();
3941
4038
  const motion = useMotionMode();
@@ -3960,18 +4057,66 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
3960
4057
  const [active, setActive] = useState(columns[0]?.id ?? "");
3961
4058
  const [dragging, setDragging] = useState(null);
3962
4059
  const [over, setOver] = useState(null);
4060
+ const [overTarget, setOverTarget] = useState(null);
3963
4061
  const [touchDrag, setTouchDrag] = useState(null);
4062
+ const [pendingDrop, setPendingDrop] = useState(null);
4063
+ const [reason, setReason] = useState("");
4064
+ const [query, setQuery] = useState("");
4065
+ const [assigneeFilter, setAssigneeFilter] = useState(null);
4066
+ const [situationFilter, setSituationFilter] = useState(null);
4067
+ const [customizing, setCustomizing] = useState(false);
4068
+ const [hidden, setHidden] = useState(() => readHidden(storageKey));
4069
+ const changeHidden = (next) => {
4070
+ setHidden(next);
4071
+ writeHidden(storageKey, next);
4072
+ };
4073
+ const show = (field) => !hidden[field];
4074
+ const today = referenceDate ?? /* @__PURE__ */ new Date();
4075
+ const statusEnabled = columns.some((c) => c.cadenceDays !== void 0) || cards.some((c) => c.activity);
4076
+ const statusOf = (card) => statusEnabled ? getKanbanCardStatus(card, columns.find((c) => c.id === card.columnId), today) : null;
4077
+ const filtering = toolbar && (query.trim() !== "" || assigneeFilter || situationFilter);
4078
+ const matches = (card) => {
4079
+ const q = normalize(query.trim());
4080
+ if (q && ![
4081
+ card.title,
4082
+ card.subtitle,
4083
+ card.contact?.name
4084
+ ].some((t) => t && normalize(t).includes(q))) return false;
4085
+ if (assigneeFilter && card.assignee !== assigneeFilter) return false;
4086
+ if (situationFilter) {
4087
+ const status = statusOf(card);
4088
+ if (!status) return false;
4089
+ if (situationFilter === "late" ? status.activity !== "late" : status.background !== situationFilter) return false;
4090
+ }
4091
+ return true;
4092
+ };
4093
+ const visibleCards = filtering ? cards.filter(matches) : cards;
4094
+ /** Lista completa da coluna: a única fonte do índice que sai em `onCardMove`. */
3964
4095
  const inColumn = (id) => cards.filter((c) => c.columnId === id);
4096
+ /** Lista visível (busca e filtros): cards desenhados, contagem, totais, paginação e abas. */
4097
+ const visibleInColumn = (id) => visibleCards.filter((c) => c.columnId === id);
3965
4098
  const drop = (columnId, index) => {
3966
- if (dragging) onCardMove?.(dragging, columnId, index);
4099
+ if (dragging) {
4100
+ const drawn = visibleInColumn(columnId).slice(0, limitOf(columnId));
4101
+ onCardMove?.(dragging, columnId, toFullIndex(inColumn(columnId), drawn, index));
4102
+ }
3967
4103
  setDragging(null);
3968
4104
  setOver(null);
4105
+ setOverTarget(null);
3969
4106
  };
3970
4107
  const draggingCardId = dragging ?? touchDrag?.cardId ?? null;
3971
4108
  const showTargetBar = Boolean(dropTargets?.length) && draggingCardId !== null;
3972
4109
  const dropOnTarget = (cardId, targetId) => {
3973
4110
  const target = dropTargets?.find((t) => t.id === targetId);
3974
4111
  if (!target || target.disabled) return;
4112
+ if (target.confirm) {
4113
+ setReason(target.confirm.reasons?.[0]?.value ?? "");
4114
+ setPendingDrop({
4115
+ cardId,
4116
+ targetId
4117
+ });
4118
+ return;
4119
+ }
3975
4120
  onDropTarget?.(cardId, targetId);
3976
4121
  };
3977
4122
  const startTouchDrag = (card, e) => {
@@ -4049,43 +4194,60 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
4049
4194
  ]
4050
4195
  })] });
4051
4196
  };
4052
- /** Barra de destinos, mostrada durante o arraste (mouse ou toque) quando há dropTargets. */
4197
+ /** Rodapé flutuante de destinos, mostrado durante o arraste (mouse ou toque). */
4198
+ const highlightedTarget = overTarget ?? touchDrag?.overTargetId ?? null;
4053
4199
  const targetBar = showTargetBar && /* @__PURE__ */ jsx("div", {
4054
4200
  "aria-label": "Soltar em",
4055
- className: "fixed inset-x-4 bottom-4 z-30 flex justify-center gap-2 overflow-x-auto rounded-surface border bg-card p-2 shadow-lg",
4056
- children: dropTargets.map((t) => /* @__PURE__ */ jsxs("div", {
4057
- "data-kanban-target": t.id,
4058
- onDragOver: (e) => {
4059
- if (dragging && !t.disabled) e.preventDefault();
4060
- },
4061
- onDrop: (e) => {
4062
- e.preventDefault();
4063
- if (dragging) {
4064
- dropOnTarget(dragging, t.id);
4065
- setDragging(null);
4066
- }
4067
- },
4068
- className: cn("flex min-w-24 flex-col items-center gap-1 rounded-block border p-2 text-center text-xs transition-colors", t.disabled ? "cursor-not-allowed opacity-50" : touchDrag?.overTargetId === t.id && "bg-primary-soft/60 ring-2 ring-ring"),
4069
- children: [
4070
- t.icon && /* @__PURE__ */ jsx("span", {
4071
- "aria-hidden": true,
4072
- className: targetIconTone[t.tone ?? "neutral"],
4073
- children: t.icon
4074
- }),
4075
- /* @__PURE__ */ jsx("span", {
4076
- className: "font-medium",
4077
- children: t.label
4078
- }),
4079
- t.hint && !t.disabled && /* @__PURE__ */ jsx("span", {
4080
- className: "text-muted-foreground",
4081
- children: t.hint
4082
- }),
4083
- t.disabled && t.disabledReason && /* @__PURE__ */ jsx("span", {
4084
- className: "text-muted-foreground",
4085
- children: t.disabledReason
4086
- })
4087
- ]
4088
- }, t.id))
4201
+ className: "fixed inset-x-4 bottom-4 z-30 grid grid-cols-2 gap-2 rounded-surface border bg-card p-2 shadow-lg md:flex md:justify-center md:overflow-x-auto",
4202
+ children: dropTargets.map((t) => {
4203
+ const tone = t.tone ?? "neutral";
4204
+ const highlighted = !t.disabled && highlightedTarget === t.id;
4205
+ return /* @__PURE__ */ jsxs("div", {
4206
+ "data-kanban-target": t.id,
4207
+ "data-over": highlighted ? "true" : void 0,
4208
+ onDragEnter: () => {
4209
+ if (dragging && !t.disabled) setOverTarget(t.id);
4210
+ },
4211
+ onDragOver: (e) => {
4212
+ if (dragging && !t.disabled) {
4213
+ e.preventDefault();
4214
+ setOverTarget(t.id);
4215
+ }
4216
+ },
4217
+ onDragLeave: (e) => {
4218
+ if (e.relatedTarget instanceof Node && e.currentTarget.contains(e.relatedTarget)) return;
4219
+ setOverTarget((id) => id === t.id ? null : id);
4220
+ },
4221
+ onDrop: (e) => {
4222
+ e.preventDefault();
4223
+ setOverTarget(null);
4224
+ if (dragging) {
4225
+ dropOnTarget(dragging, t.id);
4226
+ setDragging(null);
4227
+ }
4228
+ },
4229
+ className: cn("flex min-w-24 flex-col items-center gap-1 rounded-block border p-2 text-center text-xs transition-colors", t.disabled ? "cursor-not-allowed bg-muted opacity-50" : highlighted ? cn(targetStrong[tone], "ring-2 ring-ring") : targetSoft[tone]),
4230
+ children: [
4231
+ t.icon && /* @__PURE__ */ jsx("span", {
4232
+ "aria-hidden": true,
4233
+ className: highlighted ? void 0 : targetIconTone[tone],
4234
+ children: t.icon
4235
+ }),
4236
+ /* @__PURE__ */ jsx("span", {
4237
+ className: "font-medium",
4238
+ children: t.label
4239
+ }),
4240
+ t.hint && !t.disabled && /* @__PURE__ */ jsx("span", {
4241
+ className: highlighted ? void 0 : "text-muted-foreground",
4242
+ children: t.hint
4243
+ }),
4244
+ t.disabled && t.disabledReason && /* @__PURE__ */ jsx("span", {
4245
+ className: "text-muted-foreground",
4246
+ children: t.disabledReason
4247
+ })
4248
+ ]
4249
+ }, t.id);
4250
+ })
4089
4251
  });
4090
4252
  const canTouchDrag = Boolean(onCardMove) || Boolean(dropTargets?.length && onDropTarget);
4091
4253
  const showHandle = isMobile && canTouchDrag;
@@ -4099,7 +4261,10 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
4099
4261
  const dragEnd = () => {
4100
4262
  setDragging(null);
4101
4263
  setOver(null);
4264
+ setOverTarget(null);
4102
4265
  };
4266
+ const status = statusOf(card);
4267
+ const label = status && backgroundLabel(status);
4103
4268
  const common = {
4104
4269
  "data-kanban-card": card.id,
4105
4270
  draggable: !isMobile && Boolean(onCardMove),
@@ -4119,27 +4284,37 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
4119
4284
  e.stopPropagation();
4120
4285
  if (over) drop(over.column, over.index);
4121
4286
  },
4122
- className: cn("relative flex rounded-block border bg-card p-3 shadow-sm transition-[box-shadow,opacity]", !isMobile && onCardMove && "cursor-grab active:cursor-grabbing", (dragging === card.id || touchDrag?.cardId === card.id) && "opacity-50", over?.column === card.columnId && over.index === index && dragging !== card.id && "ring-2 ring-ring ring-offset-2 ring-offset-muted")
4287
+ className: cn("relative flex rounded-block border", status ? statusBackground[status.background] : "bg-card", "p-3 shadow-sm transition-[box-shadow,opacity]", !isMobile && onCardMove && "cursor-grab active:cursor-grabbing", (dragging === card.id || touchDrag?.cardId === card.id) && "opacity-50", over?.column === card.columnId && over.index === index && dragging !== card.id && "ring-2 ring-ring ring-offset-2 ring-offset-muted")
4123
4288
  };
4289
+ const content = renderCard ? renderCard(card) : /* @__PURE__ */ jsx(CardBody, {
4290
+ card,
4291
+ show,
4292
+ withHandle: showHandle
4293
+ });
4294
+ const footer = renderCard ? null : cardFooter({
4295
+ card,
4296
+ status,
4297
+ show,
4298
+ valueFields: valueFields ?? [],
4299
+ formatValue
4300
+ });
4301
+ const main = onCardClick ? /* @__PURE__ */ jsx("button", {
4302
+ type: "button",
4303
+ onClick: () => onCardClick(card),
4304
+ className: footer ? "flex min-w-0 cursor-pointer flex-col gap-2 rounded-block text-left outline-none after:absolute after:inset-0 focus-visible:ring-2 focus-visible:ring-ring" : "flex min-w-0 flex-1 cursor-pointer flex-col gap-2 rounded-block text-left outline-none after:absolute after:inset-0 focus-visible:ring-2 focus-visible:ring-ring",
4305
+ children: content
4306
+ }) : /* @__PURE__ */ jsx("div", {
4307
+ className: footer ? "flex min-w-0 flex-col gap-2" : "flex min-w-0 flex-1 flex-col gap-2",
4308
+ children: content
4309
+ });
4124
4310
  const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [
4125
- onCardClick ? /* @__PURE__ */ jsx("button", {
4126
- type: "button",
4127
- onClick: () => onCardClick(card),
4128
- className: "flex min-w-0 flex-1 cursor-pointer flex-col gap-2 rounded-block text-left outline-none after:absolute after:inset-0 focus-visible:ring-2 focus-visible:ring-ring",
4129
- children: renderCard ? renderCard(card) : /* @__PURE__ */ jsx(CardBody, {
4130
- card,
4131
- valueFields,
4132
- formatValue,
4133
- withHandle: showHandle
4134
- })
4135
- }) : /* @__PURE__ */ jsx("div", {
4311
+ footer ? /* @__PURE__ */ jsxs("div", {
4136
4312
  className: "flex min-w-0 flex-1 flex-col gap-2",
4137
- children: renderCard ? renderCard(card) : /* @__PURE__ */ jsx(CardBody, {
4138
- card,
4139
- valueFields,
4140
- formatValue,
4141
- withHandle: showHandle
4142
- })
4313
+ children: [main, footer]
4314
+ }) : main,
4315
+ label && /* @__PURE__ */ jsx("span", {
4316
+ className: "sr-only",
4317
+ children: label
4143
4318
  }),
4144
4319
  showHandle && /* @__PURE__ */ jsx("button", {
4145
4320
  type: "button",
@@ -4187,53 +4362,79 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
4187
4362
  children: body
4188
4363
  }, card.id);
4189
4364
  };
4190
- const totals = (col) => (valueFields ?? []).slice(0, 2).map((f) => ({
4191
- ...f,
4192
- total: inColumn(col.id).reduce((sum, c) => sum + (c.values?.[f.key] ?? 0), 0)
4193
- }));
4365
+ const totalFields = (valueFields ?? []).slice(0, 2);
4366
+ const sumOf = (list, key) => list.reduce((sum, c) => sum + (c.values?.[key] ?? 0), 0);
4367
+ const boardCards = visibleCards.filter((c) => columns.some((col) => col.id === c.columnId));
4368
+ const totals = (col) => totalFields.map((f) => {
4369
+ const total = sumOf(visibleInColumn(col.id), f.key);
4370
+ const board = sumOf(boardCards, f.key);
4371
+ return {
4372
+ ...f,
4373
+ total,
4374
+ percent: board === 0 ? 0 : Math.round(total / board * 100)
4375
+ };
4376
+ });
4194
4377
  const columnHeader = (col, count) => /* @__PURE__ */ jsxs("div", {
4195
4378
  className: "flex flex-col gap-2 px-1",
4196
- children: [/* @__PURE__ */ jsxs("div", {
4197
- className: "flex items-center gap-2",
4198
- children: [
4199
- /* @__PURE__ */ jsx("span", {
4200
- "aria-hidden": true,
4201
- className: cn("size-2 rounded-full", dotTone[col.tone ?? "neutral"])
4202
- }),
4203
- /* @__PURE__ */ jsx("h3", {
4204
- className: "min-w-0 flex-1 truncate text-sm font-semibold",
4205
- children: col.title
4206
- }),
4207
- /* @__PURE__ */ jsx(Badge, {
4208
- tone: col.limit && count > col.limit ? "warning" : "neutral",
4209
- children: col.limit ? `${count}/${col.limit}` : count
4210
- }),
4211
- onAddCard && /* @__PURE__ */ jsx(Button, {
4212
- variant: "ghost",
4213
- size: "sm",
4214
- iconOnly: true,
4215
- "aria-label": `Adicionar card em ${col.title}`,
4216
- onClick: () => onAddCard(col.id),
4217
- className: "-my-1 -mr-1 rounded-full",
4218
- children: /* @__PURE__ */ jsx(Plus, {})
4219
- })
4220
- ]
4221
- }), valueFields && valueFields.length > 0 && /* @__PURE__ */ jsx("div", {
4222
- className: "grid grid-cols-2 divide-x rounded-block bg-card text-xs",
4223
- children: totals(col).map((t) => /* @__PURE__ */ jsxs("span", {
4224
- className: "flex min-w-0 flex-col px-2 py-1",
4225
- children: [/* @__PURE__ */ jsxs("span", {
4226
- className: "text-muted-foreground",
4227
- children: ["Total ", t.label]
4228
- }), /* @__PURE__ */ jsx("span", {
4229
- className: "truncate font-semibold tabular-nums",
4230
- children: formatValue(t.total)
4231
- })]
4232
- }, t.key))
4233
- })]
4379
+ children: [
4380
+ /* @__PURE__ */ jsxs("div", {
4381
+ className: "flex items-center gap-2",
4382
+ children: [
4383
+ /* @__PURE__ */ jsx("span", {
4384
+ "aria-hidden": true,
4385
+ className: cn("size-2 rounded-full", dotTone[col.tone ?? "neutral"])
4386
+ }),
4387
+ /* @__PURE__ */ jsx("h3", {
4388
+ className: "min-w-0 flex-1 truncate text-sm font-semibold",
4389
+ children: col.title
4390
+ }),
4391
+ /* @__PURE__ */ jsx(Badge, {
4392
+ tone: col.limit && count > col.limit ? "warning" : "neutral",
4393
+ children: col.limit ? `${count}/${col.limit}` : count
4394
+ }),
4395
+ onAddCard && /* @__PURE__ */ jsx(Button, {
4396
+ variant: "ghost",
4397
+ size: "sm",
4398
+ iconOnly: true,
4399
+ "aria-label": `Adicionar card em ${col.title}`,
4400
+ onClick: () => onAddCard(col.id),
4401
+ className: "-my-1 -mr-1 rounded-full",
4402
+ children: /* @__PURE__ */ jsx(Plus, {})
4403
+ })
4404
+ ]
4405
+ }),
4406
+ col.cadenceDays !== void 0 && /* @__PURE__ */ jsxs("p", {
4407
+ className: "text-xs text-muted-foreground",
4408
+ children: ["Cadência: ", plural(col.cadenceDays, "dia", "dias")]
4409
+ }),
4410
+ valueFields && valueFields.length > 0 && /* @__PURE__ */ jsx("div", {
4411
+ className: "grid grid-cols-2 divide-x rounded-block bg-card text-xs",
4412
+ children: totals(col).map((t) => /* @__PURE__ */ jsxs("span", {
4413
+ className: "flex min-w-0 flex-col px-2 py-1",
4414
+ children: [
4415
+ /* @__PURE__ */ jsxs("span", {
4416
+ className: "text-muted-foreground",
4417
+ children: ["Total ", t.label]
4418
+ }),
4419
+ /* @__PURE__ */ jsx("span", {
4420
+ className: "truncate font-semibold tabular-nums",
4421
+ children: formatValue(t.total)
4422
+ }),
4423
+ /* @__PURE__ */ jsxs("span", {
4424
+ className: "text-muted-foreground tabular-nums",
4425
+ children: [
4426
+ "(",
4427
+ t.percent,
4428
+ "%)"
4429
+ ]
4430
+ })
4431
+ ]
4432
+ }, t.key))
4433
+ })
4434
+ ]
4234
4435
  });
4235
4436
  const columnList = (col) => {
4236
- const all = inColumn(col.id);
4437
+ const all = visibleInColumn(col.id);
4237
4438
  const list = all.slice(0, limitOf(col.id));
4238
4439
  const more = all.length > list.length || Boolean(hasMore?.(col.id));
4239
4440
  return /* @__PURE__ */ jsx("div", {
@@ -4271,32 +4472,213 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
4271
4472
  }, String(ready))
4272
4473
  });
4273
4474
  };
4274
- if (isMobile) return /* @__PURE__ */ jsxs("div", {
4275
- ref: boardRef,
4276
- className: cn("flex h-board min-w-0 flex-col gap-3", className),
4277
- "aria-label": aria["aria-label"],
4278
- "data-rendra": code,
4279
- children: [
4280
- targetBar,
4281
- /* @__PURE__ */ jsx(Tabs, {
4282
- variant: "pill",
4283
- "aria-label": "Colunas",
4284
- value: active,
4285
- onChange: setActive,
4286
- items: columns.map((col) => ({
4287
- value: col.id,
4288
- label: col.title,
4289
- count: inColumn(col.id).length,
4290
- content: null
4291
- }))
4292
- }),
4293
- columns.filter((col) => col.id === active).map((col) => /* @__PURE__ */ jsxs("div", {
4294
- className: "flex min-h-0 flex-1 flex-col gap-2 rounded-surface bg-muted p-2",
4295
- children: [columnHeader(col, inColumn(col.id).length), columnList(col)]
4296
- }, col.id))
4297
- ]
4475
+ const assignees = [...new Set(cards.map((c) => c.assignee).filter((a) => !!a))].sort((a, b) => a.localeCompare(b, "pt-BR"));
4476
+ const filterCount = (assigneeFilter ? 1 : 0) + (situationFilter ? 1 : 0);
4477
+ const hasFilters = assignees.length > 0 || statusEnabled;
4478
+ const toolbarNode = toolbar && /* @__PURE__ */ jsx(DataToolbar, {
4479
+ search: {
4480
+ value: query,
4481
+ onChange: setQuery,
4482
+ placeholder: "Buscar card"
4483
+ },
4484
+ filters: hasFilters ? /* @__PURE__ */ jsxs("div", {
4485
+ className: "flex flex-col gap-4",
4486
+ children: [assignees.length > 0 && /* @__PURE__ */ jsx(Field, {
4487
+ label: "Responsável",
4488
+ span: "full",
4489
+ children: /* @__PURE__ */ jsx(Select, {
4490
+ placeholder: "Todos",
4491
+ clearable: true,
4492
+ options: assignees.map((a) => ({
4493
+ value: a,
4494
+ label: a
4495
+ })),
4496
+ value: assigneeFilter,
4497
+ onChange: setAssigneeFilter
4498
+ })
4499
+ }), statusEnabled && /* @__PURE__ */ jsx(Field, {
4500
+ label: "Situação",
4501
+ span: "full",
4502
+ children: /* @__PURE__ */ jsx(Select, {
4503
+ placeholder: "Todas",
4504
+ clearable: true,
4505
+ options: situationOptions,
4506
+ value: situationFilter,
4507
+ onChange: setSituationFilter
4508
+ })
4509
+ })]
4510
+ }) : void 0,
4511
+ filterCount,
4512
+ onClearFilters: () => {
4513
+ setAssigneeFilter(null);
4514
+ setSituationFilter(null);
4515
+ },
4516
+ summary: totalFields.length > 0 ? totalFields.map((f) => /* @__PURE__ */ jsxs("span", {
4517
+ className: "flex items-baseline gap-1",
4518
+ children: [/* @__PURE__ */ jsxs("span", {
4519
+ className: "text-muted-foreground",
4520
+ children: [
4521
+ "Total ",
4522
+ f.label,
4523
+ ":"
4524
+ ]
4525
+ }), /* @__PURE__ */ jsx("span", {
4526
+ className: "font-semibold tabular-nums",
4527
+ children: formatValue(sumOf(boardCards, f.key))
4528
+ })]
4529
+ }, f.key)) : void 0,
4530
+ actions: /* @__PURE__ */ jsx(Button, {
4531
+ variant: "outline",
4532
+ icon: /* @__PURE__ */ jsx(Settings2, {}),
4533
+ onClick: () => setCustomizing(true),
4534
+ children: "Customizar"
4535
+ }),
4536
+ primaryAction: onNewCard ? /* @__PURE__ */ jsx(Button, {
4537
+ icon: /* @__PURE__ */ jsx(Plus, {}),
4538
+ onClick: () => onNewCard(),
4539
+ children: "Novo card"
4540
+ }) : void 0
4541
+ });
4542
+ const customizeFields = [...baseFields.map((f) => ({
4543
+ id: f.id,
4544
+ label: f.label
4545
+ })), ...totalFields.map((f) => ({
4546
+ id: `value:${f.key}`,
4547
+ label: f.label
4548
+ }))];
4549
+ const customizeDrawer = toolbar && /* @__PURE__ */ jsx(Drawer, {
4550
+ open: customizing,
4551
+ onOpenChange: setCustomizing,
4552
+ title: "Customizar",
4553
+ icon: /* @__PURE__ */ jsx(Settings2, {}),
4554
+ footer: /* @__PURE__ */ jsx(ActionBar, {
4555
+ cancel: {
4556
+ label: "Restaurar",
4557
+ onClick: () => changeHidden({})
4558
+ },
4559
+ primary: {
4560
+ label: "Pronto",
4561
+ onClick: () => setCustomizing(false)
4562
+ }
4563
+ }),
4564
+ children: /* @__PURE__ */ jsx("div", {
4565
+ className: "flex flex-col gap-1",
4566
+ children: customizeFields.map((f) => /* @__PURE__ */ jsx(Checkbox, {
4567
+ label: f.label,
4568
+ checked: show(f.id),
4569
+ onCheckedChange: (checked) => changeHidden({
4570
+ ...hidden,
4571
+ [f.id]: !checked
4572
+ })
4573
+ }, f.id))
4574
+ })
4298
4575
  });
4299
- return /* @__PURE__ */ jsxs("section", {
4576
+ const pendingTarget = pendingDrop && dropTargets?.find((t) => t.id === pendingDrop.targetId);
4577
+ const pendingCard = pendingDrop && cards.find((c) => c.id === pendingDrop.cardId);
4578
+ useEffect(() => {
4579
+ if (pendingDrop && !pendingCard) setPendingDrop(null);
4580
+ }, [pendingDrop, pendingCard]);
4581
+ const confirmation = pendingDrop && pendingTarget?.confirm && pendingCard ? /* @__PURE__ */ jsxs(Modal, {
4582
+ open: true,
4583
+ onOpenChange: (next) => !next && setPendingDrop(null),
4584
+ type: pendingTarget.confirm.destructive ? "destructive" : "confirm",
4585
+ title: pendingTarget.confirm.title,
4586
+ description: pendingTarget.confirm.description,
4587
+ confirmLabel: pendingTarget.confirm.confirmLabel ?? pendingTarget.label,
4588
+ onConfirm: () => onDropTarget?.(pendingDrop.cardId, pendingDrop.targetId, reason || void 0),
4589
+ children: [/* @__PURE__ */ jsxs("dl", {
4590
+ className: "flex w-full flex-col gap-1 rounded-block bg-muted p-3 text-left text-sm",
4591
+ children: [
4592
+ /* @__PURE__ */ jsxs("div", {
4593
+ className: "flex justify-between gap-2",
4594
+ children: [/* @__PURE__ */ jsx("dt", {
4595
+ className: "text-muted-foreground",
4596
+ children: "Empresa"
4597
+ }), /* @__PURE__ */ jsx("dd", {
4598
+ className: "font-medium",
4599
+ children: pendingCard.title
4600
+ })]
4601
+ }),
4602
+ pendingCard.subtitle && /* @__PURE__ */ jsxs("div", {
4603
+ className: "flex justify-between gap-2",
4604
+ children: [/* @__PURE__ */ jsx("dt", {
4605
+ className: "text-muted-foreground",
4606
+ children: "Documento"
4607
+ }), /* @__PURE__ */ jsx("dd", {
4608
+ className: "tabular-nums",
4609
+ children: pendingCard.subtitle
4610
+ })]
4611
+ }),
4612
+ /* @__PURE__ */ jsxs("div", {
4613
+ className: "flex justify-between gap-2",
4614
+ children: [/* @__PURE__ */ jsx("dt", {
4615
+ className: "text-muted-foreground",
4616
+ children: "Etapa"
4617
+ }), /* @__PURE__ */ jsx("dd", { children: columns.find((c) => c.id === pendingCard.columnId)?.title })]
4618
+ }),
4619
+ totalFields.map((f) => /* @__PURE__ */ jsxs("div", {
4620
+ className: "flex justify-between gap-2",
4621
+ children: [/* @__PURE__ */ jsxs("dt", {
4622
+ className: "text-muted-foreground",
4623
+ children: [f.label, ":"]
4624
+ }), /* @__PURE__ */ jsx("dd", {
4625
+ className: "font-semibold tabular-nums",
4626
+ children: formatValue(pendingCard.values?.[f.key] ?? 0)
4627
+ })]
4628
+ }, f.key))
4629
+ ]
4630
+ }), pendingTarget.confirm.reasons && /* @__PURE__ */ jsxs("div", {
4631
+ className: "flex w-full flex-col gap-1 text-left",
4632
+ children: [/* @__PURE__ */ jsx("span", {
4633
+ className: "text-sm font-medium",
4634
+ children: "Motivo"
4635
+ }), /* @__PURE__ */ jsx(Select, {
4636
+ label: "Motivo",
4637
+ options: pendingTarget.confirm.reasons,
4638
+ value: reason,
4639
+ onChange: (value) => setReason(value ?? "")
4640
+ })]
4641
+ })]
4642
+ }) : null;
4643
+ if (isMobile) {
4644
+ const board = /* @__PURE__ */ jsxs("div", {
4645
+ ref: boardRef,
4646
+ className: cn("flex h-board min-w-0 flex-col gap-3", className),
4647
+ "aria-label": aria["aria-label"],
4648
+ "data-rendra": code,
4649
+ children: [
4650
+ targetBar,
4651
+ /* @__PURE__ */ jsx(Tabs, {
4652
+ variant: "pill",
4653
+ "aria-label": "Colunas",
4654
+ value: active,
4655
+ onChange: setActive,
4656
+ items: columns.map((col) => ({
4657
+ value: col.id,
4658
+ label: col.title,
4659
+ count: visibleInColumn(col.id).length,
4660
+ content: null
4661
+ }))
4662
+ }),
4663
+ columns.filter((col) => col.id === active).map((col) => /* @__PURE__ */ jsxs("div", {
4664
+ className: "flex min-h-0 flex-1 flex-col gap-2 rounded-surface bg-muted p-2",
4665
+ children: [columnHeader(col, visibleInColumn(col.id).length), columnList(col)]
4666
+ }, col.id))
4667
+ ]
4668
+ });
4669
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
4670
+ toolbar ? /* @__PURE__ */ jsxs("div", {
4671
+ className: "flex min-w-0 flex-col gap-3",
4672
+ children: [/* @__PURE__ */ jsx("div", {
4673
+ className: "rounded-surface border bg-card",
4674
+ children: toolbarNode
4675
+ }), board]
4676
+ }) : board,
4677
+ customizeDrawer,
4678
+ confirmation
4679
+ ] });
4680
+ }
4681
+ const board = /* @__PURE__ */ jsxs("section", {
4300
4682
  ref: boardRef,
4301
4683
  "aria-label": aria["aria-label"] ?? "Quadro kanban",
4302
4684
  "data-rendra": code,
@@ -4307,10 +4689,21 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
4307
4689
  className: "flex min-h-0 w-kanban-col flex-col gap-2 rounded-surface bg-muted p-2",
4308
4690
  children: [/* @__PURE__ */ jsx("div", {
4309
4691
  className: "pt-1",
4310
- children: columnHeader(col, inColumn(col.id).length)
4692
+ children: columnHeader(col, visibleInColumn(col.id).length)
4311
4693
  }), columnList(col)]
4312
4694
  }, col.id))]
4313
4695
  });
4696
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
4697
+ toolbar ? /* @__PURE__ */ jsxs("div", {
4698
+ className: "flex min-w-0 flex-col gap-4",
4699
+ children: [/* @__PURE__ */ jsx("div", {
4700
+ className: "rounded-surface border bg-card",
4701
+ children: toolbarNode
4702
+ }), board]
4703
+ }) : board,
4704
+ customizeDrawer,
4705
+ confirmation
4706
+ ] });
4314
4707
  }
4315
4708
  /** Move um card na lista (para usar no onCardMove): devolve a lista nova. */
4316
4709
  function moveKanbanCard(cards, cardId, toColumnId, toIndex) {
@@ -5522,108 +5915,6 @@ function QrCode({ value, size = 160, errorCorrection = "medium", className, empt
5522
5915
  });
5523
5916
  }
5524
5917
  //#endregion
5525
- //#region src/components/ui/radio-group.tsx
5526
- var cols = {
5527
- 1: "",
5528
- 2: "md:grid-cols-2",
5529
- 3: "md:grid-cols-3"
5530
- };
5531
- /**
5532
- * O item do Radix. Em `on` ele é um `m.button` (asChild) que responde ao toque (whileTap 0,97,
5533
- * em `press`); em `off` é o `R.Item` de sempre, sem nó novo.
5534
- */
5535
- function Item({ children, ...props }) {
5536
- const presets = useMotionPresets();
5537
- const lib = useMotionLib();
5538
- if (!lib) return /* @__PURE__ */ jsx(RadioGroup$1.Item, {
5539
- ...props,
5540
- children
5541
- });
5542
- return /* @__PURE__ */ jsx(RadioGroup$1.Item, {
5543
- asChild: true,
5544
- ...props,
5545
- children: /* @__PURE__ */ jsx(lib.m.button, {
5546
- type: "button",
5547
- whileTap: presets.press.whileTap,
5548
- transition: presets.press.transition,
5549
- children
5550
- })
5551
- });
5552
- }
5553
- /** Radio único: em lista ou em cards, por prop. */
5554
- function RadioGroup({ options, value, defaultValue, onChange, variant = "list", columns = 2, orientation = "vertical", invalid, disabled, id, name, ...aria }) {
5555
- const lib = useMotionLib();
5556
- const on = lib !== null;
5557
- const presets = useMotionPresets();
5558
- const [inner, setInner] = useState(defaultValue);
5559
- const current = value ?? inner;
5560
- const dotFor = (optionValue) => /* @__PURE__ */ jsx("span", {
5561
- "aria-hidden": true,
5562
- className: cn("flex size-icon-md shrink-0 items-center justify-center rounded-full border border-input bg-card transition-colors group-data-[state=checked]:border-primary", invalid && "border-destructive"),
5563
- children: on ? /* @__PURE__ */ jsx(lib.m.span, {
5564
- className: "size-2 rounded-full bg-primary",
5565
- initial: false,
5566
- animate: current === optionValue ? presets.indicator.animate : presets.indicator.initial,
5567
- transition: presets.indicator.transition
5568
- }) : /* @__PURE__ */ jsx("span", { className: "size-2 scale-90 rounded-full bg-primary opacity-0 transition-[transform,opacity] duration-(--rendra-duration-fast) ease-out group-data-[state=checked]:scale-100 group-data-[state=checked]:opacity-100" })
5569
- });
5570
- return /* @__PURE__ */ jsx(RadioGroup$1.Root, {
5571
- id,
5572
- name,
5573
- value: on ? current : value,
5574
- defaultValue: on ? void 0 : defaultValue,
5575
- onValueChange: (v) => {
5576
- if (on) setInner(v);
5577
- onChange?.(v);
5578
- },
5579
- disabled,
5580
- "aria-invalid": invalid || void 0,
5581
- "aria-describedby": aria["aria-describedby"],
5582
- "aria-label": aria["aria-label"],
5583
- "data-rendra": resolveCatalogCode("RadioGroup", { variant }),
5584
- className: cn(variant === "cards" ? cn("grid grid-cols-1 gap-3", cols[columns]) : orientation === "horizontal" ? "flex flex-col sm:flex-row sm:flex-wrap sm:gap-x-6" : "flex flex-col"),
5585
- children: options.map((o) => variant === "cards" ? /* @__PURE__ */ jsxs(Item, {
5586
- value: o.value,
5587
- disabled: o.disabled,
5588
- className: cn("group relative flex cursor-pointer items-start gap-3 rounded-control border bg-card p-4 text-left transition-[border-color,box-shadow,background-color]", "hover:border-primary data-[state=checked]:border-primary data-[state=checked]:bg-primary-soft data-[state=checked]:ring-1 data-[state=checked]:ring-primary", "disabled:cursor-not-allowed disabled:opacity-50", invalid && "border-destructive"),
5589
- children: [
5590
- o.icon && /* @__PURE__ */ jsx("span", {
5591
- className: "flex size-control-sm shrink-0 items-center justify-center rounded-control bg-muted text-foreground transition-colors group-data-[state=checked]:bg-primary group-data-[state=checked]:text-primary-foreground md:size-control-md [&_svg]:size-icon-md",
5592
- children: o.icon
5593
- }),
5594
- /* @__PURE__ */ jsxs("span", {
5595
- className: "flex min-w-0 flex-1 flex-col gap-1",
5596
- children: [/* @__PURE__ */ jsx("span", {
5597
- className: "text-sm font-semibold",
5598
- children: o.label
5599
- }), o.description && /* @__PURE__ */ jsx("span", {
5600
- className: "text-sm text-muted-foreground",
5601
- children: o.description
5602
- })]
5603
- }),
5604
- dotFor(o.value)
5605
- ]
5606
- }, o.value) : /* @__PURE__ */ jsxs("label", {
5607
- className: cn("flex min-h-touch cursor-pointer items-start gap-3 py-3 md:min-h-0 md:py-1", o.disabled && "cursor-not-allowed opacity-60"),
5608
- children: [/* @__PURE__ */ jsx(Item, {
5609
- value: o.value,
5610
- disabled: o.disabled,
5611
- className: "group flex pt-px outline-none focus-visible:[&>span]:focus-ring",
5612
- children: dotFor(o.value)
5613
- }), /* @__PURE__ */ jsxs("span", {
5614
- className: "flex min-w-0 flex-col gap-1",
5615
- children: [/* @__PURE__ */ jsx("span", {
5616
- className: "text-sm font-medium",
5617
- children: o.label
5618
- }), o.description && /* @__PURE__ */ jsx("span", {
5619
- className: "text-sm text-muted-foreground",
5620
- children: o.description
5621
- })]
5622
- })]
5623
- }, o.value))
5624
- });
5625
- }
5626
- //#endregion
5627
5918
  //#region src/components/ui/rating.tsx
5628
5919
  function toneClass(ratio) {
5629
5920
  if (ratio <= 1 / 3) return "data-[state=checked]:border-destructive data-[state=checked]:bg-destructive-soft data-[state=checked]:text-destructive-soft-foreground";
@@ -6676,103 +6967,6 @@ function Table({ data: dataProp, source, queryKey = "", columns: columnsProp, st
6676
6967
  });
6677
6968
  }
6678
6969
  //#endregion
6679
- //#region src/components/ui/textarea.tsx
6680
- /** Textarea único, com contador opcional. Cresce com o conteúdo até a altura máxima e depois rola por dentro. */
6681
- var Textarea = forwardRef(function Textarea({ invalid, counter, value, defaultValue, onChange, maxLength, rows = 4, className, ...props }, ref) {
6682
- const [inner, setInner] = useState(String(value ?? defaultValue ?? ""));
6683
- const current = value ?? inner;
6684
- return /* @__PURE__ */ jsxs("div", {
6685
- className: cn("flex min-w-0 flex-col gap-1", className),
6686
- children: [/* @__PURE__ */ jsx("textarea", {
6687
- ref,
6688
- rows,
6689
- maxLength,
6690
- value: current,
6691
- "data-rendra": "TXT-001",
6692
- "aria-invalid": invalid || void 0,
6693
- onChange: (e) => {
6694
- setInner(e.target.value);
6695
- onChange?.(e.target.value);
6696
- },
6697
- className: cn("field-sizing-content max-h-chart-md min-h-24 w-full resize-y rounded-control border border-input bg-field px-3 py-2 text-base transition-[border-color,box-shadow] outline-none placeholder:text-muted-foreground hover:border-foreground/40 focus:border-ring focus:bg-card focus:ring-2 focus:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-60 md:text-sm", invalid && "border-destructive focus:border-destructive focus:ring-destructive/25"),
6698
- ...props
6699
- }), counter && /* @__PURE__ */ jsxs("span", {
6700
- "aria-live": "polite",
6701
- className: cn("self-end text-xs text-muted-foreground tabular-nums", maxLength && current.length >= maxLength && "font-medium text-destructive"),
6702
- children: [current.length, maxLength ? `/${maxLength}` : ""]
6703
- })]
6704
- });
6705
- });
6706
- //#endregion
6707
- //#region src/components/ui/toast.tsx
6708
- var tone = {
6709
- success: "border-success/25",
6710
- error: "border-destructive/25",
6711
- warning: "border-warning/25",
6712
- info: "border-info/25"
6713
- };
6714
- function show(type, title, opts = {}) {
6715
- return toast$1.custom((id) => /* @__PURE__ */ jsxs("div", {
6716
- role: type === "error" ? "alert" : "status",
6717
- "data-rendra": "TST-001",
6718
- className: cn("flex w-full items-start gap-3 rounded-control border bg-popover p-4 text-popover-foreground shadow-lg", tone[type]),
6719
- children: [
6720
- /* @__PURE__ */ jsx(BrandFeedbackIcon, {
6721
- type,
6722
- size: "lg",
6723
- animated: true,
6724
- className: "mt-px"
6725
- }),
6726
- /* @__PURE__ */ jsxs("div", {
6727
- className: "flex min-w-0 flex-1 flex-col gap-1",
6728
- children: [/* @__PURE__ */ jsx("p", {
6729
- className: "text-sm font-semibold wrap-break-word",
6730
- children: title
6731
- }), opts.description && /* @__PURE__ */ jsx("p", {
6732
- className: "text-sm wrap-break-word text-muted-foreground",
6733
- children: opts.description
6734
- })]
6735
- }),
6736
- opts.action && /* @__PURE__ */ jsx("button", {
6737
- type: "button",
6738
- onClick: () => {
6739
- opts.action?.onClick();
6740
- toast$1.dismiss(id);
6741
- },
6742
- className: "-my-1 flex min-h-touch shrink-0 cursor-pointer items-center rounded-item px-2 text-sm font-semibold text-primary-text hover:bg-accent md:min-h-0 md:py-1",
6743
- children: opts.action.label
6744
- })
6745
- ]
6746
- }), { duration: opts.duration ?? (type === "error" ? 8e3 : 4e3) });
6747
- }
6748
- var toast = {
6749
- success: (title, opts) => show("success", title, opts),
6750
- error: (title, opts) => show("error", title, opts),
6751
- warning: (title, opts) => show("warning", title, opts),
6752
- info: (title, opts) => show("info", title, opts),
6753
- dismiss: toast$1.dismiss
6754
- };
6755
- /** Posição: embaixo no centro no mobile (perto do polegar), canto inferior direito no desktop. */
6756
- function Toaster() {
6757
- const { isMobile } = useBreakpoint();
6758
- const { resolvedMode } = useBrand();
6759
- return /* @__PURE__ */ jsx(Toaster$1, {
6760
- position: isMobile ? "bottom-center" : "bottom-right",
6761
- theme: resolvedMode,
6762
- offset: 16,
6763
- mobileOffset: {
6764
- bottom: 88,
6765
- left: 16,
6766
- right: 16
6767
- },
6768
- visibleToasts: 3,
6769
- toastOptions: {
6770
- unstyled: true,
6771
- className: "w-full"
6772
- }
6773
- });
6774
- }
6775
- //#endregion
6776
6970
  //#region src/components/ui/upload.tsx
6777
6971
  var formatSize = (b) => b < 1048576 ? `${Math.max(1, Math.round(b / 1024))} KB` : `${(b / 1024 / 1024).toLocaleString("pt-BR", { maximumFractionDigits: 1 })} MB`;
6778
6972
  function kindOf(file) {
@@ -9557,6 +9751,6 @@ function createTheme(input) {
9557
9751
  };
9558
9752
  }
9559
9753
  //#endregion
9560
- export { Accordion, ActionBar, Alert, AppShell, Avatar, AvatarGroup, Badge, BrandFeedbackIcon, BrandLogo, BrandProvider, Breadcrumb, Button, ButtonGroup, CATALOG, CATALOG_EXCLUDED_FILES, COMPONENT_CODE_PATTERN, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChannelBadge, ChatComposer, ChatThread, Checkbox, CheckboxGroup, Checklist, ColorPicker, Container, ConversationList, DEFAULT_DDI, DataToolbar, DatePicker, Drawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorPage, Field, Form, FormField, FormSection, Grid, ImageCropper, ImageViewer, InfoHint, Inline, Input, Kanban, Label, List, Modal, OtpInput, PageHeader, Pagination, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QR_MAX_VERSION, QrCode, QrEncodingError, RENDRA_CREDIT_HREF, RENDRA_CREDIT_TEXT, RadioGroup, Rating, RendraCredit, RendraProvider, RepeatableField, Section, Select, Separator, Skeleton, Slider, Spinner, Stack, StatCard, Stepper, Switch, TABLE_PAGE_SIZE, TOKEN_KEYS, Table, Tabs, Textarea, Timeline, Toaster, Tooltip, TooltipProvider, Upload, Wizard, applyPalette, applyTheme, assertCatalogIntegrity, bindPointerDrag, breakpoints, buildDataCodewords, buttonVariants, catalogByComponent, chatChannels, cn, computeCropGeometry, computeFormatBits, computeMaskPenalty, computeVersionBits, contrast, contrastRatio, controlAdornmentButton, controlAdornmentSpace, controlFrame, controlInput, createPalette, createTheme, defaultShellLayout, encodeQrMatrix, feedbackLabels, filesMissingCatalogEntry, findComponentsWithMultipleDefaults, findComponentsWithoutDefault, findDragTarget, findDuplicateCodes, findInvalidFormatCodes, findPresetCollisions, formatCents, formatCurrency, getCatalogEntry, getReducedMotion, internationalPhoneMask, isValidCnpj, isValidCpf, isValidDateBR, layoutOptions, lookupCep, lookupCnpj, masks, moveKanbanCard, parseLocaleNumber, percentMask, phoneCountries, qrMatrixToSvgPath, readCodewordsForTest, readVar, reedSolomonComputeDivisor, reedSolomonComputeRemainder, reedSolomonEncode, reedSolomonMultiply, resolveCatalogCode, resolveDropIndex, shapeLabels, subscribeReducedMotion, toCents, toE164, toast, useBrand, useBreakpoint, useCurrentPath, useDebouncedValue, useFieldControl, useFillHeight, useLookup, usePrefersReducedMotion, useRendraBreadcrumbs, useRendraLink, useRendraNavigate, useSortable, zBR };
9754
+ export { Accordion, ActionBar, Alert, AppShell, Avatar, AvatarGroup, Badge, BrandFeedbackIcon, BrandLogo, BrandProvider, Breadcrumb, Button, ButtonGroup, CATALOG, CATALOG_EXCLUDED_FILES, COMPONENT_CODE_PATTERN, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChannelBadge, ChatComposer, ChatThread, Checkbox, CheckboxGroup, Checklist, ColorPicker, Container, ConversationList, DEFAULT_DDI, DataToolbar, DatePicker, Drawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorPage, Field, Form, FormField, FormSection, Grid, ImageCropper, ImageViewer, InfoHint, Inline, Input, Kanban, Label, List, Modal, OtpInput, PageHeader, Pagination, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QR_MAX_VERSION, QrCode, QrEncodingError, RENDRA_CREDIT_HREF, RENDRA_CREDIT_TEXT, RadioGroup, Rating, RendraCredit, RendraProvider, RepeatableField, Section, Select, Separator, Skeleton, Slider, Spinner, Stack, StatCard, Stepper, Switch, TABLE_PAGE_SIZE, TOKEN_KEYS, Table, Tabs, Textarea, Timeline, Toaster, Tooltip, TooltipProvider, Upload, Wizard, applyPalette, applyTheme, assertCatalogIntegrity, bindPointerDrag, breakpoints, buildDataCodewords, buttonVariants, catalogByComponent, chatChannels, cn, computeCropGeometry, computeFormatBits, computeMaskPenalty, computeVersionBits, contrast, contrastRatio, controlAdornmentButton, controlAdornmentSpace, controlFrame, controlInput, createPalette, createTheme, defaultShellLayout, encodeQrMatrix, feedbackLabels, filesMissingCatalogEntry, findComponentsWithMultipleDefaults, findComponentsWithoutDefault, findDragTarget, findDuplicateCodes, findInvalidFormatCodes, findPresetCollisions, formatCents, formatCurrency, getCatalogEntry, getKanbanCardStatus, getReducedMotion, internationalPhoneMask, isValidCnpj, isValidCpf, isValidDateBR, layoutOptions, lookupCep, lookupCnpj, masks, moveKanbanCard, parseLocaleNumber, percentMask, phoneCountries, qrMatrixToSvgPath, readCodewordsForTest, readVar, reedSolomonComputeDivisor, reedSolomonComputeRemainder, reedSolomonEncode, reedSolomonMultiply, resolveCatalogCode, resolveDropIndex, shapeLabels, subscribeReducedMotion, toCents, toE164, toast, useBrand, useBreakpoint, useCurrentPath, useDebouncedValue, useFieldControl, useFillHeight, useLookup, usePrefersReducedMotion, useRendraBreadcrumbs, useRendraLink, useRendraNavigate, useSortable, zBR };
9561
9755
 
9562
9756
  //# sourceMappingURL=index.js.map