@rendra-ui/web 2.5.0 → 2.7.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 (68) hide show
  1. package/README.md +13 -3
  2. package/dist/base.css +1 -1
  3. package/dist/{empty-state-Cdb1vkMT.js → brand-feedback-icon-BYNcqBel.js} +4 -64
  4. package/dist/brand-feedback-icon-BYNcqBel.js.map +1 -0
  5. package/dist/{button-BzJgR2gH.js → button-DlzWwpZk.js} +7 -7
  6. package/dist/button-DlzWwpZk.js.map +1 -0
  7. package/dist/chart.js +15 -13
  8. package/dist/chart.js.map +1 -1
  9. package/dist/cli/auditar.js +1 -1
  10. package/dist/cli/codigos.js +2 -2
  11. package/dist/cli/executar-auditar.js +1 -1
  12. package/dist/cli/help.js +1 -1
  13. package/dist/cli/trocar.js +2 -2
  14. package/dist/cli/typescript-loader.js +1 -1
  15. package/dist/{cn-Cw7M5kEP.js → cn-B0N3Pek0.js} +2 -2
  16. package/dist/{cn-Cw7M5kEP.js.map → cn-B0N3Pek0.js.map} +1 -1
  17. package/dist/{components-DkpspH9h.js → components-CpQPMGfT.js} +18 -2
  18. package/dist/{components-DkpspH9h.js.map → components-CpQPMGfT.js.map} +1 -1
  19. package/dist/components.css +90 -1
  20. package/dist/document-viewer.js +4 -4
  21. package/dist/{tooltip-BAMSaGbS.js → dropdown-menu-M8vs0byD.js} +15 -81
  22. package/dist/dropdown-menu-M8vs0byD.js.map +1 -0
  23. package/dist/empty-state-a47Kd_Ci.js +67 -0
  24. package/dist/empty-state-a47Kd_Ci.js.map +1 -0
  25. package/dist/{features-max--5VEt6M7.js → features-max-ScxV8gb3.js} +1 -1
  26. package/dist/flow.js +1485 -0
  27. package/dist/flow.js.map +1 -0
  28. package/dist/index.js +130 -1899
  29. package/dist/index.js.map +1 -1
  30. package/dist/motion-context-BUMPf0e9.js +222 -0
  31. package/dist/motion-context-BUMPf0e9.js.map +1 -0
  32. package/dist/motion-on-CNN6y8g-.js +29 -0
  33. package/dist/motion-on-CNN6y8g-.js.map +1 -0
  34. package/dist/motion.js +3 -0
  35. package/dist/{rendra-provider-CRe0XdOU.js → rendra-provider-DEURIIL3.js} +3 -3
  36. package/dist/rendra-provider-DEURIIL3.js.map +1 -0
  37. package/dist/rich-text-editor.js +4 -3
  38. package/dist/rich-text-editor.js.map +1 -1
  39. package/dist/router-bridge.js +2 -2
  40. package/dist/router-bridge.js.map +1 -1
  41. package/dist/timeline-BOh7gUdA.js +1803 -0
  42. package/dist/timeline-BOh7gUdA.js.map +1 -0
  43. package/dist/tokens.css +1 -1
  44. package/dist/tooltip-Ym9S4h9_.js +76 -0
  45. package/dist/tooltip-Ym9S4h9_.js.map +1 -0
  46. package/dist/types/components/rendra-provider.d.ts +7 -2
  47. package/dist/types/components/rendra-router-bridge.d.ts +2 -1
  48. package/dist/types/components/ui/flow-editor.d.ts +11 -0
  49. package/dist/types/components/ui/flow-viewer.d.ts +58 -0
  50. package/dist/types/flow.d.ts +3 -0
  51. package/dist/types/index.d.ts +1 -0
  52. package/dist/types/lib/flow.d.ts +121 -0
  53. package/dist/types/lib/motion/index.d.ts +1 -1
  54. package/dist/types/lib/motion/motion-context.d.ts +21 -6
  55. package/dist/types/lib/motion/motion-on.d.ts +12 -0
  56. package/dist/types/motion.d.ts +1 -0
  57. package/dist/{use-breakpoint-O9eqFmsF.js → use-breakpoint-En17oXKY.js} +2 -2
  58. package/dist/{use-breakpoint-O9eqFmsF.js.map → use-breakpoint-En17oXKY.js.map} +1 -1
  59. package/dist/{use-motion-presets-BrkgL8lG.js → use-motion-presets-D3ww1oJX.js} +3 -3
  60. package/dist/{use-motion-presets-BrkgL8lG.js.map → use-motion-presets-D3ww1oJX.js.map} +1 -1
  61. package/dist/widget-grid.js +2 -2
  62. package/package.json +14 -1
  63. package/dist/button-BzJgR2gH.js.map +0 -1
  64. package/dist/empty-state-Cdb1vkMT.js.map +0 -1
  65. package/dist/motion-context-5BRIQAJm.js +0 -107
  66. package/dist/motion-context-5BRIQAJm.js.map +0 -1
  67. package/dist/rendra-provider-CRe0XdOU.js.map +0 -1
  68. package/dist/tooltip-BAMSaGbS.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,23 +1,23 @@
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";
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";
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";
14
- import { Fragment, cloneElement, createContext, forwardRef, isValidElement, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
1
+ /*! Rendra Design System v2.7.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
2
+ import { t as cn } from "./cn-B0N3Pek0.js";
3
+ import { a as useMotionMode, c as getReducedMotion, i as useMotionLib, l as subscribeReducedMotion, n as useLayoutReady, o as useMotionOn, r as useMotionAdopted, u as usePrefersReducedMotion } from "./motion-context-BUMPf0e9.js";
4
+ import { t as useMotionPresets } from "./use-motion-presets-D3ww1oJX.js";
5
+ import { A as lookupCnpj, B as ActionBar, C as toE164, D as controlInput, E as controlFrame, F as CardHeader, H as useShell, I as CardTitle, L as InfoHint, M as CardContent, N as CardDescription, O as useLookup, P as CardFooter, R as Modal, S as toCents, T as controlAdornmentSpace, V as ShellContext, _ as internationalPhoneMask, a as Label, b as percentMask, c as fieldGridClass, d as Drawer, f as PickerPanel, g as formatCurrency, h as formatCents, i as Field, j as Card, k as lookupCep, l as gapClass, m as DEFAULT_DDI, n as useFillHeight, o as useFieldControl, p as Input, r as Select, s as alignClass, t as Timeline, u as justifyClass, v as masks, w as controlAdornmentButton, x as phoneCountries, y as parseLocaleNumber, z as Alert } from "./timeline-BOh7gUdA.js";
6
+ import { a as catalogByComponent, c as findComponentsWithoutDefault, d as findPresetCollisions, f as getCatalogEntry, i as assertCatalogIntegrity, l as findDuplicateCodes, n as CATALOG_EXCLUDED_FILES, o as filesMissingCatalogEntry, p as resolveCatalogCode, r as COMPONENT_CODE_PATTERN, s as findComponentsWithMultipleDefaults, t as CATALOG, u as findInvalidFormatCodes } from "./components-CpQPMGfT.js";
7
+ import { n as buttonVariants, r as Spinner, t as Button } from "./button-DlzWwpZk.js";
8
+ import { a as DropdownMenuItem, c as DropdownMenuRadioItem, d as DropdownMenuSubContent, f as DropdownMenuSubTrigger, i as DropdownMenuGroup, l as DropdownMenuSeparator, n as DropdownMenuCheckboxItem, o as DropdownMenuLabel, p as DropdownMenuTrigger, r as DropdownMenuContent, s as DropdownMenuRadioGroup, t as DropdownMenu, u as DropdownMenuSub } from "./dropdown-menu-M8vs0byD.js";
9
+ import { i as BrandContext, n as feedbackLabels, r as useBrand, t as BrandFeedbackIcon } from "./brand-feedback-icon-BYNcqBel.js";
10
+ import { a as useRendraNavigate, i as useRendraLink, n as useCurrentPath, r as useRendraBreadcrumbs, t as RendraProvider } from "./rendra-provider-DEURIIL3.js";
11
+ import { n as useBreakpoint, t as breakpoints } from "./use-breakpoint-En17oXKY.js";
12
+ import { t as EmptyState } from "./empty-state-a47Kd_Ci.js";
13
+ import { n as TooltipProvider, t as Tooltip } from "./tooltip-Ym9S4h9_.js";
14
+ import { ArrowDown, ArrowDownRight, ArrowLeft, ArrowRight, ArrowRightLeft, ArrowUp, ArrowUpRight, Bell, Bot, CalendarDays, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Clock, Columns3, Download, EllipsisVertical, FileText, Film, Filter, Globe, GripVertical, Home, ImageIcon, ImagePlus, LayoutTemplate, LogOut, Mail, MapPin, Menu, MessageCircle, MessagesSquare, Mic, Minus, Monitor, Moon, MoreHorizontal, Palette, PanelLeft, Paperclip, Pause, Pencil, Phone, Play, Plus, Reply, RotateCw, Search, Send, Smartphone, Smile, Star, Sun, Trash2, TriangleAlert, UploadCloud, User, VideoIcon, X, Zap } from "lucide-react";
15
+ import { Accordion as Accordion$1, Avatar as Avatar$1, Checkbox as Checkbox$1, Collapsible, ContextMenu, Dialog, NavigationMenu, Popover as Popover$1, Progress as Progress$1, RadioGroup as RadioGroup$1, Slider as Slider$1, Slot, Switch as Switch$1, Tabs as Tabs$1, VisuallyHidden } from "radix-ui";
16
+ import { Fragment, createContext, forwardRef, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
15
17
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
16
- import { createPortal } from "react-dom";
17
18
  import { cva } from "class-variance-authority";
18
19
  import { addDays, addMonths, addWeeks, differenceInMinutes, endOfMonth, endOfWeek, format, isSameDay, isSameMonth, isToday, isYesterday, startOfDay, startOfMonth, startOfWeek } from "date-fns";
19
20
  import { ptBR } from "date-fns/locale";
20
- import IMask from "imask";
21
21
  import { DayPicker } from "react-day-picker";
22
22
  import { ptBR as ptBR$1 } from "react-day-picker/locale";
23
23
  import { FormProvider, useController, useFormContext } from "react-hook-form";
@@ -74,10 +74,10 @@ function formatLike(parsed, n) {
74
74
  //#region src/components/ui/accordion.tsx
75
75
  /** Accordion único, com animação de altura e área de toque de 44px no mobile. */
76
76
  function Accordion({ items, multiple, defaultValue, className }) {
77
- const motion = useMotionMode();
77
+ const lib = useMotionLib();
78
78
  const presets = useMotionPresets();
79
79
  const [open, setOpen] = useState(multiple ? defaultValue ?? [] : defaultValue?.[0] ? [defaultValue[0]] : []);
80
- if (motion === "on") {
80
+ if (lib) {
81
81
  const rootProps = multiple ? {
82
82
  type: "multiple",
83
83
  value: open,
@@ -100,19 +100,19 @@ function Accordion({ items, multiple, defaultValue, className }) {
100
100
  className: "border-b last:border-b-0",
101
101
  children: [/* @__PURE__ */ jsx(Accordion$1.Header, { children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
102
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, {
103
+ children: [it.title, /* @__PURE__ */ jsx(lib.m.span, {
104
104
  "aria-hidden": true,
105
105
  className: "flex shrink-0",
106
106
  animate: { rotate: isOpen ? 180 : 0 },
107
107
  transition: presets.fade.transition,
108
108
  children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-icon-sm text-muted-foreground" })
109
109
  })]
110
- }) }), /* @__PURE__ */ jsx(AnimatePresence, {
110
+ }) }), /* @__PURE__ */ jsx(lib.AnimatePresence, {
111
111
  initial: false,
112
112
  children: isOpen && /* @__PURE__ */ jsx(Accordion$1.Content, {
113
113
  forceMount: true,
114
114
  asChild: true,
115
- children: /* @__PURE__ */ jsx(m.div, {
115
+ children: /* @__PURE__ */ jsx(lib.m.div, {
116
116
  className: "overflow-hidden text-sm wrap-break-word text-muted-foreground",
117
117
  initial: {
118
118
  height: 0,
@@ -172,129 +172,6 @@ function Accordion({ items, multiple, defaultValue, className }) {
172
172
  });
173
173
  }
174
174
  //#endregion
175
- //#region src/components/app-shell/shell-context.ts
176
- var ShellContext = createContext(null);
177
- function useShell() {
178
- const ctx = useContext(ShellContext);
179
- if (!ctx) throw new Error("useShell precisa estar dentro de <AppShell>.");
180
- return ctx;
181
- }
182
- //#endregion
183
- //#region src/components/ui/action-bar.tsx
184
- /**
185
- * Barra de ações única, com a regra de botões do sistema:
186
- * 1 botão = 100%; 2 botões = cancelar 30% + principal 70%; 3 ou mais = extras no menu.
187
- * Vale para drawer, modal e formulário em página, em qualquer tamanho de tela.
188
- */
189
- function ActionBar({ primary, cancel, secondary, sticky, className }) {
190
- const slot = useContext(ShellContext)?.footerSlot;
191
- const hasMenu = Boolean(secondary?.length);
192
- const layout = cancel ? hasMenu ? "grid-actions-3" : "grid-actions-2" : hasMenu ? "grid-actions-3" : "";
193
- const bar = /* @__PURE__ */ jsx("div", {
194
- "data-rendra": "ACB-001",
195
- className: cn(sticky && "border-t bg-card px-4 pt-4 pb-safe md:px-6", sticky && !slot && "sticky bottom-0 z-20", className),
196
- children: /* @__PURE__ */ jsxs("div", {
197
- className: cn("grid gap-3", layout || "grid-cols-1", sticky && "w-full"),
198
- children: [
199
- hasMenu && /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
200
- asChild: true,
201
- children: /* @__PURE__ */ jsx(Button, {
202
- variant: "outline",
203
- iconOnly: true,
204
- "aria-label": "Mais ações",
205
- children: /* @__PURE__ */ jsx(MoreHorizontal, {})
206
- })
207
- }), /* @__PURE__ */ jsx(DropdownMenuContent, {
208
- align: "start",
209
- side: "top",
210
- children: secondary.map((a) => /* @__PURE__ */ jsxs(DropdownMenuItem, {
211
- onSelect: a.onClick,
212
- disabled: a.disabled,
213
- destructive: a.destructive,
214
- children: [a.icon, a.label]
215
- }, a.label))
216
- })] }),
217
- cancel ? /* @__PURE__ */ jsx(Button, {
218
- variant: "outline",
219
- icon: cancel.icon,
220
- onClick: cancel.onClick,
221
- disabled: cancel.disabled || primary.loading,
222
- fullWidth: true,
223
- children: cancel.label
224
- }) : hasMenu ? /* @__PURE__ */ jsx("span", { "aria-hidden": true }) : null,
225
- /* @__PURE__ */ jsx(Button, {
226
- type: primary.type ?? "button",
227
- form: primary.form,
228
- variant: primary.destructive ? "destructive" : "primary",
229
- icon: primary.icon,
230
- onClick: primary.onClick,
231
- disabled: primary.disabled,
232
- loading: primary.loading,
233
- fullWidth: true,
234
- children: primary.loading ? primary.loadingLabel ?? "Salvando..." : primary.label
235
- })
236
- ]
237
- })
238
- });
239
- return sticky && slot ? createPortal(bar, slot) : bar;
240
- }
241
- //#endregion
242
- //#region src/components/ui/alert.tsx
243
- /**
244
- * Alert único do sistema: ícone da marca à esquerda, título em destaque e descrição.
245
- * O tipo é prop; o formato vem do template ativo (quadrado, meio-termo ou arredondado).
246
- */
247
- var alertVariants = cva("flex w-full min-w-0 items-start gap-3 rounded-control border", {
248
- variants: { type: {
249
- success: "border-success/25 bg-success-soft text-success-soft-foreground",
250
- error: "border-destructive/25 bg-destructive-soft text-destructive-soft-foreground",
251
- warning: "border-warning/25 bg-warning-soft text-warning-soft-foreground",
252
- info: "border-info/25 bg-info-soft text-info-soft-foreground"
253
- } },
254
- defaultVariants: { type: "info" }
255
- });
256
- function Alert({ type, title, description, action, onDismiss, animated = false, className }) {
257
- const { shape } = useBrand();
258
- const pill = shape === "pill";
259
- return /* @__PURE__ */ jsxs("div", {
260
- role: type === "error" || type === "warning" ? "alert" : "status",
261
- "data-rendra": "ALRT-001",
262
- className: cn(alertVariants({ type }), pill ? "items-center py-3 pr-4 pl-4 md:pr-6" : "p-4", className),
263
- children: [
264
- /* @__PURE__ */ jsx(BrandFeedbackIcon, {
265
- type,
266
- size: "lg",
267
- animated,
268
- className: cn(!pill && "mt-px")
269
- }),
270
- /* @__PURE__ */ jsxs("div", {
271
- className: cn("flex min-w-0 flex-1 flex-col", !pill && "gap-1"),
272
- children: [/* @__PURE__ */ jsx("p", {
273
- className: "text-sm font-semibold",
274
- children: title
275
- }), description && /* @__PURE__ */ jsx("p", {
276
- className: "text-sm opacity-90",
277
- children: description
278
- })]
279
- }),
280
- action && /* @__PURE__ */ jsx("div", {
281
- className: "shrink-0 self-center",
282
- children: action
283
- }),
284
- onDismiss && /* @__PURE__ */ jsx("button", {
285
- type: "button",
286
- onClick: onDismiss,
287
- "aria-label": "Fechar aviso",
288
- className: cn("flex size-touch shrink-0 items-center justify-center rounded-full transition-colors hover:bg-card/60 md:size-8", pill ? "-my-2" : "-mt-2 -mr-2"),
289
- children: /* @__PURE__ */ jsx(X, {
290
- className: "size-icon-sm",
291
- "aria-hidden": true
292
- })
293
- })
294
- ]
295
- });
296
- }
297
- //#endregion
298
175
  //#region src/lib/initials.ts
299
176
  /** Iniciais de um nome: primeira letra do primeiro e do último nome, em maiúsculas. */
300
177
  function initials(name) {
@@ -618,264 +495,6 @@ function ButtonGroup({ children, options, value, onChange, size = "md", fullWidt
618
495
  });
619
496
  }
620
497
  //#endregion
621
- //#region src/components/ui/overlay-shell.tsx
622
- function OverlayShell({ title, description, icon, children, footer, hideHeader, onRequestClose, bodyClassName }) {
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
- }),
638
- /* @__PURE__ */ jsxs("header", {
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"),
640
- children: [
641
- icon && /* @__PURE__ */ jsx("span", {
642
- "aria-hidden": true,
643
- className: "flex size-control-md shrink-0 items-center justify-center rounded-control bg-primary-soft text-primary-soft-foreground [&_svg]:size-icon-md",
644
- children: icon
645
- }),
646
- /* @__PURE__ */ jsxs("div", {
647
- className: "flex min-w-0 flex-1 flex-col gap-1 pt-1",
648
- children: [/* @__PURE__ */ jsx(Dialog.Title, {
649
- className: "text-lg font-semibold wrap-break-word",
650
- children: title
651
- }), description ? /* @__PURE__ */ jsx(Dialog.Description, {
652
- className: "text-sm wrap-break-word text-muted-foreground",
653
- children: description
654
- }) : /* @__PURE__ */ jsx(Dialog.Description, {
655
- className: "sr-only",
656
- children: title
657
- })]
658
- }),
659
- !hideHeader && closeButton
660
- ]
661
- }),
662
- /* @__PURE__ */ jsx("div", {
663
- className: cn("min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-6 md:px-6", bodyClassName),
664
- children
665
- }),
666
- footer && /* @__PURE__ */ jsx("footer", {
667
- className: "shrink-0 border-t bg-card px-4 pt-4 pb-safe md:px-6 md:pb-6",
668
- children: footer
669
- })
670
- ] });
671
- }
672
- //#endregion
673
- //#region src/components/ui/modal.tsx
674
- var sizes$1 = {
675
- sm: "md:max-w-sm",
676
- md: "md:max-w-lg",
677
- lg: "md:max-w-2xl"
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");
682
- var feedback = {
683
- confirm: "info",
684
- destructive: "error",
685
- info: "info"
686
- };
687
- function Modal({ open, onOpenChange, title, description, type = "confirm", size = "sm", children, confirmLabel = type === "destructive" ? "Excluir" : type === "info" ? "Entendi" : "Confirmar", cancelLabel, onConfirm, formId, loading }) {
688
- const [busy, setBusy] = useState(false);
689
- const close = () => onOpenChange(false);
690
- const confirm = async () => {
691
- if (!onConfirm) return close();
692
- try {
693
- setBusy(true);
694
- await onConfirm();
695
- close();
696
- } finally {
697
- setBusy(false);
698
- }
699
- };
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
- });
773
- return /* @__PURE__ */ jsx(Dialog.Root, {
774
- open,
775
- onOpenChange,
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
780
- })] })
781
- });
782
- }
783
- //#endregion
784
- //#region src/components/ui/info-hint.tsx
785
- function InfoHint({ title, children, className }) {
786
- const [open, setOpen] = useState(false);
787
- return /* @__PURE__ */ jsxs("span", {
788
- className: "contents",
789
- "data-rendra": "INFO-001",
790
- children: [/* @__PURE__ */ jsx(Button, {
791
- variant: "ghost",
792
- size: "sm",
793
- iconOnly: true,
794
- "aria-label": `Sobre: ${title}`,
795
- onClick: () => setOpen(true),
796
- className: cn("shrink-0 text-muted-foreground hover:text-primary-text max-md:size-touch", className),
797
- children: /* @__PURE__ */ jsx(Info, { "aria-hidden": true })
798
- }), /* @__PURE__ */ jsx(Modal, {
799
- open,
800
- onOpenChange: setOpen,
801
- type: "info",
802
- title,
803
- size: "md",
804
- children: /* @__PURE__ */ jsx("div", {
805
- className: "flex flex-col gap-3 text-sm text-muted-foreground",
806
- children
807
- })
808
- })]
809
- });
810
- }
811
- //#endregion
812
- //#region src/components/ui/card.tsx
813
- function Card({ className, "data-rendra": dataRendra, ...props }) {
814
- return /* @__PURE__ */ jsx("div", {
815
- "data-slot": "card",
816
- "data-rendra": dataRendra ?? "CARD-001",
817
- className: cn("flex min-w-0 flex-col rounded-surface border bg-card text-card-foreground", className),
818
- ...props
819
- });
820
- }
821
- function CardHeader({ className, actions, children, ...props }) {
822
- if (!actions) return /* @__PURE__ */ jsx("div", {
823
- "data-slot": "card-header",
824
- className: cn("flex flex-col gap-1 p-4 md:p-6", className),
825
- ...props,
826
- children
827
- });
828
- return /* @__PURE__ */ jsxs("div", {
829
- "data-slot": "card-header",
830
- className: cn("flex flex-wrap items-start justify-between gap-x-4 gap-y-3 p-4 md:p-6", className),
831
- ...props,
832
- children: [/* @__PURE__ */ jsx("div", {
833
- className: "flex min-w-0 flex-1 flex-col gap-1",
834
- children
835
- }), /* @__PURE__ */ jsx("div", {
836
- className: "flex shrink-0 items-center gap-2",
837
- children: actions
838
- })]
839
- });
840
- }
841
- function CardTitle({ className, children, help, ...props }) {
842
- const heading = /* @__PURE__ */ jsx("h3", {
843
- "data-slot": "card-title",
844
- className: cn("text-lg font-semibold", className),
845
- ...props,
846
- children
847
- });
848
- if (!help) return heading;
849
- return /* @__PURE__ */ jsxs("div", {
850
- className: "flex min-w-0 items-center gap-1",
851
- children: [heading, /* @__PURE__ */ jsx(InfoHint, {
852
- title: typeof children === "string" ? children : "Sobre esta seção",
853
- children: help
854
- })]
855
- });
856
- }
857
- function CardDescription({ className, ...props }) {
858
- return /* @__PURE__ */ jsx("p", {
859
- "data-slot": "card-description",
860
- className: cn("text-sm text-muted-foreground", className),
861
- ...props
862
- });
863
- }
864
- function CardContent({ className, ...props }) {
865
- return /* @__PURE__ */ jsx("div", {
866
- "data-slot": "card-content",
867
- className: cn("p-4 md:p-6 [[data-slot=card-header]+&]:pt-0", className),
868
- ...props
869
- });
870
- }
871
- function CardFooter({ className, ...props }) {
872
- return /* @__PURE__ */ jsx("div", {
873
- "data-slot": "card-footer",
874
- className: cn("flex items-center gap-3 border-t px-4 py-3 md:px-6", className),
875
- ...props
876
- });
877
- }
878
- //#endregion
879
498
  //#region src/components/ui/calendar.tsx
