@rendra-ui/web 2.3.0 → 2.5.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 (85) hide show
  1. package/README.md +107 -61
  2. package/bin/rendra.mjs +19 -7
  3. package/dist/base.css +33 -1
  4. package/dist/{button-DWhICtIG.js → button-BzJgR2gH.js} +86 -21
  5. package/dist/button-BzJgR2gH.js.map +1 -0
  6. package/dist/chart.js +61 -15
  7. package/dist/chart.js.map +1 -1
  8. package/dist/cli/auditar.js +66 -16
  9. package/dist/cli/auditar.js.map +1 -1
  10. package/dist/cli/codigos.js +2 -2
  11. package/dist/cli/executar-auditar.js +634 -0
  12. package/dist/cli/executar-auditar.js.map +1 -0
  13. package/dist/cli/help.js +7 -2
  14. package/dist/cli/help.js.map +1 -1
  15. package/dist/cli/trocar.js +2 -2
  16. package/dist/cli/typescript-loader.js +1 -1
  17. package/dist/{cn-DDZQKUVV.js → cn-Cw7M5kEP.js} +2 -2
  18. package/dist/{cn-DDZQKUVV.js.map → cn-Cw7M5kEP.js.map} +1 -1
  19. package/dist/{components-Cq_PmN4y.js → components-DkpspH9h.js} +21 -4
  20. package/dist/components-DkpspH9h.js.map +1 -0
  21. package/dist/components.css +274 -32
  22. package/dist/document-viewer.js +6 -6
  23. package/dist/document-viewer.js.map +1 -1
  24. package/dist/{empty-state-C491qfzf.js → empty-state-Cdb1vkMT.js} +81 -37
  25. package/dist/empty-state-Cdb1vkMT.js.map +1 -0
  26. package/dist/features-max--5VEt6M7.js +3 -0
  27. package/dist/index.js +1170 -390
  28. package/dist/index.js.map +1 -1
  29. package/dist/motion-context-5BRIQAJm.js +107 -0
  30. package/dist/motion-context-5BRIQAJm.js.map +1 -0
  31. package/dist/{rendra-provider-BRtk5Qa1.js → rendra-provider-CRe0XdOU.js} +9 -5
  32. package/dist/rendra-provider-CRe0XdOU.js.map +1 -0
  33. package/dist/rich-text-editor.js +4 -4
  34. package/dist/router-bridge.js +5 -4
  35. package/dist/router-bridge.js.map +1 -1
  36. package/dist/tokens.css +73 -15
  37. package/dist/tooltip-BAMSaGbS.js +224 -0
  38. package/dist/tooltip-BAMSaGbS.js.map +1 -0
  39. package/dist/types/components/app-shell/app-shell.d.ts +22 -2
  40. package/dist/types/components/app-shell/shell-context.d.ts +7 -1
  41. package/dist/types/components/app-shell/types.d.ts +23 -0
  42. package/dist/types/components/layout/page-header.d.ts +17 -1
  43. package/dist/types/components/rendra-provider.d.ts +7 -1
  44. package/dist/types/components/rendra-router-bridge.d.ts +3 -1
  45. package/dist/types/components/ui/accordion.d.ts +1 -1
  46. package/dist/types/components/ui/badge.d.ts +1 -1
  47. package/dist/types/components/ui/brand-feedback-icon.d.ts +20 -3
  48. package/dist/types/components/ui/button-group.d.ts +8 -1
  49. package/dist/types/components/ui/button.d.ts +1 -1
  50. package/dist/types/components/ui/dropdown-menu.d.ts +5 -5
  51. package/dist/types/components/ui/empty-state.d.ts +4 -0
  52. package/dist/types/components/ui/error-page.d.ts +6 -1
  53. package/dist/types/components/ui/modal.d.ts +4 -0
  54. package/dist/types/components/ui/picker-panel.d.ts +1 -1
  55. package/dist/types/components/ui/popover.d.ts +3 -3
  56. package/dist/types/components/ui/radio-group.d.ts +1 -1
  57. package/dist/types/components/ui/skeleton.d.ts +5 -1
  58. package/dist/types/components/ui/stat-card.d.ts +1 -1
  59. package/dist/types/components/ui/table.d.ts +0 -6
  60. package/dist/types/components/ui/tooltip.d.ts +1 -1
  61. package/dist/types/components/ui/wizard.d.ts +14 -1
  62. package/dist/types/hooks/use-reduced-motion.d.ts +3 -0
  63. package/dist/types/index.d.ts +1 -0
  64. package/dist/types/lib/initials.d.ts +2 -0
  65. package/dist/types/lib/motion/count.d.ts +17 -0
  66. package/dist/types/lib/motion/features-max.d.ts +1 -0
  67. package/dist/types/lib/motion/index.d.ts +5 -0
  68. package/dist/types/lib/motion/motion-context.d.ts +43 -0
  69. package/dist/types/lib/motion/native-events.d.ts +16 -0
  70. package/dist/types/lib/motion/presets.d.ts +92 -0
  71. package/dist/types/lib/motion/reorder.d.ts +7 -0
  72. package/dist/types/lib/motion/tokens.d.ts +66 -0
  73. package/dist/types/lib/motion/use-motion-presets.d.ts +8 -0
  74. package/dist/{use-breakpoint-C3ivDt2R.js → use-breakpoint-O9eqFmsF.js} +2 -2
  75. package/dist/{use-breakpoint-C3ivDt2R.js.map → use-breakpoint-O9eqFmsF.js.map} +1 -1
  76. package/dist/use-motion-presets-BrkgL8lG.js +401 -0
  77. package/dist/use-motion-presets-BrkgL8lG.js.map +1 -0
  78. package/dist/widget-grid.js +3 -3
  79. package/package.json +4 -1
  80. package/dist/button-DWhICtIG.js.map +0 -1
  81. package/dist/components-Cq_PmN4y.js.map +0 -1
  82. package/dist/empty-state-C491qfzf.js.map +0 -1
  83. package/dist/rendra-provider-BRtk5Qa1.js.map +0 -1
  84. package/dist/tooltip-DsNlnBSY.js +0 -105
  85. package/dist/tooltip-DsNlnBSY.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,15 +1,18 @@
1
- /*! Rendra Design System v2.3.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
- import { t as cn } from "./cn-DDZQKUVV.js";
3
- 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-Cq_PmN4y.js";
4
- import { i as usePrefersReducedMotion, n as buttonVariants, r as Spinner, t as Button } from "./button-DWhICtIG.js";
5
- import { a as DropdownMenuContent, c as DropdownMenuLabel, d as DropdownMenuSeparator, f as DropdownMenuSub, h as DropdownMenuTrigger, i as DropdownMenuCheckboxItem, l as DropdownMenuRadioGroup, m as DropdownMenuSubTrigger, n as TooltipProvider, o as DropdownMenuGroup, p as DropdownMenuSubContent, r as DropdownMenu, s as DropdownMenuItem, t as Tooltip, u as DropdownMenuRadioItem } from "./tooltip-DsNlnBSY.js";
6
- import { a as BrandContext, i as useBrand, n as BrandFeedbackIcon, r as feedbackLabels, t as EmptyState } from "./empty-state-C491qfzf.js";
7
- import { a as useRendraNavigate, i as useRendraLink, n as useCurrentPath, r as useRendraBreadcrumbs, t as RendraProvider } from "./rendra-provider-BRtk5Qa1.js";
8
- import { n as useBreakpoint, t as breakpoints } from "./use-breakpoint-C3ivDt2R.js";
1
+ /*! Rendra Design System v2.5.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
+ import { t as cn } from "./cn-Cw7M5kEP.js";
3
+ import { a as getReducedMotion, n as useLayoutReady, o as subscribeReducedMotion, r as useMotionMode, s as usePrefersReducedMotion } from "./motion-context-5BRIQAJm.js";
4
+ import { t as useMotionPresets } from "./use-motion-presets-BrkgL8lG.js";
5
+ 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-DkpspH9h.js";
6
+ import { n as buttonVariants, r as Spinner, t as Button } from "./button-BzJgR2gH.js";
7
+ import { a as DropdownMenuContent, c as DropdownMenuLabel, d as DropdownMenuSeparator, f as DropdownMenuSub, h as DropdownMenuTrigger, i as DropdownMenuCheckboxItem, l as DropdownMenuRadioGroup, m as DropdownMenuSubTrigger, n as TooltipProvider, o as DropdownMenuGroup, p as DropdownMenuSubContent, r as DropdownMenu, s as DropdownMenuItem, t as Tooltip, u as DropdownMenuRadioItem } from "./tooltip-BAMSaGbS.js";
8
+ import { a as BrandContext, i as useBrand, n as BrandFeedbackIcon, r as feedbackLabels, t as EmptyState } from "./empty-state-Cdb1vkMT.js";
9
+ import { a as useRendraNavigate, i as useRendraLink, n as useCurrentPath, r as useRendraBreadcrumbs, t as RendraProvider } from "./rendra-provider-CRe0XdOU.js";
10
+ import { n as useBreakpoint, t as breakpoints } from "./use-breakpoint-O9eqFmsF.js";
9
11
  import { ArrowDown, ArrowDownRight, ArrowLeft, ArrowRight, ArrowRightLeft, ArrowUp, ArrowUpRight, Bell, Bot, CalendarDays, Check, CheckCheck, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Clock, Columns3, Download, EllipsisVertical, Eye, EyeOff, FileText, Film, Filter, Globe, GripVertical, Home, ImageIcon, ImagePlus, Info, LayoutTemplate, LogOut, Mail, MapPin, Menu, MessageCircle, MessagesSquare, Mic, Minus, Monitor, Moon, MoreHorizontal, Palette, PanelLeft, Paperclip, Pause, Pencil, Phone, Play, Plus, Reply, RotateCw, Search, Send, SkipForward, Smartphone, Smile, Star, Sun, Trash2, TriangleAlert, UploadCloud, User, VideoIcon, X, XCircle, Zap } from "lucide-react";
12
+ import { AnimatePresence, animate, m, useDragControls, useMotionValue, useTransform } from "motion/react";
10
13
  import { Accordion as Accordion$1, Avatar as Avatar$1, Checkbox as Checkbox$1, Collapsible, ContextMenu, Dialog, Label as Label$1, 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";
11
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
- import { Fragment as Fragment$1, cloneElement, createContext, forwardRef, isValidElement, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
14
+ import { Fragment, cloneElement, createContext, forwardRef, isValidElement, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
15
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
13
16
  import { createPortal } from "react-dom";
14
17
  import { cva } from "class-variance-authority";
15
18
  import { addDays, addMonths, addWeeks, differenceInMinutes, endOfMonth, endOfWeek, format, isSameDay, isSameMonth, isToday, isYesterday, startOfDay, startOfMonth, startOfWeek } from "date-fns";
@@ -22,9 +25,119 @@ import { Command } from "cmdk";
22
25
  import { columnFilteringFeature, columnVisibilityFeature, createExpandedRowModel, createFilteredRowModel, createPaginatedRowModel, createSortedRowModel, filterFn_includesString, globalFilteringFeature, rowExpandingFeature, rowPaginationFeature, rowSelectionFeature, rowSortingFeature, sortFn_alphanumeric, sortFn_basic, tableFeatures, useTable } from "@tanstack/react-table";
23
26
  import { Toaster as Toaster$1, toast as toast$1 } from "sonner";
24
27
  import { z } from "zod";
28
+ //#region src/lib/motion/reorder.ts
29
+ function layoutEnabled({ mode, ready, dragging }) {
30
+ return mode === "on" && ready && !dragging;
31
+ }
32
+ //#endregion
33
+ //#region src/lib/motion/count.ts
34
+ var PT_BR = /^([^\d-]*)(-?)(\d{1,3}(?:\.\d{3})+|\d+)(?:,(\d+))?([^\d]*)$/;
35
+ function parseLocaleNumber$1(value) {
36
+ if (typeof value === "number") {
37
+ if (!Number.isFinite(value)) return null;
38
+ const text = String(Math.abs(value));
39
+ if (/e/i.test(text)) return null;
40
+ const decimals = text.includes(".") ? text.split(".")[1].length : 0;
41
+ return {
42
+ prefix: value < 0 ? "-" : "",
43
+ suffix: "",
44
+ value: Math.abs(value),
45
+ decimals,
46
+ grouping: false,
47
+ decimalSeparator: "."
48
+ };
49
+ }
50
+ if (typeof value !== "string") return null;
51
+ const match = PT_BR.exec(value);
52
+ if (!match) return null;
53
+ const [, prefix = "", sign = "", integer = "", fraction = "", suffix = ""] = match;
54
+ const grouping = integer.includes(".");
55
+ const n = Number(`${integer.replace(/\./g, "")}${fraction ? `.${fraction}` : ""}`);
56
+ if (!Number.isFinite(n)) return null;
57
+ return {
58
+ prefix: `${prefix}${sign}`,
59
+ suffix,
60
+ value: n,
61
+ decimals: fraction.length,
62
+ grouping,
63
+ decimalSeparator: ","
64
+ };
65
+ }
66
+ /** Escreve `n` com o mesmo formato do valor original. */
67
+ function formatLike(parsed, n) {
68
+ const [int = "0", frac = ""] = Math.abs(n).toFixed(parsed.decimals).split(".");
69
+ const grouped = parsed.grouping ? int.replace(/\B(?=(\d{3})+(?!\d))/g, ".") : int;
70
+ const number = frac ? `${grouped}${parsed.decimalSeparator}${frac}` : grouped;
71
+ return `${parsed.prefix}${number}${parsed.suffix}`;
72
+ }
73
+ //#endregion
25
74
  //#region src/components/ui/accordion.tsx
26
75
  /** Accordion único, com animação de altura e área de toque de 44px no mobile. */