880
499
  var viewLabels = {
881
500
  month: "Mês",
@@ -1314,575 +933,6 @@ function Calendar({ events, view: viewProp, defaultView = "month", onViewChange,
1314
933
  });
1315
934
  }
1316
935
  //#endregion
1317
- //#region src/lib/lookup.ts
1318
- var digits$1 = (v) => v.replace(/\D/g, "");
1319
- /** Endereço do CEP (8 dígitos). null se não existir; lança erro se a busca falhar. */
1320
- async function lookupCep(cep, signal) {
1321
- const d = digits$1(cep);
1322
- if (d.length !== 8) return null;
1323
- const res = await fetch(`https://viacep.com.br/ws/${d}/json/`, { signal });
1324
- if (!res.ok) throw new Error("Não foi possível buscar o CEP agora.");
1325
- const data = await res.json();
1326
- if (data.erro) return null;
1327
- return {
1328
- cep: String(data.cep ?? ""),
1329
- logradouro: String(data.logradouro ?? ""),
1330
- complemento: String(data.complemento ?? ""),
1331
- bairro: String(data.bairro ?? ""),
1332
- cidade: String(data.localidade ?? ""),
1333
- uf: String(data.uf ?? "")
1334
- };
1335
- }
1336
- /** Dados públicos do CNPJ (14 dígitos). null se não existir; lança erro se a busca falhar. */
1337
- async function lookupCnpj(cnpj, signal) {
1338
- const d = digits$1(cnpj);
1339
- if (d.length !== 14) return null;
1340
- const res = await fetch(`https://brasilapi.com.br/api/cnpj/v1/${d}`, { signal });
1341
- if (res.status === 404) return null;
1342
- if (!res.ok) throw new Error("Não foi possível buscar o CNPJ agora.");
1343
- const data = await res.json();
1344
- const s = (k) => data[k] == null ? "" : String(data[k]);
1345
- const fone = digits$1(s("ddd_telefone_1"));
1346
- return {
1347
- razaoSocial: s("razao_social"),
1348
- nomeFantasia: s("nome_fantasia"),
1349
- email: s("email").toLowerCase(),
1350
- telefone: fone.length >= 10 ? `(${fone.slice(0, 2)}) ${fone.slice(2, -4)}-${fone.slice(-4)}` : "",
1351
- situacao: s("descricao_situacao_cadastral"),
1352
- endereco: {
1353
- cep: s("cep"),
1354
- logradouro: [s("descricao_tipo_de_logradouro"), s("logradouro")].filter(Boolean).join(" "),
1355
- numero: s("numero"),
1356
- complemento: s("complemento"),
1357
- bairro: s("bairro"),
1358
- cidade: s("municipio"),
1359
- uf: s("uf")
1360
- }
1361
- };
1362
- }
1363
- //#endregion
1364
- //#region src/hooks/use-lookup.ts
1365
- /**
1366
- * Busca CEP (8 dígitos) ou CNPJ (14 dígitos) assim que o valor fica completo. Cancela a
1367
- * busca anterior quando o valor muda. `kind` 'auto' decide pelo tamanho (CPF ou CNPJ: só
1368
- * o CNPJ busca). Sem `onResult`, não faz nada.
1369
- */
1370
- function useLookup(kind, value, onResult) {
1371
- const [loading, setLoading] = useState(false);
1372
- const cb = useRef(onResult);
1373
- cb.current = onResult;
1374
- const digits = value.replace(/\D/g, "");
1375
- const target = kind === "cep" && digits.length === 8 ? "cep" : (kind === "cnpj" || kind === "auto") && digits.length === 14 ? "cnpj" : null;
1376
- const enabled = Boolean(onResult) && target !== null;
1377
- useEffect(() => {
1378
- if (!enabled || !target) return;
1379
- const ctrl = new AbortController();
1380
- const send = (r) => {
1381
- if (!ctrl.signal.aborted) cb.current?.(r);
1382
- };
1383
- setLoading(true);
1384
- send({
1385
- status: "loading",
1386
- kind: target
1387
- });
1388
- (target === "cep" ? lookupCep(digits, ctrl.signal).then((data) => data ? send({
1389
- status: "found",
1390
- kind: "cep",
1391
- data,
1392
- message: "Endereço preenchido pelo CEP."
1393
- }) : send({
1394
- status: "not-found",
1395
- kind: "cep",
1396
- message: "CEP não encontrado. Preencha o endereço."
1397
- })) : lookupCnpj(digits, ctrl.signal).then((data) => data ? send({
1398
- status: "found",
1399
- kind: "cnpj",
1400
- data,
1401
- message: `${data.situacao ? `Situação: ${data.situacao}. ` : ""}Dados preenchidos pelo CNPJ.`
1402
- }) : send({
1403
- status: "not-found",
1404
- kind: "cnpj",
1405
- message: "CNPJ não encontrado. Preencha os dados abaixo."
1406
- }))).catch((e) => send({
1407
- status: "error",
1408
- kind: target,
1409
- message: e instanceof Error ? e.message : "Não foi possível buscar agora."
1410
- })).finally(() => {
1411
- if (!ctrl.signal.aborted) setLoading(false);
1412
- });
1413
- return () => {
1414
- ctrl.abort();
1415
- setLoading(false);
1416
- };
1417
- }, [
1418
- enabled,
1419
- target,
1420
- digits
1421
- ]);
1422
- return loading;
1423
- }
1424
- //#endregion
1425
- //#region src/lib/control.ts
1426
- /**
1427
- * Moldura única dos campos (Input, Select, DatePicker, Textarea). Mesma altura dos botões
1428
- * em cada tamanho; fonte de 16px no mobile para o iOS não dar zoom ao focar.
1429
- */
1430
- /** Marque o elemento com data-slot="control": o teste de toque mede a moldura, não o input. */
1431
- var controlFrame = cva("group/control flex w-full min-w-0 items-center gap-2 rounded-control border border-input bg-field text-base text-foreground transition-[border-color,box-shadow] duration-150 focus-within:border-ring focus-within:bg-card focus-within:ring-2 focus-within:ring-ring/25 hover:border-foreground/40 has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-60 has-[:disabled]:hover:border-input md:text-sm", {
1432
- variants: {
1433
- size: {
1434
- sm: "h-control-sm px-3",
1435
- md: "h-control-md px-3",
1436
- lg: "h-control-lg px-4"
1437
- },
1438
- invalid: {
1439
- true: "border-destructive focus-within:border-destructive focus-within:ring-destructive/25 hover:border-destructive",
1440
- false: ""
1441
- }
1442
- },
1443
- defaultVariants: {
1444
- size: "md",
1445
- invalid: false
1446
- }
1447
- });
1448
- /** Classe do <input> nativo dentro da moldura. */
1449
- var controlInput = "h-full min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed";
1450
- /** Botão pequeno dentro da moldura (limpar, mostrar senha). */
1451
- var controlAdornmentButton = "-mr-2 flex size-control-sm shrink-0 cursor-pointer items-center justify-center rounded-item text-muted-foreground transition-colors outline-none hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring md:-mr-1 md:size-8 [&_svg]:size-icon-sm";
1452
- /**
1453
- * Reserva, dentro de um gatilho, o espaço do botão sobreposto (limpar do Select e do
1454
- * DatePicker), para o texto não passar por baixo dele.
1455
- */
1456
- var controlAdornmentSpace = "size-control-sm shrink-0 md:size-8";
1457
- //#endregion
1458
- //#region src/lib/masks.ts
1459
- var numberBlock = (scale, max) => ({
1460
- mask: Number,
1461
- scale,
1462
- thousandsSeparator: ".",
1463
- radix: ",",
1464
- mapToRadix: ["."],
1465
- padFractionalZeros: true,
1466
- normalizeZeros: true,
1467
- min: 0,
1468
- ...max !== void 0 ? { max } : {}
1469
- });
1470
- var masks = {
1471
- cpf: {
1472
- options: { mask: "000.000.000-00" },
1473
- inputMode: "numeric",
1474
- placeholder: "000.000.000-00"
1475
- },
1476
- cnpj: {
1477
- options: { mask: "00.000.000/0000-00" },
1478
- inputMode: "numeric",
1479
- placeholder: "00.000.000/0000-00"
1480
- },
1481
- cpfCnpj: {
1482
- options: { mask: [{ mask: "000.000.000-00" }, { mask: "00.000.000/0000-00" }] },
1483
- inputMode: "numeric",
1484
- placeholder: "CPF ou CNPJ"
1485
- },
1486
- phone: {
1487
- options: { mask: [{ mask: "(00) 0000-0000" }, { mask: "(00) 00000-0000" }] },
1488
- inputMode: "tel",
1489
- placeholder: "(00) 00000-0000"
1490
- },
1491
- cep: {
1492
- options: { mask: "00000-000" },
1493
- inputMode: "numeric",
1494
- placeholder: "00000-000"
1495
- },
1496
- date: {
1497
- options: { mask: "00/00/0000" },
1498
- inputMode: "numeric",
1499
- placeholder: "DD/MM/AAAA"
1500
- },
1501
- time: {
1502
- options: { mask: "00:00" },
1503
- inputMode: "numeric",
1504
- placeholder: "00:00"
1505
- },
1506
- currency: {
1507
- options: {
1508
- mask: "R$ num",
1509
- lazy: false,
1510
- blocks: { num: numberBlock(2) }
1511
- },
1512
- inputMode: "decimal",
1513
- placeholder: "R$ 0,00"
1514
- },
1515
- percent: {
1516
- options: {
1517
- mask: "num %",
1518
- lazy: false,
1519
- blocks: { num: numberBlock(2, 100) }
1520
- },
1521
- inputMode: "decimal",
1522
- placeholder: "0,00 %"
1523
- }
1524
- };
1525
- /** Máscara de percentual com teto configurável (padrão 100), para o Input com unidades (A9). */
1526
- function percentMask(max = 100) {
1527
- return {
1528
- options: {
1529
- mask: "num %",
1530
- lazy: false,
1531
- blocks: { num: numberBlock(2, max) }
1532
- },
1533
- inputMode: "decimal",
1534
- placeholder: "0,00 %"
1535
- };
1536
- }
1537
- /** DDI padrão do campo de telefone. */
1538
- var DEFAULT_DDI = "55";
1539
- /** Lista padrão do seletor de DDI (Brasil primeiro). Troque com a prop ddiOptions do Input. */
1540
- var phoneCountries = [
1541
- {
1542
- ddi: "55",
1543
- name: "Brasil"
1544
- },
1545
- {
1546
- ddi: "54",
1547
- name: "Argentina"
1548
- },
1549
- {
1550
- ddi: "56",
1551
- name: "Chile"
1552
- },
1553
- {
1554
- ddi: "57",
1555
- name: "Colômbia"
1556
- },
1557
- {
1558
- ddi: "595",
1559
- name: "Paraguai"
1560
- },
1561
- {
1562
- ddi: "598",
1563
- name: "Uruguai"
1564
- },
1565
- {
1566
- ddi: "52",
1567
- name: "México"
1568
- },
1569
- {
1570
- ddi: "1",
1571
- name: "Estados Unidos e Canadá"
1572
- },
1573
- {
1574
- ddi: "351",
1575
- name: "Portugal"
1576
- },
1577
- {
1578
- ddi: "34",
1579
- name: "Espanha"
1580
- },
1581
- {
1582
- ddi: "33",
1583
- name: "França"
1584
- },
1585
- {
1586
- ddi: "39",
1587
- name: "Itália"
1588
- },
1589
- {
1590
- ddi: "49",
1591
- name: "Alemanha"
1592
- },
1593
- {
1594
- ddi: "44",
1595
- name: "Reino Unido"
1596
- }
1597
- ];
1598
- /** Máscara do número fora do Brasil: só dígitos, em grupos, até 15 (limite do padrão E.164). */
1599
- var internationalPhoneMask = {
1600
- options: { mask: "000 000 000 000 000" },
1601
- inputMode: "tel",
1602
- placeholder: "Número com DDD"
1603
- };
1604
- /** Número completo no padrão internacional: toE164("55", "(11) 91234-5678") = "+5511912345678". */
1605
- function toE164(ddi, national) {
1606
- const digits = national.replace(/\D/g, "");
1607
- return digits ? `+${ddi}${digits}` : "";
1608
- }
1609
- /** Converte "R$ 1.250,00" ou "12,5 %" em número. */
1610
- function parseLocaleNumber(masked) {
1611
- const clean = masked.replace(/[^\d,-]/g, "").replace(",", ".");
1612
- if (!clean) return null;
1613
- const n = Number(clean);
1614
- return Number.isFinite(n) ? n : null;
1615
- }
1616
- /**
1617
- * Moeda em centavos inteiros, sem erro de arredondamento de ponto flutuante:
1618
- * "R$ 1.250,50" -> 125050. Vazio -> null. Use centavos para guardar e somar dinheiro.
1619
- */
1620
- function toCents(masked) {
1621
- const d = masked.replace(/\D/g, "");
1622
- if (!d) return null;
1623
- if (!/,\d{1,2}\s*$/.test(masked.replace(/\s*%$/, ""))) return Number(d) * 100;
1624
- const [int = "", dec = ""] = masked.replace(/[^\d,]/g, "").split(",");
1625
- return Number(int || "0") * 100 + Number(dec.padEnd(2, "0").slice(0, 2));
1626
- }
1627
- /** Centavos para o texto do campo de moeda: 125050 -> "R$ 1.250,50". */
1628
- function formatCents(cents) {
1629
- return formatCurrency(cents / 100);
1630
- }
1631
- /** Formata número como moeda brasileira: 1250 -> "R$ 1.250,00". */
1632
- function formatCurrency(value) {
1633
- return value.toLocaleString("pt-BR", {
1634
- style: "currency",
1635
- currency: "BRL"
1636
- });
1637
- }
1638
- //#endregion
1639
- //#region src/components/ui/input.tsx
1640
- /**
1641
- * Input único. Tipos, máscaras, ícone, limpar, senha, unidades e valor guardado são props:
1642
- * nunca crie InputCPF, InputTelefone, InputSenha ou InputSegredo.
1643
- */
1644
- var Input = forwardRef(function Input({ size, mask, icon, suffix, clearable, invalid, type = "text", value, defaultValue, onChange, onValueChange, disabled, className, inputClassName, inputMode, placeholder, ddi: ddiProp, onDdiChange, ddiOptions = phoneCountries, hideDdi, onCentsChange, onLookup, units, unit: unitProp, onUnitChange, percentMax, variant, hasValue, maskedHint, isEditing, onStartEdit, onCancelEdit, onRemove, removing, ...props }, ref) {
1645
- const inputRef = useRef(null);
1646
- useImperativeHandle(ref, () => inputRef.current);
1647
- const maskRef = useRef(null);
1648
- const [showPassword, setShowPassword] = useState(false);
1649
- const [inner, setInner] = useState(String(value ?? defaultValue ?? ""));
1650
- const current = value ?? inner;
1651
- const [secretDraft, setSecretDraft] = useState("");
1652
- const [lastIsEditing, setLastIsEditing] = useState(isEditing);
1653
- if (isEditing !== lastIsEditing) {
1654
- setLastIsEditing(isEditing);
1655
- if (isEditing) setSecretDraft("");
1656
- }
1657
- const cb = useRef({
1658
- onChange,
1659
- onValueChange,
1660
- onCentsChange
1661
- });
1662
- cb.current = {
1663
- onChange,
1664
- onValueChange,
1665
- onCentsChange
1666
- };
1667
- const searching = useLookup(mask === "cep" ? "cep" : mask === "cnpj" ? "cnpj" : mask === "cpfCnpj" ? "auto" : void 0, current, onLookup);
1668
- const isPhone = mask === "phone";
1669
- const [innerDdi, setInnerDdi] = useState(ddiProp ?? "55");
1670
- const ddi = ddiProp ?? innerDdi;
1671
- const showDdi = isPhone && !hideDdi;
1672
- const intl = isPhone && ddi !== "55";
1673
- const hasUnits = Boolean(units && units.length > 0);
1674
- const [innerUnit, setInnerUnit] = useState(unitProp ?? units?.[0]?.id ?? "");
1675
- const unit = hasUnits ? unitProp ?? innerUnit : void 0;
1676
- const unitMaskName = unit === "percent" ? "percent" : unit === "currency" ? "currency" : void 0;
1677
- const def = intl ? internationalPhoneMask : hasUnits ? unitMaskName === "percent" ? percentMask(percentMax) : unitMaskName === "currency" ? masks.currency : void 0 : mask ? masks[mask] : void 0;
1678
- const maskKey = !def ? void 0 : intl ? "phone-intl" : hasUnits ? `unit-${unitMaskName}-${percentMax ?? ""}` : mask;
1679
- useEffect(() => {
1680
- if (!maskKey || !def || !inputRef.current) return;
1681
- const m = IMask(inputRef.current, def.options);
1682
- maskRef.current = m;
1683
- m.on("accept", () => {
1684
- setInner(m.value);
1685
- cb.current.onChange?.(m.value);
1686
- cb.current.onValueChange?.(m.unmaskedValue, m.value);
1687
- if (mask === "currency" || unitMaskName === "currency") cb.current.onCentsChange?.(toCents(m.value));
1688
- });
1689
- return () => {
1690
- m.destroy();
1691
- maskRef.current = null;
1692
- };
1693
- }, [maskKey]);
1694
- useEffect(() => {
1695
- const m = maskRef.current;
1696
- if (m && value !== void 0 && value !== m.value) m.value = value;
1697
- }, [value]);
1698
- const isPassword = type === "password";
1699
- const country = ddiOptions.find((c) => c.ddi === ddi);
1700
- const isSecret = variant === "secret";
1701
- const { id: fieldId, "aria-describedby": fieldDescribedBy, "aria-required": fieldRequired } = props;
1702
- const resetValue = () => {
1703
- if (maskRef.current) maskRef.current.value = "";
1704
- setInner("");
1705
- setSecretDraft("");
1706
- onChange?.("");
1707
- onValueChange?.("", "");
1708
- onCentsChange?.(null);
1709
- };
1710
- const clear = () => {
1711
- resetValue();
1712
- inputRef.current?.focus();
1713
- };
1714
- const changeUnit = (id) => {
1715
- setInnerUnit(id);
1716
- onUnitChange?.(id);
1717
- resetValue();
1718
- };
1719
- if (isSecret && !isEditing) return /* @__PURE__ */ jsxs("div", {
1720
- "data-slot": "control",
1721
- "data-rendra": "CAMP-001",
1722
- className: cn(controlFrame({
1723
- size,
1724
- invalid
1725
- }), className),
1726
- children: [
1727
- /* @__PURE__ */ jsx("span", {
1728
- className: "min-w-0 flex-1 truncate font-mono text-sm text-muted-foreground",
1729
- children: hasValue ? maskedHint ?? "••••••••" : "Nenhum valor salvo"
1730
- }),
1731
- /* @__PURE__ */ jsx(Button, {
1732
- type: "button",
1733
- variant: "ghost",
1734
- size: "sm",
1735
- onClick: onStartEdit,
1736
- disabled,
1737
- id: fieldId,
1738
- "aria-describedby": fieldDescribedBy,
1739
- "aria-required": fieldRequired,
1740
- children: "Trocar"
1741
- }),
1742
- hasValue && onRemove && /* @__PURE__ */ jsx(Button, {
1743
- type: "button",
1744
- variant: "ghost",
1745
- size: "sm",
1746
- onClick: onRemove,
1747
- disabled: disabled || removing,
1748
- loading: removing,
1749
- children: "Remover"
1750
- })
1751
- ]
1752
- });
1753
- return /* @__PURE__ */ jsxs("div", {
1754
- "data-slot": "control",
1755
- "data-rendra": "CAMP-001",
1756
- className: cn(controlFrame({
1757
- size,
1758
- invalid
1759
- }), className),
1760
- children: [
1761
- showDdi && /* @__PURE__ */ jsxs("span", {
1762
- className: "relative -ml-1 flex h-full min-w-touch shrink-0 items-center gap-1 border-r pr-2 text-sm font-medium",
1763
- children: [
1764
- /* @__PURE__ */ jsxs("span", {
1765
- "aria-hidden": true,
1766
- children: ["+", ddi]
1767
- }),
1768
- /* @__PURE__ */ jsx(ChevronDown, {
1769
- className: "size-icon-sm text-muted-foreground",
1770
- "aria-hidden": true
1771
- }),
1772
- /* @__PURE__ */ jsx("select", {
1773
- "aria-label": `Código do país (DDI): ${country?.name ?? ""} +${ddi}`,
1774
- value: ddi,
1775
- disabled,
1776
- onChange: (e) => {
1777
- setInnerDdi(e.target.value);
1778
- onDdiChange?.(e.target.value);
1779
- },
1780
- className: "absolute inset-0 cursor-pointer bg-popover text-popover-foreground opacity-0 disabled:cursor-not-allowed",
1781
- children: ddiOptions.map((c) => /* @__PURE__ */ jsxs("option", {
1782
- value: c.ddi,
1783
- className: "bg-popover text-popover-foreground",
1784
- children: [
1785
- c.name,
1786
- " (+",
1787
- c.ddi,
1788
- ")"
1789
- ]
1790
- }, c.ddi))
1791
- })
1792
- ]
1793
- }),
1794
- icon && /* @__PURE__ */ jsx("span", {
1795
- className: "flex shrink-0 text-muted-foreground [&_svg]:size-icon-sm",
1796
- "aria-hidden": true,
1797
- children: icon
1798
- }),
1799
- /* @__PURE__ */ jsx("input", {
1800
- ref: inputRef,
1801
- type: isSecret ? showPassword ? "text" : "password" : isPassword && showPassword ? "text" : type,
1802
- inputMode: inputMode ?? def?.inputMode,
1803
- placeholder: placeholder ?? def?.placeholder,
1804
- disabled,
1805
- "aria-invalid": invalid || void 0,
1806
- "aria-busy": searching || void 0,
1807
- className: cn(controlInput, inputClassName),
1808
- ...isSecret ? {
1809
- value: secretDraft,
1810
- onChange: (e) => {
1811
- setSecretDraft(e.target.value);
1812
- onChange?.(e.target.value);
1813
- onValueChange?.(e.target.value, e.target.value);
1814
- }
1815
- } : maskKey ? { defaultValue: current } : {
1816
- value: current,
1817
- onChange: (e) => {
1818
- setInner(e.target.value);
1819
- onChange?.(e.target.value);
1820
- onValueChange?.(e.target.value, e.target.value);
1821
- }
1822
- },
1823
- ...props
1824
- }, hasUnits ? `unit-${unit}` : void 0),
1825
- searching && /* @__PURE__ */ jsx(Spinner, {
1826
- size: "sm",
1827
- label: "Buscando…",
1828
- className: "shrink-0 text-muted-foreground"
1829
- }),
1830
- hasUnits && /* @__PURE__ */ jsxs("span", {
1831
- className: "relative -mr-1 flex h-full min-w-touch shrink-0 items-center gap-1 border-l pl-2 text-sm font-medium",
1832
- children: [
1833
- /* @__PURE__ */ jsx("span", {
1834
- "aria-hidden": true,
1835
- children: units?.find((u) => u.id === unit)?.label ?? unit
1836
- }),
1837
- /* @__PURE__ */ jsx(ChevronDown, {
1838
- className: "size-icon-sm text-muted-foreground",
1839
- "aria-hidden": true
1840
- }),
1841
- /* @__PURE__ */ jsx("select", {
1842
- "aria-label": `Unidade: ${units?.find((u) => u.id === unit)?.label ?? unit}`,
1843
- value: unit,
1844
- disabled,
1845
- onChange: (e) => changeUnit(e.target.value),
1846
- className: "absolute inset-0 cursor-pointer bg-popover text-popover-foreground opacity-0 disabled:cursor-not-allowed",
1847
- children: units?.map((u) => /* @__PURE__ */ jsx("option", {
1848
- value: u.id,
1849
- className: "bg-popover text-popover-foreground",
1850
- children: u.label
1851
- }, u.id))
1852
- })
1853
- ]
1854
- }),
1855
- !hasUnits && suffix && /* @__PURE__ */ jsx("span", {
1856
- className: "shrink-0 text-sm text-muted-foreground",
1857
- children: suffix
1858
- }),
1859
- clearable && (isSecret ? secretDraft : current) && !disabled && /* @__PURE__ */ jsx("button", {
1860
- type: "button",
1861
- onClick: clear,
1862
- "aria-label": "Limpar campo",
1863
- className: "-mr-2 flex size-control-sm shrink-0 cursor-pointer items-center justify-center rounded-item text-muted-foreground transition-colors outline-none hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring md:-mr-1 md:size-8 [&_svg]:size-icon-sm",
1864
- children: /* @__PURE__ */ jsx(X, { "aria-hidden": true })
1865
- }),
1866
- (isPassword || isSecret) && /* @__PURE__ */ jsx("button", {
1867
- type: "button",
1868
- onClick: () => setShowPassword((s) => !s),
1869
- "aria-label": showPassword ? "Ocultar senha" : "Mostrar senha",
1870
- "aria-pressed": showPassword,
1871
- className: "-mr-2 flex size-control-sm shrink-0 cursor-pointer items-center justify-center rounded-item text-muted-foreground transition-colors outline-none hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring md:-mr-1 md:size-8 [&_svg]:size-icon-sm",
1872
- children: showPassword ? /* @__PURE__ */ jsx(EyeOff, { "aria-hidden": true }) : /* @__PURE__ */ jsx(Eye, { "aria-hidden": true })
1873
- }),
1874
- isSecret && /* @__PURE__ */ jsx(Button, {
1875
- type: "button",
1876
- variant: "ghost",
1877
- size: "sm",
1878
- onClick: onCancelEdit,
1879
- disabled,
1880
- children: "Cancelar"
1881
- })
1882
- ]
1883
- });
1884
- });
1885
- //#endregion
1886
936
  //#region src/components/ui/popover.tsx