27
76
  function Accordion({ items, multiple, defaultValue, className }) {
77
+ const motion = useMotionMode();
78
+ const presets = useMotionPresets();
79
+ const [open, setOpen] = useState(multiple ? defaultValue ?? [] : defaultValue?.[0] ? [defaultValue[0]] : []);
80
+ if (motion === "on") {
81
+ const rootProps = multiple ? {
82
+ type: "multiple",
83
+ value: open,
84
+ onValueChange: setOpen
85
+ } : {
86
+ type: "single",
87
+ collapsible: true,
88
+ value: open[0] ?? "",
89
+ onValueChange: (v) => setOpen(v ? [v] : [])
90
+ };
91
+ return /* @__PURE__ */ jsx(Accordion$1.Root, {
92
+ ...rootProps,
93
+ "data-rendra": "ACRN-001",
94
+ className: cn("flex flex-col", className),
95
+ children: items.map((it) => {
96
+ const isOpen = open.includes(it.value);
97
+ return /* @__PURE__ */ jsxs(Accordion$1.Item, {
98
+ value: it.value,
99
+ disabled: it.disabled,
100
+ className: "border-b last:border-b-0",
101
+ children: [/* @__PURE__ */ jsx(Accordion$1.Header, { children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
102
+ className: "group flex min-h-touch w-full cursor-pointer items-center justify-between gap-4 py-4 text-left text-sm font-medium transition-colors hover:text-primary-text disabled:cursor-not-allowed disabled:opacity-50 md:min-h-0",
103
+ children: [it.title, /* @__PURE__ */ jsx(m.span, {
104
+ "aria-hidden": true,
105
+ className: "flex shrink-0",
106
+ animate: { rotate: isOpen ? 180 : 0 },
107
+ transition: presets.fade.transition,
108
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-icon-sm text-muted-foreground" })
109
+ })]
110
+ }) }), /* @__PURE__ */ jsx(AnimatePresence, {
111
+ initial: false,
112
+ children: isOpen && /* @__PURE__ */ jsx(Accordion$1.Content, {
113
+ forceMount: true,
114
+ asChild: true,
115
+ children: /* @__PURE__ */ jsx(m.div, {
116
+ className: "overflow-hidden text-sm wrap-break-word text-muted-foreground",
117
+ initial: {
118
+ height: 0,
119
+ opacity: 0
120
+ },
121
+ animate: {
122
+ height: "auto",
123
+ opacity: 1
124
+ },
125
+ exit: {
126
+ height: 0,
127
+ opacity: 0
128
+ },
129
+ transition: presets.fade.transition,
130
+ children: /* @__PURE__ */ jsx("div", {
131
+ className: "pb-4",
132
+ children: it.content
133
+ })
134
+ })
135
+ })
136
+ })]
137
+ }, it.value);
138
+ })
139
+ });
140
+ }
28
141
  const content = items.map((it) => /* @__PURE__ */ jsxs(Accordion$1.Item, {
29
142
  value: it.value,
30
143
  disabled: it.disabled,
@@ -33,10 +146,10 @@ function Accordion({ items, multiple, defaultValue, className }) {
33
146
  className: "group flex min-h-touch w-full cursor-pointer items-center justify-between gap-4 py-4 text-left text-sm font-medium transition-colors hover:text-primary-text disabled:cursor-not-allowed disabled:opacity-50 md:min-h-0",
34
147
  children: [it.title, /* @__PURE__ */ jsx(ChevronDown, {
35
148
  "aria-hidden": true,
36
- className: "size-icon-sm shrink-0 text-muted-foreground transition-transform duration-200 group-data-[state=open]:rotate-180"
149
+ className: "size-icon-sm shrink-0 text-muted-foreground transition-transform duration-(--rendra-duration-base) ease-move group-data-[state=open]:rotate-180"
37
150
  })]
38
151
  }) }), /* @__PURE__ */ jsx(Accordion$1.Content, {
39
- className: "overflow-hidden text-sm text-muted-foreground data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
152
+ className: "overflow-hidden text-sm wrap-break-word text-muted-foreground data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
40
153
  children: /* @__PURE__ */ jsx("div", {
41
154
  className: "pb-4",
42
155
  children: it.content
@@ -182,6 +295,13 @@ function Alert({ type, title, description, action, onDismiss, animated = false,
182
295
  });
183
296
  }
184
297
  //#endregion
298
+ //#region src/lib/initials.ts
299
+ /** Iniciais de um nome: primeira letra do primeiro e do último nome, em maiúsculas. */
300
+ function initials(name) {
301
+ const parts = name.trim().split(/\s+/);
302
+ return ((parts[0]?.charAt(0) ?? "") + (parts.length > 1 ? parts[parts.length - 1]?.charAt(0) ?? "" : "")).toUpperCase();
303
+ }
304
+ //#endregion
185
305
  //#region src/components/ui/avatar.tsx
186
306
  var avatarVariants = cva("relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-avatar bg-primary-soft font-medium text-primary-soft-foreground select-none", {
187
307
  variants: { size: {
@@ -191,10 +311,6 @@ var avatarVariants = cva("relative inline-flex shrink-0 items-center justify-cen
191
311
  } },
192
312
  defaultVariants: { size: "md" }
193
313
  });
194
- function initials(name) {
195
- const parts = name.trim().split(/\s+/);
196
- return ((parts[0]?.charAt(0) ?? "") + (parts.length > 1 ? parts[parts.length - 1]?.charAt(0) ?? "" : "")).toUpperCase();
197
- }
198
314
  function Avatar({ name, src, size, className }) {
199
315
  return /* @__PURE__ */ jsxs(Avatar$1.Root, {
200
316
  "data-rendra": "AVT-001",
@@ -362,13 +478,17 @@ function BrandLogo({ on = "surface", symbolOnly, size = "md", className }) {
362
478
  }),
363
479
  !symbolOnly && /* @__PURE__ */ jsxs("span", {
364
480
  className: "truncate text-lg leading-none tracking-tight",
365
- children: [/* @__PURE__ */ jsx("span", {
366
- className: cn("font-semibold", strong),
367
- children: first
368
- }), rest.length > 0 && /* @__PURE__ */ jsxs("span", {
369
- className: cn("font-normal", soft),
370
- children: [" ", rest.join(" ")]
371
- })]
481
+ children: [
482
+ /* @__PURE__ */ jsx("span", {
483
+ className: cn("font-semibold", strong),
484
+ children: first
485
+ }),
486
+ rest.length > 0 && " ",
487
+ rest.length > 0 && /* @__PURE__ */ jsx("span", {
488
+ className: cn("font-normal", soft),
489
+ children: rest.join(" ")
490
+ })
491
+ ]
372
492
  }),
373
493
  symbolOnly && /* @__PURE__ */ jsx("span", {
374
494
  className: "sr-only",
@@ -397,7 +517,7 @@ function Breadcrumb({ items, variant = "responsive", className }) {
397
517
  const last = i === items.length - 1;
398
518
  return /* @__PURE__ */ jsxs("li", {
399
519
  className: cn("flex min-w-0 items-center gap-1", !last && "shrink-0 max-sm:max-w-24"),
400
- children: [item.to && !last ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Link, {
520
+ children: [item.to && !last ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Link, {
401
521
  to: item.to,
402
522
  className: "hidden truncate rounded-item transition-colors hover:text-primary-text md:inline",
403
523
  children: item.label
@@ -468,11 +588,11 @@ function Breadcrumb({ items, variant = "responsive", className }) {
468
588
  * ButtonGroup único: agrupa botões de ação (children) ou funciona como controle
469
589
  * segmentado de escolha única (options + value).
470
590
  */
471
- function ButtonGroup({ children, options, value, onChange, size = "md", fullWidth, className, ...aria }) {
591
+ function ButtonGroup({ children, options, value, onChange, size = "md", fullWidth, orientation = "horizontal", className, ...aria }) {
472
592
  if (options) return /* @__PURE__ */ jsx("div", {
473
593
  role: "radiogroup",
474
594
  "aria-label": aria["aria-label"],
475
- "data-rendra": "BTNG-001",
595
+ "data-rendra": resolveCatalogCode("ButtonGroup", { orientation: "horizontal" }),
476
596
  className: cn("inline-flex max-w-full flex-wrap gap-1 rounded-control border bg-muted p-1", fullWidth && "flex w-full", className),
477
597
  children: options.map((o) => {
478
598
  const active = o.value === value;
@@ -487,18 +607,34 @@ function ButtonGroup({ children, options, value, onChange, size = "md", fullWidt
487
607
  }, o.value);
488
608
  })
489
609
  });
610
+ const vertical = orientation === "vertical";
611
+ const responsive = orientation === "responsive";
490
612
  return /* @__PURE__ */ jsx("div", {
491
613
  role: "group",
492
614
  "aria-label": aria["aria-label"],
493
- "data-rendra": "BTNG-001",
494
- className: cn("inline-flex max-w-full", "[&>*]:rounded-none [&>*]:shadow-none [&>*:first-child]:rounded-l-control [&>*:focus-visible]:z-10 [&>*:last-child]:rounded-r-control [&>*:not(:first-child)]:-ml-px", fullWidth && "flex w-full [&>*]:flex-1", className),
615
+ "data-rendra": resolveCatalogCode("ButtonGroup", { orientation }),
616
+ className: cn("inline-flex max-w-full", "[&>*]:rounded-none [&>*]:shadow-none [&>*:focus-visible]:z-10", orientation === "horizontal" && "[&>*:first-child]:rounded-l-control [&>*:last-child]:rounded-r-control [&>*:not(:first-child)]:-ml-px", vertical && "flex-col [&>*]:w-full [&>*:first-child]:rounded-t-control [&>*:last-child]:rounded-b-control [&>*:not(:first-child)]:-mt-px", responsive && "flex-col md:flex-row [&>*]:w-full md:[&>*]:w-auto [&>*:first-child]:rounded-t-control md:[&>*:first-child]:rounded-l-control md:[&>*:first-child]:rounded-tr-none [&>*:last-child]:rounded-b-control md:[&>*:last-child]:rounded-r-control md:[&>*:last-child]:rounded-bl-none [&>*:not(:first-child)]:-mt-px md:[&>*:not(:first-child)]:mt-0 md:[&>*:not(:first-child)]:-ml-px", fullWidth && (vertical ? "flex w-full" : "flex w-full [&>*]:flex-1"), className),
495
617
  children
496
618
  });
497
619
  }
498
620
  //#endregion
499
621
  //#region src/components/ui/overlay-shell.tsx
500
622
  function OverlayShell({ title, description, icon, children, footer, hideHeader, onRequestClose, bodyClassName }) {
501
- return /* @__PURE__ */ jsxs(Fragment, { children: [
623
+ const closeButton = /* @__PURE__ */ jsx("button", {
624
+ type: "button",
625
+ onClick: onRequestClose,
626
+ "aria-label": "Fechar",
627
+ className: cn("-mt-1 -mr-2 flex size-touch shrink-0 cursor-pointer items-center justify-center rounded-item text-muted-foreground transition-colors hover:bg-accent hover:text-foreground md:size-control-md", hideHeader && "pointer-events-auto m-0 cursor-default opacity-0 focus-visible:cursor-pointer focus-visible:opacity-100"),
628
+ children: /* @__PURE__ */ jsx(X, {
629
+ className: "size-icon-md",
630
+ "aria-hidden": true
631
+ })
632
+ });
633
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
634
+ hideHeader && /* @__PURE__ */ jsx("div", {
635
+ className: "pointer-events-none absolute inset-x-0 top-0 z-10 flex justify-end px-2 pt-safe md:px-4 md:pt-4",
636
+ children: closeButton
637
+ }),
502
638
  /* @__PURE__ */ jsxs("header", {
503
639
  className: cn("flex shrink-0 items-start gap-3 border-b px-4 pt-safe pb-4 md:px-6 md:pt-6", hideHeader && "sr-only"),
504
640
  children: [
@@ -510,26 +646,17 @@ function OverlayShell({ title, description, icon, children, footer, hideHeader,
510
646
  /* @__PURE__ */ jsxs("div", {
511
647
  className: "flex min-w-0 flex-1 flex-col gap-1 pt-1",
512
648
  children: [/* @__PURE__ */ jsx(Dialog.Title, {
513
- className: "text-lg font-semibold",
649
+ className: "text-lg font-semibold wrap-break-word",
514
650
  children: title
515
651
  }), description ? /* @__PURE__ */ jsx(Dialog.Description, {
516
- className: "text-sm text-muted-foreground",
652
+ className: "text-sm wrap-break-word text-muted-foreground",
517
653
  children: description
518
654
  }) : /* @__PURE__ */ jsx(Dialog.Description, {
519
655
  className: "sr-only",
520
656
  children: title
521
657
  })]
522
658
  }),
523
- /* @__PURE__ */ jsx("button", {
524
- type: "button",
525
- onClick: onRequestClose,
526
- "aria-label": "Fechar",
527
- className: "-mt-1 -mr-2 flex size-touch shrink-0 cursor-pointer items-center justify-center rounded-item text-muted-foreground transition-colors hover:bg-accent hover:text-foreground md:size-control-md",
528
- children: /* @__PURE__ */ jsx(X, {
529
- className: "size-icon-md",
530
- "aria-hidden": true
531
- })
532
- })
659
+ !hideHeader && closeButton
533
660
  ]
534
661
  }),
535
662
  /* @__PURE__ */ jsx("div", {
@@ -549,12 +676,15 @@ var sizes$1 = {
549
676
  md: "md:max-w-lg",
550
677
  lg: "md:max-w-2xl"
551
678
  };
679
+ var overlayCls$1 = "fixed inset-0 z-50 bg-overlay";
680
+ var overlayOffCls = cn(overlayCls$1, "data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0");
681
+ var contentCls = cn("fixed inset-0 z-50 flex h-dvh flex-col bg-card text-card-foreground outline-none", "md:inset-auto md:top-1/2 md:left-1/2 md:h-auto md:max-h-sheet md:w-full md:-translate-x-1/2 md:-translate-y-1/2 md:rounded-surface md:border md:shadow-lg");
552
682
  var feedback = {
553
683
  confirm: "info",
554
684
  destructive: "error",
555
685
  info: "info"
556
686
  };
557
- function Modal({ open, onOpenChange, title, description, type = "confirm", size = "sm", children, confirmLabel = type === "destructive" ? "Excluir" : type === "info" ? "Entendi" : "Confirmar", cancelLabel = "Cancelar", onConfirm, formId, loading }) {
687
+ function Modal({ open, onOpenChange, title, description, type = "confirm", size = "sm", children, confirmLabel = type === "destructive" ? "Excluir" : type === "info" ? "Entendi" : "Confirmar", cancelLabel, onConfirm, formId, loading }) {
558
688
  const [busy, setBusy] = useState(false);
559
689
  const close = () => onOpenChange(false);
560
690
  const confirm = async () => {
@@ -568,55 +698,85 @@ function Modal({ open, onOpenChange, title, description, type = "confirm", size
568
698
  }
569
699
  };
570
700
  const isForm = type === "form";
701
+ const motion = useMotionMode();
702
+ const presets = useMotionPresets();
703
+ const { isMobile } = useBreakpoint();
704
+ const code = resolveCatalogCode("Modal", { type: type === "destructive" ? "confirm" : type });
705
+ const sizeCls = sizes$1[size];
706
+ const shell = /* @__PURE__ */ jsxs(OverlayShell, {
707
+ title,
708
+ description: isForm ? description : void 0,
709
+ hideHeader: !isForm,
710
+ onRequestClose: close,
711
+ bodyClassName: cn(!isForm && "flex flex-col items-center justify-center gap-4 text-center"),
712
+ footer: /* @__PURE__ */ jsx(ActionBar, {
713
+ primary: {
714
+ label: confirmLabel,
715
+ destructive: type === "destructive",
716
+ loading: busy || loading,
717
+ loadingLabel: `${confirmLabel}...`,
718
+ type: isForm && formId ? "submit" : "button",
719
+ form: isForm ? formId : void 0,
720
+ onClick: isForm && formId ? void 0 : confirm
721
+ },
722
+ cancel: type === "info" && cancelLabel === void 0 ? void 0 : {
723
+ label: cancelLabel ?? "Cancelar",
724
+ onClick: close
725
+ }
726
+ }),
727
+ children: [!isForm && /* @__PURE__ */ jsxs(Fragment$1, { children: [
728
+ /* @__PURE__ */ jsx(BrandFeedbackIcon, {
729
+ type: feedback[type],
730
+ size: "2xl",
731
+ animated: true
732
+ }),
733
+ /* @__PURE__ */ jsxs("div", {
734
+ className: "flex flex-col gap-2",
735
+ children: [/* @__PURE__ */ jsx("p", {
736
+ className: "text-lg font-semibold wrap-anywhere",
737
+ children: title
738
+ }), description && /* @__PURE__ */ jsx("p", {
739
+ className: "text-sm wrap-anywhere text-muted-foreground",
740
+ children: description
741
+ })]
742
+ }),
743
+ children
744
+ ] }), isForm && /* @__PURE__ */ jsx("div", {
745
+ className: "flex flex-col gap-2",
746
+ children
747
+ })]
748
+ });
749
+ if (motion === "on") return /* @__PURE__ */ jsx(Dialog.Root, {
750
+ open,
751
+ onOpenChange,
752
+ children: /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsxs(Dialog.Portal, {
753
+ forceMount: true,
754
+ children: [/* @__PURE__ */ jsx(Dialog.Overlay, {
755
+ forceMount: true,
756
+ asChild: true,
757
+ children: /* @__PURE__ */ jsx(m.div, {
758
+ className: overlayCls$1,
759
+ ...presets.fade
760
+ })
761
+ }), /* @__PURE__ */ jsx(Dialog.Content, {
762
+ forceMount: true,
763
+ asChild: true,
764
+ "data-rendra": code,
765
+ className: cn(contentCls, sizeCls),
766
+ children: /* @__PURE__ */ jsx(m.div, {
767
+ ...presets.open(isMobile ? { y: 8 } : void 0),
768
+ children: shell
769
+ })
770
+ })]
771
+ }, "modal") })
772
+ });
571
773
  return /* @__PURE__ */ jsx(Dialog.Root, {
572
774
  open,
573
775
  onOpenChange,
574
- children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-overlay data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0" }), /* @__PURE__ */ jsx(Dialog.Content, {
575
- "data-rendra": resolveCatalogCode("Modal", { type: type === "destructive" ? "confirm" : type }),
576
- className: cn("fixed inset-0 z-50 flex h-dvh flex-col bg-card text-card-foreground outline-none", "md:inset-auto md:top-1/2 md:left-1/2 md:h-auto md:max-h-sheet md:w-full md:-translate-x-1/2 md:-translate-y-1/2 md:rounded-surface md:border md:shadow-lg", "data-[state=open]:animate-in data-[state=open]:fade-in-0 md:data-[state=open]:zoom-in-95", sizes$1[size]),
577
- children: /* @__PURE__ */ jsxs(OverlayShell, {
578
- title,
579
- description: isForm ? description : void 0,
580
- hideHeader: !isForm,
581
- onRequestClose: close,
582
- bodyClassName: cn(!isForm && "flex flex-col items-center justify-center gap-4 text-center"),
583
- footer: /* @__PURE__ */ jsx(ActionBar, {
584
- primary: {
585
- label: confirmLabel,
586
- destructive: type === "destructive",
587
- loading: busy || loading,
588
- loadingLabel: `${confirmLabel}...`,
589
- type: isForm && formId ? "submit" : "button",
590
- form: isForm ? formId : void 0,
591
- onClick: isForm && formId ? void 0 : confirm
592
- },
593
- cancel: type === "info" ? void 0 : {
594
- label: cancelLabel,
595
- onClick: close
596
- }
597
- }),
598
- children: [!isForm && /* @__PURE__ */ jsxs(Fragment, { children: [
599
- /* @__PURE__ */ jsx(BrandFeedbackIcon, {
600
- type: feedback[type],
601
- size: "2xl",
602
- animated: true
603
- }),
604
- /* @__PURE__ */ jsxs("div", {
605
- className: "flex flex-col gap-2",
606
- children: [/* @__PURE__ */ jsx("p", {
607
- className: "text-lg font-semibold",
608
- children: title
609
- }), description && /* @__PURE__ */ jsx("p", {
610
- className: "text-sm text-muted-foreground",
611
- children: description
612
- })]
613
- }),
614
- children
615
- ] }), isForm && /* @__PURE__ */ jsx("div", {
616
- className: "flex flex-col gap-2",
617
- children
618
- })]
619
- })
776
+ children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: overlayOffCls }), /* @__PURE__ */ jsx(Dialog.Content, {
777
+ "data-rendra": code,
778
+ className: cn(contentCls, "data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 md:data-[state=open]:zoom-in-95", sizeCls),
779
+ children: shell
620
780
  })] })
621
781
  });
622
782
  }
@@ -1091,7 +1251,7 @@ function Calendar({ events, view: viewProp, defaultView = "month", onViewChange,
1091
1251
  " ",
1092
1252
  e.title
1093
1253
  ]
1094
- }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
1254
+ }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
1095
1255
  className: "truncate font-medium",
1096
1256
  children: e.title
1097
1257
  }), /* @__PURE__ */ jsx("span", {
@@ -1724,18 +1884,59 @@ var Input = forwardRef(function Input({ size, mask, icon, suffix, clearable, inv
1724
1884
  });
1725
1885
  //#endregion
1726
1886
  //#region src/components/ui/popover.tsx
1727
- var Popover = Popover$1.Root;
1887
+ var PopoverOpenContext = createContext(null);
1888
+ function AnimatedRoot({ open, defaultOpen, onOpenChange, ...rest }) {
1889
+ const [inner, setInner] = useState(defaultOpen ?? false);
1890
+ const current = open ?? inner;
1891
+ return /* @__PURE__ */ jsx(PopoverOpenContext.Provider, {
1892
+ value: current,
1893
+ children: /* @__PURE__ */ jsx(Popover$1.Root, {
1894
+ ...rest,
1895
+ open: current,
1896
+ onOpenChange: (next) => {
1897
+ setInner(next);
1898
+ onOpenChange?.(next);
1899
+ }
1900
+ })
1901
+ });
1902
+ }
1903
+ function Popover(props) {
1904
+ return useMotionMode() === "on" ? /* @__PURE__ */ jsx(AnimatedRoot, { ...props }) : /* @__PURE__ */ jsx(Popover$1.Root, { ...props });
1905
+ }
1728
1906
  var PopoverTrigger = Popover$1.Trigger;
1729
1907
  var PopoverClose = Popover$1.Close;
1730
1908
  var PopoverAnchor = Popover$1.Anchor;
1731
- function PopoverContent({ className, align = "center", sideOffset = 8, width = "md", ...props }) {
1909
+ function PopoverContent({ className, align = "center", sideOffset = 8, width = "md", children, asChild, ...props }) {
1910
+ const open = useContext(PopoverOpenContext);
1911
+ const motion = useMotionMode();
1912
+ const presets = useMotionPresets();
1913
+ const base = cn("z-50 origin-(--radix-popover-content-transform-origin) rounded-surface border bg-popover text-popover-foreground shadow-md outline-none", width === "sm" ? "w-popover-sm" : "w-popover");
1914
+ if (motion === "on" && open !== null && !asChild) return /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(Popover$1.Portal, {
1915
+ forceMount: true,
1916
+ children: /* @__PURE__ */ jsx(Popover$1.Content, {
1917
+ forceMount: true,
1918
+ asChild: true,
1919
+ align,
1920
+ sideOffset,
1921
+ collisionPadding: 16,
1922
+ "data-rendra": "POP-001",
1923
+ className: cn(base, className),
1924
+ ...props,
1925
+ children: /* @__PURE__ */ jsx(m.div, {
1926
+ ...presets.open(),
1927
+ children
1928
+ })
1929
+ })
1930
+ }, "popover") });
1732
1931
  return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Content, {
1733
1932
  align,
1734
1933
  sideOffset,
1735
1934
  collisionPadding: 16,
1736
1935
  "data-rendra": "POP-001",
1737
- className: cn("z-50 rounded-surface border bg-popover text-popover-foreground shadow-md outline-none", width === "sm" ? "w-popover-sm" : "w-popover", "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", className),
1738
- ...props
1936
+ className: cn(base, "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", className),
1937
+ asChild,
1938
+ ...props,
1939
+ children
1739
1940
  }) });
1740
1941
  }
1741
1942
  //#endregion
@@ -2083,7 +2284,7 @@ function Attachments({ files, mine }) {
2083
2284
  function MessageActions({ m, mine, onReply, onReact, onEdit, onDelete, kind }) {
2084
2285
  const Item = kind === "context" ? ContextMenu.Item : DropdownMenuItem;
2085
2286
  const itemClass = kind === "context" ? "flex min-h-touch cursor-pointer items-center gap-2 rounded-item px-3 text-sm outline-none select-none data-[highlighted]:bg-accent md:min-h-0 md:py-2 [&_svg]:size-icon-sm" : void 0;
2086
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2287
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
2087
2288
  /* @__PURE__ */ jsx("div", {
2088
2289
  role: "group",
2089
2290
  "aria-label": "Reagir",
@@ -2100,7 +2301,7 @@ function MessageActions({ m, mine, onReply, onReact, onEdit, onDelete, kind }) {
2100
2301
  onSelect: () => onReply?.(m),
2101
2302
  children: [/* @__PURE__ */ jsx(Reply, { "aria-hidden": true }), " Responder"]
2102
2303
  }),
2103
- mine && !m.deleted && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Item, {
2304
+ mine && !m.deleted && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Item, {
2104
2305
  className: itemClass,
2105
2306
  onSelect: () => onEdit?.(m),
2106
2307
  children: [/* @__PURE__ */ jsx(Pencil, { "aria-hidden": true }), " Editar"]
@@ -2224,7 +2425,7 @@ function ChatThread({ messages, onReply, onReact, onEdit, onDelete, className })
2224
2425
  }),
2225
2426
  m.replyTo && (() => {
2226
2427
  const quoteClass = cn("flex flex-col rounded-block border-l-4 px-2 py-1 text-left text-xs", mine && !m.deleted ? "border-primary-foreground/60 bg-primary-foreground/15" : "border-primary bg-muted");
2227
- const body = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
2428
+ const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
2228
2429
  className: "font-semibold",
2229
2430
  children: m.replyTo.author
2230
2431
  }), /* @__PURE__ */ jsx("span", {
@@ -2547,7 +2748,7 @@ function ChatComposer({ onSend, placeholder = "Escreva uma mensagem", disabled,
2547
2748
  }, i))
2548
2749
  })
2549
2750
  ]
2550
- }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2751
+ }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
2551
2752
  /* @__PURE__ */ jsx(Button, {
2552
2753
  variant: "ghost",
2553
2754
  iconOnly: true,
@@ -2627,7 +2828,7 @@ function ChatComposer({ onSend, placeholder = "Escreva uma mensagem", disabled,
2627
2828
  className: "@max-xl:hidden",
2628
2829
  children: /* @__PURE__ */ jsx(Mic, {})
2629
2830
  })
2630
- ] }), recording ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Button, {
2831
+ ] }), recording ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button, {
2631
2832
  variant: "ghost",
2632
2833
  iconOnly: true,
2633
2834
  "aria-label": "Cancelar gravação",
@@ -2638,7 +2839,7 @@ function ChatComposer({ onSend, placeholder = "Escreva uma mensagem", disabled,
2638
2839
  "aria-label": "Enviar áudio",
2639
2840
  onClick: () => stopRecording(true),
2640
2841
  children: /* @__PURE__ */ jsx(Send, {})
2641
- })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Button, {
2842
+ })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button, {
2642
2843
  iconOnly: true,
2643
2844
  "aria-label": "Enviar",
2644
2845
  disabled: disabled || !text.trim() && !files.length,
@@ -2783,7 +2984,7 @@ function QuickReplyList({ items, onPick }) {
2783
2984
  const [q, setQ] = useState("");
2784
2985
  const term = q.trim().toLowerCase();
2785
2986
  const list = term ? items.filter((i) => `${i.title} ${i.text}`.toLowerCase().includes(term)) : items;
2786
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2987
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
2787
2988
  /* @__PURE__ */ jsx("span", {
2788
2989
  className: "px-2 pt-1 text-xs font-semibold",
2789
2990
  children: "Mensagens rápidas"
@@ -2828,29 +3029,60 @@ function QuickReplyList({ items, onPick }) {
2828
3029
  function Checkbox({ checked, defaultChecked, onCheckedChange, label, description, disabled, invalid, id, name, className, ...aria }) {
2829
3030
  const auto = useId();
2830
3031
  const cid = id ?? `cb${auto}`;
2831
- const box = /* @__PURE__ */ jsx(Checkbox$1.Root, {
3032
+ const on = useMotionMode() === "on";
3033
+ const presets = useMotionPresets();
3034
+ const [inner, setInner] = useState(defaultChecked ?? false);
3035
+ const state = checked ?? inner;
3036
+ const mark = checked === "indeterminate" ? /* @__PURE__ */ jsx(Minus, {
3037
+ className: "size-3",
3038
+ strokeWidth: 3,
3039
+ "aria-hidden": true
3040
+ }) : /* @__PURE__ */ jsx(Check, {
3041
+ className: "size-3",
3042
+ strokeWidth: 3,
3043
+ "aria-hidden": true
3044
+ });
3045
+ const rootProps = {
2832
3046
  id: cid,
2833
3047
  name,
2834
- checked,
2835
- defaultChecked,
2836
- onCheckedChange: (v) => onCheckedChange?.(v === true),
3048
+ checked: on ? state : checked,
3049
+ defaultChecked: on ? void 0 : defaultChecked,
3050
+ onCheckedChange: (v) => {
3051
+ if (on) setInner(v);
3052
+ onCheckedChange?.(v === true);
3053
+ },
2837
3054
  disabled,
2838
3055
  "aria-invalid": invalid || void 0,
2839
3056
  "aria-label": aria["aria-label"],
2840
3057
  "data-touch": label ? void 0 : "expanded",
2841
- 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"),
2842
- children: /* @__PURE__ */ jsx(Checkbox$1.Indicator, {
2843
- className: "flex items-center justify-center data-[state=checked]:animate-in data-[state=checked]:zoom-in-50",
2844
- children: checked === "indeterminate" ? /* @__PURE__ */ jsx(Minus, {
2845
- className: "size-3",
2846
- strokeWidth: 3,
2847
- "aria-hidden": true
2848
- }) : /* @__PURE__ */ jsx(Check, {
2849
- className: "size-3",
2850
- strokeWidth: 3,
2851
- "aria-hidden": true
3058
+ 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")
3059
+ };
3060
+ const box = on ? /* @__PURE__ */ jsx(Checkbox$1.Root, {
3061
+ asChild: true,
3062
+ ...rootProps,
3063
+ children: /* @__PURE__ */ jsx(m.button, {
3064
+ type: "button",
3065
+ whileTap: presets.press.whileTap,
3066
+ transition: presets.press.transition,
3067
+ children: /* @__PURE__ */ jsx(AnimatePresence, {
3068
+ initial: false,
3069
+ children: state !== false && /* @__PURE__ */ jsx(Checkbox$1.Indicator, {
3070
+ forceMount: true,
3071
+ asChild: true,
3072
+ children: /* @__PURE__ */ jsx(m.span, {
3073
+ className: "flex items-center justify-center",
3074
+ ...presets.indicator,
3075
+ children: mark
3076
+ })
3077
+ })
2852
3078
  })
2853
3079
  })
3080
+ }) : /* @__PURE__ */ jsx(Checkbox$1.Root, {
3081
+ ...rootProps,
3082
+ children: /* @__PURE__ */ jsx(Checkbox$1.Indicator, {
3083
+ className: "flex items-center justify-center data-[state=checked]:animate-in data-[state=checked]:duration-(--rendra-duration-fast) data-[state=checked]:zoom-in-90",
3084
+ children: mark
3085
+ })
2854
3086
  });
2855
3087
  if (!label) return /* @__PURE__ */ jsx("span", {
2856
3088
  "data-rendra": "CHK-001",
@@ -3251,6 +3483,89 @@ function applyPalette(seeds, doc = document) {
3251
3483
  }
3252
3484
  //#endregion
3253
3485
  //#region src/components/ui/picker-panel.tsx
3486
+ /** A folha fecha se o arraste passou de 40% da altura ou se foi um arremesso (> 0,11 px/ms). */
3487
+ var DISMISS_FRACTION = .4;
3488
+ var DISMISS_VELOCITY = 110;
3489
+ /**
3490
+ * A folha do celular em `on`: entra de baixo, acompanha o dedo (arraste vertical pela alça, com
3491
+ * fricção ao puxar para cima), fecha por distância ou por arremesso e, se o dedo solta antes
3492
+ * disso, volta à origem com a mola da folha (a velocidade do dedo entra na mola, sem costura). O
3493
+ * fundo escurecido acompanha a distância. Só a alça arrasta: o corpo rola sem disputar o gesto.
3494
+ * Nenhum valor passa por `style`: o Motion guarda a posição do arraste, e o escurecimento do
3495
+ * fundo é gravado direto no elemento (sem render por quadro).
3496
+ */
3497
+ function MobileSheet({ open, onOpenChange, trigger, adornment, head, rest }) {
3498
+ const presets = useMotionPresets();
3499
+ const ready = useLayoutReady();
3500
+ const controls = useDragControls();
3501
+ const sheetRef = useRef(null);
3502
+ const dimRef = useRef(null);
3503
+ const height = useRef(1);
3504
+ return /* @__PURE__ */ jsxs(Dialog.Root, {
3505
+ open,
3506
+ onOpenChange,
3507
+ children: [/* @__PURE__ */ jsx(Anchor, {
3508
+ adornment,
3509
+ children: /* @__PURE__ */ jsx(Dialog.Trigger, {
3510
+ asChild: true,
3511
+ children: trigger
3512
+ })
3513
+ }), /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsxs(Dialog.Portal, {
3514
+ forceMount: true,
3515
+ children: [/* @__PURE__ */ jsx(Dialog.Overlay, {
3516
+ forceMount: true,
3517
+ asChild: true,
3518
+ children: /* @__PURE__ */ jsx(m.div, {
3519
+ className: "fixed inset-0 z-40",
3520
+ ...presets.fade,
3521
+ children: /* @__PURE__ */ jsx("div", {
3522
+ ref: dimRef,
3523
+ className: "absolute inset-0 bg-overlay"
3524
+ })
3525
+ })
3526
+ }), /* @__PURE__ */ jsx(Dialog.Content, {
3527
+ forceMount: true,
3528
+ asChild: true,
3529
+ "aria-describedby": void 0,
3530
+ className: "fixed inset-x-0 bottom-0 z-50 flex max-h-sheet flex-col rounded-t-surface border-t bg-popover text-popover-foreground shadow-lg outline-none",
3531
+ children: /* @__PURE__ */ jsxs(m.div, {
3532
+ ref: sheetRef,
3533
+ ...presets.sheet("bottom"),
3534
+ drag: ready ? "y" : false,
3535
+ dragControls: controls,
3536
+ dragListener: false,
3537
+ dragConstraints: { top: 0 },
3538
+ dragElastic: {
3539
+ top: .2,
3540
+ bottom: 0
3541
+ },
3542
+ dragSnapToOrigin: true,
3543
+ dragTransition: presets.sheetBounce,
3544
+ onDragStart: () => {
3545
+ height.current = sheetRef.current?.offsetHeight || 1;
3546
+ },
3547
+ onDrag: (_, info) => {
3548
+ const dim = dimRef.current;
3549
+ if (dim) dim.style.opacity = String(1 - Math.min(1, Math.max(0, info.offset.y / height.current)));
3550
+ },
3551
+ onDragEnd: (_, info) => {
3552
+ if (info.offset.y > height.current * DISMISS_FRACTION || info.velocity.y > DISMISS_VELOCITY) {
3553
+ onOpenChange(false);
3554
+ return;
3555
+ }
3556
+ if (dimRef.current) animate(dimRef.current, { opacity: 1 }, presets.springSheet);
3557
+ },
3558
+ children: [/* @__PURE__ */ jsx("div", {
3559
+ "data-sheet-handle": true,
3560
+ onPointerDown: (e) => controls.start(e),
3561
+ className: "touch-none",
3562
+ children: head
3563
+ }), rest]
3564
+ })
3565
+ })]
3566
+ }, "sheet") })]
3567
+ });
3568
+ }
3254
3569
  function Anchor({ adornment, children }) {
3255
3570
  if (!adornment) return children;
3256
3571
  return /* @__PURE__ */ jsxs("div", {
@@ -3260,6 +3575,92 @@ function Anchor({ adornment, children }) {
3260
3575
  }
3261
3576
  function PickerPanel({ open, onOpenChange, trigger, title, header, children, footer, width = "trigger", adornment, align = "start" }) {
3262
3577
  const { isMobile } = useBreakpoint();
3578
+ const motion = useMotionMode();
3579
+ const presets = useMotionPresets();
3580
+ const on = motion === "on";
3581
+ const sheetHead = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
3582
+ className: "flex shrink-0 flex-col items-center pt-2",
3583
+ children: /* @__PURE__ */ jsx("span", {
3584
+ "aria-hidden": true,
3585
+ className: "h-1 w-12 rounded-full bg-border"
3586
+ })
3587
+ }), /* @__PURE__ */ jsxs("div", {
3588
+ className: "flex shrink-0 items-center justify-between gap-2 pr-2 pl-4",
3589
+ children: [/* @__PURE__ */ jsx(Dialog.Title, {
3590
+ className: "truncate text-base font-semibold",
3591
+ children: title
3592
+ }), /* @__PURE__ */ jsx(Dialog.Close, {
3593
+ "aria-label": "Fechar",
3594
+ className: "flex size-touch items-center justify-center rounded-item text-muted-foreground hover:bg-accent",
3595
+ children: /* @__PURE__ */ jsx(X, {
3596
+ className: "size-icon-md",
3597
+ "aria-hidden": true
3598
+ })
3599
+ })]
3600
+ })] });
3601
+ const sheetRest = /* @__PURE__ */ jsxs(Fragment$1, { children: [
3602
+ header && /* @__PURE__ */ jsx("div", {
3603
+ className: "shrink-0 border-b px-4 pb-3",
3604
+ children: header
3605
+ }),
3606
+ /* @__PURE__ */ jsx("div", {
3607
+ className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-2",
3608
+ children
3609
+ }),
3610
+ footer && /* @__PURE__ */ jsx("div", {
3611
+ className: "shrink-0 border-t px-4 pt-3 pb-safe",
3612
+ children: footer
3613
+ })
3614
+ ] });
3615
+ const sheetBody = /* @__PURE__ */ jsxs(Fragment$1, { children: [sheetHead, sheetRest] });
3616
+ const panelCls = cn("z-50 flex max-h-command origin-(--radix-popover-content-transform-origin) flex-col overflow-hidden rounded-surface border bg-popover text-popover-foreground shadow-md outline-none", width === "trigger" ? "w-trigger max-w-popover" : "w-auto max-w-popover md:max-w-none");
3617
+ const panelBody = /* @__PURE__ */ jsxs(Fragment$1, { children: [
3618
+ header && /* @__PURE__ */ jsx("div", {
3619
+ className: "shrink-0 border-b p-2",
3620
+ children: header
3621
+ }),
3622
+ /* @__PURE__ */ jsx("div", {
3623
+ className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-1",
3624
+ children
3625
+ }),
3626
+ footer && /* @__PURE__ */ jsx("div", {
3627
+ className: "shrink-0 border-t p-2",
3628
+ children: footer
3629
+ })
3630
+ ] });
3631
+ if (on && isMobile) return /* @__PURE__ */ jsx(MobileSheet, {
3632
+ open,
3633
+ onOpenChange,
3634
+ trigger,
3635
+ adornment,
3636
+ head: sheetHead,
3637
+ rest: sheetRest
3638
+ });
3639
+ if (on) return /* @__PURE__ */ jsxs(Popover$1.Root, {
3640
+ open,
3641
+ onOpenChange,
3642
+ children: [/* @__PURE__ */ jsx(Anchor, {
3643
+ adornment,
3644
+ children: /* @__PURE__ */ jsx(Popover$1.Trigger, {
3645
+ asChild: true,
3646
+ children: trigger
3647
+ })
3648
+ }), /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(Popover$1.Portal, {
3649
+ forceMount: true,
3650
+ children: /* @__PURE__ */ jsx(Popover$1.Content, {
3651
+ forceMount: true,
3652
+ asChild: true,
3653
+ align,
3654
+ sideOffset: 6,
3655
+ collisionPadding: 16,
3656
+ className: panelCls,
3657
+ children: /* @__PURE__ */ jsx(m.div, {
3658
+ ...presets.open(),
3659
+ children: panelBody
3660
+ })
3661
+ })
3662
+ }, "panel") })]
3663
+ });
3263
3664
  if (isMobile) return /* @__PURE__ */ jsxs(Dialog.Root, {
3264
3665
  open,
3265
3666
  onOpenChange,
@@ -3269,44 +3670,10 @@ function PickerPanel({ open, onOpenChange, trigger, title, header, children, foo
3269
3670
  asChild: true,
3270
3671
  children: trigger
3271
3672
  })
3272
- }), /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: "fixed inset-0 z-40 bg-overlay data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0" }), /* @__PURE__ */ jsxs(Dialog.Content, {
3673
+ }), /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: "fixed inset-0 z-40 bg-overlay data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0" }), /* @__PURE__ */ jsx(Dialog.Content, {
3273
3674
  "aria-describedby": void 0,
3274
- className: "fixed inset-x-0 bottom-0 z-50 flex max-h-sheet flex-col rounded-t-surface border-t bg-popover text-popover-foreground shadow-lg outline-none data-[state=closed]:animate-out data-[state=closed]:slide-out-to-bottom data-[state=open]:animate-in data-[state=open]:slide-in-from-bottom",
3275
- children: [
3276
- /* @__PURE__ */ jsx("div", {
3277
- className: "flex shrink-0 flex-col items-center pt-2",
3278
- children: /* @__PURE__ */ jsx("span", {
3279
- "aria-hidden": true,
3280
- className: "h-1 w-12 rounded-full bg-border"
3281
- })
3282
- }),
3283
- /* @__PURE__ */ jsxs("div", {
3284
- className: "flex shrink-0 items-center justify-between gap-2 pr-2 pl-4",
3285
- children: [/* @__PURE__ */ jsx(Dialog.Title, {
3286
- className: "truncate text-base font-semibold",
3287
- children: title
3288
- }), /* @__PURE__ */ jsx(Dialog.Close, {
3289
- "aria-label": "Fechar",
3290
- className: "flex size-touch items-center justify-center rounded-item text-muted-foreground hover:bg-accent",
3291
- children: /* @__PURE__ */ jsx(X, {
3292
- className: "size-icon-md",
3293
- "aria-hidden": true
3294
- })
3295
- })]
3296
- }),
3297
- header && /* @__PURE__ */ jsx("div", {
3298
- className: "shrink-0 border-b px-4 pb-3",
3299
- children: header
3300
- }),
3301
- /* @__PURE__ */ jsx("div", {
3302
- className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-2",
3303
- children
3304
- }),
3305
- footer && /* @__PURE__ */ jsx("div", {
3306
- className: "shrink-0 border-t px-4 pt-3 pb-safe",
3307
- children: footer
3308
- })
3309
- ]
3675
+ className: "fixed inset-x-0 bottom-0 z-50 flex max-h-sheet flex-col rounded-t-surface border-t bg-popover text-popover-foreground shadow-lg outline-none data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:slide-out-to-bottom data-[state=open]:animate-in data-[state=open]:slide-in-from-bottom",
3676
+ children: sheetBody
3310
3677
  })] })]
3311
3678
  });
3312
3679
  return /* @__PURE__ */ jsxs(Popover$1.Root, {
@@ -3318,25 +3685,12 @@ function PickerPanel({ open, onOpenChange, trigger, title, header, children, foo
3318
3685
  asChild: true,
3319
3686
  children: trigger
3320
3687
  })
3321
- }), /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsxs(Popover$1.Content, {
3688
+ }), /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Content, {
3322
3689
  align,
3323
3690
  sideOffset: 6,
3324
3691
  collisionPadding: 16,
3325
- className: cn("z-50 flex max-h-command flex-col overflow-hidden rounded-surface border bg-popover text-popover-foreground shadow-md outline-none", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", width === "trigger" ? "w-trigger max-w-popover" : "w-auto max-w-popover md:max-w-none"),
3326
- children: [
3327
- header && /* @__PURE__ */ jsx("div", {
3328
- className: "shrink-0 border-b p-2",
3329
- children: header
3330
- }),
3331
- /* @__PURE__ */ jsx("div", {
3332
- className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-1",
3333
- children
3334
- }),
3335
- footer && /* @__PURE__ */ jsx("div", {
3336
- className: "shrink-0 border-t p-2",
3337
- children: footer
3338
- })
3339
- ]
3692
+ className: cn("z-50 flex max-h-command origin-(--radix-popover-content-transform-origin) flex-col overflow-hidden rounded-surface border bg-popover text-popover-foreground shadow-md outline-none", "data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", width === "trigger" ? "w-trigger max-w-popover" : "w-auto max-w-popover md:max-w-none"),
3693
+ children: panelBody
3340
3694
  }) })]
3341
3695
  });
3342
3696
  }
@@ -3447,35 +3801,57 @@ var sizes = {
3447
3801
  lg: "md:w-sheet-50",
3448
3802
  xl: "md:w-sheet-75"
3449
3803
  };
3804
+ var overlayCls = "fixed inset-0 z-50 bg-overlay";
3805
+ var panelCls = "fixed inset-y-0 right-0 z-50 flex h-dvh w-full flex-col bg-card text-card-foreground shadow-lg outline-none md:border-l";
3450
3806
  function Drawer({ open, onOpenChange, title, description, icon, size = "30", children, footer, dirty, discardTitle = "Descartar alterações?", discardDescription = "As informações preenchidas neste painel serão perdidas." }) {
3451
3807
  const [confirming, setConfirming] = useState(false);
3452
3808
  const requestClose = () => dirty ? setConfirming(true) : onOpenChange(false);
3453
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Dialog.Root, {
3809
+ const motion = useMotionMode();
3810
+ const presets = useMotionPresets();
3811
+ const keepOpenIfDirty = (e) => {
3812
+ if (dirty) {
3813
+ e.preventDefault();
3814
+ setConfirming(true);
3815
+ }
3816
+ };
3817
+ const shell = /* @__PURE__ */ jsx(OverlayShell, {
3818
+ title,
3819
+ description,
3820
+ icon,
3821
+ footer,
3822
+ onRequestClose: requestClose,
3823
+ children
3824
+ });
3825
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Dialog.Root, {
3454
3826
  open,
3455
3827
  onOpenChange: (o) => o ? onOpenChange(true) : requestClose(),
3456
- children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-overlay data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0" }), /* @__PURE__ */ jsx(Dialog.Content, {
3457
- onEscapeKeyDown: (e) => {
3458
- if (dirty) {
3459
- e.preventDefault();
3460
- setConfirming(true);
3461
- }
3462
- },
3463
- onPointerDownOutside: (e) => {
3464
- if (dirty) {
3465
- e.preventDefault();
3466
- setConfirming(true);
3467
- }
3468
- },
3828
+ children: motion === "on" ? /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsxs(Dialog.Portal, {
3829
+ forceMount: true,
3830
+ children: [/* @__PURE__ */ jsx(Dialog.Overlay, {
3831
+ forceMount: true,
3832
+ asChild: true,
3833
+ children: /* @__PURE__ */ jsx(m.div, {
3834
+ className: overlayCls,
3835
+ ...presets.fade
3836
+ })
3837
+ }), /* @__PURE__ */ jsx(Dialog.Content, {
3838
+ forceMount: true,
3839
+ asChild: true,
3840
+ onEscapeKeyDown: keepOpenIfDirty,
3841
+ onPointerDownOutside: keepOpenIfDirty,
3842
+ "data-rendra": "GAV-001",
3843
+ className: cn(panelCls, sizes[size]),
3844
+ children: /* @__PURE__ */ jsx(m.div, {
3845
+ ...presets.sheet("right"),
3846
+ children: shell
3847
+ })
3848
+ })]
3849
+ }, "drawer") }) : /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: cn(overlayCls, "data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0") }), /* @__PURE__ */ jsx(Dialog.Content, {
3850
+ onEscapeKeyDown: keepOpenIfDirty,
3851
+ onPointerDownOutside: keepOpenIfDirty,
3469
3852
  "data-rendra": "GAV-001",
3470
- className: cn("fixed inset-y-0 right-0 z-50 flex h-dvh w-full flex-col bg-card text-card-foreground shadow-lg outline-none md:border-l", "data-[state=closed]:animate-out data-[state=closed]:slide-out-to-right data-[state=open]:animate-in data-[state=open]:slide-in-from-right", sizes[size]),
3471
- children: /* @__PURE__ */ jsx(OverlayShell, {
3472
- title,
3473
- description,
3474
- icon,
3475
- footer,
3476
- onRequestClose: requestClose,
3477
- children
3478
- })
3853
+ className: cn(panelCls, "data-[state=closed]:animate-out data-[state=closed]:duration-(--rendra-duration-fast) data-[state=closed]:slide-out-to-right data-[state=open]:animate-in data-[state=open]:slide-in-from-right", sizes[size]),
3854
+ children: shell
3479
3855
  })] })
3480
3856
  }), /* @__PURE__ */ jsx(Modal, {
3481
3857
  open: confirming,
@@ -3494,7 +3870,13 @@ function Drawer({ open, onOpenChange, title, description, icon, size = "30", chi
3494
3870
  function Switch({ checked, defaultChecked, onCheckedChange, label, description, disabled, id, name, className, ...aria }) {
3495
3871
  const auto = useId();
3496
3872
  const sid = id ?? `sw${auto}`;
3497
- const control = /* @__PURE__ */ jsx(Switch$1.Root, {
3873
+ const motion = useMotionMode();
3874
+ const presets = useMotionPresets();
3875
+ const rootCls = "relative inline-flex h-6 w-12 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-input transition-colors disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary max-md:before:absolute max-md:before:-inset-3";
3876
+ const thumbCls = cn("pointer-events-none block size-icon-md rounded-full bg-card shadow-sm duration-(--rendra-duration-base) ease-move data-[state=checked]:translate-x-6", motion === "on" ? "transition-[translate]" : "transition-transform");
3877
+ const tap = presets.tap;
3878
+ const control = motion === "on" ? /* @__PURE__ */ jsx(Switch$1.Root, {
3879
+ asChild: true,
3498
3880
  id: sid,
3499
3881
  name,
3500
3882
  checked,
@@ -3504,8 +3886,36 @@ function Switch({ checked, defaultChecked, onCheckedChange, label, description,
3504
3886
  "aria-label": aria["aria-label"],
3505
3887
  "data-touch": "expanded",
3506
3888
  "data-rendra": "SWT-001",
3507
- className: "relative inline-flex h-6 w-12 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-input transition-colors disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary max-md:before:absolute max-md:before:-inset-3",
3508
- children: /* @__PURE__ */ jsx(Switch$1.Thumb, { className: "pointer-events-none block size-icon-md rounded-full bg-card shadow-sm transition-transform duration-200 ease-out data-[state=checked]:translate-x-6" })
3889
+ children: /* @__PURE__ */ jsx(m.button, {
3890
+ type: "button",
3891
+ className: rootCls,
3892
+ initial: "rest",
3893
+ animate: "rest",
3894
+ whileTap: tap ? "tap" : void 0,
3895
+ children: /* @__PURE__ */ jsx(Switch$1.Thumb, {
3896
+ asChild: true,
3897
+ children: /* @__PURE__ */ jsx(m.span, {
3898
+ className: thumbCls,
3899
+ variants: {
3900
+ rest: { scale: 1 },
3901
+ tap: { scale: tap ? 1.15 : 1 }
3902
+ },
3903
+ transition: presets.press.transition
3904
+ })
3905
+ })
3906
+ })
3907
+ }) : /* @__PURE__ */ jsx(Switch$1.Root, {
3908
+ id: sid,
3909
+ name,
3910
+ checked,
3911
+ defaultChecked,
3912
+ onCheckedChange,
3913
+ disabled,
3914
+ "aria-label": aria["aria-label"],
3915
+ "data-touch": "expanded",
3916
+ "data-rendra": "SWT-001",
3917
+ className: rootCls,
3918
+ children: /* @__PURE__ */ jsx(Switch$1.Thumb, { className: thumbCls })
3509
3919
  });
3510
3920
  if (!label) return control;
3511
3921
  return /* @__PURE__ */ jsxs("label", {
@@ -3572,7 +3982,7 @@ function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips =
3572
3982
  "aria-label": search.placeholder ?? "Buscar",
3573
3983
  type: "search",
3574
3984
  className: "md:w-3xs lg:w-sm"
3575
- }), isMobile ? /* @__PURE__ */ jsxs(Fragment, { children: [(hasPanel || primaryAction) && /* @__PURE__ */ jsxs("div", {
3985
+ }), isMobile ? /* @__PURE__ */ jsxs(Fragment$1, { children: [(hasPanel || primaryAction) && /* @__PURE__ */ jsxs("div", {
3576
3986
  className: cn("grid gap-3", hasPanel && primaryAction ? "grid-actions-2" : "grid-cols-1"),
3577
3987
  children: [hasPanel && filterButton(() => setDrawer(true)), primaryAction]
3578
3988
  }), actions && /* @__PURE__ */ jsx("div", {
@@ -4017,10 +4427,11 @@ var content = {
4017
4427
  * Tela de erro única (404 e 500), com o ícone de feedback da marca animado.
4018
4428
  * Ações seguem a regra 30/70: secundária à esquerda, principal à direita.
4019
4429
  */
4020
- function ErrorPage({ code, title, description, fullScreen = false }) {
4430
+ function ErrorPage({ code, title, description, fullScreen = false, back = true }) {
4021
4431
  const Link = useRendraLink();
4022
4432
  const { goBack } = useRendraNavigate();
4023
4433
  const c = content[code];
4434
+ const principal = back ? "col-span-7" : "col-span-10";
4024
4435
  return /* @__PURE__ */ jsx("div", {
4025
4436
  "data-rendra": "ERRO-001",
4026
4437
  className: cn("flex w-full items-center justify-center px-4 py-12", fullScreen ? "min-h-dvh" : "min-h-full"),
@@ -4058,7 +4469,7 @@ function ErrorPage({ code, title, description, fullScreen = false }) {
4058
4469
  }),
4059
4470
  /* @__PURE__ */ jsxs("div", {
4060
4471
  className: "grid w-full grid-cols-10 gap-3",
4061
- children: [/* @__PURE__ */ jsx(Button, {
4472
+ children: [back && /* @__PURE__ */ jsx(Button, {
4062
4473
  variant: "outline",
4063
4474
  icon: /* @__PURE__ */ jsx(ArrowLeft, {}),
4064
4475
  className: "col-span-3",
@@ -4070,12 +4481,12 @@ function ErrorPage({ code, title, description, fullScreen = false }) {
4070
4481
  })
4071
4482
  }), code === 500 ? /* @__PURE__ */ jsx(Button, {
4072
4483
  icon: /* @__PURE__ */ jsx(RotateCw, {}),
4073
- className: "col-span-7",
4484
+ className: principal,
4074
4485
  onClick: () => location.reload(),
4075
4486
  children: "Tentar de novo"
4076
4487
  }) : /* @__PURE__ */ jsx(Button, {
4077
4488
  asChild: true,
4078
- className: "col-span-7",
4489
+ className: principal,
4079
4490
  children: /* @__PURE__ */ jsxs(Link, {
4080
4491
  to: "/",
4081
4492
  children: [/* @__PURE__ */ jsx(Home, { "aria-hidden": true }), "Ir para o painel"]
@@ -4337,7 +4748,7 @@ var Select = forwardRef(function Select(props, ref) {
4337
4748
  }),
4338
4749
  /* @__PURE__ */ jsx(ChevronDown, {
4339
4750
  "aria-hidden": true,
4340
- className: cn("size-icon-sm shrink-0 text-muted-foreground transition-transform duration-200", open && "rotate-180")
4751
+ className: cn("size-icon-sm shrink-0 text-muted-foreground transition-transform duration-(--rendra-duration-base) ease-move", open && "rotate-180")
4341
4752
  })
4342
4753
  ]
4343
4754
  });
@@ -4485,6 +4896,8 @@ var Select = forwardRef(function Select(props, ref) {
4485
4896
  });
4486
4897
  //#endregion
4487
4898
  //#region src/components/ui/tabs.tsx
4899
+ /** Contador de instâncias, só para o `layoutId` do indicador (ver `indicatorId`). */
4900
+ var tabsCreated = 0;
4488
4901
  /**
4489
4902
  * Tabs único. Se as abas não couberem na largura, a mesma lista vira um Select
4490
4903
  * (nunca rolagem lateral). A troca é medida no próprio contêiner, não na tela.
@@ -4509,9 +4922,48 @@ function Tabs({ items, value, defaultValue, onChange, variant = "line", classNam
4509
4922
  ro.observe(box);
4510
4923
  return () => ro.disconnect();
4511
4924
  }, [items, variant]);
4512
- 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" ? "-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" : "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");
4925
+ const presets = useMotionPresets();
4926
+ const on = useLayoutReady();
4927
+ const listRef = useRef(null);
4928
+ const [clip, setClip] = useState({
4929
+ l: 0,
4930
+ r: 0
4931
+ });
4932
+ useLayoutEffect(() => {
4933
+ const list = listRef.current;
4934
+ if (!on || !list) return;
4935
+ const measure = () => {
4936
+ const active = list.querySelector("[role=\"tab\"][data-state=\"active\"]");
4937
+ if (!active) return;
4938
+ const l = active.offsetLeft;
4939
+ const r = list.offsetWidth - l - active.offsetWidth;
4940
+ setClip((prev) => prev.l === l && prev.r === r ? prev : {
4941
+ l,
4942
+ r
4943
+ });
4944
+ };
4945
+ measure();
4946
+ const ro = new ResizeObserver(measure);
4947
+ ro.observe(list);
4948
+ return () => ro.disconnect();
4949
+ }, [
4950
+ on,
4951
+ current,
4952
+ items,
4953
+ variant,
4954
+ overflow
4955
+ ]);
4956
+ const [indicatorId] = useState(() => `rendra-tabs-${++tabsCreated}`);
4957
+ 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");
4958
+ const indicator = /* @__PURE__ */ jsx(m.span, {
4959
+ layoutId: indicatorId,
4960
+ "data-indicator": "tabs",
4961
+ "aria-hidden": true,
4962
+ transition: presets.move,
4963
+ 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"
4964
+ });
4513
4965
  const list = cn("flex", variant === "line" ? "gap-2 border-b" : "gap-1 rounded-control bg-muted p-1");
4514
- const label = (it) => /* @__PURE__ */ jsxs(Fragment, { children: [
4966
+ const label = (it) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
4515
4967
  it.icon,
4516
4968
  it.label,
4517
4969
  it.count !== void 0 && /* @__PURE__ */ jsx("span", {
@@ -4544,16 +4996,29 @@ function Tabs({ items, value, defaultValue, onChange, variant = "line", classNam
4544
4996
  label: it.count !== void 0 ? `${it.label} (${it.count})` : it.label,
4545
4997
  disabled: it.disabled
4546
4998
  }))
4547
- }) : /* @__PURE__ */ jsx(Tabs$1.List, {
4999
+ }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Tabs$1.List, {
5000
+ ref: listRef,
4548
5001
  "aria-label": aria["aria-label"],
4549
5002
  className: list,
4550
- children: items.map((it) => /* @__PURE__ */ jsx(Tabs$1.Trigger, {
5003
+ children: items.map((it) => /* @__PURE__ */ jsxs(Tabs$1.Trigger, {
4551
5004
  value: it.value,
4552
5005
  disabled: it.disabled,
4553
5006
  className: trigger,
5007
+ children: [on && current === it.value && indicator, label(it)]
5008
+ }, it.value))
5009
+ }), on && /* @__PURE__ */ jsx("div", {
5010
+ "data-tabs-copy": true,
5011
+ "aria-hidden": true,
5012
+ className: cn(list, "pointer-events-none absolute inset-0 border-transparent bg-transparent text-foreground tabs-clip"),
5013
+ style: {
5014
+ "--tabs-l": `${clip.l}px`,
5015
+ "--tabs-r": `${clip.r}px`
5016
+ },
5017
+ children: items.map((it) => /* @__PURE__ */ jsx("span", {
5018
+ className: cn(trigger, "text-foreground"),
4554
5019
  children: label(it)
4555
5020
  }, it.value))
4556
- })]
5021
+ })] })]
4557
5022
  }), items.map((it) => /* @__PURE__ */ jsx(Tabs$1.Content, {
4558
5023
  value: it.value,
4559
5024
  className: "min-w-0 outline-none",
@@ -5040,6 +5505,8 @@ function LoadMore({ onVisible }) {
5040
5505
  children: "Carregando mais cards..."
5041
5506
  });
5042
5507
  }
5508
+ /** Contador de quadros, só para o `layoutId` dos cards em `on` (um prefixo por instância). */
5509
+ var boardsCreated = 0;
5043
5510
  var dotTone = {
5044
5511
  neutral: "bg-muted-foreground",
5045
5512
  primary: "bg-primary",
@@ -5060,7 +5527,7 @@ var targetIconTone = {
5060
5527
  };
5061
5528
  function CardBody({ card, valueFields = [], formatValue, withHandle }) {
5062
5529
  const shown = valueFields.slice(0, 2);
5063
- return /* @__PURE__ */ jsxs(Fragment, { children: [
5530
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
5064
5531
  card.tags && card.tags.length > 0 && /* @__PURE__ */ jsx("span", {
5065
5532
  className: "flex flex-wrap gap-1",
5066
5533
  children: card.tags.map((t) => /* @__PURE__ */ jsx(Badge, {
@@ -5162,6 +5629,10 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
5162
5629
  }), pageSize = 20, visibleColumns = 5, onLoadMore, hasMore, dropTargets, onDropTarget, className, ...aria }) {
5163
5630
  const code = resolveCatalogCode("Kanban", { hasDropTargets: Boolean(dropTargets?.length) });
5164
5631
  const { isMobile } = useBreakpoint();
5632
+ const motion = useMotionMode();
5633
+ const ready = useLayoutReady();
5634
+ const presets = useMotionPresets();
5635
+ const [boardId] = useState(() => `rendra-kanban-${++boardsCreated}`);
5165
5636
  const boardRef = useFillHeight();
5166
5637
  useEffect(() => {
5167
5638
  const el = boardRef.current;
@@ -5246,7 +5717,7 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
5246
5717
  }), /* @__PURE__ */ jsxs(DropdownMenuContent, {
5247
5718
  align: "end",
5248
5719
  children: [
5249
- otherColumns.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Mover para" }), otherColumns.map((c) => /* @__PURE__ */ jsxs(DropdownMenuItem, {
5720
+ otherColumns.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Mover para" }), otherColumns.map((c) => /* @__PURE__ */ jsxs(DropdownMenuItem, {
5250
5721
  onSelect: () => onCardMove?.(card.id, c.id, inColumn(c.id).length),
5251
5722
  children: [/* @__PURE__ */ jsx(ArrowRightLeft, {}), c.title]
5252
5723
  }, c.id))] }),
@@ -5308,36 +5779,39 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
5308
5779
  });
5309
5780
  const canTouchDrag = Boolean(onCardMove) || Boolean(dropTargets?.length && onDropTarget);
5310
5781
  const showHandle = isMobile && canTouchDrag;
5311
- const cardItem = (card, index) => /* @__PURE__ */ jsxs("li", {
5312
- "data-kanban-card": card.id,
5313
- draggable: !isMobile && Boolean(onCardMove),
5314
- onDragStart: (e) => {
5782
+ const cardItem = (card, index) => {
5783
+ const dragStart = (dataTransfer) => {
5315
5784
  setDragging(card.id);
5316
- e.dataTransfer.effectAllowed = "move";
5317
- e.dataTransfer.setData("text/plain", card.id);
5318
- },
5319
- onDragEnd: () => {
5785
+ if (!dataTransfer) return;
5786
+ dataTransfer.effectAllowed = "move";
5787
+ dataTransfer.setData("text/plain", card.id);
5788
+ };
5789
+ const dragEnd = () => {
5320
5790
  setDragging(null);
5321
5791
  setOver(null);
5322
- },
5323
- onDragOver: (e) => {
5324
- if (!dragging) return;
5325
- e.preventDefault();
5326
- e.stopPropagation();
5327
- const r = e.currentTarget.getBoundingClientRect();
5328
- const after = e.clientY > r.top + r.height / 2;
5329
- setOver({
5330
- column: card.columnId,
5331
- index: index + (after ? 1 : 0)
5332
- });
5333
- },
5334
- onDrop: (e) => {
5335
- e.preventDefault();
5336
- e.stopPropagation();
5337
- if (over) drop(over.column, over.index);
5338
- },
5339
- 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"),
5340
- children: [
5792
+ };
5793
+ const common = {
5794
+ "data-kanban-card": card.id,
5795
+ draggable: !isMobile && Boolean(onCardMove),
5796
+ onDragOver: (e) => {
5797
+ if (!dragging) return;
5798
+ e.preventDefault();
5799
+ e.stopPropagation();
5800
+ const r = e.currentTarget.getBoundingClientRect();
5801
+ const after = e.clientY > r.top + r.height / 2;
5802
+ setOver({
5803
+ column: card.columnId,
5804
+ index: index + (after ? 1 : 0)
5805
+ });
5806
+ },
5807
+ onDrop: (e) => {
5808
+ e.preventDefault();
5809
+ e.stopPropagation();
5810
+ if (over) drop(over.column, over.index);
5811
+ },
5812
+ 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")
5813
+ };
5814
+ const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [
5341
5815
  onCardClick ? /* @__PURE__ */ jsx("button", {
5342
5816
  type: "button",
5343
5817
  onClick: () => onCardClick(card),
@@ -5371,8 +5845,38 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
5371
5845
  className: "absolute top-2 right-2 z-10",
5372
5846
  children: moveMenu(card)
5373
5847
  })
5374
- ]
5375
- }, card.id);
5848
+ ] });
5849
+ if (motion === "on") {
5850
+ const layout = layoutEnabled({
5851
+ mode: motion,
5852
+ ready,
5853
+ dragging: touchDrag !== null
5854
+ });
5855
+ return /* @__PURE__ */ jsx(m.li, {
5856
+ ref: (el) => {
5857
+ if (!el) return;
5858
+ const onStart = (e) => dragStart(e.dataTransfer);
5859
+ el.addEventListener("dragstart", onStart);
5860
+ el.addEventListener("dragend", dragEnd);
5861
+ return () => {
5862
+ el.removeEventListener("dragstart", onStart);
5863
+ el.removeEventListener("dragend", dragEnd);
5864
+ };
5865
+ },
5866
+ layout,
5867
+ layoutId: layout ? `${boardId}-${card.id}` : void 0,
5868
+ transition: presets.settle,
5869
+ ...common,
5870
+ children: body
5871
+ }, card.id);
5872
+ }
5873
+ return /* @__PURE__ */ jsx("li", {
5874
+ onDragStart: (e) => dragStart(e.dataTransfer),
5875
+ onDragEnd: dragEnd,
5876
+ ...common,
5877
+ children: body
5878
+ }, card.id);
5879
+ };
5376
5880
  const totals = (col) => (valueFields ?? []).slice(0, 2).map((f) => ({
5377
5881
  ...f,
5378
5882
  total: inColumn(col.id).reduce((sum, c) => sum + (c.values?.[f.key] ?? 0), 0)
@@ -5454,7 +5958,7 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
5454
5958
  else onLoadMore?.(col.id);
5455
5959
  } })
5456
5960
  ]
5457
- })
5961
+ }, String(ready))
5458
5962
  });
5459
5963
  };
5460
5964
  if (isMobile) return /* @__PURE__ */ jsxs("div", {
@@ -5575,14 +6079,26 @@ function List({ items, divided = true, empty, className, onReorder, itemLabel =
5575
6079
  onReorder: onReorder && ((sorted) => onReorder(sorted.map((s) => s.data)))
5576
6080
  });
5577
6081
  const sortableEnabled = Boolean(onReorder);
6082
+ const motion = useMotionMode();
6083
+ const ready = useLayoutReady();
6084
+ const presets = useMotionPresets();
6085
+ const Item = motion === "on" ? m.li : "li";
6086
+ const itemMotion = motion === "on" ? {
6087
+ layout: layoutEnabled({
6088
+ mode: motion,
6089
+ ready,
6090
+ dragging: sortable.draggingId !== null
6091
+ }),
6092
+ transition: presets.move
6093
+ } : {};
5578
6094
  const code = resolveCatalogCode("List", { sortable: sortableEnabled });
5579
- if (items.length === 0 && empty) return /* @__PURE__ */ jsx(Fragment, { children: empty });
6095
+ if (items.length === 0 && empty) return /* @__PURE__ */ jsx(Fragment$1, { children: empty });
5580
6096
  return /* @__PURE__ */ jsx("ul", {
5581
6097
  "data-rendra": code,
5582
6098
  className: cn("flex w-full min-w-0 flex-col", divided && "divide-y", className),
5583
6099
  children: items.map((it) => {
5584
6100
  const interactive = Boolean(it.to || it.onClick);
5585
- const body = /* @__PURE__ */ jsxs(Fragment, { children: [
6101
+ const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [
5586
6102
  it.leading && /* @__PURE__ */ jsx("span", {
5587
6103
  className: "flex shrink-0",
5588
6104
  children: it.leading
@@ -5618,8 +6134,9 @@ function List({ items, divided = true, empty, className, onReorder, itemLabel =
5618
6134
  label: `Reordenar ${label}`,
5619
6135
  sortable
5620
6136
  });
5621
- return /* @__PURE__ */ jsxs("li", {
6137
+ return /* @__PURE__ */ jsxs(Item, {
5622
6138
  ...sortableEnabled ? sortable.itemProps(it.id) : {},
6139
+ ...itemMotion,
5623
6140
  className: cn("flex min-w-0 items-center gap-1", sortable.draggingId === it.id && "opacity-50"),
5624
6141
  children: [handle, it.to ? /* @__PURE__ */ jsx(Link, {
5625
6142
  to: it.to,
@@ -5636,7 +6153,7 @@ function List({ items, divided = true, empty, className, onReorder, itemLabel =
5636
6153
  })]
5637
6154
  }, it.id);
5638
6155
  })
5639
- });
6156
+ }, String(ready));
5640
6157
  }
5641
6158
  //#endregion
5642
6159
  //#region src/components/ui/otp-input.tsx
@@ -5646,6 +6163,9 @@ function List({ items, divided = true, empty, className, onReorder, itemLabel =
5646
6163
  */
5647
6164
  function OtpInput({ length = 6, value, onChange, onComplete, invalid, disabled, id, ...aria }) {
5648
6165
  const refs = useRef([]);
6166
+ const on = useMotionMode() === "on";
6167
+ const presets = useMotionPresets();
6168
+ const Cell = on ? m.input : "input";
5649
6169
  const digits = Array.from({ length }, (_, i) => value[i] ?? "");
5650
6170
  const set = (next) => {
5651
6171
  const clean = next.replace(/\D/g, "").slice(0, length);
@@ -5671,7 +6191,8 @@ function OtpInput({ length = 6, value, onChange, onComplete, invalid, disabled,
5671
6191
  "data-rendra": "OTP-001",
5672
6192
  className: "grid w-full max-w-sm grid-cols-otp gap-1 sm:gap-2",
5673
6193
  style: { "--otp": length },
5674
- children: digits.map((d, i) => /* @__PURE__ */ jsx("input", {
6194
+ children: digits.map((d, i) => /* @__PURE__ */ jsx(Cell, {
6195
+ ...on ? { animate: d ? presets.bump : void 0 } : {},
5675
6196
  ref: (el) => {
5676
6197
  refs.current[i] = el;
5677
6198
  },
@@ -5836,7 +6357,7 @@ function Pagination({ page, pageSize, total, onPageChange, onPageSizeChange, pag
5836
6357
  }
5837
6358
  //#endregion
5838
6359
  //#region src/components/ui/progress.tsx
5839
- var bar = cva("h-full rounded-full transition-[width] duration-300 ease-out", {
6360
+ var bar = cva("h-full rounded-full transition-[width] duration-(--rendra-duration-base) ease-linear", {
5840
6361
  variants: { tone: {
5841
6362
  primary: "bg-primary",
5842
6363
  brand: "bg-gradient-accent",
@@ -5855,6 +6376,7 @@ function Progress({ value, size = "md", tone, showValue, label, className }) {
5855
6376
  children: [/* @__PURE__ */ jsx(Progress$1.Root, {
5856
6377
  value: indeterminate ? null : value,
5857
6378
  "aria-label": label,
6379
+ "data-allow-overflow": true,
5858
6380
  className: cn("relative w-full overflow-hidden rounded-full bg-muted", size === "sm" ? "h-1" : "h-2"),
5859
6381
  children: /* @__PURE__ */ jsx(Progress$1.Indicator, {
5860
6382
  className: cn(bar({ tone }), indeterminate ? "absolute inset-y-0 left-0 w-1/3 progress-slide" : "w-progress"),
@@ -6694,26 +7216,60 @@ var cols = {
6694
7216
  2: "md:grid-cols-2",
6695
7217
  3: "md:grid-cols-3"
6696
7218
  };
7219
+ /**
7220
+ * O item do Radix. Em `on` ele é um `m.button` (asChild) que responde ao toque (whileTap 0,97,
7221
+ * em `press`); em `off` é o `R.Item` de sempre, sem nó novo.
7222
+ */
7223
+ function Item({ on, children, ...props }) {
7224
+ const presets = useMotionPresets();
7225
+ if (!on) return /* @__PURE__ */ jsx(RadioGroup$1.Item, {
7226
+ ...props,
7227
+ children
7228
+ });
7229
+ return /* @__PURE__ */ jsx(RadioGroup$1.Item, {
7230
+ asChild: true,
7231
+ ...props,
7232
+ children: /* @__PURE__ */ jsx(m.button, {
7233
+ type: "button",
7234
+ whileTap: presets.press.whileTap,
7235
+ transition: presets.press.transition,
7236
+ children
7237
+ })
7238
+ });
7239
+ }
6697
7240
  /** Radio único: em lista ou em cards, por prop. */
6698
7241
  function RadioGroup({ options, value, defaultValue, onChange, variant = "list", columns = 2, orientation = "vertical", invalid, disabled, id, name, ...aria }) {
6699
- const dot = /* @__PURE__ */ jsx("span", {
7242
+ const on = useMotionMode() === "on";
7243
+ const presets = useMotionPresets();
7244
+ const [inner, setInner] = useState(defaultValue);
7245
+ const current = value ?? inner;
7246
+ const dotFor = (optionValue) => /* @__PURE__ */ jsx("span", {
6700
7247
  "aria-hidden": true,
6701
7248
  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"),
6702
- children: /* @__PURE__ */ jsx("span", { className: "size-2 scale-0 rounded-full bg-primary transition-transform duration-150 group-data-[state=checked]:scale-100" })
7249
+ children: on ? /* @__PURE__ */ jsx(m.span, {
7250
+ className: "size-2 rounded-full bg-primary",
7251
+ initial: false,
7252
+ animate: current === optionValue ? presets.indicator.animate : presets.indicator.initial,
7253
+ transition: presets.indicator.transition
7254
+ }) : /* @__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" })
6703
7255
  });
6704
7256
  return /* @__PURE__ */ jsx(RadioGroup$1.Root, {
6705
7257
  id,
6706
7258
  name,
6707
- value,
6708
- defaultValue,
6709
- onValueChange: onChange,
7259
+ value: on ? current : value,
7260
+ defaultValue: on ? void 0 : defaultValue,
7261
+ onValueChange: (v) => {
7262
+ if (on) setInner(v);
7263
+ onChange?.(v);
7264
+ },
6710
7265
  disabled,
6711
7266
  "aria-invalid": invalid || void 0,
6712
7267
  "aria-describedby": aria["aria-describedby"],
6713
7268
  "aria-label": aria["aria-label"],
6714
7269
  "data-rendra": resolveCatalogCode("RadioGroup", { variant }),
6715
7270
  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"),
6716
- children: options.map((o) => variant === "cards" ? /* @__PURE__ */ jsxs(RadioGroup$1.Item, {
7271
+ children: options.map((o) => variant === "cards" ? /* @__PURE__ */ jsxs(Item, {
7272
+ on,
6717
7273
  value: o.value,
6718
7274
  disabled: o.disabled,
6719
7275
  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"),
@@ -6732,15 +7288,16 @@ function RadioGroup({ options, value, defaultValue, onChange, variant = "list",
6732
7288
  children: o.description
6733
7289
  })]
6734
7290
  }),
6735
- dot
7291
+ dotFor(o.value)
6736
7292
  ]
6737
7293
  }, o.value) : /* @__PURE__ */ jsxs("label", {
6738
7294
  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"),
6739
- children: [/* @__PURE__ */ jsx(RadioGroup$1.Item, {
7295
+ children: [/* @__PURE__ */ jsx(Item, {
7296
+ on,
6740
7297
  value: o.value,
6741
7298
  disabled: o.disabled,
6742
7299
  className: "group flex pt-px outline-none focus-visible:[&>span]:focus-ring",
6743
- children: dot
7300
+ children: dotFor(o.value)
6744
7301
  }), /* @__PURE__ */ jsxs("span", {
6745
7302
  className: "flex min-w-0 flex-col gap-1",
6746
7303
  children: [/* @__PURE__ */ jsx("span", {
@@ -6975,18 +7532,65 @@ function Separator({ orientation = "horizontal", label, className }) {
6975
7532
  }
6976
7533
  //#endregion
6977
7534
  //#region src/components/ui/skeleton.tsx
6978
- /** Bloco de carregamento. Monte o skeleton com a mesma estrutura do conteúdo final. */
7535
+ /**
7536
+ * Bloco de carregamento. Monte o skeleton com a mesma estrutura do conteúdo final. Em `off` pulsa
7537
+ * (animate-pulse do Tailwind); em `on` um brilho suave cruza o bloco (skeleton-shimmer, em
7538
+ * globals.css: transform, tempo e curva pelos tokens, parado com "reduzir movimento").
7539
+ */
6979
7540
  function Skeleton({ className, ...props }) {
7541
+ const on = useMotionMode() === "on";
6980
7542
  return /* @__PURE__ */ jsx("div", {
6981
7543
  "aria-hidden": true,
6982
7544
  "data-slot": "skeleton",
6983
7545
  "data-rendra": "SKEL-001",
6984
- className: cn("animate-pulse rounded-block bg-muted", className),
7546
+ className: cn(on ? "skeleton-shimmer" : "animate-pulse", "rounded-block bg-muted", className),
6985
7547
  ...props
6986
7548
  });
6987
7549
  }
6988
7550
  //#endregion
6989
7551
  //#region src/components/ui/stat-card.tsx
7552
+ /** Contagem de 0 até o valor, com o formato do texto original; no fim mostra o `value` exato. */
7553
+ function Counter({ parsed, value }) {
7554
+ const presets = useMotionPresets();
7555
+ const progress = useMotionValue(0);
7556
+ const text = useTransform(progress, (n) => formatLike(parsed, n));
7557
+ const [done, setDone] = useState(false);
7558
+ useEffect(() => {
7559
+ const controls = animate(progress, parsed.value, {
7560
+ duration: presets.tokens.reveal.count,
7561
+ ease: presets.tokens.ease.out,
7562
+ onComplete: () => setDone(true)
7563
+ });
7564
+ return () => controls.stop();
7565
+ }, [
7566
+ progress,
7567
+ parsed.value,
7568
+ presets.tokens
7569
+ ]);
7570
+ return /* @__PURE__ */ jsx(m.span, {
7571
+ ...presets.fade,
7572
+ children: done ? value : text
7573
+ });
7574
+ }
7575
+ /**
7576
+ * O valor do card. Em `off`, o valor como sempre veio. Em `on`, número (ou texto pt-BR com
7577
+ * número) conta até o valor; qualquer outra coisa só aparece com fade. Com "reduzir movimento"
7578
+ * o valor final aparece direto.
7579
+ */
7580
+ function StatValue({ value }) {
7581
+ const motion = useMotionMode();
7582
+ const presets = useMotionPresets();
7583
+ const parsed = useMemo(() => parseLocaleNumber$1(value), [value]);
7584
+ if (motion !== "on") return /* @__PURE__ */ jsx(Fragment$1, { children: value });
7585
+ if (!parsed || presets.reduced) return /* @__PURE__ */ jsx(m.span, {
7586
+ ...presets.fade,
7587
+ children: value
7588
+ });
7589
+ return /* @__PURE__ */ jsx(Counter, {
7590
+ parsed,
7591
+ value
7592
+ }, String(value));
7593
+ }
6990
7594
  /** Card de indicador. Em grid: 1 coluna no mobile, 2 para cards pequenos. */
6991
7595
  function StatCard({ label, value, change, changeLabel, inverse, icon, highlight, loading, footer, className }) {
6992
7596
  const up = (change ?? 0) > 0;
@@ -7008,9 +7612,9 @@ function StatCard({ label, value, change, changeLabel, inverse, icon, highlight,
7008
7612
  children: icon
7009
7613
  })]
7010
7614
  }),
7011
- loading ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-24" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-16" })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
7615
+ loading ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-24" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-16" })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
7012
7616
  className: "text-2xl font-semibold tracking-tight tabular-nums @xs:text-3xl",
7013
- children: value
7617
+ children: /* @__PURE__ */ jsx(StatValue, { value })
7014
7618
  }), change !== void 0 && /* @__PURE__ */ jsxs("span", {
7015
7619
  className: "flex flex-wrap items-center gap-1 text-xs",
7016
7620
  children: [/* @__PURE__ */ jsxs("span", {
@@ -7094,7 +7698,7 @@ function CellContent({ col, row, title }) {
7094
7698
  className: cn("rounded-item font-medium text-foreground underline-offset-4 transition-colors outline-none hover:text-primary-text hover:underline focus-visible:ring-2 focus-visible:ring-ring", title && "inline-flex min-h-touch items-center md:min-h-0"),
7095
7699
  children: main
7096
7700
  }) : main;
7097
- if (!extra.length) return /* @__PURE__ */ jsx(Fragment, { children: value });
7701
+ if (!extra.length) return /* @__PURE__ */ jsx(Fragment$1, { children: value });
7098
7702
  return /* @__PURE__ */ jsxs("span", {
7099
7703
  className: "flex min-w-0 flex-col",
7100
7704
  children: [/* @__PURE__ */ jsx("span", {
@@ -7174,8 +7778,68 @@ var tableFeatureSet = tableFeatures({
7174
7778
  * Mobile (< 768px): a mesma tabela vira lista de cards, sem rolagem horizontal.
7175
7779
  * Desktop: tabela larga rola na horizontal só dentro do próprio contêiner.
7176
7780
  */
7781
+ /**
7782
+ * Bloco "Ver detalhes" do card no celular. Em `on` a altura abre e fecha pelos presets e o
7783
+ * conteúdo fechado sai do DOM; em `off` é o Collapsible de sempre, com as animações em CSS.
7784
+ */
7785
+ function MobileDetails({ children }) {
7786
+ const motion = useMotionMode();
7787
+ const presets = useMotionPresets();
7788
+ const [open, setOpen] = useState(false);
7789
+ const trigger = /* @__PURE__ */ jsxs(Collapsible.Trigger, {
7790
+ className: "group flex min-h-touch cursor-pointer items-center gap-1 text-sm font-medium text-primary-text",
7791
+ children: [
7792
+ /* @__PURE__ */ jsx("span", {
7793
+ className: "group-data-[state=open]:hidden",
7794
+ children: "Ver detalhes"
7795
+ }),
7796
+ /* @__PURE__ */ jsx("span", {
7797
+ className: "hidden group-data-[state=open]:inline",
7798
+ children: "Ocultar detalhes"
7799
+ }),
7800
+ /* @__PURE__ */ jsx(ChevronDown, {
7801
+ className: "size-icon-sm transition-transform duration-(--rendra-duration-base) ease-move group-data-[state=open]:rotate-180",
7802
+ "aria-hidden": true
7803
+ })
7804
+ ]
7805
+ });
7806
+ if (motion === "on") return /* @__PURE__ */ jsxs(Collapsible.Root, {
7807
+ open,
7808
+ onOpenChange: setOpen,
7809
+ children: [trigger, /* @__PURE__ */ jsx(AnimatePresence, {
7810
+ initial: false,
7811
+ children: open && /* @__PURE__ */ jsx(Collapsible.Content, {
7812
+ forceMount: true,
7813
+ asChild: true,
7814
+ children: /* @__PURE__ */ jsx(m.div, {
7815
+ className: "overflow-hidden",
7816
+ initial: {
7817
+ height: 0,
7818
+ opacity: 0
7819
+ },
7820
+ animate: {
7821
+ height: "auto",
7822
+ opacity: 1
7823
+ },
7824
+ exit: {
7825
+ height: 0,
7826
+ opacity: 0
7827
+ },
7828
+ transition: presets.fade.transition,
7829
+ children
7830
+ })
7831
+ })
7832
+ })]
7833
+ });
7834
+ return /* @__PURE__ */ jsxs(Collapsible.Root, { children: [trigger, /* @__PURE__ */ jsx(Collapsible.Content, {
7835
+ className: "overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
7836
+ children
7837
+ })] });
7838
+ }
7177
7839
  function Table({ data: dataProp, source, queryKey = "", columns: columnsProp, statusLast = true, getRowId, selectable, expandable, sortable = true, globalFilter, columnVisibility, bulkActions, bulkMenu, rowActions, density = "default", loading, error, onRetry, empty, pageSize: pageSizeProp = 15, mobilePagination = "pages", toolbar, ...aria }) {
7178
7840
  const { isMobile } = useBreakpoint();
7841
+ const on = useMotionMode() === "on";
7842
+ const presets = useMotionPresets();
7179
7843
  const columns = useMemo(() => statusLast ? [...columnsProp.filter((c) => c.kind !== "badge"), ...columnsProp.filter((c) => c.kind === "badge")] : columnsProp, [columnsProp, statusLast]);
7180
7844
  const [sorting, setSorting] = useState([]);
7181
7845
  const [rowSelection, setRowSelection] = useState({});
@@ -7342,7 +8006,7 @@ function Table({ data: dataProp, source, queryKey = "", columns: columnsProp, st
7342
8006
  label: `${c.header} (decrescente)`
7343
8007
  }])
7344
8008
  }) : void 0;
7345
- const selectionBar = selectable && selectedRows.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
8009
+ const selectionBar = selectable && selectedRows.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
7346
8010
  /* @__PURE__ */ jsxs("span", {
7347
8011
  className: "text-sm font-medium tabular-nums",
7348
8012
  children: [
@@ -7433,43 +8097,24 @@ function Table({ data: dataProp, source, queryKey = "", columns: columnsProp, st
7433
8097
  }, c.id))]
7434
8098
  })]
7435
8099
  }),
7436
- (secondary.length > 0 || expandable) && /* @__PURE__ */ jsxs(Collapsible.Root, { children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, {
7437
- className: "group flex min-h-touch cursor-pointer items-center gap-1 text-sm font-medium text-primary-text",
7438
- children: [
7439
- /* @__PURE__ */ jsx("span", {
7440
- className: "group-data-[state=open]:hidden",
7441
- children: "Ver detalhes"
7442
- }),
7443
- /* @__PURE__ */ jsx("span", {
7444
- className: "hidden group-data-[state=open]:inline",
7445
- children: "Ocultar detalhes"
7446
- }),
7447
- /* @__PURE__ */ jsx(ChevronDown, {
7448
- className: "size-icon-sm transition-transform duration-200 group-data-[state=open]:rotate-180",
7449
- "aria-hidden": true
7450
- })
7451
- ]
7452
- }), /* @__PURE__ */ jsxs(Collapsible.Content, {
7453
- className: "overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
7454
- children: [/* @__PURE__ */ jsx("dl", {
7455
- className: "grid grid-cols-1 gap-3 pt-2 sm:grid-cols-2",
7456
- children: secondary.map((c) => /* @__PURE__ */ jsxs("div", {
7457
- className: "flex flex-col gap-1",
7458
- children: [/* @__PURE__ */ jsx("dt", {
7459
- className: "text-xs text-muted-foreground",
7460
- children: c.header
7461
- }), /* @__PURE__ */ jsx("dd", {
7462
- className: "text-sm",
7463
- children: /* @__PURE__ */ jsx(CellContent, {
7464
- col: c,
7465
- row
7466
- })
7467
- })]
7468
- }, c.id))
7469
- }), expandable && /* @__PURE__ */ jsx("div", {
7470
- className: "pt-3",
7471
- children: expandable(row)
7472
- })]
8100
+ (secondary.length > 0 || expandable) && /* @__PURE__ */ jsxs(MobileDetails, { children: [/* @__PURE__ */ jsx("dl", {
8101
+ className: "grid grid-cols-1 gap-3 pt-2 sm:grid-cols-2",
8102
+ children: secondary.map((c) => /* @__PURE__ */ jsxs("div", {
8103
+ className: "flex flex-col gap-1",
8104
+ children: [/* @__PURE__ */ jsx("dt", {
8105
+ className: "text-xs text-muted-foreground",
8106
+ children: c.header
8107
+ }), /* @__PURE__ */ jsx("dd", {
8108
+ className: "text-sm",
8109
+ children: /* @__PURE__ */ jsx(CellContent, {
8110
+ col: c,
8111
+ row
8112
+ })
8113
+ })]
8114
+ }, c.id))
8115
+ }), expandable && /* @__PURE__ */ jsx("div", {
8116
+ className: "pt-3",
8117
+ children: expandable(row)
7473
8118
  })] }),
7474
8119
  rowActions && rowActions.length > 0 && /* @__PURE__ */ jsx("div", {
7475
8120
  className: "border-t pt-3",
@@ -7559,59 +8204,92 @@ function Table({ data: dataProp, source, queryKey = "", columns: columnsProp, st
7559
8204
  })
7560
8205
  ] }, i)) : rows.map((r) => {
7561
8206
  const row = r.original;
7562
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("tr", {
7563
- "data-state": r.getIsSelected() ? "selected" : void 0,
7564
- className: "group/row transition-colors hover:bg-muted/40 data-[state=selected]:bg-primary-soft/60",
7565
- children: [
7566
- selectable && /* @__PURE__ */ jsx("td", {
7567
- className: "pr-2 pl-4",
7568
- children: /* @__PURE__ */ jsx(Checkbox, {
7569
- "aria-label": "Selecionar linha",
7570
- checked: r.getIsSelected(),
7571
- onCheckedChange: (v) => r.toggleSelected(v)
7572
- })
7573
- }),
7574
- expandable && /* @__PURE__ */ jsx("td", {
7575
- className: "px-2",
7576
- children: /* @__PURE__ */ jsx(Button, {
7577
- variant: "ghost",
7578
- size: "sm",
7579
- iconOnly: true,
7580
- "aria-label": r.getIsExpanded() ? "Recolher linha" : "Expandir linha",
7581
- "aria-expanded": r.getIsExpanded(),
7582
- onClick: () => r.toggleExpanded(),
7583
- children: /* @__PURE__ */ jsx(ChevronDown, { className: cn("transition-transform", r.getIsExpanded() && "rotate-180") })
7584
- })
7585
- }),
7586
- visibleCols.map((c) => {
7587
- const align = alignOf(c);
7588
- return /* @__PURE__ */ jsx("td", {
7589
- className: cn("px-4 align-middle", pad, align === "right" ? "text-right tabular-nums" : align === "center" ? "text-center" : "text-left", c.width && minWidth[c.width]),
7590
- children: /* @__PURE__ */ jsx("div", {
7591
- className: cn(clamp[c.lines ?? 2], align === "right" && "ml-auto"),
7592
- children: /* @__PURE__ */ jsx(CellContent, {
7593
- col: c,
7594
- row
8207
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
8208
+ /* @__PURE__ */ jsxs("tr", {
8209
+ "data-state": r.getIsSelected() ? "selected" : void 0,
8210
+ className: "group/row transition-colors hover:bg-muted/40 data-[state=selected]:bg-primary-soft/60",
8211
+ children: [
8212
+ selectable && /* @__PURE__ */ jsx("td", {
8213
+ className: "pr-2 pl-4",
8214
+ children: /* @__PURE__ */ jsx(Checkbox, {
8215
+ "aria-label": "Selecionar linha",
8216
+ checked: r.getIsSelected(),
8217
+ onCheckedChange: (v) => r.toggleSelected(v)
8218
+ })
8219
+ }),
8220
+ expandable && /* @__PURE__ */ jsx("td", {
8221
+ className: "px-2",
8222
+ children: /* @__PURE__ */ jsx(Button, {
8223
+ variant: "ghost",
8224
+ size: "sm",
8225
+ iconOnly: true,
8226
+ "aria-label": r.getIsExpanded() ? "Recolher linha" : "Expandir linha",
8227
+ "aria-expanded": r.getIsExpanded(),
8228
+ onClick: () => r.toggleExpanded(),
8229
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: cn("transition-transform", r.getIsExpanded() && "rotate-180") })
8230
+ })
8231
+ }),
8232
+ visibleCols.map((c) => {
8233
+ const align = alignOf(c);
8234
+ return /* @__PURE__ */ jsx("td", {
8235
+ className: cn("px-4 align-middle", pad, align === "right" ? "text-right tabular-nums" : align === "center" ? "text-center" : "text-left", c.width && minWidth[c.width]),
8236
+ children: /* @__PURE__ */ jsx("div", {
8237
+ className: cn(clamp[c.lines ?? 2], align === "right" && "ml-auto"),
8238
+ children: /* @__PURE__ */ jsx(CellContent, {
8239
+ col: c,
8240
+ row
8241
+ })
7595
8242
  })
8243
+ }, c.id);
8244
+ }),
8245
+ rowActions && /* @__PURE__ */ jsx("td", {
8246
+ className: "sticky right-0 w-24 bg-card px-4 group-hover/row:bg-muted group-data-[state=selected]/row:bg-primary-soft",
8247
+ children: /* @__PURE__ */ jsx(RowActions, {
8248
+ row,
8249
+ actions: rowActions
7596
8250
  })
7597
- }, c.id);
7598
- }),
7599
- rowActions && /* @__PURE__ */ jsx("td", {
7600
- className: "sticky right-0 w-24 bg-card px-4 group-hover/row:bg-muted group-data-[state=selected]/row:bg-primary-soft",
7601
- children: /* @__PURE__ */ jsx(RowActions, {
7602
- row,
7603
- actions: rowActions
7604
8251
  })
8252
+ ]
8253
+ }),
8254
+ expandable && !on && r.getIsExpanded() && /* @__PURE__ */ jsx("tr", {
8255
+ className: "bg-muted/30",
8256
+ children: /* @__PURE__ */ jsx("td", {
8257
+ colSpan: visibleCols.length + (selectable ? 1 : 0) + 1 + (rowActions ? 1 : 0),
8258
+ className: "px-4 py-4",
8259
+ children: expandable(row)
7605
8260
  })
7606
- ]
7607
- }), expandable && r.getIsExpanded() && /* @__PURE__ */ jsx("tr", {
7608
- className: "bg-muted/30",
7609
- children: /* @__PURE__ */ jsx("td", {
7610
- colSpan: visibleCols.length + (selectable ? 1 : 0) + 1 + (rowActions ? 1 : 0),
7611
- className: "px-4 py-4",
7612
- children: expandable(row)
8261
+ }),
8262
+ expandable && on && /* @__PURE__ */ jsx(AnimatePresence, {
8263
+ initial: false,
8264
+ children: r.getIsExpanded() && /* @__PURE__ */ jsx("tr", {
8265
+ className: "bg-muted/30",
8266
+ children: /* @__PURE__ */ jsx("td", {
8267
+ colSpan: visibleCols.length + (selectable ? 1 : 0) + 1 + (rowActions ? 1 : 0),
8268
+ className: "px-4",
8269
+ children: /* @__PURE__ */ jsx(m.div, {
8270
+ className: "overflow-hidden",
8271
+ initial: {
8272
+ height: 0,
8273
+ opacity: 0
8274
+ },
8275
+ animate: {
8276
+ height: "auto",
8277
+ opacity: 1
8278
+ },
8279
+ exit: {
8280
+ height: 0,
8281
+ opacity: 0
8282
+ },
8283
+ transition: presets.fade.transition,
8284
+ children: /* @__PURE__ */ jsx("div", {
8285
+ className: "py-4",
8286
+ children: expandable(row)
8287
+ })
8288
+ })
8289
+ })
8290
+ }, "expanded")
7613
8291
  })
7614
- })] }, r.id);
8292
+ ] }, r.id);
7615
8293
  })
7616
8294
  })]
7617
8295
  })
@@ -7738,14 +8416,25 @@ var statusTextTone = {
7738
8416
  };
7739
8417
  /** Linha do tempo única, com eventos em ordem e tom semântico por evento. */
7740
8418
  function Timeline({ events, className }) {
8419
+ const on = useMotionMode() === "on";
8420
+ const presets = useMotionPresets();
8421
+ const Item = on ? m.li : "li";
8422
+ const enter = presets.slide("bottom", "short");
7741
8423
  return /* @__PURE__ */ jsx("ol", {
7742
8424
  "data-rendra": "TLN-001",
7743
8425
  className: cn("@container flex flex-col", className),
7744
8426
  children: events.map((e, i) => {
7745
8427
  const StatusIcon = e.status ? statusIcon[e.status] : null;
7746
8428
  const tone = e.tone ?? (e.status ? statusTone[e.status] : "neutral");
7747
- return /* @__PURE__ */ jsxs("li", {
8429
+ return /* @__PURE__ */ jsxs(Item, {
7748
8430
  className: "relative flex gap-3 pb-6 last:pb-0",
8431
+ ...on ? {
8432
+ ...enter,
8433
+ transition: {
8434
+ ...enter.transition,
8435
+ ...presets.stagger(i)
8436
+ }
8437
+ } : {},
7749
8438
  children: [
7750
8439
  i < events.length - 1 && /* @__PURE__ */ jsx("span", {
7751
8440
  "aria-hidden": true,
@@ -7762,7 +8451,7 @@ function Timeline({ events, className }) {
7762
8451
  /* @__PURE__ */ jsxs("div", {
7763
8452
  className: "flex min-w-0 flex-col gap-1 @sm:flex-row @sm:items-baseline @sm:justify-between @sm:gap-3",
7764
8453
  children: [/* @__PURE__ */ jsx("span", {
7765
- className: "text-sm font-medium",
8454
+ className: "text-sm font-medium wrap-break-word",
7766
8455
  children: e.title
7767
8456
  }), /* @__PURE__ */ jsx("time", {
7768
8457
  className: "shrink-0 text-xs text-muted-foreground tabular-nums",
@@ -7770,7 +8459,7 @@ function Timeline({ events, className }) {
7770
8459
  })]
7771
8460
  }),
7772
8461
  e.description && /* @__PURE__ */ jsx("p", {
7773
- className: "text-sm text-muted-foreground",
8462
+ className: "text-sm wrap-break-word text-muted-foreground",
7774
8463
  children: e.description
7775
8464
  }),
7776
8465
  e.status && StatusIcon && /* @__PURE__ */ jsxs("span", {
@@ -7807,10 +8496,10 @@ function show(type, title, opts = {}) {
7807
8496
  /* @__PURE__ */ jsxs("div", {
7808
8497
  className: "flex min-w-0 flex-1 flex-col gap-1",
7809
8498
  children: [/* @__PURE__ */ jsx("p", {
7810
- className: "text-sm font-semibold",
8499
+ className: "text-sm font-semibold wrap-break-word",
7811
8500
  children: title
7812
8501
  }), opts.description && /* @__PURE__ */ jsx("p", {
7813
- className: "text-sm text-muted-foreground",
8502
+ className: "text-sm wrap-break-word text-muted-foreground",
7814
8503
  children: opts.description
7815
8504
  })]
7816
8505
  }),
@@ -7990,6 +8679,27 @@ function Upload({ accept, multiple = true, maxSizeMb = 10, onUpload, onChange, h
7990
8679
  onReorder?.(sorted.map((s) => s.id));
7991
8680
  }
7992
8681
  });
8682
+ const motion = useMotionMode();
8683
+ const ready = useLayoutReady();
8684
+ const presets = useMotionPresets();
8685
+ const Item = motion === "on" ? m.li : "li";
8686
+ const itemMotion = motion === "on" ? {
8687
+ ...presets.fade,
8688
+ layout: layoutEnabled({
8689
+ mode: motion,
8690
+ ready,
8691
+ dragging: sortable.draggingId !== null
8692
+ }),
8693
+ transition: {
8694
+ ...presets.fade.transition,
8695
+ layout: presets.move
8696
+ }
8697
+ } : {};
8698
+ const animated = (nodes) => motion === "on" ? /* @__PURE__ */ jsx(AnimatePresence, {
8699
+ mode: "popLayout",
8700
+ initial: false,
8701
+ children: nodes
8702
+ }) : nodes;
7993
8703
  const dropzone = !(maxItems !== void 0 && items.length + pendingCrop.length >= maxItems) && /* @__PURE__ */ jsxs("label", {
7994
8704
  htmlFor: inputId,
7995
8705
  onDragOver: (e) => {
@@ -8047,8 +8757,9 @@ function Upload({ accept, multiple = true, maxSizeMb = 10, onUpload, onChange, h
8047
8757
  const listView = items.length > 0 && /* @__PURE__ */ jsx("ul", {
8048
8758
  className: "flex flex-col divide-y rounded-control border bg-card",
8049
8759
  "aria-live": "polite",
8050
- children: items.map((it) => /* @__PURE__ */ jsxs("li", {
8760
+ children: animated(items.map((it) => /* @__PURE__ */ jsxs(Item, {
8051
8761
  ...onReorder ? sortable.itemProps(it.id) : {},
8762
+ ...itemMotion,
8052
8763
  className: cn("flex items-center gap-3 p-3", sortable.draggingId === it.id && "opacity-50"),
8053
8764
  children: [
8054
8765
  handle(it),
@@ -8116,12 +8827,13 @@ function Upload({ accept, multiple = true, maxSizeMb = 10, onUpload, onChange, h
8116
8827
  children: /* @__PURE__ */ jsx(Trash2, {})
8117
8828
  })
8118
8829
  ]
8119
- }, it.id))
8120
- });
8830
+ }, it.id)))
8831
+ }, String(ready));
8121
8832
  const galleryView = items.length > 0 && /* @__PURE__ */ jsx("ul", {
8122
8833
  className: "grid grid-cols-2 gap-3 md:grid-cols-3",
8123
- children: items.map((it) => /* @__PURE__ */ jsxs("li", {
8834
+ children: animated(items.map((it) => /* @__PURE__ */ jsxs(Item, {
8124
8835
  ...onReorder ? sortable.itemProps(it.id) : {},
8836
+ ...itemMotion,
8125
8837
  className: cn("relative flex aspect-square flex-col overflow-hidden rounded-control border bg-card", sortable.draggingId === it.id && "opacity-50"),
8126
8838
  children: [
8127
8839
  it.previewUrl && it.kind === "image" ? /* @__PURE__ */ jsx("img", {
@@ -8185,8 +8897,8 @@ function Upload({ accept, multiple = true, maxSizeMb = 10, onUpload, onChange, h
8185
8897
  })]
8186
8898
  })
8187
8899
  ]
8188
- }, it.id))
8189
- });
8900
+ }, it.id)))
8901
+ }, String(ready));
8190
8902
  return /* @__PURE__ */ jsxs("div", {
8191
8903
  "data-rendra": code,
8192
8904
  className: "flex min-w-0 flex-col gap-3",
@@ -8232,6 +8944,8 @@ var statusLabel = {
8232
8944
  */
8233
8945
  function Stepper({ steps, current, errors = [], orientation = "horizontal", onStepClick, className }) {
8234
8946
  const step = steps[current];
8947
+ const motion = useMotionMode();
8948
+ const presets = useMotionPresets();
8235
8949
  return /* @__PURE__ */ jsxs("div", {
8236
8950
  "data-rendra": "WIZ-002",
8237
8951
  className: cn("min-w-0", className),
@@ -8271,7 +8985,15 @@ function Stepper({ steps, current, errors = [], orientation = "horizontal", onSt
8271
8985
  const clickable = onStepClick && st === "complete";
8272
8986
  const circle = /* @__PURE__ */ jsx("span", {
8273
8987
  className: cn("flex size-8 shrink-0 items-center justify-center rounded-full border-2 text-sm font-semibold tabular-nums transition-colors", st === "complete" && "border-primary bg-primary text-primary-foreground", st === "current" && "border-primary bg-card text-primary-text", st === "pending" && "border-border bg-card text-muted-foreground", st === "error" && "border-destructive bg-destructive text-destructive-foreground"),
8274
- children: st === "complete" ? /* @__PURE__ */ jsx(Check, {
8988
+ children: st === "complete" ? motion === "on" ? /* @__PURE__ */ jsx(m.span, {
8989
+ className: "flex",
8990
+ ...presets.pop,
8991
+ children: /* @__PURE__ */ jsx(Check, {
8992
+ className: "size-icon-sm",
8993
+ strokeWidth: 3,
8994
+ "aria-hidden": true
8995
+ })
8996
+ }) : /* @__PURE__ */ jsx(Check, {
8275
8997
  className: "size-icon-sm",
8276
8998
  strokeWidth: 3,
8277
8999
  "aria-hidden": true
@@ -8329,7 +9051,7 @@ function Stepper({ steps, current, errors = [], orientation = "horizontal", onSt
8329
9051
  });
8330
9052
  }
8331
9053
  /** Cadastro em etapas, com validação por etapa e rodapé Voltar / Avançar. */
8332
- function Wizard({ steps, children, onValidateStep, onFinish, onCancel, finishLabel = "Concluir", orientation = "horizontal", stickyFooter = false }) {
9054
+ function Wizard({ steps, children, onValidateStep, onFinish, onCancel, cancelLabel = "Cancelar", backLabel = "Voltar", nextLabel = "Avançar", finishLabel = "Concluir", onSkip, skipLabel = "Pular", orientation = "horizontal", stickyFooter = false }) {
8333
9055
  const [current, setCurrent] = useState(0);
8334
9056
  const [errors, setErrors] = useState([]);
8335
9057
  const [busy, setBusy] = useState(false);
@@ -8348,7 +9070,28 @@ function Wizard({ steps, children, onValidateStep, onFinish, onCancel, finishLab
8348
9070
  setBusy(false);
8349
9071
  }
8350
9072
  };
8351
- const body = /* @__PURE__ */ jsx("div", {
9073
+ const skip = () => {
9074
+ setErrors((e) => e.filter((x) => x !== current));
9075
+ setCurrent((c) => c + 1);
9076
+ onSkip?.();
9077
+ };
9078
+ const motion = useMotionMode();
9079
+ const presets = useMotionPresets();
9080
+ const previous = useRef(current);
9081
+ const direction = current >= previous.current ? 1 : -1;
9082
+ previous.current = current;
9083
+ const body = motion === "on" ? /* @__PURE__ */ jsx("div", {
9084
+ className: "relative flex min-w-0 flex-col gap-6",
9085
+ children: /* @__PURE__ */ jsx(AnimatePresence, {
9086
+ mode: "popLayout",
9087
+ initial: false,
9088
+ children: /* @__PURE__ */ jsx(m.div, {
9089
+ ...presets.swap(direction),
9090
+ className: "flex min-w-0 flex-col gap-6",
9091
+ children: children[current]
9092
+ }, current)
9093
+ })
9094
+ }) : /* @__PURE__ */ jsx("div", {
8352
9095
  className: "flex min-w-0 flex-col gap-6",
8353
9096
  children: children[current]
8354
9097
  });
@@ -8367,15 +9110,19 @@ function Wizard({ steps, children, onValidateStep, onFinish, onCancel, finishLab
8367
9110
  children: [body, /* @__PURE__ */ jsx(ActionBar, {
8368
9111
  sticky: stickyFooter,
8369
9112
  cancel: current > 0 ? {
8370
- label: "Voltar",
9113
+ label: backLabel,
8371
9114
  icon: /* @__PURE__ */ jsx(ArrowLeft, {}),
8372
9115
  onClick: () => setCurrent((c) => c - 1)
8373
9116
  } : onCancel ? {
8374
- label: "Cancelar",
9117
+ label: cancelLabel,
8375
9118
  onClick: onCancel
8376
9119
  } : void 0,
9120
+ secondary: onSkip && !last ? [{
9121
+ label: skipLabel,
9122
+ onClick: skip
9123
+ }] : void 0,
8377
9124
  primary: {
8378
- label: last ? finishLabel : "Avançar",
9125
+ label: last ? finishLabel : nextLabel,
8379
9126
  icon: last ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(ArrowRight, {}),
8380
9127
  onClick: next,
8381
9128
  loading: busy,
@@ -8548,7 +9295,7 @@ function Section({ title, description, actions, level = 2, gap = "4", className,
8548
9295
  * O título fica no header (com a trilha); aqui ele só é lido por leitores de tela,
8549
9296
  * para que cada página tenha um único título principal (h1).
8550
9297
  */
8551
- function PageHeader({ title, showTitle = false, description, help, breadcrumb, actions, children, className }) {
9298
+ function PageHeader({ title, showTitle = false, description, help, breadcrumb, actions, bodyTitle = false, titleSpace = "reserve", children, className }) {
8552
9299
  const shell = useContext(ShellContext);
8553
9300
  const setPageHelp = shell?.setPageHelp;
8554
9301
  useEffect(() => {
@@ -8557,18 +9304,24 @@ function PageHeader({ title, showTitle = false, description, help, breadcrumb, a
8557
9304
  return () => setPageHelp(null);
8558
9305
  }, [help, setPageHelp]);
8559
9306
  const inlineHelp = help && !shell;
9307
+ const visible = showTitle || bodyTitle || description || actions || breadcrumb || children || inlineHelp;
9308
+ const collapseTitle = titleSpace === "none" && !showTitle && !bodyTitle && !inlineHelp && !description;
9309
+ const titleClass = showTitle || inlineHelp ? "text-2xl md:text-3xl" : bodyTitle ? "text-base md:sr-only" : "sr-only";
8560
9310
  return /* @__PURE__ */ jsxs("header", {
8561
- className: cn("-mb-2 flex min-w-0 flex-col gap-4 md:-mb-4", !(showTitle || description || actions || breadcrumb || children || inlineHelp) && "sr-only", className),
9311
+ className: cn("-mb-2 flex min-w-0 flex-col gap-4 md:-mb-4", !visible && "sr-only", className),
8562
9312
  children: [
8563
9313
  breadcrumb && /* @__PURE__ */ jsx(Breadcrumb, { items: breadcrumb }),
8564
9314
  /* @__PURE__ */ jsxs("div", {
8565
9315
  className: "flex min-w-0 flex-col gap-4 md:flex-row md:items-center md:justify-between md:gap-6",
8566
- children: [/* @__PURE__ */ jsxs("div", {
9316
+ children: [collapseTitle ? /* @__PURE__ */ jsx("h1", {
9317
+ className: "sr-only",
9318
+ children: title
9319
+ }) : /* @__PURE__ */ jsxs("div", {
8567
9320
  className: "flex min-w-0 flex-col gap-1",
8568
9321
  children: [/* @__PURE__ */ jsxs("div", {
8569
9322
  className: "flex min-w-0 items-center gap-1",
8570
9323
  children: [/* @__PURE__ */ jsx("h1", {
8571
- className: showTitle || inlineHelp ? "text-2xl md:text-3xl" : "sr-only",
9324
+ className: titleClass,
8572
9325
  children: title
8573
9326
  }), inlineHelp && /* @__PURE__ */ jsx(InfoHint, {
8574
9327
  title: typeof title === "string" ? title : "Sobre esta tela",
@@ -8738,7 +9491,7 @@ function MegaItem({ item }) {
8738
9491
  const Link = useRendraLink();
8739
9492
  const Icon = item.icon;
8740
9493
  const active = item.to ? isActive(pathname, item.to) : false;
8741
- const head = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
9494
+ const head = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
8742
9495
  className: cn("flex size-control-md shrink-0 items-center justify-center rounded-control transition-colors", active ? "bg-primary text-primary-foreground" : "bg-primary-soft text-primary-soft-foreground group-hover/item:bg-primary group-hover/item:text-primary-foreground"),
8743
9496
  children: /* @__PURE__ */ jsx(Icon, {
8744
9497
  className: "size-icon-md",
@@ -8984,7 +9737,7 @@ function ModeItems() {
8984
9737
  }
8985
9738
  function LayoutItems() {
8986
9739
  const { layout, setLayout, resetLayout } = useShell();
8987
- const radio = (key, title) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DropdownMenuLabel, { children: title }), /* @__PURE__ */ jsx(DropdownMenuRadioGroup, {
9740
+ const radio = (key, title) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DropdownMenuLabel, { children: title }), /* @__PURE__ */ jsx(DropdownMenuRadioGroup, {
8988
9741
  value: layout[key],
8989
9742
  onValueChange: (v) => setLayout(key, v),
8990
9743
  children: layoutOptions[key].map((o) => /* @__PURE__ */ jsx(DropdownMenuRadioItem, {
@@ -8993,10 +9746,10 @@ function LayoutItems() {
8993
9746
  }, o.value))
8994
9747
  })] });
8995
9748
  const sidebar = layout.navigation === "sidebar";
8996
- return /* @__PURE__ */ jsxs(Fragment, { children: [
9749
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
8997
9750
  radio("navigation", "Posição do menu"),
8998
- !sidebar && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DropdownMenuSeparator, {}), radio("topbarSubmenu", "Submenu")] }),
8999
- sidebar && /* @__PURE__ */ jsxs(Fragment, { children: [
9751
+ !sidebar && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DropdownMenuSeparator, {}), radio("topbarSubmenu", "Submenu")] }),
9752
+ sidebar && /* @__PURE__ */ jsxs(Fragment$1, { children: [
9000
9753
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
9001
9754
  radio("sidebar", "Sidebar"),
9002
9755
  /* @__PURE__ */ jsx(DropdownMenuCheckboxItem, {
@@ -9025,14 +9778,18 @@ function LayoutItems() {
9025
9778
  }
9026
9779
  function UserMenu() {
9027
9780
  const Link = useRendraLink();
9028
- const { user, userMenuItems, onLogout } = useShell();
9781
+ const { user, userMenuItems, onLogout, userMenu, workspaces } = useShell();
9029
9782
  const { brand, brands, setBrandId, palette, palettes, setPaletteId } = useBrand();
9783
+ const showTheme = userMenu?.theme !== false;
9784
+ const showTemplate = userMenu?.template !== false;
9785
+ const showLayout = userMenu?.layout !== false;
9786
+ const showPreferences = showTheme || showTemplate || showLayout;
9030
9787
  return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
9031
9788
  asChild: true,
9032
9789
  children: /* @__PURE__ */ jsx(Button, {
9033
9790
  variant: "ghost",
9034
9791
  iconOnly: true,
9035
- "aria-label": `Menu de ${user.name}`,
9792
+ "aria-label": `${initials(user.name)}, menu de ${user.name}`,
9036
9793
  children: /* @__PURE__ */ jsx(Avatar, {
9037
9794
  name: user.name,
9038
9795
  src: user.avatarUrl
@@ -9051,7 +9808,19 @@ function UserMenu() {
9051
9808
  children: user.email
9052
9809
  })]
9053
9810
  }),
9054
- userMenuItems.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DropdownMenuSeparator, {}), userMenuItems.map((item) => {
9811
+ workspaces && workspaces.items.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [
9812
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
9813
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { children: workspaces.label ?? "Espaço" }),
9814
+ /* @__PURE__ */ jsx(DropdownMenuRadioGroup, {
9815
+ value: workspaces.activeId,
9816
+ onValueChange: workspaces.onSelect,
9817
+ children: workspaces.items.map((w) => /* @__PURE__ */ jsx(DropdownMenuRadioItem, {
9818
+ value: w.id,
9819
+ children: w.label
9820
+ }, w.id))
9821
+ })
9822
+ ] }),
9823
+ userMenuItems.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DropdownMenuSeparator, {}), userMenuItems.map((item) => {
9055
9824
  const Icon = item.icon;
9056
9825
  return item.to ? /* @__PURE__ */ jsx(DropdownMenuItem, {
9057
9826
  asChild: true,
@@ -9064,9 +9833,9 @@ function UserMenu() {
9064
9833
  children: [Icon && /* @__PURE__ */ jsx(Icon, { "aria-hidden": true }), item.label]
9065
9834
  }, item.label);
9066
9835
  })] }),
9067
- /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
9068
- /* @__PURE__ */ jsxs(DropdownMenuSub, { children: [/* @__PURE__ */ jsxs(DropdownMenuSubTrigger, { children: [/* @__PURE__ */ jsx(Sun, { "aria-hidden": true }), "Tema"] }), /* @__PURE__ */ jsx(DropdownMenuSubContent, { children: /* @__PURE__ */ jsx(ModeItems, {}) })] }),
9069
- /* @__PURE__ */ jsxs(DropdownMenuSub, { children: [/* @__PURE__ */ jsxs(DropdownMenuSubTrigger, { children: [/* @__PURE__ */ jsx(Palette, { "aria-hidden": true }), "Template"] }), /* @__PURE__ */ jsxs(DropdownMenuSubContent, { children: [
9836
+ showPreferences && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
9837
+ showTheme && /* @__PURE__ */ jsxs(DropdownMenuSub, { children: [/* @__PURE__ */ jsxs(DropdownMenuSubTrigger, { children: [/* @__PURE__ */ jsx(Sun, { "aria-hidden": true }), "Tema"] }), /* @__PURE__ */ jsx(DropdownMenuSubContent, { children: /* @__PURE__ */ jsx(ModeItems, {}) })] }),
9838
+ showTemplate && /* @__PURE__ */ jsxs(DropdownMenuSub, { children: [/* @__PURE__ */ jsxs(DropdownMenuSubTrigger, { children: [/* @__PURE__ */ jsx(Palette, { "aria-hidden": true }), "Template"] }), /* @__PURE__ */ jsxs(DropdownMenuSubContent, { children: [
9070
9839
  /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Modelo" }),
9071
9840
  /* @__PURE__ */ jsx(DropdownMenuRadioGroup, {
9072
9841
  value: brand.id,
@@ -9096,7 +9865,7 @@ function UserMenu() {
9096
9865
  }, b.id))
9097
9866
  })
9098
9867
  ] })] }),
9099
- /* @__PURE__ */ jsxs(DropdownMenuSub, { children: [/* @__PURE__ */ jsxs(DropdownMenuSubTrigger, { children: [/* @__PURE__ */ jsx(LayoutTemplate, { "aria-hidden": true }), "Layout"] }), /* @__PURE__ */ jsx(DropdownMenuSubContent, { children: /* @__PURE__ */ jsx(LayoutItems, {}) })] }),
9868
+ showLayout && /* @__PURE__ */ jsxs(DropdownMenuSub, { children: [/* @__PURE__ */ jsxs(DropdownMenuSubTrigger, { children: [/* @__PURE__ */ jsx(LayoutTemplate, { "aria-hidden": true }), "Layout"] }), /* @__PURE__ */ jsx(DropdownMenuSubContent, { children: /* @__PURE__ */ jsx(LayoutItems, {}) })] }),
9100
9869
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
9101
9870
  /* @__PURE__ */ jsxs(DropdownMenuItem, {
9102
9871
  destructive: true,
@@ -9217,7 +9986,7 @@ function TopNav() {
9217
9986
  });
9218
9987
  }
9219
9988
  function Header() {
9220
- const { layout, setLayout, setMobileNavOpen, setSearchOpen, pageHelp, homeLabel, notifications } = useShell();
9989
+ const { layout, setLayout, setMobileNavOpen, setSearchOpen, pageHelp, homeLabel, notifications, headerLogo } = useShell();
9221
9990
  const { brand, resolvedMode } = useBrand();
9222
9991
  const Link = useRendraLink();
9223
9992
  const crumbs = useRendraBreadcrumbs();
@@ -9229,12 +9998,16 @@ function Header() {
9229
9998
  const topbar = layout.navigation === "topbar";
9230
9999
  const hasParent = Boolean(crumbs.length >= 2 && crumbs[crumbs.length - 2]?.to);
9231
10000
  const menuInFooter = layout.bottomNav || hasParent;
9232
- const pageTitle = /* @__PURE__ */ jsxs("div", {
9233
- className: "flex min-w-0 flex-1 flex-col justify-center",
10001
+ const pageTitle = /* @__PURE__ */ jsxs(Fragment$1, { children: [headerLogo && /* @__PURE__ */ jsx("span", {
10002
+ "aria-hidden": true,
10003
+ className: "flex min-w-0 flex-1 items-center md:hidden",
10004
+ children: headerLogo
10005
+ }), /* @__PURE__ */ jsxs("div", {
10006
+ className: cn("flex min-w-0 flex-1 flex-col justify-center", headerLogo && "max-md:flex-none"),
9234
10007
  children: [/* @__PURE__ */ jsxs("span", {
9235
10008
  className: "flex min-w-0 items-center gap-1",
9236
10009
  children: [/* @__PURE__ */ jsx("p", {
9237
- className: "truncate text-sm leading-tight font-semibold md:text-base",
10010
+ className: cn("truncate text-sm leading-tight font-semibold md:text-base", headerLogo && "max-md:sr-only"),
9238
10011
  children: crumbs[crumbs.length - 1]?.label ?? brand.productName
9239
10012
  }), pageHelp && /* @__PURE__ */ jsx(InfoHint, {
9240
10013
  title: crumbs[crumbs.length - 1]?.label ?? brand.productName,
@@ -9243,9 +10016,10 @@ function Header() {
9243
10016
  })]
9244
10017
  }), /* @__PURE__ */ jsx(Breadcrumb, {
9245
10018
  items: trail,
9246
- variant: "trail"
10019
+ variant: "trail",
10020
+ className: cn(headerLogo && "max-md:hidden")
9247
10021
  })]
9248
- });
10022
+ })] });
9249
10023
  const collapsed = layout.sidebar === "collapsed";
9250
10024
  return /* @__PURE__ */ jsxs("header", {
9251
10025
  className: "relative z-30 flex h-header shrink-0 items-center gap-1 border-b bg-card px-2 md:gap-2 md:px-4",
@@ -9258,7 +10032,7 @@ function Header() {
9258
10032
  onClick: () => setMobileNavOpen(true),
9259
10033
  children: /* @__PURE__ */ jsx(Menu, { "aria-hidden": true })
9260
10034
  }),
9261
- topbar ? /* @__PURE__ */ jsxs(Fragment, { children: [
10035
+ topbar ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
9262
10036
  /* @__PURE__ */ jsx(Link, {
9263
10037
  to: "/",
9264
10038
  "aria-label": `${brand.productName}, ir para o painel`,
@@ -9273,7 +10047,7 @@ function Header() {
9273
10047
  className: "hidden min-w-0 flex-1 lg:flex lg:justify-center",
9274
10048
  children: layout.topbarSubmenu === "mega" ? /* @__PURE__ */ jsx(MegaMenu, {}) : /* @__PURE__ */ jsx(TopNav, {})
9275
10049
  })
9276
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
10050
+ ] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
9277
10051
  /* @__PURE__ */ jsx(Tooltip, {
9278
10052
  content: collapsed ? "Expandir menu" : "Recolher menu",
9279
10053
  side: "bottom",
@@ -9429,7 +10203,7 @@ function NavEntry({ item, compact, submenu, hoverExpands, panelOpenFor, onToggle
9429
10203
  className: "size-icon-md shrink-0",
9430
10204
  "aria-hidden": true
9431
10205
  }),
9432
- !compact && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
10206
+ !compact && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
9433
10207
  className: "truncate",
9434
10208
  children: item.title
9435
10209
  }), /* @__PURE__ */ jsx(ChevronRight, {
@@ -9694,7 +10468,7 @@ function Sidebar() {
9694
10468
  return Boolean(el && rootRef.current?.contains(el) && el.matches(":focus-visible"));
9695
10469
  };
9696
10470
  const desktop = layout.navigation === "sidebar";
9697
- return /* @__PURE__ */ jsxs(Fragment, { children: [desktop && /* @__PURE__ */ jsx("aside", {
10471
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [desktop && /* @__PURE__ */ jsx("aside", {
9698
10472
  "aria-label": "Menu lateral",
9699
10473
  className: cn("relative hidden shrink-0 transition-[width] duration-200 ease-out md:block", collapsed ? "w-sidebar-collapsed" : "w-sidebar"),
9700
10474
  children: /* @__PURE__ */ jsxs("div", {
@@ -9809,7 +10583,7 @@ function BottomNav({ onMenu }) {
9809
10583
  * Título da aba e meta description (SEO) não são responsabilidade do AppShell: o
9810
10584
  * boilerplate (src/app/app-layout.tsx) aplica isso com useRouteMeta, que lê @/config/seo.
9811
10585
  */
9812
- function AppShell({ navigation, layout: layoutProp, user = defaultUser, userMenuItems = [], onLogout, homeLabel = "Início", quickActions = [], notifications, userConfigurable = true, children }) {
10586
+ function AppShell({ navigation, layout: layoutProp, user = defaultUser, userMenuItems = [], onLogout, homeLabel = "Início", quickActions = [], notifications, userMenu, workspaces, headerLogo, userConfigurable = true, children }) {
9813
10587
  const [userLayout, setUserLayout] = useState(() => userConfigurable ? readUserLayout() : {});
9814
10588
  const [mobileNavOpen, setMobileNavOpen] = useState(false);
9815
10589
  const [searchOpen, setSearchOpen] = useState(false);
@@ -9872,7 +10646,10 @@ function AppShell({ navigation, layout: layoutProp, user = defaultUser, userMenu
9872
10646
  onLogout,
9873
10647
  homeLabel,
9874
10648
  quickActions,
9875
- notifications
10649
+ notifications,
10650
+ userMenu,
10651
+ workspaces,
10652
+ headerLogo
9876
10653
  };
9877
10654
  }, [
9878
10655
  layout,
@@ -9889,7 +10666,10 @@ function AppShell({ navigation, layout: layoutProp, user = defaultUser, userMenu
9889
10666
  onLogout,
9890
10667
  homeLabel,
9891
10668
  quickActions,
9892
- notifications
10669
+ notifications,
10670
+ userMenu,
10671
+ workspaces,
10672
+ headerLogo
9893
10673
  ]);
9894
10674
  return /* @__PURE__ */ jsx(ShellContext.Provider, {
9895
10675
  value,
@@ -10546,6 +11326,6 @@ function createTheme(input) {
10546
11326
  };
10547
11327
  }
10548
11328
  //#endregion
10549
- 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, internationalPhoneMask, isValidCnpj, isValidCpf, isValidDateBR, layoutOptions, lookupCep, lookupCnpj, masks, moveKanbanCard, parseLocaleNumber, percentMask, phoneCountries, qrMatrixToSvgPath, readCodewordsForTest, readVar, reedSolomonComputeDivisor, reedSolomonComputeRemainder, reedSolomonEncode, reedSolomonMultiply, resolveCatalogCode, resolveDropIndex, shapeLabels, toCents, toE164, toast, useBrand, useBreakpoint, useCurrentPath, useDebouncedValue, useFieldControl, useFillHeight, useLookup, usePrefersReducedMotion, useRendraBreadcrumbs, useRendraLink, useRendraNavigate, useSortable, zBR };
11329
+ 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 };
10550
11330
 
10551
11331
  //# sourceMappingURL=index.js.map