1887
937
  var PopoverOpenContext = createContext(null);
1888
938
  function AnimatedRoot({ open, defaultOpen, onOpenChange, ...rest }) {
@@ -1908,10 +958,10 @@ var PopoverClose = Popover$1.Close;
1908
958
  var PopoverAnchor = Popover$1.Anchor;
1909
959
  function PopoverContent({ className, align = "center", sideOffset = 8, width = "md", children, asChild, ...props }) {
1910
960
  const open = useContext(PopoverOpenContext);
1911
- const motion = useMotionMode();
961
+ const lib = useMotionLib();
1912
962
  const presets = useMotionPresets();
1913
963
  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, {
964
+ if (lib && open !== null && !asChild) return /* @__PURE__ */ jsx(lib.AnimatePresence, { children: open && /* @__PURE__ */ jsx(Popover$1.Portal, {
1915
965
  forceMount: true,
1916
966
  children: /* @__PURE__ */ jsx(Popover$1.Content, {
1917
967
  forceMount: true,
@@ -1922,7 +972,7 @@ function PopoverContent({ className, align = "center", sideOffset = 8, width = "
1922
972
  "data-rendra": "POP-001",
1923
973
  className: cn(base, className),
1924
974
  ...props,
1925
- children: /* @__PURE__ */ jsx(m.div, {
975
+ children: /* @__PURE__ */ jsx(lib.m.div, {
1926
976
  ...presets.open(),
1927
977
  children
1928
978
  })
@@ -3029,7 +2079,8 @@ function QuickReplyList({ items, onPick }) {
3029
2079
  function Checkbox({ checked, defaultChecked, onCheckedChange, label, description, disabled, invalid, id, name, className, ...aria }) {
3030
2080
  const auto = useId();
3031
2081
  const cid = id ?? `cb${auto}`;
3032
- const on = useMotionMode() === "on";
2082
+ const lib = useMotionLib();
2083
+ const on = lib !== null;
3033
2084
  const presets = useMotionPresets();
3034
2085
  const [inner, setInner] = useState(defaultChecked ?? false);
3035
2086
  const state = checked ?? inner;
@@ -3060,16 +2111,16 @@ function Checkbox({ checked, defaultChecked, onCheckedChange, label, description
3060
2111
  const box = on ? /* @__PURE__ */ jsx(Checkbox$1.Root, {
3061
2112
  asChild: true,
3062
2113
  ...rootProps,
3063
- children: /* @__PURE__ */ jsx(m.button, {
2114
+ children: /* @__PURE__ */ jsx(lib.m.button, {
3064
2115
  type: "button",
3065
2116
  whileTap: presets.press.whileTap,
3066
2117
  transition: presets.press.transition,
3067
- children: /* @__PURE__ */ jsx(AnimatePresence, {
2118
+ children: /* @__PURE__ */ jsx(lib.AnimatePresence, {
3068
2119
  initial: false,
3069
2120
  children: state !== false && /* @__PURE__ */ jsx(Checkbox$1.Indicator, {
3070
2121
  forceMount: true,
3071
2122
  asChild: true,
3072
- children: /* @__PURE__ */ jsx(m.span, {
2123
+ children: /* @__PURE__ */ jsx(lib.m.span, {
3073
2124
  className: "flex items-center justify-center",
3074
2125
  ...presets.indicator,
3075
2126
  children: mark
@@ -3429,270 +2480,57 @@ function createPalette(seeds) {
3429
2480
  "--rendra-muted-foreground": reach(mix(fgD, mutedD, .35), mutedD, 4.5, "light"),
3430
2481
  "--rendra-border": mix(cardD, WHITE$1, .12),
3431
2482
  "--rendra-input": reach(mix(cardD, WHITE$1, .32), cardD, 3, "light"),
3432
- "--rendra-field": mix(g2, BLACK$1, .1),
3433
- "--rendra-overlay": alpha(mix(g2, BLACK$1, .6), .7),
3434
- ...brandDark,
3435
- "--rendra-primary-soft": softD,
3436
- "--rendra-primary-soft-foreground": reach(mix(P, WHITE$1, .45), softD, 4.5, "light"),
3437
- "--rendra-primary-text": textD,
3438
- "--rendra-ring": textD,
3439
- "--rendra-accent": mix(cardD, WHITE$1, .06),
3440
- "--rendra-accent-foreground": fgD,
3441
- ...sidebar,
3442
- "--rendra-sidebar": mix(g2, BLACK$1, .1),
3443
- "--rendra-gradient-soft": `linear-gradient(135deg, ${softD} 0%, ${cardD} 65%)`,
3444
- "--rendra-chart-1": reach(P, cardD, 3, "light"),
3445
- "--rendra-chart-2": reach(S, cardD, 3, "light"),
3446
- "--rendra-chart-3": mix(P, WHITE$1, .45),
3447
- "--rendra-chart-4": mix(P, WHITE$1, .72),
3448
- "--rendra-chart-5": reach(mix(S, WHITE$1, .3), cardD, 3, "light"),
3449
- "--rendra-shadow-color": "0 0 0"
3450
- },
3451
- sidebarLogo: sidebarDark ? "dark" : "light",
3452
- adjustments: notes
3453
- };
3454
- }
3455
- var block$1 = (selector, vars) => `${selector} {\n${Object.entries(vars).map(([k, v]) => ` ${k}: ${v};`).join("\n")}\n}\n`;
3456
- /**
3457
- * CSS da paleta. `isDefault` também aplica a paleta quando o <html> ainda não tem
3458
- * data-palette (primeira pintura).
3459
- */
3460
- function paletteCss(palette, isDefault = false) {
3461
- const id = palette.seeds.id;
3462
- const light = isDefault ? `:root:not([data-palette]),\n:root[data-palette='${id}']` : `:root[data-palette='${id}']`;
3463
- const dark = isDefault ? `:root:not([data-palette]).dark,\n:root[data-palette='${id}'].dark` : `:root[data-palette='${id}'].dark`;
3464
- const notes = palette.adjustments.length ? `/* Ajustes de contraste: ${palette.adjustments.join("; ")}. */\n` : "";
3465
- return `/* ${palette.seeds.name} */\n${notes}${block$1(light, palette.light)}\n${block$1(dark, palette.dark)}`;
3466
- }
3467
- /**
3468
- * White label em tempo de execução: gera a paleta de um cliente e a injeta na página
3469
- * (um <style> por paleta), sem build. Depois é só usar data-palette com o id dela.
3470
- * Devolve a paleta gerada, com os ajustes de contraste feitos.
3471
- */
3472
- function applyPalette(seeds, doc = document) {
3473
- const palette = createPalette(seeds);
3474
- const attr = "data-palette-runtime";
3475
- let style = doc.head.querySelector(`style[${attr}="${seeds.id}"]`);
3476
- if (!style) {
3477
- style = doc.createElement("style");
3478
- style.setAttribute(attr, seeds.id);
3479
- doc.head.appendChild(style);
3480
- }
3481
- style.textContent = paletteCss(palette);
3482
- return palette;
3483
- }
3484
- //#endregion
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
- }
3569
- function Anchor({ adornment, children }) {
3570
- if (!adornment) return children;
3571
- return /* @__PURE__ */ jsxs("div", {
3572
- className: "relative w-full min-w-0",
3573
- children: [children, adornment]
3574
- });
3575
- }
3576
- function PickerPanel({ open, onOpenChange, trigger, title, header, children, footer, width = "trigger", adornment, align = "start" }) {
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
- });
3664
- if (isMobile) return /* @__PURE__ */ jsxs(Dialog.Root, {
3665
- open,
3666
- onOpenChange,
3667
- children: [/* @__PURE__ */ jsx(Anchor, {
3668
- adornment,
3669
- children: /* @__PURE__ */ jsx(Dialog.Trigger, {
3670
- asChild: true,
3671
- children: trigger
3672
- })
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, {
3674
- "aria-describedby": void 0,
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
3677
- })] })]
3678
- });
3679
- return /* @__PURE__ */ jsxs(Popover$1.Root, {
3680
- open,
3681
- onOpenChange,
3682
- children: [/* @__PURE__ */ jsx(Anchor, {
3683
- adornment,
3684
- children: /* @__PURE__ */ jsx(Popover$1.Trigger, {
3685
- asChild: true,
3686
- children: trigger
3687
- })
3688
- }), /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Content, {
3689
- align,
3690
- sideOffset: 6,
3691
- collisionPadding: 16,
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
3694
- }) })]
3695
- });
2483
+ "--rendra-field": mix(g2, BLACK$1, .1),
2484
+ "--rendra-overlay": alpha(mix(g2, BLACK$1, .6), .7),
2485
+ ...brandDark,
2486
+ "--rendra-primary-soft": softD,
2487
+ "--rendra-primary-soft-foreground": reach(mix(P, WHITE$1, .45), softD, 4.5, "light"),
2488
+ "--rendra-primary-text": textD,
2489
+ "--rendra-ring": textD,
2490
+ "--rendra-accent": mix(cardD, WHITE$1, .06),
2491
+ "--rendra-accent-foreground": fgD,
2492
+ ...sidebar,
2493
+ "--rendra-sidebar": mix(g2, BLACK$1, .1),
2494
+ "--rendra-gradient-soft": `linear-gradient(135deg, ${softD} 0%, ${cardD} 65%)`,
2495
+ "--rendra-chart-1": reach(P, cardD, 3, "light"),
2496
+ "--rendra-chart-2": reach(S, cardD, 3, "light"),
2497
+ "--rendra-chart-3": mix(P, WHITE$1, .45),
2498
+ "--rendra-chart-4": mix(P, WHITE$1, .72),
2499
+ "--rendra-chart-5": reach(mix(S, WHITE$1, .3), cardD, 3, "light"),
2500
+ "--rendra-shadow-color": "0 0 0"
2501
+ },
2502
+ sidebarLogo: sidebarDark ? "dark" : "light",
2503
+ adjustments: notes
2504
+ };
2505
+ }
2506
+ var block$1 = (selector, vars) => `${selector} {\n${Object.entries(vars).map(([k, v]) => ` ${k}: ${v};`).join("\n")}\n}\n`;
2507
+ /**
2508
+ * CSS da paleta. `isDefault` também aplica a paleta quando o <html> ainda não tem
2509
+ * data-palette (primeira pintura).
2510
+ */
2511
+ function paletteCss(palette, isDefault = false) {
2512
+ const id = palette.seeds.id;
2513
+ const light = isDefault ? `:root:not([data-palette]),\n:root[data-palette='${id}']` : `:root[data-palette='${id}']`;
2514
+ const dark = isDefault ? `:root:not([data-palette]).dark,\n:root[data-palette='${id}'].dark` : `:root[data-palette='${id}'].dark`;
2515
+ const notes = palette.adjustments.length ? `/* Ajustes de contraste: ${palette.adjustments.join("; ")}. */\n` : "";
2516
+ return `/* ${palette.seeds.name} */\n${notes}${block$1(light, palette.light)}\n${block$1(dark, palette.dark)}`;
2517
+ }
2518
+ /**
2519
+ * White label em tempo de execução: gera a paleta de um cliente e a injeta na página
2520
+ * (um <style> por paleta), sem build. Depois é só usar data-palette com o id dela.
2521
+ * Devolve a paleta gerada, com os ajustes de contraste feitos.
2522
+ */
2523
+ function applyPalette(seeds, doc = document) {
2524
+ const palette = createPalette(seeds);
2525
+ const attr = "data-palette-runtime";
2526
+ let style = doc.head.querySelector(`style[${attr}="${seeds.id}"]`);
2527
+ if (!style) {
2528
+ style = doc.createElement("style");
2529
+ style.setAttribute(attr, seeds.id);
2530
+ doc.head.appendChild(style);
2531
+ }
2532
+ style.textContent = paletteCss(palette);
2533
+ return palette;
3696
2534
  }
3697
2535
  //#endregion
3698
2536
  //#region src/components/ui/color-picker.tsx
@@ -3789,93 +2627,17 @@ var ColorPicker = forwardRef(function ColorPicker({ value, onChange, swatches =
3789
2627
  });
3790
2628
  });
3791
2629
  //#endregion
3792
- //#region src/components/ui/drawer.tsx
3793
- var sizes = {
3794
- "30": "md:w-sheet-30",
3795
- "40": "md:w-sheet-40",
3796
- "50": "md:w-sheet-50",
3797
- "75": "md:w-sheet-75",
3798
- full: "md:w-full",
3799
- sm: "md:w-sheet-30",
3800
- md: "md:w-sheet-30",
3801
- lg: "md:w-sheet-50",
3802
- xl: "md:w-sheet-75"
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";
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." }) {
3807
- const [confirming, setConfirming] = useState(false);
3808
- const requestClose = () => dirty ? setConfirming(true) : onOpenChange(false);
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, {
3826
- open,
3827
- onOpenChange: (o) => o ? onOpenChange(true) : requestClose(),
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,
3852
- "data-rendra": "GAV-001",
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
3855
- })] })
3856
- }), /* @__PURE__ */ jsx(Modal, {
3857
- open: confirming,
3858
- onOpenChange: setConfirming,
3859
- type: "destructive",
3860
- title: discardTitle,
3861
- description: discardDescription,
3862
- confirmLabel: "Descartar",
3863
- cancelLabel: "Continuar editando",
3864
- onConfirm: () => onOpenChange(false)
3865
- })] });
3866
- }
3867
- //#endregion
3868
2630
  //#region src/components/ui/switch.tsx
3869
2631
  /** Switch único, com rótulo e descrição à esquerda e a chave à direita. */
3870
2632
  function Switch({ checked, defaultChecked, onCheckedChange, label, description, disabled, id, name, className, ...aria }) {
3871
2633
  const auto = useId();
3872
2634
  const sid = id ?? `sw${auto}`;
3873
- const motion = useMotionMode();
2635
+ const lib = useMotionLib();
3874
2636
  const presets = useMotionPresets();
3875
2637
  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");
2638
+ 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", lib ? "transition-[translate]" : "transition-transform");
3877
2639
  const tap = presets.tap;
3878
- const control = motion === "on" ? /* @__PURE__ */ jsx(Switch$1.Root, {
2640
+ const control = lib ? /* @__PURE__ */ jsx(Switch$1.Root, {
3879
2641
  asChild: true,
3880
2642
  id: sid,
3881
2643
  name,
@@ -3886,7 +2648,7 @@ function Switch({ checked, defaultChecked, onCheckedChange, label, description,
3886
2648
  "aria-label": aria["aria-label"],
3887
2649
  "data-touch": "expanded",
3888
2650
  "data-rendra": "SWT-001",
3889
- children: /* @__PURE__ */ jsx(m.button, {
2651
+ children: /* @__PURE__ */ jsx(lib.m.button, {
3890
2652
  type: "button",
3891
2653
  className: rootCls,
3892
2654
  initial: "rest",
@@ -3894,7 +2656,7 @@ function Switch({ checked, defaultChecked, onCheckedChange, label, description,
3894
2656
  whileTap: tap ? "tap" : void 0,
3895
2657
  children: /* @__PURE__ */ jsx(Switch$1.Thumb, {
3896
2658
  asChild: true,
3897
- children: /* @__PURE__ */ jsx(m.span, {
2659
+ children: /* @__PURE__ */ jsx(lib.m.span, {
3898
2660
  className: thumbCls,
3899
2661
  variants: {
3900
2662
  rest: { scale: 1 },
@@ -4086,121 +2848,6 @@ function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips =
4086
2848
  });
4087
2849
  }
4088
2850
  //#endregion
4089
- //#region src/components/layout/tokens.ts
4090
- var gapClass = {
4091
- "0": "gap-0",
4092
- "1": "gap-1",
4093
- "2": "gap-2",
4094
- "3": "gap-3",
4095
- "4": "gap-4",
4096
- "6": "gap-6",
4097
- "8": "gap-8",
4098
- "12": "gap-12",
4099
- "16": "gap-16",
4100
- "24": "gap-24",
4101
- section: "gap-8 md:gap-12",
4102
- fields: "gap-x-4 gap-y-4 md:gap-x-6"
4103
- };
4104
- /**
4105
- * Grade de formulário, pela largura do próprio bloco (container query), não da tela:
4106
- * 1 coluna estreito, 6 colunas a partir de 28rem, 12 colunas a partir de 48rem.
4107
- * No largo, o padrão é 3 campos por linha (md = 4/12). Nunca 2 por linha por padrão.
4108
- */
4109
- var fieldGridClass = "grid grid-cols-1 @md:grid-cols-6 @3xl:grid-cols-12";
4110
- /** Largura do Field na grade de formulário (no largo, em 12 colunas). */
4111
- var fieldSpanClass = {
4112
- /** 2/12, cerca de 17%: UF, número, DDD. */
4113
- xs: "@md:col-span-2 @3xl:col-span-2",
4114
- /** 3/12 = 25%: CEP, CNPJ, CPF, datas curtas. */
4115
- sm: "@md:col-span-2 @3xl:col-span-3",
4116
- /** 4/12 = 33%: o padrão, 3 campos por linha. */
4117
- md: "@md:col-span-3 @3xl:col-span-4",
4118
- /** 6/12 = 50%. */
4119
- lg: "@md:col-span-3 @3xl:col-span-6",
4120
- /** 8/12 = 67%: nome, logradouro longo. */
4121
- xl: "@md:col-span-6 @3xl:col-span-8",
4122
- /** Linha inteira. */
4123
- full: "@md:col-span-6 @3xl:col-span-12"
4124
- };
4125
- var alignClass = {
4126
- start: "items-start",
4127
- center: "items-center",
4128
- end: "items-end",
4129
- stretch: "items-stretch",
4130
- baseline: "items-baseline"
4131
- };
4132
- var justifyClass = {
4133
- start: "justify-start",
4134
- center: "justify-center",
4135
- end: "justify-end",
4136
- between: "justify-between"
4137
- };
4138
- //#endregion
4139
- //#region src/components/ui/field.tsx
4140
- function Label({ className, required, children, ...props }) {
4141
- return /* @__PURE__ */ jsxs(Label$1.Root, {
4142
- "data-rendra": "FLD-002",
4143
- className: cn("text-label text-label-foreground label-case", className),
4144
- ...props,
4145
- children: [
4146
- children,
4147
- required && /* @__PURE__ */ jsxs("span", {
4148
- className: "text-destructive",
4149
- "aria-hidden": true,
4150
- children: [" ", "*"]
4151
- }),
4152
- required && /* @__PURE__ */ jsx("span", {
4153
- className: "sr-only",
4154
- children: " (obrigatório)"
4155
- })
4156
- ]
4157
- });
4158
- }
4159
- var FieldContext = createContext(null);
4160
- /** Liga um controle ao Field mais próximo (id, aria-describedby, aria-invalid). */
4161
- function useFieldControl() {
4162
- return useContext(FieldContext);
4163
- }
4164
- function Field({ label, required, help, error, span = "md", newRow, reserveMessage = false, id, className, children }) {
4165
- const auto = useId();
4166
- const controlId = id ?? `campo${auto}`;
4167
- const messageId = `${controlId}-mensagem`;
4168
- const invalid = Boolean(error);
4169
- const message = error ?? help;
4170
- const child = isValidElement(children) && typeof children.type !== "string" ? cloneElement(children, {
4171
- id: children.props.id ?? controlId,
4172
- ...invalid ? { invalid: children.props.invalid ?? true } : {},
4173
- "aria-describedby": message ? messageId : void 0,
4174
- "aria-required": required || void 0
4175
- }) : children;
4176
- return /* @__PURE__ */ jsx(FieldContext.Provider, {
4177
- value: {
4178
- id: controlId,
4179
- describedBy: message ? messageId : "",
4180
- invalid
4181
- },
4182
- children: /* @__PURE__ */ jsxs("div", {
4183
- "data-slot": "field",
4184
- "data-rendra": "FLD-001",
4185
- className: cn("flex min-w-0 flex-col gap-2", fieldSpanClass[span === "half" ? "md" : span], newRow && "@md:col-start-1 @3xl:col-start-1", className),
4186
- children: [
4187
- label && /* @__PURE__ */ jsx(Label, {
4188
- htmlFor: controlId,
4189
- required,
4190
- children: label
4191
- }),
4192
- child,
4193
- (reserveMessage || message) && /* @__PURE__ */ jsx("p", {
4194
- id: messageId,
4195
- role: invalid ? "alert" : void 0,
4196
- className: cn("-mt-1 min-h-4 text-help", invalid ? "font-medium text-destructive" : "text-help-foreground"),
4197
- children: message
4198
- })
4199
- ]
4200
- })
4201
- });
4202
- }
4203
- //#endregion
4204
2851
  //#region src/components/ui/date-picker.tsx
4205
2852
  var fmtDate = (d) => format(d, "dd/MM/yyyy");
4206
2853
  var fmtTime = (d) => format(d, "HH:mm");
@@ -4583,318 +3230,6 @@ function Slider({ value, defaultValue = [50], onChange, min = 0, max = 100, step
4583
3230
  });
4584
3231
  }
4585
3232
  //#endregion
4586
- //#region src/components/ui/select.tsx
4587
- /** Acima deste número de opções, o "Selecionar todos" aparece sem a prop `selectAll`. */
4588
- var SELECT_ALL_AUTO_MIN = 5;
4589
- /**
4590
- * Select único do sistema. Busca, múltiplo, selecionar todos, contador, criar opção,
4591
- * busca remota e carregamento são props. No mobile abre como bottom sheet.
4592
- */
4593
- var Select = forwardRef(function Select(props, ref) {
4594
- const { options: staticOptions = [], placeholder = "Selecione", label, size, invalid, disabled, searchable, creatable, onCreate, loadOptions, loading, clearable, emptyText = "Nenhuma opção encontrada.", id, className } = props;
4595
- const multiple = props.multiple === true;
4596
- const { isMobile } = useBreakpoint();
4597
- const [open, setOpen] = useState(false);
4598
- const listId = `${useId()}-lista`;
4599
- const [query, setQuery] = useState("");
4600
- const [remote, setRemote] = useState(null);
4601
- const [remoteLoading, setRemoteLoading] = useState(false);
4602
- const [created, setCreated] = useState([]);
4603
- const [innerSingle, setInnerSingle] = useState(null);
4604
- const [innerMulti, setInnerMulti] = useState([]);
4605
- const [draft, setDraft] = useState([]);
4606
- const selectedSingle = multiple ? null : props.value ?? innerSingle;
4607
- const selectedMulti = multiple ? props.value ?? innerMulti : [];
4608
- const seq = useRef(0);
4609
- useEffect(() => {
4610
- if (!loadOptions || !open) return;
4611
- const n = ++seq.current;
4612
- setRemoteLoading(true);
4613
- const t = window.setTimeout(async () => {
4614
- const res = await loadOptions(query);
4615
- if (n === seq.current) {
4616
- setRemote(res);
4617
- setRemoteLoading(false);
4618
- }
4619
- }, 250);
4620
- return () => window.clearTimeout(t);
4621
- }, [
4622
- loadOptions,
4623
- query,
4624
- open
4625
- ]);
4626
- const all = useMemo(() => {
4627
- const base = remote ?? staticOptions;
4628
- const map = /* @__PURE__ */ new Map();
4629
- [...base, ...created].forEach((o) => map.set(o.value, o));
4630
- return [...map.values()];
4631
- }, [
4632
- remote,
4633
- staticOptions,
4634
- created
4635
- ]);
4636
- const byValue = (v) => all.find((o) => o.value === v);
4637
- const isSearchable = searchable || creatable || Boolean(loadOptions);
4638
- const busy = loading || remoteLoading;
4639
- const multiValue = isMobile && multiple ? draft : selectedMulti;
4640
- const commitSingle = (v) => {
4641
- setInnerSingle(v);
4642
- props.onChange?.(v);
4643
- };
4644
- const commitMulti = (v) => {
4645
- setInnerMulti(v);
4646
- props.onChange?.(v);
4647
- };
4648
- const toggle = (v) => {
4649
- if (!multiple) {
4650
- commitSingle(v);
4651
- setOpen(false);
4652
- return;
4653
- }
4654
- const next = multiValue.includes(v) ? multiValue.filter((x) => x !== v) : [...multiValue, v];
4655
- if (isMobile) setDraft(next);
4656
- else commitMulti(next);
4657
- };
4658
- const enabled = all.filter((o) => !o.disabled);
4659
- const allSelected = enabled.length > 0 && enabled.every((o) => multiValue.includes(o.value));
4660
- const showSelectAll = multiple && (props.selectAll ?? all.length > SELECT_ALL_AUTO_MIN);
4661
- const toggleAll = () => {
4662
- const next = allSelected ? [] : enabled.map((o) => o.value);
4663
- if (isMobile) setDraft(next);
4664
- else commitMulti(next);
4665
- };
4666
- const create = async () => {
4667
- const text = query.trim();
4668
- if (!text) return;
4669
- const opt = onCreate ? await onCreate(text) : {
4670
- value: text,
4671
- label: text
4672
- };
4673
- setCreated((c) => [...c, opt]);
4674
- setQuery("");
4675
- toggle(opt.value);
4676
- };
4677
- const onOpenChange = (o) => {
4678
- setOpen(o);
4679
- if (o) setDraft(selectedMulti);
4680
- else setQuery("");
4681
- };
4682
- const hasValue = multiple ? selectedMulti.length > 0 : selectedSingle != null;
4683
- const maxChips = props.maxChips ?? 2;
4684
- let display = /* @__PURE__ */ jsx("span", {
4685
- className: "truncate text-muted-foreground",
4686
- children: placeholder
4687
- });
4688
- if (!multiple && selectedSingle != null) {
4689
- const o = byValue(selectedSingle);
4690
- display = /* @__PURE__ */ jsxs("span", {
4691
- className: "flex min-w-0 items-center gap-2",
4692
- children: [o?.icon, /* @__PURE__ */ jsx("span", {
4693
- className: "truncate",
4694
- children: o?.label ?? selectedSingle
4695
- })]
4696
- });
4697
- } else if (multiple && selectedMulti.length > 0) display = props.showCount ? /* @__PURE__ */ jsxs("span", {
4698
- className: "truncate",
4699
- children: [
4700
- selectedMulti.length,
4701
- " ",
4702
- selectedMulti.length === 1 ? "selecionado" : "selecionados"
4703
- ]
4704
- }) : /* @__PURE__ */ jsxs("span", {
4705
- className: "flex min-w-0 items-center gap-1 overflow-hidden",
4706
- children: [selectedMulti.slice(0, maxChips).map((v) => /* @__PURE__ */ jsx("span", {
4707
- className: "max-w-3xs shrink-0 truncate rounded-item bg-primary-soft px-2 py-1 text-xs leading-none font-medium text-primary-soft-foreground",
4708
- children: byValue(v)?.label ?? v
4709
- }, v)), selectedMulti.length > maxChips && /* @__PURE__ */ jsxs("span", {
4710
- className: "shrink-0 rounded-item bg-muted px-2 py-1 text-xs leading-none font-medium",
4711
- children: ["+", selectedMulti.length - maxChips]
4712
- })]
4713
- });
4714
- const showClear = clearable && hasValue && !disabled;
4715
- const clear = showClear ? /* @__PURE__ */ jsx("button", {
4716
- type: "button",
4717
- "aria-label": "Limpar seleção",
4718
- className: cn(controlAdornmentButton, "absolute top-1/2 right-8 mr-0 -translate-y-1/2 md:mr-0"),
4719
- onClick: () => multiple ? commitMulti([]) : commitSingle(null),
4720
- children: /* @__PURE__ */ jsx(X, { "aria-hidden": true })
4721
- }) : void 0;
4722
- const trigger = /* @__PURE__ */ jsxs("button", {
4723
- ref,
4724
- id,
4725
- type: "button",
4726
- role: "combobox",
4727
- "aria-expanded": open,
4728
- "aria-controls": listId,
4729
- "aria-haspopup": "listbox",
4730
- "aria-invalid": invalid || void 0,
4731
- "aria-describedby": props["aria-describedby"],
4732
- "aria-label": id ? void 0 : label,
4733
- disabled,
4734
- "data-rendra": "SEL-001",
4735
- onKeyDown: (e) => e.stopPropagation(),
4736
- className: cn(controlFrame({
4737
- size,
4738
- invalid
4739
- }), "cursor-pointer text-left disabled:cursor-not-allowed disabled:opacity-60", className),
4740
- children: [
4741
- /* @__PURE__ */ jsx("span", {
4742
- className: "flex min-w-0 flex-1 items-center",
4743
- children: display
4744
- }),
4745
- showClear && /* @__PURE__ */ jsx("span", {
4746
- "aria-hidden": true,
4747
- className: cn("size-control-sm shrink-0 md:size-8", "-mr-1")
4748
- }),
4749
- /* @__PURE__ */ jsx(ChevronDown, {
4750
- "aria-hidden": true,
4751
- className: cn("size-icon-sm shrink-0 text-muted-foreground transition-transform duration-(--rendra-duration-base) ease-move", open && "rotate-180")
4752
- })
4753
- ]
4754
- });
4755
- const groups = all.reduce((acc, o) => {
4756
- (acc[o.group ?? ""] ??= []).push(o);
4757
- return acc;
4758
- }, {});
4759
- const q = query.trim().toLowerCase();
4760
- const showCreate = creatable && q && !all.some((o) => o.label.toLowerCase() === q);
4761
- const itemClass = "relative flex min-h-touch cursor-pointer items-center gap-3 rounded-item px-3 text-sm outline-none select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-accent md:min-h-0 md:py-2";
4762
- const checkbox = (checked) => /* @__PURE__ */ jsx("span", {
4763
- "aria-hidden": true,
4764
- className: cn("flex size-icon-sm shrink-0 items-center justify-center rounded-item border transition-colors", checked ? "border-primary bg-primary text-primary-foreground" : "border-input bg-card"),
4765
- children: checked && /* @__PURE__ */ jsx(Check, {
4766
- className: "size-3",
4767
- strokeWidth: 3
4768
- })
4769
- });
4770
- const list = /* @__PURE__ */ jsxs(Command.List, {
4771
- id: listId,
4772
- "aria-label": label ?? placeholder,
4773
- children: [
4774
- busy && /* @__PURE__ */ jsx(Command.Loading, { children: /* @__PURE__ */ jsxs("div", {
4775
- className: "flex items-center gap-2 px-3 py-4 text-sm text-muted-foreground",
4776
- children: [/* @__PURE__ */ jsx(Spinner, { size: "sm" }), "Carregando opções..."]
4777
- }) }),
4778
- !busy && /* @__PURE__ */ jsx(Command.Empty, {
4779
- className: "px-3 py-6 text-center text-sm text-muted-foreground",
4780
- children: emptyText
4781
- }),
4782
- showCreate && /* @__PURE__ */ jsxs(Command.Item, {
4783
- value: `__criar__${query}`,
4784
- onSelect: create,
4785
- className: itemClass,
4786
- children: [/* @__PURE__ */ jsx(Plus, {
4787
- className: "size-icon-sm shrink-0 text-primary-text",
4788
- "aria-hidden": true
4789
- }), /* @__PURE__ */ jsxs("span", {
4790
- className: "truncate",
4791
- children: ["Criar ", /* @__PURE__ */ jsxs("strong", {
4792
- className: "font-semibold",
4793
- children: [
4794
- "“",
4795
- query.trim(),
4796
- "”"
4797
- ]
4798
- })]
4799
- })]
4800
- }),
4801
- showSelectAll && !q && enabled.length > 0 && /* @__PURE__ */ jsxs(Command.Item, {
4802
- value: "__todos__",
4803
- onSelect: toggleAll,
4804
- className: cn(itemClass, "font-medium"),
4805
- children: [checkbox(allSelected), allSelected ? "Desmarcar todos" : "Selecionar todos"]
4806
- }),
4807
- Object.entries(groups).map(([group, opts]) => /* @__PURE__ */ jsx(Command.Group, {
4808
- heading: group || void 0,
4809
- className: "[&_[cmdk-group-heading]]:px-3 [&_[cmdk-group-heading]]:py-2 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
4810
- children: opts.map((o) => {
4811
- const checked = multiple ? multiValue.includes(o.value) : selectedSingle === o.value;
4812
- return /* @__PURE__ */ jsxs(Command.Item, {
4813
- value: `${o.label} ${o.description ?? ""} ${o.value}`,
4814
- disabled: o.disabled,
4815
- onSelect: () => toggle(o.value),
4816
- "aria-selected": checked,
4817
- className: itemClass,
4818
- children: [
4819
- multiple && checkbox(checked),
4820
- o.icon && /* @__PURE__ */ jsx("span", {
4821
- className: "flex shrink-0 [&_svg]:size-icon-sm",
4822
- children: o.icon
4823
- }),
4824
- /* @__PURE__ */ jsxs("span", {
4825
- className: "flex min-w-0 flex-1 flex-col",
4826
- children: [/* @__PURE__ */ jsx("span", {
4827
- className: cn("truncate", checked && !multiple && "font-medium"),
4828
- children: o.label
4829
- }), o.description && /* @__PURE__ */ jsx("span", {
4830
- className: "truncate text-xs text-muted-foreground",
4831
- children: o.description
4832
- })]
4833
- }),
4834
- !multiple && checked && /* @__PURE__ */ jsx(Check, {
4835
- className: "size-icon-sm shrink-0 text-primary-text",
4836
- "aria-hidden": true
4837
- })
4838
- ]
4839
- }, o.value);
4840
- })
4841
- }, group || "sem-grupo"))
4842
- ]
4843
- });
4844
- const search = isSearchable ? /* @__PURE__ */ jsxs("div", {
4845
- className: cn(controlFrame({ size: "md" }), "bg-background"),
4846
- children: [/* @__PURE__ */ jsx(Search, {
4847
- className: "size-icon-sm shrink-0 text-muted-foreground",
4848
- "aria-hidden": true
4849
- }), /* @__PURE__ */ jsx(Command.Input, {
4850
- value: query,
4851
- onValueChange: setQuery,
4852
- placeholder: creatable ? "Buscar ou criar..." : "Buscar...",
4853
- className: "h-full min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground"
4854
- })]
4855
- }) : null;
4856
- const count = multiValue.length;
4857
- const footer = multiple && (isMobile || count > 0) ? /* @__PURE__ */ jsxs("div", {
4858
- className: "grid grid-actions-2 gap-3",
4859
- children: [/* @__PURE__ */ jsx(Button, {
4860
- variant: "outline",
4861
- onClick: () => isMobile ? setDraft([]) : commitMulti([]),
4862
- disabled: count === 0,
4863
- children: "Limpar"
4864
- }), isMobile ? /* @__PURE__ */ jsxs(Button, {
4865
- onClick: () => {
4866
- commitMulti(draft);
4867
- setOpen(false);
4868
- },
4869
- children: ["Aplicar", count ? ` (${count})` : ""]
4870
- }) : /* @__PURE__ */ jsxs(Button, {
4871
- variant: "secondary",
4872
- onClick: () => setOpen(false),
4873
- children: [
4874
- "Pronto (",
4875
- count,
4876
- ")"
4877
- ]
4878
- })]
4879
- }) : void 0;
4880
- return /* @__PURE__ */ jsx(Command, {
4881
- shouldFilter: !loadOptions,
4882
- loop: true,
4883
- className: "contents",
4884
- label: label ?? placeholder,
4885
- children: /* @__PURE__ */ jsx(PickerPanel, {
4886
- open,
4887
- onOpenChange,
4888
- trigger,
4889
- adornment: clear,
4890
- title: label ?? placeholder,
4891
- header: search,
4892
- footer,
4893
- children: list
4894
- })
4895
- });
4896
- });
4897
- //#endregion
4898
3233
  //#region src/components/ui/tabs.tsx
4899
3234
  /** Contador de instâncias, só para o `layoutId` do indicador (ver `indicatorId`). */
4900
3235
  var tabsCreated = 0;
@@ -4924,6 +3259,7 @@ function Tabs({ items, value, defaultValue, onChange, variant = "line", classNam
4924
3259
  }, [items, variant]);
4925
3260
  const presets = useMotionPresets();
4926
3261
  const on = useLayoutReady();
3262
+ const lib = useMotionLib();
4927
3263
  const listRef = useRef(null);
4928
3264
  const [clip, setClip] = useState({
4929
3265
  l: 0,
@@ -4955,7 +3291,7 @@ function Tabs({ items, value, defaultValue, onChange, variant = "line", classNam
4955
3291
  ]);
4956
3292
  const [indicatorId] = useState(() => `rendra-tabs-${++tabsCreated}`);
4957
3293
  const trigger = cn("inline-flex min-h-touch shrink-0 cursor-pointer items-center justify-center gap-2 px-3 text-sm font-medium whitespace-nowrap transition-colors outline-none disabled:cursor-not-allowed disabled:opacity-50 md:min-h-0 [&_svg]:size-icon-sm", variant === "line" ? on ? "relative -mb-px border-b-2 border-transparent py-3 text-muted-foreground hover:text-foreground" : "-mb-px border-b-2 border-transparent py-3 text-muted-foreground hover:text-foreground data-[state=active]:border-primary data-[state=active]:text-foreground" : on ? "relative isolate rounded-item py-2 text-muted-foreground hover:bg-card/60 hover:text-foreground" : "rounded-item py-2 text-muted-foreground hover:bg-card/60 hover:text-foreground data-[state=active]:bg-card data-[state=active]:text-foreground data-[state=active]:shadow-sm");
4958
- const indicator = /* @__PURE__ */ jsx(m.span, {
3294
+ const indicator = lib && /* @__PURE__ */ jsx(lib.m.span, {
4959
3295
  layoutId: indicatorId,
4960
3296
  "data-indicator": "tabs",
4961
3297
  "aria-hidden": true,
@@ -5456,33 +3792,6 @@ function ImageViewer({ images, index, onIndexChange }) {
5456
3792
  });
5457
3793
  }
5458
3794
  //#endregion
5459
- //#region src/hooks/use-fill-height.ts
5460
- /**
5461
- * Mede o espaço que sobra na área de conteúdo (o <main>) abaixo do elemento e grava em
5462
- * --board-h. Com a classe h-board, o elemento ocupa exatamente essa altura: a página não
5463
- * rola e a rolagem acontece dentro dele (kanban, chat).
5464
- */
5465
- function useFillHeight() {
5466
- const ref = useRef(null);
5467
- useLayoutEffect(() => {
5468
- const el = ref.current;
5469
- if (!el) return;
5470
- const main = el.closest("main");
5471
- const measure = () => {
5472
- const h = el.getBoundingClientRect().height;
5473
- const page = main?.firstElementChild;
5474
- const room = main && page ? main.clientHeight - (page.getBoundingClientRect().height - h) : window.innerHeight - el.getBoundingClientRect().top;
5475
- el.style.setProperty("--board-h", `${Math.max(320, Math.floor(room))}px`);
5476
- };
5477
- measure();
5478
- const ro = new ResizeObserver(measure);
5479
- ro.observe(document.documentElement);
5480
- if (main) ro.observe(main);
5481
- return () => ro.disconnect();
5482
- }, []);
5483
- return ref;
5484
- }
5485
- //#endregion
5486
3795
  //#region src/components/ui/kanban.tsx
5487
3796
  /** Marca o fim da lista: ao aparecer na rolagem da etapa, pede mais cards. */
5488
3797
  function LoadMore({ onVisible }) {
@@ -5630,6 +3939,7 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
5630
3939
  const code = resolveCatalogCode("Kanban", { hasDropTargets: Boolean(dropTargets?.length) });
5631
3940
  const { isMobile } = useBreakpoint();
5632
3941
  const motion = useMotionMode();
3942
+ const lib = useMotionLib();
5633
3943
  const ready = useLayoutReady();
5634
3944
  const presets = useMotionPresets();
5635
3945
  const [boardId] = useState(() => `rendra-kanban-${++boardsCreated}`);
@@ -5846,13 +4156,13 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
5846
4156
  children: moveMenu(card)
5847
4157
  })
5848
4158
  ] });
5849
- if (motion === "on") {
4159
+ if (lib) {
5850
4160
  const layout = layoutEnabled({
5851
4161
  mode: motion,
5852
4162
  ready,
5853
4163
  dragging: touchDrag !== null
5854
4164
  });
5855
- return /* @__PURE__ */ jsx(m.li, {
4165
+ return /* @__PURE__ */ jsx(lib.m.li, {
5856
4166
  ref: (el) => {
5857
4167
  if (!el) return;
5858
4168
  const onStart = (e) => dragStart(e.dataTransfer);
@@ -6080,9 +4390,10 @@ function List({ items, divided = true, empty, className, onReorder, itemLabel =
6080
4390
  });
6081
4391
  const sortableEnabled = Boolean(onReorder);
6082
4392
  const motion = useMotionMode();
4393
+ const lib = useMotionLib();
6083
4394
  const ready = useLayoutReady();
6084
4395
  const presets = useMotionPresets();
6085
- const Item = motion === "on" ? m.li : "li";
4396
+ const Item = lib ? lib.m.li : "li";
6086
4397
  const itemMotion = motion === "on" ? {
6087
4398
  layout: layoutEnabled({
6088
4399
  mode: motion,
@@ -6163,9 +4474,10 @@ function List({ items, divided = true, empty, className, onReorder, itemLabel =
6163
4474
  */
6164
4475
  function OtpInput({ length = 6, value, onChange, onComplete, invalid, disabled, id, ...aria }) {
6165
4476
  const refs = useRef([]);
6166
- const on = useMotionMode() === "on";
4477
+ const lib = useMotionLib();
4478
+ const on = lib !== null;
6167
4479
  const presets = useMotionPresets();
6168
- const Cell = on ? m.input : "input";
4480
+ const Cell = on ? lib.m.input : "input";
6169
4481
  const digits = Array.from({ length }, (_, i) => value[i] ?? "");
6170
4482
  const set = (next) => {
6171
4483
  const clean = next.replace(/\D/g, "").slice(0, length);
@@ -7220,16 +5532,17 @@ var cols = {
7220
5532
  * O item do Radix. Em `on` ele é um `m.button` (asChild) que responde ao toque (whileTap 0,97,
7221
5533
  * em `press`); em `off` é o `R.Item` de sempre, sem nó novo.
7222
5534
  */
7223
- function Item({ on, children, ...props }) {
5535
+ function Item({ children, ...props }) {
7224
5536
  const presets = useMotionPresets();
7225
- if (!on) return /* @__PURE__ */ jsx(RadioGroup$1.Item, {
5537
+ const lib = useMotionLib();
5538
+ if (!lib) return /* @__PURE__ */ jsx(RadioGroup$1.Item, {
7226
5539
  ...props,
7227
5540
  children
7228
5541
  });
7229
5542
  return /* @__PURE__ */ jsx(RadioGroup$1.Item, {
7230
5543
  asChild: true,
7231
5544
  ...props,
7232
- children: /* @__PURE__ */ jsx(m.button, {
5545
+ children: /* @__PURE__ */ jsx(lib.m.button, {
7233
5546
  type: "button",
7234
5547
  whileTap: presets.press.whileTap,
7235
5548
  transition: presets.press.transition,
@@ -7239,14 +5552,15 @@ function Item({ on, children, ...props }) {
7239
5552
  }
7240
5553
  /** Radio único: em lista ou em cards, por prop. */
7241
5554
  function RadioGroup({ options, value, defaultValue, onChange, variant = "list", columns = 2, orientation = "vertical", invalid, disabled, id, name, ...aria }) {
7242
- const on = useMotionMode() === "on";
5555
+ const lib = useMotionLib();
5556
+ const on = lib !== null;
7243
5557
  const presets = useMotionPresets();
7244
5558
  const [inner, setInner] = useState(defaultValue);
7245
5559
  const current = value ?? inner;
7246
5560
  const dotFor = (optionValue) => /* @__PURE__ */ jsx("span", {
7247
5561
  "aria-hidden": true,
7248
5562
  className: cn("flex size-icon-md shrink-0 items-center justify-center rounded-full border border-input bg-card transition-colors group-data-[state=checked]:border-primary", invalid && "border-destructive"),
7249
- children: on ? /* @__PURE__ */ jsx(m.span, {
5563
+ children: on ? /* @__PURE__ */ jsx(lib.m.span, {
7250
5564
  className: "size-2 rounded-full bg-primary",
7251
5565
  initial: false,
7252
5566
  animate: current === optionValue ? presets.indicator.animate : presets.indicator.initial,
@@ -7269,7 +5583,6 @@ function RadioGroup({ options, value, defaultValue, onChange, variant = "list",
7269
5583
  "data-rendra": resolveCatalogCode("RadioGroup", { variant }),
7270
5584
  className: cn(variant === "cards" ? cn("grid grid-cols-1 gap-3", cols[columns]) : orientation === "horizontal" ? "flex flex-col sm:flex-row sm:flex-wrap sm:gap-x-6" : "flex flex-col"),
7271
5585
  children: options.map((o) => variant === "cards" ? /* @__PURE__ */ jsxs(Item, {
7272
- on,
7273
5586
  value: o.value,
7274
5587
  disabled: o.disabled,
7275
5588
  className: cn("group relative flex cursor-pointer items-start gap-3 rounded-control border bg-card p-4 text-left transition-[border-color,box-shadow,background-color]", "hover:border-primary data-[state=checked]:border-primary data-[state=checked]:bg-primary-soft data-[state=checked]:ring-1 data-[state=checked]:ring-primary", "disabled:cursor-not-allowed disabled:opacity-50", invalid && "border-destructive"),
@@ -7293,7 +5606,6 @@ function RadioGroup({ options, value, defaultValue, onChange, variant = "list",
7293
5606
  }, o.value) : /* @__PURE__ */ jsxs("label", {
7294
5607
  className: cn("flex min-h-touch cursor-pointer items-start gap-3 py-3 md:min-h-0 md:py-1", o.disabled && "cursor-not-allowed opacity-60"),
7295
5608
  children: [/* @__PURE__ */ jsx(Item, {
7296
- on,
7297
5609
  value: o.value,
7298
5610
  disabled: o.disabled,
7299
5611
  className: "group flex pt-px outline-none focus-visible:[&>span]:focus-ring",
@@ -7551,11 +5863,14 @@ function Skeleton({ className, ...props }) {
7551
5863
  //#region src/components/ui/stat-card.tsx
7552
5864
  /** Contagem de 0 até o valor, com o formato do texto original; no fim mostra o `value` exato. */
7553
5865
  function Counter({ parsed, value }) {
5866
+ const { animate, m, useMotionValue, useTransform } = useMotionOn();
7554
5867
  const presets = useMotionPresets();
7555
- const progress = useMotionValue(0);
5868
+ const [skip] = useState(useMotionAdopted());
5869
+ const progress = useMotionValue(skip ? parsed.value : 0);
7556
5870
  const text = useTransform(progress, (n) => formatLike(parsed, n));
7557
- const [done, setDone] = useState(false);
5871
+ const [done, setDone] = useState(skip);
7558
5872
  useEffect(() => {
5873
+ if (skip) return;
7559
5874
  const controls = animate(progress, parsed.value, {
7560
5875
  duration: presets.tokens.reveal.count,
7561
5876
  ease: presets.tokens.ease.out,
@@ -7563,9 +5878,11 @@ function Counter({ parsed, value }) {
7563
5878
  });
7564
5879
  return () => controls.stop();
7565
5880
  }, [
5881
+ animate,
7566
5882
  progress,
7567
5883
  parsed.value,
7568
- presets.tokens
5884
+ presets.tokens,
5885
+ skip
7569
5886
  ]);
7570
5887
  return /* @__PURE__ */ jsx(m.span, {
7571
5888
  ...presets.fade,
@@ -7578,11 +5895,11 @@ function Counter({ parsed, value }) {
7578
5895
  * o valor final aparece direto.
7579
5896
  */
7580
5897
  function StatValue({ value }) {
7581
- const motion = useMotionMode();
5898
+ const lib = useMotionLib();
7582
5899
  const presets = useMotionPresets();
7583
5900
  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, {
5901
+ if (!lib) return /* @__PURE__ */ jsx(Fragment$1, { children: value });
5902
+ if (!parsed || presets.reduced) return /* @__PURE__ */ jsx(lib.m.span, {
7586
5903
  ...presets.fade,
7587
5904
  children: value
7588
5905
  });
@@ -7783,7 +6100,7 @@ var tableFeatureSet = tableFeatures({
7783
6100
  * conteúdo fechado sai do DOM; em `off` é o Collapsible de sempre, com as animações em CSS.
7784
6101
  */
7785
6102
  function MobileDetails({ children }) {
7786
- const motion = useMotionMode();
6103
+ const lib = useMotionLib();
7787
6104
  const presets = useMotionPresets();
7788
6105
  const [open, setOpen] = useState(false);
7789
6106
  const trigger = /* @__PURE__ */ jsxs(Collapsible.Trigger, {
@@ -7803,15 +6120,15 @@ function MobileDetails({ children }) {
7803
6120
  })
7804
6121
  ]
7805
6122
  });
7806
- if (motion === "on") return /* @__PURE__ */ jsxs(Collapsible.Root, {
6123
+ if (lib) return /* @__PURE__ */ jsxs(Collapsible.Root, {
7807
6124
  open,
7808
6125
  onOpenChange: setOpen,
7809
- children: [trigger, /* @__PURE__ */ jsx(AnimatePresence, {
6126
+ children: [trigger, /* @__PURE__ */ jsx(lib.AnimatePresence, {
7810
6127
  initial: false,
7811
6128
  children: open && /* @__PURE__ */ jsx(Collapsible.Content, {
7812
6129
  forceMount: true,
7813
6130
  asChild: true,
7814
- children: /* @__PURE__ */ jsx(m.div, {
6131
+ children: /* @__PURE__ */ jsx(lib.m.div, {
7815
6132
  className: "overflow-hidden",
7816
6133
  initial: {
7817
6134
  height: 0,
@@ -7838,7 +6155,8 @@ function MobileDetails({ children }) {
7838
6155
  }
7839
6156
  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 }) {
7840
6157
  const { isMobile } = useBreakpoint();
7841
- const on = useMotionMode() === "on";
6158
+ const lib = useMotionLib();
6159
+ const on = lib !== null;
7842
6160
  const presets = useMotionPresets();
7843
6161
  const columns = useMemo(() => statusLast ? [...columnsProp.filter((c) => c.kind !== "badge"), ...columnsProp.filter((c) => c.kind === "badge")] : columnsProp, [columnsProp, statusLast]);
7844
6162
  const [sorting, setSorting] = useState([]);
@@ -8259,14 +6577,14 @@ function Table({ data: dataProp, source, queryKey = "", columns: columnsProp, st
8259
6577
  children: expandable(row)
8260
6578
  })
8261
6579
  }),
8262
- expandable && on && /* @__PURE__ */ jsx(AnimatePresence, {
6580
+ expandable && on && /* @__PURE__ */ jsx(lib.AnimatePresence, {
8263
6581
  initial: false,
8264
6582
  children: r.getIsExpanded() && /* @__PURE__ */ jsx("tr", {
8265
6583
  className: "bg-muted/30",
8266
6584
  children: /* @__PURE__ */ jsx("td", {
8267
6585
  colSpan: visibleCols.length + (selectable ? 1 : 0) + 1 + (rowActions ? 1 : 0),
8268
6586
  className: "px-4",
8269
- children: /* @__PURE__ */ jsx(m.div, {
6587
+ children: /* @__PURE__ */ jsx(lib.m.div, {
8270
6588
  className: "overflow-hidden",
8271
6589
  initial: {
8272
6590
  height: 0,
@@ -8386,94 +6704,6 @@ var Textarea = forwardRef(function Textarea({ invalid, counter, value, defaultVa
8386
6704
  });
8387
6705
  });
8388
6706
  //#endregion
8389
- //#region src/components/ui/timeline.tsx
8390
- var dot = {
8391
- neutral: "bg-muted text-muted-foreground",
8392
- info: "bg-info-soft text-info-soft-foreground",
8393
- success: "bg-success-soft text-success-soft-foreground",
8394
- warning: "bg-warning-soft text-warning-soft-foreground",
8395
- error: "bg-destructive-soft text-destructive-soft-foreground"
8396
- };
8397
- var statusTone = {
8398
- succeeded: "success",
8399
- failed: "error",
8400
- skipped: "neutral"
8401
- };
8402
- var statusIcon = {
8403
- succeeded: CheckCircle2,
8404
- failed: XCircle,
8405
- skipped: SkipForward
8406
- };
8407
- var statusLabel$1 = {
8408
- succeeded: "Concluído",
8409
- failed: "Falhou",
8410
- skipped: "Ignorado"
8411
- };
8412
- var statusTextTone = {
8413
- succeeded: "text-success-soft-foreground",
8414
- failed: "text-destructive-soft-foreground",
8415
- skipped: "text-muted-foreground"
8416
- };
8417
- /** Linha do tempo única, com eventos em ordem e tom semântico por evento. */
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");
8423
- return /* @__PURE__ */ jsx("ol", {
8424
- "data-rendra": "TLN-001",
8425
- className: cn("@container flex flex-col", className),
8426
- children: events.map((e, i) => {
8427
- const StatusIcon = e.status ? statusIcon[e.status] : null;
8428
- const tone = e.tone ?? (e.status ? statusTone[e.status] : "neutral");
8429
- return /* @__PURE__ */ jsxs(Item, {
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
- } : {},
8438
- children: [
8439
- i < events.length - 1 && /* @__PURE__ */ jsx("span", {
8440
- "aria-hidden": true,
8441
- className: "absolute top-8 bottom-0 left-4 w-px -translate-x-1/2 bg-border"
8442
- }),
8443
- /* @__PURE__ */ jsx("span", {
8444
- "aria-hidden": true,
8445
- className: cn("relative flex size-8 shrink-0 items-center justify-center rounded-full [&_svg]:size-icon-sm", dot[tone]),
8446
- children: e.icon ?? (StatusIcon && /* @__PURE__ */ jsx(StatusIcon, {})) ?? /* @__PURE__ */ jsx("span", { className: "size-2 rounded-full bg-current" })
8447
- }),
8448
- /* @__PURE__ */ jsxs("div", {
8449
- className: "flex min-w-0 flex-1 flex-col gap-1 pt-1",
8450
- children: [
8451
- /* @__PURE__ */ jsxs("div", {
8452
- className: "flex min-w-0 flex-col gap-1 @sm:flex-row @sm:items-baseline @sm:justify-between @sm:gap-3",
8453
- children: [/* @__PURE__ */ jsx("span", {
8454
- className: "text-sm font-medium wrap-break-word",
8455
- children: e.title
8456
- }), /* @__PURE__ */ jsx("time", {
8457
- className: "shrink-0 text-xs text-muted-foreground tabular-nums",
8458
- children: e.date
8459
- })]
8460
- }),
8461
- e.description && /* @__PURE__ */ jsx("p", {
8462
- className: "text-sm wrap-break-word text-muted-foreground",
8463
- children: e.description
8464
- }),
8465
- e.status && StatusIcon && /* @__PURE__ */ jsxs("span", {
8466
- className: cn("inline-flex w-fit items-center gap-1 text-xs font-medium [&_svg]:size-icon-sm", statusTextTone[e.status]),
8467
- children: [/* @__PURE__ */ jsx(StatusIcon, {}), statusLabel$1[e.status]]
8468
- })
8469
- ]
8470
- })
8471
- ]
8472
- }, e.id);
8473
- })
8474
- });
8475
- }
8476
- //#endregion
8477
6707
  //#region src/components/ui/toast.tsx
8478
6708
  var tone = {
8479
6709
  success: "border-success/25",
@@ -8680,9 +6910,10 @@ function Upload({ accept, multiple = true, maxSizeMb = 10, onUpload, onChange, h
8680
6910
  }
8681
6911
  });
8682
6912
  const motion = useMotionMode();
6913
+ const lib = useMotionLib();
8683
6914
  const ready = useLayoutReady();
8684
6915
  const presets = useMotionPresets();
8685
- const Item = motion === "on" ? m.li : "li";
6916
+ const Item = lib ? lib.m.li : "li";
8686
6917
  const itemMotion = motion === "on" ? {
8687
6918
  ...presets.fade,
8688
6919
  layout: layoutEnabled({
@@ -8695,7 +6926,7 @@ function Upload({ accept, multiple = true, maxSizeMb = 10, onUpload, onChange, h
8695
6926
  layout: presets.move
8696
6927
  }
8697
6928
  } : {};
8698
- const animated = (nodes) => motion === "on" ? /* @__PURE__ */ jsx(AnimatePresence, {
6929
+ const animated = (nodes) => lib ? /* @__PURE__ */ jsx(lib.AnimatePresence, {
8699
6930
  mode: "popLayout",
8700
6931
  initial: false,
8701
6932
  children: nodes
@@ -8944,7 +7175,7 @@ var statusLabel = {
8944
7175
  */
8945
7176
  function Stepper({ steps, current, errors = [], orientation = "horizontal", onStepClick, className }) {
8946
7177
  const step = steps[current];
8947
- const motion = useMotionMode();
7178
+ const lib = useMotionLib();
8948
7179
  const presets = useMotionPresets();
8949
7180
  return /* @__PURE__ */ jsxs("div", {
8950
7181
  "data-rendra": "WIZ-002",
@@ -8985,7 +7216,7 @@ function Stepper({ steps, current, errors = [], orientation = "horizontal", onSt
8985
7216
  const clickable = onStepClick && st === "complete";
8986
7217
  const circle = /* @__PURE__ */ jsx("span", {
8987
7218
  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"),
8988
- children: st === "complete" ? motion === "on" ? /* @__PURE__ */ jsx(m.span, {
7219
+ children: st === "complete" ? lib ? /* @__PURE__ */ jsx(lib.m.span, {
8989
7220
  className: "flex",
8990
7221
  ...presets.pop,
8991
7222
  children: /* @__PURE__ */ jsx(Check, {
@@ -9075,17 +7306,17 @@ function Wizard({ steps, children, onValidateStep, onFinish, onCancel, cancelLab
9075
7306
  setCurrent((c) => c + 1);
9076
7307
  onSkip?.();
9077
7308
  };
9078
- const motion = useMotionMode();
7309
+ const lib = useMotionLib();
9079
7310
  const presets = useMotionPresets();
9080
7311
  const previous = useRef(current);
9081
7312
  const direction = current >= previous.current ? 1 : -1;
9082
7313
  previous.current = current;
9083
- const body = motion === "on" ? /* @__PURE__ */ jsx("div", {
7314
+ const body = lib ? /* @__PURE__ */ jsx("div", {
9084
7315
  className: "relative flex min-w-0 flex-col gap-6",
9085
- children: /* @__PURE__ */ jsx(AnimatePresence, {
7316
+ children: /* @__PURE__ */ jsx(lib.AnimatePresence, {
9086
7317
  mode: "popLayout",
9087
7318
  initial: false,
9088
- children: /* @__PURE__ */ jsx(m.div, {
7319
+ children: /* @__PURE__ */ jsx(lib.m.div, {
9089
7320
  ...presets.swap(direction),
9090
7321
  className: "flex min-w-0 flex-col gap-6",
9091
7322
  children: children[current]