@rendra-ui/web 2.6.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -14
- package/dist/base.css +1 -1
- package/dist/{empty-state-DrQjqxvp.js → brand-feedback-icon-CVux4pNh.js} +4 -64
- package/dist/brand-feedback-icon-CVux4pNh.js.map +1 -0
- package/dist/{button-B6-644xP.js → button-CrSlVIsY.js} +6 -6
- package/dist/{button-B6-644xP.js.map → button-CrSlVIsY.js.map} +1 -1
- package/dist/chart.js +7 -7
- package/dist/cli/auditar.js +1 -1
- package/dist/cli/codigos.js +2 -2
- package/dist/cli/executar-auditar.js +1 -1
- package/dist/cli/help.js +1 -1
- package/dist/cli/trocar.js +2 -2
- package/dist/cli/typescript-loader.js +1 -1
- package/dist/{cn-TBlI6-gS.js → cn-BlJHpkDs.js} +2 -2
- package/dist/{cn-TBlI6-gS.js.map → cn-BlJHpkDs.js.map} +1 -1
- package/dist/{components-Btk1cUg2.js → components-6RpoJ2Od.js} +20 -4
- package/dist/{components-Btk1cUg2.js.map → components-6RpoJ2Od.js.map} +1 -1
- package/dist/components.css +108 -1
- package/dist/document-viewer.js +4 -4
- package/dist/{tooltip-kgsorOg6.js → dropdown-menu-BUGKtR6k.js} +9 -75
- package/dist/dropdown-menu-BUGKtR6k.js.map +1 -0
- package/dist/empty-state-i4e-LacG.js +67 -0
- package/dist/empty-state-i4e-LacG.js.map +1 -0
- package/dist/{features-max-CC6CorTg.js → features-max-BCIy1Ic-.js} +1 -1
- package/dist/flow.js +1485 -0
- package/dist/flow.js.map +1 -0
- package/dist/index.js +816 -2019
- package/dist/index.js.map +1 -1
- package/dist/{motion-context-BL545cb6.js → motion-context-PJPj6X4g.js} +4 -4
- package/dist/{motion-context-BL545cb6.js.map → motion-context-PJPj6X4g.js.map} +1 -1
- package/dist/{motion-on-DMoTsWrG.js → motion-on-Bocf4Smc.js} +2 -2
- package/dist/{motion-on-DMoTsWrG.js.map → motion-on-Bocf4Smc.js.map} +1 -1
- package/dist/motion.js +2 -2
- package/dist/{rendra-provider-CeCkPafT.js → rendra-provider-Do_qWjJC.js} +3 -3
- package/dist/{rendra-provider-CeCkPafT.js.map → rendra-provider-Do_qWjJC.js.map} +1 -1
- package/dist/rich-text-editor.js +4 -3
- package/dist/rich-text-editor.js.map +1 -1
- package/dist/router-bridge.js +2 -2
- package/dist/timeline-xrMHeV92.js +1803 -0
- package/dist/timeline-xrMHeV92.js.map +1 -0
- package/dist/tokens.css +9 -1
- package/dist/tooltip-to0h6aPe.js +76 -0
- package/dist/tooltip-to0h6aPe.js.map +1 -0
- package/dist/types/components/ui/data-toolbar.d.ts +6 -1
- package/dist/types/components/ui/flow-editor.d.ts +11 -0
- package/dist/types/components/ui/flow-viewer.d.ts +58 -0
- package/dist/types/components/ui/kanban.d.ts +75 -6
- package/dist/types/flow.d.ts +3 -0
- package/dist/types/lib/flow.d.ts +121 -0
- package/dist/{use-breakpoint-CNxDwEpc.js → use-breakpoint-CM-yeDHJ.js} +2 -2
- package/dist/{use-breakpoint-CNxDwEpc.js.map → use-breakpoint-CM-yeDHJ.js.map} +1 -1
- package/dist/{use-motion-presets-DCJPBfNJ.js → use-motion-presets-I4StrsCi.js} +3 -3
- package/dist/{use-motion-presets-DCJPBfNJ.js.map → use-motion-presets-I4StrsCi.js.map} +1 -1
- package/dist/widget-grid.js +2 -2
- package/package.json +8 -1
- package/dist/empty-state-DrQjqxvp.js.map +0 -1
- package/dist/tooltip-kgsorOg6.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
/*! Rendra Design System v2.
|
|
2
|
-
import { t as cn } from "./cn-
|
|
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-
|
|
4
|
-
import { t as useMotionPresets } from "./use-motion-presets-
|
|
5
|
-
import { a as
|
|
6
|
-
import { n as
|
|
7
|
-
import {
|
|
8
|
-
import { a as
|
|
9
|
-
import {
|
|
10
|
-
import { n as
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
1
|
+
/*! Rendra Design System v2.8.0 | MIT | © 2026 Bruno Magalhaes | brunomagalhaes.me */
|
|
2
|
+
import { t as cn } from "./cn-BlJHpkDs.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-PJPj6X4g.js";
|
|
4
|
+
import { t as useMotionPresets } from "./use-motion-presets-I4StrsCi.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-xrMHeV92.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-6RpoJ2Od.js";
|
|
7
|
+
import { n as buttonVariants, r as Spinner, t as Button } from "./button-CrSlVIsY.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-BUGKtR6k.js";
|
|
9
|
+
import { i as BrandContext, n as feedbackLabels, r as useBrand, t as BrandFeedbackIcon } from "./brand-feedback-icon-CVux4pNh.js";
|
|
10
|
+
import { a as useRendraNavigate, i as useRendraLink, n as useCurrentPath, r as useRendraBreadcrumbs, t as RendraProvider } from "./rendra-provider-Do_qWjJC.js";
|
|
11
|
+
import { n as useBreakpoint, t as breakpoints } from "./use-breakpoint-CM-yeDHJ.js";
|
|
12
|
+
import { t as EmptyState } from "./empty-state-i4e-LacG.js";
|
|
13
|
+
import { n as TooltipProvider, t as Tooltip } from "./tooltip-to0h6aPe.js";
|
|
14
|
+
import { ArrowDown, ArrowDownRight, ArrowLeft, ArrowRight, ArrowRightLeft, ArrowUp, ArrowUpRight, Bell, Bot, CalendarClock, CalendarDays, CalendarX2, Check, CheckCheck, ChevronDown, ChevronLeft, ChevronRight, ChevronsUpDown, Clock, Columns3, Download, EllipsisVertical, FileText, Film, Filter, Globe, GripVertical, Home, ImageIcon, ImagePlus, LayoutTemplate, LogOut, Mail, MapPin, Menu, MessageCircle, MessagesSquare, Mic, Minus, Monitor, Moon, MoreHorizontal, Palette, PanelLeft, Paperclip, Pause, Pencil, Phone, Play, Plus, Reply, RotateCw, Search, Send, Settings2, Smartphone, Smile, Star, Sun, Trash2, TriangleAlert, UploadCloud, User, VideoIcon, X, Zap } from "lucide-react";
|
|
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";
|
|
14
17
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
-
import { createPortal } from "react-dom";
|
|
16
18
|
import { cva } from "class-variance-authority";
|
|
17
|
-
import { addDays, addMonths, addWeeks, differenceInMinutes, endOfMonth, endOfWeek, format, isSameDay, isSameMonth, isToday, isYesterday, startOfDay, startOfMonth, startOfWeek } from "date-fns";
|
|
19
|
+
import { addDays, addMonths, addWeeks, differenceInCalendarDays, differenceInMinutes, endOfMonth, endOfWeek, format, isSameDay, isSameMonth, isToday, isYesterday, startOfDay, startOfMonth, startOfWeek } from "date-fns";
|
|
18
20
|
import { ptBR } from "date-fns/locale";
|
|
19
|
-
import IMask from "imask";
|
|
20
21
|
import { DayPicker } from "react-day-picker";
|
|
21
22
|
import { ptBR as ptBR$1 } from "react-day-picker/locale";
|
|
22
23
|
import { FormProvider, useController, useFormContext } from "react-hook-form";
|
|
@@ -171,129 +172,6 @@ function Accordion({ items, multiple, defaultValue, className }) {
|
|
|
171
172
|
});
|
|
172
173
|
}
|
|
173
174
|
//#endregion
|
|
174
|
-
//#region src/components/app-shell/shell-context.ts
|
|
175
|
-
var ShellContext = createContext(null);
|
|
176
|
-
function useShell() {
|
|
177
|
-
const ctx = useContext(ShellContext);
|
|
178
|
-
if (!ctx) throw new Error("useShell precisa estar dentro de <AppShell>.");
|
|
179
|
-
return ctx;
|
|
180
|
-
}
|
|
181
|
-
//#endregion
|
|
182
|
-
//#region src/components/ui/action-bar.tsx
|
|
183
|
-
/**
|
|
184
|
-
* Barra de ações única, com a regra de botões do sistema:
|
|
185
|
-
* 1 botão = 100%; 2 botões = cancelar 30% + principal 70%; 3 ou mais = extras no menu.
|
|
186
|
-
* Vale para drawer, modal e formulário em página, em qualquer tamanho de tela.
|
|
187
|
-
*/
|
|
188
|
-
function ActionBar({ primary, cancel, secondary, sticky, className }) {
|
|
189
|
-
const slot = useContext(ShellContext)?.footerSlot;
|
|
190
|
-
const hasMenu = Boolean(secondary?.length);
|
|
191
|
-
const layout = cancel ? hasMenu ? "grid-actions-3" : "grid-actions-2" : hasMenu ? "grid-actions-3" : "";
|
|
192
|
-
const bar = /* @__PURE__ */ jsx("div", {
|
|
193
|
-
"data-rendra": "ACB-001",
|
|
194
|
-
className: cn(sticky && "border-t bg-card px-4 pt-4 pb-safe md:px-6", sticky && !slot && "sticky bottom-0 z-20", className),
|
|
195
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
196
|
-
className: cn("grid gap-3", layout || "grid-cols-1", sticky && "w-full"),
|
|
197
|
-
children: [
|
|
198
|
-
hasMenu && /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
|
|
199
|
-
asChild: true,
|
|
200
|
-
children: /* @__PURE__ */ jsx(Button, {
|
|
201
|
-
variant: "outline",
|
|
202
|
-
iconOnly: true,
|
|
203
|
-
"aria-label": "Mais ações",
|
|
204
|
-
children: /* @__PURE__ */ jsx(MoreHorizontal, {})
|
|
205
|
-
})
|
|
206
|
-
}), /* @__PURE__ */ jsx(DropdownMenuContent, {
|
|
207
|
-
align: "start",
|
|
208
|
-
side: "top",
|
|
209
|
-
children: secondary.map((a) => /* @__PURE__ */ jsxs(DropdownMenuItem, {
|
|
210
|
-
onSelect: a.onClick,
|
|
211
|
-
disabled: a.disabled,
|
|
212
|
-
destructive: a.destructive,
|
|
213
|
-
children: [a.icon, a.label]
|
|
214
|
-
}, a.label))
|
|
215
|
-
})] }),
|
|
216
|
-
cancel ? /* @__PURE__ */ jsx(Button, {
|
|
217
|
-
variant: "outline",
|
|
218
|
-
icon: cancel.icon,
|
|
219
|
-
onClick: cancel.onClick,
|
|
220
|
-
disabled: cancel.disabled || primary.loading,
|
|
221
|
-
fullWidth: true,
|
|
222
|
-
children: cancel.label
|
|
223
|
-
}) : hasMenu ? /* @__PURE__ */ jsx("span", { "aria-hidden": true }) : null,
|
|
224
|
-
/* @__PURE__ */ jsx(Button, {
|
|
225
|
-
type: primary.type ?? "button",
|
|
226
|
-
form: primary.form,
|
|
227
|
-
variant: primary.destructive ? "destructive" : "primary",
|
|
228
|
-
icon: primary.icon,
|
|
229
|
-
onClick: primary.onClick,
|
|
230
|
-
disabled: primary.disabled,
|
|
231
|
-
loading: primary.loading,
|
|
232
|
-
fullWidth: true,
|
|
233
|
-
children: primary.loading ? primary.loadingLabel ?? "Salvando..." : primary.label
|
|
234
|
-
})
|
|
235
|
-
]
|
|
236
|
-
})
|
|
237
|
-
});
|
|
238
|
-
return sticky && slot ? createPortal(bar, slot) : bar;
|
|
239
|
-
}
|
|
240
|
-
//#endregion
|
|
241
|
-
//#region src/components/ui/alert.tsx
|
|
242
|
-
/**
|
|
243
|
-
* Alert único do sistema: ícone da marca à esquerda, título em destaque e descrição.
|
|
244
|
-
* O tipo é prop; o formato vem do template ativo (quadrado, meio-termo ou arredondado).
|
|
245
|
-
*/
|
|
246
|
-
var alertVariants = cva("flex w-full min-w-0 items-start gap-3 rounded-control border", {
|
|
247
|
-
variants: { type: {
|
|
248
|
-
success: "border-success/25 bg-success-soft text-success-soft-foreground",
|
|
249
|
-
error: "border-destructive/25 bg-destructive-soft text-destructive-soft-foreground",
|
|
250
|
-
warning: "border-warning/25 bg-warning-soft text-warning-soft-foreground",
|
|
251
|
-
info: "border-info/25 bg-info-soft text-info-soft-foreground"
|
|
252
|
-
} },
|
|
253
|
-
defaultVariants: { type: "info" }
|
|
254
|
-
});
|
|
255
|
-
function Alert({ type, title, description, action, onDismiss, animated = false, className }) {
|
|
256
|
-
const { shape } = useBrand();
|
|
257
|
-
const pill = shape === "pill";
|
|
258
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
259
|
-
role: type === "error" || type === "warning" ? "alert" : "status",
|
|
260
|
-
"data-rendra": "ALRT-001",
|
|
261
|
-
className: cn(alertVariants({ type }), pill ? "items-center py-3 pr-4 pl-4 md:pr-6" : "p-4", className),
|
|
262
|
-
children: [
|
|
263
|
-
/* @__PURE__ */ jsx(BrandFeedbackIcon, {
|
|
264
|
-
type,
|
|
265
|
-
size: "lg",
|
|
266
|
-
animated,
|
|
267
|
-
className: cn(!pill && "mt-px")
|
|
268
|
-
}),
|
|
269
|
-
/* @__PURE__ */ jsxs("div", {
|
|
270
|
-
className: cn("flex min-w-0 flex-1 flex-col", !pill && "gap-1"),
|
|
271
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
272
|
-
className: "text-sm font-semibold",
|
|
273
|
-
children: title
|
|
274
|
-
}), description && /* @__PURE__ */ jsx("p", {
|
|
275
|
-
className: "text-sm opacity-90",
|
|
276
|
-
children: description
|
|
277
|
-
})]
|
|
278
|
-
}),
|
|
279
|
-
action && /* @__PURE__ */ jsx("div", {
|
|
280
|
-
className: "shrink-0 self-center",
|
|
281
|
-
children: action
|
|
282
|
-
}),
|
|
283
|
-
onDismiss && /* @__PURE__ */ jsx("button", {
|
|
284
|
-
type: "button",
|
|
285
|
-
onClick: onDismiss,
|
|
286
|
-
"aria-label": "Fechar aviso",
|
|
287
|
-
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"),
|
|
288
|
-
children: /* @__PURE__ */ jsx(X, {
|
|
289
|
-
className: "size-icon-sm",
|
|
290
|
-
"aria-hidden": true
|
|
291
|
-
})
|
|
292
|
-
})
|
|
293
|
-
]
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
//#endregion
|
|
297
175
|
//#region src/lib/initials.ts
|
|
298
176
|
/** Iniciais de um nome: primeira letra do primeiro e do último nome, em maiúsculas. */
|
|
299
177
|
function initials(name) {
|
|
@@ -617,264 +495,6 @@ function ButtonGroup({ children, options, value, onChange, size = "md", fullWidt
|
|
|
617
495
|
});
|
|
618
496
|
}
|
|
619
497
|
//#endregion
|
|
620
|
-
//#region src/components/ui/overlay-shell.tsx
|
|
621
|
-
function OverlayShell({ title, description, icon, children, footer, hideHeader, onRequestClose, bodyClassName }) {
|
|
622
|
-
const closeButton = /* @__PURE__ */ jsx("button", {
|
|
623
|
-
type: "button",
|
|
624
|
-
onClick: onRequestClose,
|
|
625
|
-
"aria-label": "Fechar",
|
|
626
|
-
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"),
|
|
627
|
-
children: /* @__PURE__ */ jsx(X, {
|
|
628
|
-
className: "size-icon-md",
|
|
629
|
-
"aria-hidden": true
|
|
630
|
-
})
|
|
631
|
-
});
|
|
632
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
633
|
-
hideHeader && /* @__PURE__ */ jsx("div", {
|
|
634
|
-
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",
|
|
635
|
-
children: closeButton
|
|
636
|
-
}),
|
|
637
|
-
/* @__PURE__ */ jsxs("header", {
|
|
638
|
-
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"),
|
|
639
|
-
children: [
|
|
640
|
-
icon && /* @__PURE__ */ jsx("span", {
|
|
641
|
-
"aria-hidden": true,
|
|
642
|
-
className: "flex size-control-md shrink-0 items-center justify-center rounded-control bg-primary-soft text-primary-soft-foreground [&_svg]:size-icon-md",
|
|
643
|
-
children: icon
|
|
644
|
-
}),
|
|
645
|
-
/* @__PURE__ */ jsxs("div", {
|
|
646
|
-
className: "flex min-w-0 flex-1 flex-col gap-1 pt-1",
|
|
647
|
-
children: [/* @__PURE__ */ jsx(Dialog.Title, {
|
|
648
|
-
className: "text-lg font-semibold wrap-break-word",
|
|
649
|
-
children: title
|
|
650
|
-
}), description ? /* @__PURE__ */ jsx(Dialog.Description, {
|
|
651
|
-
className: "text-sm wrap-break-word text-muted-foreground",
|
|
652
|
-
children: description
|
|
653
|
-
}) : /* @__PURE__ */ jsx(Dialog.Description, {
|
|
654
|
-
className: "sr-only",
|
|
655
|
-
children: title
|
|
656
|
-
})]
|
|
657
|
-
}),
|
|
658
|
-
!hideHeader && closeButton
|
|
659
|
-
]
|
|
660
|
-
}),
|
|
661
|
-
/* @__PURE__ */ jsx("div", {
|
|
662
|
-
className: cn("min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-6 md:px-6", bodyClassName),
|
|
663
|
-
children
|
|
664
|
-
}),
|
|
665
|
-
footer && /* @__PURE__ */ jsx("footer", {
|
|
666
|
-
className: "shrink-0 border-t bg-card px-4 pt-4 pb-safe md:px-6 md:pb-6",
|
|
667
|
-
children: footer
|
|
668
|
-
})
|
|
669
|
-
] });
|
|
670
|
-
}
|
|
671
|
-
//#endregion
|
|
672
|
-
//#region src/components/ui/modal.tsx
|
|
673
|
-
var sizes$1 = {
|
|
674
|
-
sm: "md:max-w-sm",
|
|
675
|
-
md: "md:max-w-lg",
|
|
676
|
-
lg: "md:max-w-2xl"
|
|
677
|
-
};
|
|
678
|
-
var overlayCls$1 = "fixed inset-0 z-50 bg-overlay";
|
|
679
|
-
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");
|
|
680
|
-
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");
|
|
681
|
-
var feedback = {
|
|
682
|
-
confirm: "info",
|
|
683
|
-
destructive: "error",
|
|
684
|
-
info: "info"
|
|
685
|
-
};
|
|
686
|
-
function Modal({ open, onOpenChange, title, description, type = "confirm", size = "sm", children, confirmLabel = type === "destructive" ? "Excluir" : type === "info" ? "Entendi" : "Confirmar", cancelLabel, onConfirm, formId, loading }) {
|
|
687
|
-
const [busy, setBusy] = useState(false);
|
|
688
|
-
const close = () => onOpenChange(false);
|
|
689
|
-
const confirm = async () => {
|
|
690
|
-
if (!onConfirm) return close();
|
|
691
|
-
try {
|
|
692
|
-
setBusy(true);
|
|
693
|
-
await onConfirm();
|
|
694
|
-
close();
|
|
695
|
-
} finally {
|
|
696
|
-
setBusy(false);
|
|
697
|
-
}
|
|
698
|
-
};
|
|
699
|
-
const isForm = type === "form";
|
|
700
|
-
const lib = useMotionLib();
|
|
701
|
-
const presets = useMotionPresets();
|
|
702
|
-
const { isMobile } = useBreakpoint();
|
|
703
|
-
const code = resolveCatalogCode("Modal", { type: type === "destructive" ? "confirm" : type });
|
|
704
|
-
const sizeCls = sizes$1[size];
|
|
705
|
-
const shell = /* @__PURE__ */ jsxs(OverlayShell, {
|
|
706
|
-
title,
|
|
707
|
-
description: isForm ? description : void 0,
|
|
708
|
-
hideHeader: !isForm,
|
|
709
|
-
onRequestClose: close,
|
|
710
|
-
bodyClassName: cn(!isForm && "flex flex-col items-center justify-center gap-4 text-center"),
|
|
711
|
-
footer: /* @__PURE__ */ jsx(ActionBar, {
|
|
712
|
-
primary: {
|
|
713
|
-
label: confirmLabel,
|
|
714
|
-
destructive: type === "destructive",
|
|
715
|
-
loading: busy || loading,
|
|
716
|
-
loadingLabel: `${confirmLabel}...`,
|
|
717
|
-
type: isForm && formId ? "submit" : "button",
|
|
718
|
-
form: isForm ? formId : void 0,
|
|
719
|
-
onClick: isForm && formId ? void 0 : confirm
|
|
720
|
-
},
|
|
721
|
-
cancel: type === "info" && cancelLabel === void 0 ? void 0 : {
|
|
722
|
-
label: cancelLabel ?? "Cancelar",
|
|
723
|
-
onClick: close
|
|
724
|
-
}
|
|
725
|
-
}),
|
|
726
|
-
children: [!isForm && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
727
|
-
/* @__PURE__ */ jsx(BrandFeedbackIcon, {
|
|
728
|
-
type: feedback[type],
|
|
729
|
-
size: "2xl",
|
|
730
|
-
animated: true
|
|
731
|
-
}),
|
|
732
|
-
/* @__PURE__ */ jsxs("div", {
|
|
733
|
-
className: "flex flex-col gap-2",
|
|
734
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
735
|
-
className: "text-lg font-semibold wrap-anywhere",
|
|
736
|
-
children: title
|
|
737
|
-
}), description && /* @__PURE__ */ jsx("p", {
|
|
738
|
-
className: "text-sm wrap-anywhere text-muted-foreground",
|
|
739
|
-
children: description
|
|
740
|
-
})]
|
|
741
|
-
}),
|
|
742
|
-
children
|
|
743
|
-
] }), isForm && /* @__PURE__ */ jsx("div", {
|
|
744
|
-
className: "flex flex-col gap-2",
|
|
745
|
-
children
|
|
746
|
-
})]
|
|
747
|
-
});
|
|
748
|
-
if (lib) return /* @__PURE__ */ jsx(Dialog.Root, {
|
|
749
|
-
open,
|
|
750
|
-
onOpenChange,
|
|
751
|
-
children: /* @__PURE__ */ jsx(lib.AnimatePresence, { children: open && /* @__PURE__ */ jsxs(Dialog.Portal, {
|
|
752
|
-
forceMount: true,
|
|
753
|
-
children: [/* @__PURE__ */ jsx(Dialog.Overlay, {
|
|
754
|
-
forceMount: true,
|
|
755
|
-
asChild: true,
|
|
756
|
-
children: /* @__PURE__ */ jsx(lib.m.div, {
|
|
757
|
-
className: overlayCls$1,
|
|
758
|
-
...presets.fade
|
|
759
|
-
})
|
|
760
|
-
}), /* @__PURE__ */ jsx(Dialog.Content, {
|
|
761
|
-
forceMount: true,
|
|
762
|
-
asChild: true,
|
|
763
|
-
"data-rendra": code,
|
|
764
|
-
className: cn(contentCls, sizeCls),
|
|
765
|
-
children: /* @__PURE__ */ jsx(lib.m.div, {
|
|
766
|
-
...presets.open(isMobile ? { y: 8 } : void 0),
|
|
767
|
-
children: shell
|
|
768
|
-
})
|
|
769
|
-
})]
|
|
770
|
-
}, "modal") })
|
|
771
|
-
});
|
|
772
|
-
return /* @__PURE__ */ jsx(Dialog.Root, {
|
|
773
|
-
open,
|
|
774
|
-
onOpenChange,
|
|
775
|
-
children: /* @__PURE__ */ jsxs(Dialog.Portal, { children: [/* @__PURE__ */ jsx(Dialog.Overlay, { className: overlayOffCls }), /* @__PURE__ */ jsx(Dialog.Content, {
|
|
776
|
-
"data-rendra": code,
|
|
777
|
-
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),
|
|
778
|
-
children: shell
|
|
779
|
-
})] })
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
|
-
//#endregion
|
|
783
|
-
//#region src/components/ui/info-hint.tsx
|
|
784
|
-
function InfoHint({ title, children, className }) {
|
|
785
|
-
const [open, setOpen] = useState(false);
|
|
786
|
-
return /* @__PURE__ */ jsxs("span", {
|
|
787
|
-
className: "contents",
|
|
788
|
-
"data-rendra": "INFO-001",
|
|
789
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
790
|
-
variant: "ghost",
|
|
791
|
-
size: "sm",
|
|
792
|
-
iconOnly: true,
|
|
793
|
-
"aria-label": `Sobre: ${title}`,
|
|
794
|
-
onClick: () => setOpen(true),
|
|
795
|
-
className: cn("shrink-0 text-muted-foreground hover:text-primary-text max-md:size-touch", className),
|
|
796
|
-
children: /* @__PURE__ */ jsx(Info, { "aria-hidden": true })
|
|
797
|
-
}), /* @__PURE__ */ jsx(Modal, {
|
|
798
|
-
open,
|
|
799
|
-
onOpenChange: setOpen,
|
|
800
|
-
type: "info",
|
|
801
|
-
title,
|
|
802
|
-
size: "md",
|
|
803
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
804
|
-
className: "flex flex-col gap-3 text-sm text-muted-foreground",
|
|
805
|
-
children
|
|
806
|
-
})
|
|
807
|
-
})]
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
//#endregion
|
|
811
|
-
//#region src/components/ui/card.tsx
|
|
812
|
-
function Card({ className, "data-rendra": dataRendra, ...props }) {
|
|
813
|
-
return /* @__PURE__ */ jsx("div", {
|
|
814
|
-
"data-slot": "card",
|
|
815
|
-
"data-rendra": dataRendra ?? "CARD-001",
|
|
816
|
-
className: cn("flex min-w-0 flex-col rounded-surface border bg-card text-card-foreground", className),
|
|
817
|
-
...props
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
function CardHeader({ className, actions, children, ...props }) {
|
|
821
|
-
if (!actions) return /* @__PURE__ */ jsx("div", {
|
|
822
|
-
"data-slot": "card-header",
|
|
823
|
-
className: cn("flex flex-col gap-1 p-4 md:p-6", className),
|
|
824
|
-
...props,
|
|
825
|
-
children
|
|
826
|
-
});
|
|
827
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
828
|
-
"data-slot": "card-header",
|
|
829
|
-
className: cn("flex flex-wrap items-start justify-between gap-x-4 gap-y-3 p-4 md:p-6", className),
|
|
830
|
-
...props,
|
|
831
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
832
|
-
className: "flex min-w-0 flex-1 flex-col gap-1",
|
|
833
|
-
children
|
|
834
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
835
|
-
className: "flex shrink-0 items-center gap-2",
|
|
836
|
-
children: actions
|
|
837
|
-
})]
|
|
838
|
-
});
|
|
839
|
-
}
|
|
840
|
-
function CardTitle({ className, children, help, ...props }) {
|
|
841
|
-
const heading = /* @__PURE__ */ jsx("h3", {
|
|
842
|
-
"data-slot": "card-title",
|
|
843
|
-
className: cn("text-lg font-semibold", className),
|
|
844
|
-
...props,
|
|
845
|
-
children
|
|
846
|
-
});
|
|
847
|
-
if (!help) return heading;
|
|
848
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
849
|
-
className: "flex min-w-0 items-center gap-1",
|
|
850
|
-
children: [heading, /* @__PURE__ */ jsx(InfoHint, {
|
|
851
|
-
title: typeof children === "string" ? children : "Sobre esta seção",
|
|
852
|
-
children: help
|
|
853
|
-
})]
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
function CardDescription({ className, ...props }) {
|
|
857
|
-
return /* @__PURE__ */ jsx("p", {
|
|
858
|
-
"data-slot": "card-description",
|
|
859
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
860
|
-
...props
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
|
-
function CardContent({ className, ...props }) {
|
|
864
|
-
return /* @__PURE__ */ jsx("div", {
|
|
865
|
-
"data-slot": "card-content",
|
|
866
|
-
className: cn("p-4 md:p-6 [[data-slot=card-header]+&]:pt-0", className),
|
|
867
|
-
...props
|
|
868
|
-
});
|
|
869
|
-
}
|
|
870
|
-
function CardFooter({ className, ...props }) {
|
|
871
|
-
return /* @__PURE__ */ jsx("div", {
|
|
872
|
-
"data-slot": "card-footer",
|
|
873
|
-
className: cn("flex items-center gap-3 border-t px-4 py-3 md:px-6", className),
|
|
874
|
-
...props
|
|
875
|
-
});
|
|
876
|
-
}
|
|
877
|
-
//#endregion
|
|
878
498
|
//#region src/components/ui/calendar.tsx
|
|
879
499
|
var viewLabels = {
|
|
880
500
|
month: "Mês",
|
|
@@ -1313,575 +933,6 @@ function Calendar({ events, view: viewProp, defaultView = "month", onViewChange,
|
|
|
1313
933
|
});
|
|
1314
934
|
}
|
|
1315
935
|
//#endregion
|
|
1316
|
-
//#region src/lib/lookup.ts
|
|
1317
|
-
var digits$1 = (v) => v.replace(/\D/g, "");
|
|
1318
|
-
/** Endereço do CEP (8 dígitos). null se não existir; lança erro se a busca falhar. */
|
|
1319
|
-
async function lookupCep(cep, signal) {
|
|
1320
|
-
const d = digits$1(cep);
|
|
1321
|
-
if (d.length !== 8) return null;
|
|
1322
|
-
const res = await fetch(`https://viacep.com.br/ws/${d}/json/`, { signal });
|
|
1323
|
-
if (!res.ok) throw new Error("Não foi possível buscar o CEP agora.");
|
|
1324
|
-
const data = await res.json();
|
|
1325
|
-
if (data.erro) return null;
|
|
1326
|
-
return {
|
|
1327
|
-
cep: String(data.cep ?? ""),
|
|
1328
|
-
logradouro: String(data.logradouro ?? ""),
|
|
1329
|
-
complemento: String(data.complemento ?? ""),
|
|
1330
|
-
bairro: String(data.bairro ?? ""),
|
|
1331
|
-
cidade: String(data.localidade ?? ""),
|
|
1332
|
-
uf: String(data.uf ?? "")
|
|
1333
|
-
};
|
|
1334
|
-
}
|
|
1335
|
-
/** Dados públicos do CNPJ (14 dígitos). null se não existir; lança erro se a busca falhar. */
|
|
1336
|
-
async function lookupCnpj(cnpj, signal) {
|
|
1337
|
-
const d = digits$1(cnpj);
|
|
1338
|
-
if (d.length !== 14) return null;
|
|
1339
|
-
const res = await fetch(`https://brasilapi.com.br/api/cnpj/v1/${d}`, { signal });
|
|
1340
|
-
if (res.status === 404) return null;
|
|
1341
|
-
if (!res.ok) throw new Error("Não foi possível buscar o CNPJ agora.");
|
|
1342
|
-
const data = await res.json();
|
|
1343
|
-
const s = (k) => data[k] == null ? "" : String(data[k]);
|
|
1344
|
-
const fone = digits$1(s("ddd_telefone_1"));
|
|
1345
|
-
return {
|
|
1346
|
-
razaoSocial: s("razao_social"),
|
|
1347
|
-
nomeFantasia: s("nome_fantasia"),
|
|
1348
|
-
email: s("email").toLowerCase(),
|
|
1349
|
-
telefone: fone.length >= 10 ? `(${fone.slice(0, 2)}) ${fone.slice(2, -4)}-${fone.slice(-4)}` : "",
|
|
1350
|
-
situacao: s("descricao_situacao_cadastral"),
|
|
1351
|
-
endereco: {
|
|
1352
|
-
cep: s("cep"),
|
|
1353
|
-
logradouro: [s("descricao_tipo_de_logradouro"), s("logradouro")].filter(Boolean).join(" "),
|
|
1354
|
-
numero: s("numero"),
|
|
1355
|
-
complemento: s("complemento"),
|
|
1356
|
-
bairro: s("bairro"),
|
|
1357
|
-
cidade: s("municipio"),
|
|
1358
|
-
uf: s("uf")
|
|
1359
|
-
}
|
|
1360
|
-
};
|
|
1361
|
-
}
|
|
1362
|
-
//#endregion
|
|
1363
|
-
//#region src/hooks/use-lookup.ts
|
|
1364
|
-
/**
|
|
1365
|
-
* Busca CEP (8 dígitos) ou CNPJ (14 dígitos) assim que o valor fica completo. Cancela a
|
|
1366
|
-
* busca anterior quando o valor muda. `kind` 'auto' decide pelo tamanho (CPF ou CNPJ: só
|
|
1367
|
-
* o CNPJ busca). Sem `onResult`, não faz nada.
|
|
1368
|
-
*/
|
|
1369
|
-
function useLookup(kind, value, onResult) {
|
|
1370
|
-
const [loading, setLoading] = useState(false);
|
|
1371
|
-
const cb = useRef(onResult);
|
|
1372
|
-
cb.current = onResult;
|
|
1373
|
-
const digits = value.replace(/\D/g, "");
|
|
1374
|
-
const target = kind === "cep" && digits.length === 8 ? "cep" : (kind === "cnpj" || kind === "auto") && digits.length === 14 ? "cnpj" : null;
|
|
1375
|
-
const enabled = Boolean(onResult) && target !== null;
|
|
1376
|
-
useEffect(() => {
|
|
1377
|
-
if (!enabled || !target) return;
|
|
1378
|
-
const ctrl = new AbortController();
|
|
1379
|
-
const send = (r) => {
|
|
1380
|
-
if (!ctrl.signal.aborted) cb.current?.(r);
|
|
1381
|
-
};
|
|
1382
|
-
setLoading(true);
|
|
1383
|
-
send({
|
|
1384
|
-
status: "loading",
|
|
1385
|
-
kind: target
|
|
1386
|
-
});
|
|
1387
|
-
(target === "cep" ? lookupCep(digits, ctrl.signal).then((data) => data ? send({
|
|
1388
|
-
status: "found",
|
|
1389
|
-
kind: "cep",
|
|
1390
|
-
data,
|
|
1391
|
-
message: "Endereço preenchido pelo CEP."
|
|
1392
|
-
}) : send({
|
|
1393
|
-
status: "not-found",
|
|
1394
|
-
kind: "cep",
|
|
1395
|
-
message: "CEP não encontrado. Preencha o endereço."
|
|
1396
|
-
})) : lookupCnpj(digits, ctrl.signal).then((data) => data ? send({
|
|
1397
|
-
status: "found",
|
|
1398
|
-
kind: "cnpj",
|
|
1399
|
-
data,
|
|
1400
|
-
message: `${data.situacao ? `Situação: ${data.situacao}. ` : ""}Dados preenchidos pelo CNPJ.`
|
|
1401
|
-
}) : send({
|
|
1402
|
-
status: "not-found",
|
|
1403
|
-
kind: "cnpj",
|
|
1404
|
-
message: "CNPJ não encontrado. Preencha os dados abaixo."
|
|
1405
|
-
}))).catch((e) => send({
|
|
1406
|
-
status: "error",
|
|
1407
|
-
kind: target,
|
|
1408
|
-
message: e instanceof Error ? e.message : "Não foi possível buscar agora."
|
|
1409
|
-
})).finally(() => {
|
|
1410
|
-
if (!ctrl.signal.aborted) setLoading(false);
|
|
1411
|
-
});
|
|
1412
|
-
return () => {
|
|
1413
|
-
ctrl.abort();
|
|
1414
|
-
setLoading(false);
|
|
1415
|
-
};
|
|
1416
|
-
}, [
|
|
1417
|
-
enabled,
|
|
1418
|
-
target,
|
|
1419
|
-
digits
|
|
1420
|
-
]);
|
|
1421
|
-
return loading;
|
|
1422
|
-
}
|
|
1423
|
-
//#endregion
|
|
1424
|
-
//#region src/lib/control.ts
|
|
1425
|
-
/**
|
|
1426
|
-
* Moldura única dos campos (Input, Select, DatePicker, Textarea). Mesma altura dos botões
|
|
1427
|
-
* em cada tamanho; fonte de 16px no mobile para o iOS não dar zoom ao focar.
|
|
1428
|
-
*/
|
|
1429
|
-
/** Marque o elemento com data-slot="control": o teste de toque mede a moldura, não o input. */
|
|
1430
|
-
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", {
|
|
1431
|
-
variants: {
|
|
1432
|
-
size: {
|
|
1433
|
-
sm: "h-control-sm px-3",
|
|
1434
|
-
md: "h-control-md px-3",
|
|
1435
|
-
lg: "h-control-lg px-4"
|
|
1436
|
-
},
|
|
1437
|
-
invalid: {
|
|
1438
|
-
true: "border-destructive focus-within:border-destructive focus-within:ring-destructive/25 hover:border-destructive",
|
|
1439
|
-
false: ""
|
|
1440
|
-
}
|
|
1441
|
-
},
|
|
1442
|
-
defaultVariants: {
|
|
1443
|
-
size: "md",
|
|
1444
|
-
invalid: false
|
|
1445
|
-
}
|
|
1446
|
-
});
|
|
1447
|
-
/** Classe do <input> nativo dentro da moldura. */
|
|
1448
|
-
var controlInput = "h-full min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed";
|
|
1449
|
-
/** Botão pequeno dentro da moldura (limpar, mostrar senha). */
|
|
1450
|
-
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";
|
|
1451
|
-
/**
|
|
1452
|
-
* Reserva, dentro de um gatilho, o espaço do botão sobreposto (limpar do Select e do
|
|
1453
|
-
* DatePicker), para o texto não passar por baixo dele.
|
|
1454
|
-
*/
|
|
1455
|
-
var controlAdornmentSpace = "size-control-sm shrink-0 md:size-8";
|
|
1456
|
-
//#endregion
|
|
1457
|
-
//#region src/lib/masks.ts
|
|
1458
|
-
var numberBlock = (scale, max) => ({
|
|
1459
|
-
mask: Number,
|
|
1460
|
-
scale,
|
|
1461
|
-
thousandsSeparator: ".",
|
|
1462
|
-
radix: ",",
|
|
1463
|
-
mapToRadix: ["."],
|
|
1464
|
-
padFractionalZeros: true,
|
|
1465
|
-
normalizeZeros: true,
|
|
1466
|
-
min: 0,
|
|
1467
|
-
...max !== void 0 ? { max } : {}
|
|
1468
|
-
});
|
|
1469
|
-
var masks = {
|
|
1470
|
-
cpf: {
|
|
1471
|
-
options: { mask: "000.000.000-00" },
|
|
1472
|
-
inputMode: "numeric",
|
|
1473
|
-
placeholder: "000.000.000-00"
|
|
1474
|
-
},
|
|
1475
|
-
cnpj: {
|
|
1476
|
-
options: { mask: "00.000.000/0000-00" },
|
|
1477
|
-
inputMode: "numeric",
|
|
1478
|
-
placeholder: "00.000.000/0000-00"
|
|
1479
|
-
},
|
|
1480
|
-
cpfCnpj: {
|
|
1481
|
-
options: { mask: [{ mask: "000.000.000-00" }, { mask: "00.000.000/0000-00" }] },
|
|
1482
|
-
inputMode: "numeric",
|
|
1483
|
-
placeholder: "CPF ou CNPJ"
|
|
1484
|
-
},
|
|
1485
|
-
phone: {
|
|
1486
|
-
options: { mask: [{ mask: "(00) 0000-0000" }, { mask: "(00) 00000-0000" }] },
|
|
1487
|
-
inputMode: "tel",
|
|
1488
|
-
placeholder: "(00) 00000-0000"
|
|
1489
|
-
},
|
|
1490
|
-
cep: {
|
|
1491
|
-
options: { mask: "00000-000" },
|
|
1492
|
-
inputMode: "numeric",
|
|
1493
|
-
placeholder: "00000-000"
|
|
1494
|
-
},
|
|
1495
|
-
date: {
|
|
1496
|
-
options: { mask: "00/00/0000" },
|
|
1497
|
-
inputMode: "numeric",
|
|
1498
|
-
placeholder: "DD/MM/AAAA"
|
|
1499
|
-
},
|
|
1500
|
-
time: {
|
|
1501
|
-
options: { mask: "00:00" },
|
|
1502
|
-
inputMode: "numeric",
|
|
1503
|
-
placeholder: "00:00"
|
|
1504
|
-
},
|
|
1505
|
-
currency: {
|
|
1506
|
-
options: {
|
|
1507
|
-
mask: "R$ num",
|
|
1508
|
-
lazy: false,
|
|
1509
|
-
blocks: { num: numberBlock(2) }
|
|
1510
|
-
},
|
|
1511
|
-
inputMode: "decimal",
|
|
1512
|
-
placeholder: "R$ 0,00"
|
|
1513
|
-
},
|
|
1514
|
-
percent: {
|
|
1515
|
-
options: {
|
|
1516
|
-
mask: "num %",
|
|
1517
|
-
lazy: false,
|
|
1518
|
-
blocks: { num: numberBlock(2, 100) }
|
|
1519
|
-
},
|
|
1520
|
-
inputMode: "decimal",
|
|
1521
|
-
placeholder: "0,00 %"
|
|
1522
|
-
}
|
|
1523
|
-
};
|
|
1524
|
-
/** Máscara de percentual com teto configurável (padrão 100), para o Input com unidades (A9). */
|
|
1525
|
-
function percentMask(max = 100) {
|
|
1526
|
-
return {
|
|
1527
|
-
options: {
|
|
1528
|
-
mask: "num %",
|
|
1529
|
-
lazy: false,
|
|
1530
|
-
blocks: { num: numberBlock(2, max) }
|
|
1531
|
-
},
|
|
1532
|
-
inputMode: "decimal",
|
|
1533
|
-
placeholder: "0,00 %"
|
|
1534
|
-
};
|
|
1535
|
-
}
|
|
1536
|
-
/** DDI padrão do campo de telefone. */
|
|
1537
|
-
var DEFAULT_DDI = "55";
|
|
1538
|
-
/** Lista padrão do seletor de DDI (Brasil primeiro). Troque com a prop ddiOptions do Input. */
|
|
1539
|
-
var phoneCountries = [
|
|
1540
|
-
{
|
|
1541
|
-
ddi: "55",
|
|
1542
|
-
name: "Brasil"
|
|
1543
|
-
},
|
|
1544
|
-
{
|
|
1545
|
-
ddi: "54",
|
|
1546
|
-
name: "Argentina"
|
|
1547
|
-
},
|
|
1548
|
-
{
|
|
1549
|
-
ddi: "56",
|
|
1550
|
-
name: "Chile"
|
|
1551
|
-
},
|
|
1552
|
-
{
|
|
1553
|
-
ddi: "57",
|
|
1554
|
-
name: "Colômbia"
|
|
1555
|
-
},
|
|
1556
|
-
{
|
|
1557
|
-
ddi: "595",
|
|
1558
|
-
name: "Paraguai"
|
|
1559
|
-
},
|
|
1560
|
-
{
|
|
1561
|
-
ddi: "598",
|
|
1562
|
-
name: "Uruguai"
|
|
1563
|
-
},
|
|
1564
|
-
{
|
|
1565
|
-
ddi: "52",
|
|
1566
|
-
name: "México"
|
|
1567
|
-
},
|
|
1568
|
-
{
|
|
1569
|
-
ddi: "1",
|
|
1570
|
-
name: "Estados Unidos e Canadá"
|
|
1571
|
-
},
|
|
1572
|
-
{
|
|
1573
|
-
ddi: "351",
|
|
1574
|
-
name: "Portugal"
|
|
1575
|
-
},
|
|
1576
|
-
{
|
|
1577
|
-
ddi: "34",
|
|
1578
|
-
name: "Espanha"
|
|
1579
|
-
},
|
|
1580
|
-
{
|
|
1581
|
-
ddi: "33",
|
|
1582
|
-
name: "França"
|
|
1583
|
-
},
|
|
1584
|
-
{
|
|
1585
|
-
ddi: "39",
|
|
1586
|
-
name: "Itália"
|
|
1587
|
-
},
|
|
1588
|
-
{
|
|
1589
|
-
ddi: "49",
|
|
1590
|
-
name: "Alemanha"
|
|
1591
|
-
},
|
|
1592
|
-
{
|
|
1593
|
-
ddi: "44",
|
|
1594
|
-
name: "Reino Unido"
|
|
1595
|
-
}
|
|
1596
|
-
];
|
|
1597
|
-
/** Máscara do número fora do Brasil: só dígitos, em grupos, até 15 (limite do padrão E.164). */
|
|
1598
|
-
var internationalPhoneMask = {
|
|
1599
|
-
options: { mask: "000 000 000 000 000" },
|
|
1600
|
-
inputMode: "tel",
|
|
1601
|
-
placeholder: "Número com DDD"
|
|
1602
|
-
};
|
|
1603
|
-
/** Número completo no padrão internacional: toE164("55", "(11) 91234-5678") = "+5511912345678". */
|
|
1604
|
-
function toE164(ddi, national) {
|
|
1605
|
-
const digits = national.replace(/\D/g, "");
|
|
1606
|
-
return digits ? `+${ddi}${digits}` : "";
|
|
1607
|
-
}
|
|
1608
|
-
/** Converte "R$ 1.250,00" ou "12,5 %" em número. */
|
|
1609
|
-
function parseLocaleNumber(masked) {
|
|
1610
|
-
const clean = masked.replace(/[^\d,-]/g, "").replace(",", ".");
|
|
1611
|
-
if (!clean) return null;
|
|
1612
|
-
const n = Number(clean);
|
|
1613
|
-
return Number.isFinite(n) ? n : null;
|
|
1614
|
-
}
|
|
1615
|
-
/**
|
|
1616
|
-
* Moeda em centavos inteiros, sem erro de arredondamento de ponto flutuante:
|
|
1617
|
-
* "R$ 1.250,50" -> 125050. Vazio -> null. Use centavos para guardar e somar dinheiro.
|
|
1618
|
-
*/
|
|
1619
|
-
function toCents(masked) {
|
|
1620
|
-
const d = masked.replace(/\D/g, "");
|
|
1621
|
-
if (!d) return null;
|
|
1622
|
-
if (!/,\d{1,2}\s*$/.test(masked.replace(/\s*%$/, ""))) return Number(d) * 100;
|
|
1623
|
-
const [int = "", dec = ""] = masked.replace(/[^\d,]/g, "").split(",");
|
|
1624
|
-
return Number(int || "0") * 100 + Number(dec.padEnd(2, "0").slice(0, 2));
|
|
1625
|
-
}
|
|
1626
|
-
/** Centavos para o texto do campo de moeda: 125050 -> "R$ 1.250,50". */
|
|
1627
|
-
function formatCents(cents) {
|
|
1628
|
-
return formatCurrency(cents / 100);
|
|
1629
|
-
}
|
|
1630
|
-
/** Formata número como moeda brasileira: 1250 -> "R$ 1.250,00". */
|
|
1631
|
-
function formatCurrency(value) {
|
|
1632
|
-
return value.toLocaleString("pt-BR", {
|
|
1633
|
-
style: "currency",
|
|
1634
|
-
currency: "BRL"
|
|
1635
|
-
});
|
|
1636
|
-
}
|
|
1637
|
-
//#endregion
|
|
1638
|
-
//#region src/components/ui/input.tsx
|
|
1639
|
-
/**
|
|
1640
|
-
* Input único. Tipos, máscaras, ícone, limpar, senha, unidades e valor guardado são props:
|
|
1641
|
-
* nunca crie InputCPF, InputTelefone, InputSenha ou InputSegredo.
|
|
1642
|
-
*/
|
|
1643
|
-
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) {
|
|
1644
|
-
const inputRef = useRef(null);
|
|
1645
|
-
useImperativeHandle(ref, () => inputRef.current);
|
|
1646
|
-
const maskRef = useRef(null);
|
|
1647
|
-
const [showPassword, setShowPassword] = useState(false);
|
|
1648
|
-
const [inner, setInner] = useState(String(value ?? defaultValue ?? ""));
|
|
1649
|
-
const current = value ?? inner;
|
|
1650
|
-
const [secretDraft, setSecretDraft] = useState("");
|
|
1651
|
-
const [lastIsEditing, setLastIsEditing] = useState(isEditing);
|
|
1652
|
-
if (isEditing !== lastIsEditing) {
|
|
1653
|
-
setLastIsEditing(isEditing);
|
|
1654
|
-
if (isEditing) setSecretDraft("");
|
|
1655
|
-
}
|
|
1656
|
-
const cb = useRef({
|
|
1657
|
-
onChange,
|
|
1658
|
-
onValueChange,
|
|
1659
|
-
onCentsChange
|
|
1660
|
-
});
|
|
1661
|
-
cb.current = {
|
|
1662
|
-
onChange,
|
|
1663
|
-
onValueChange,
|
|
1664
|
-
onCentsChange
|
|
1665
|
-
};
|
|
1666
|
-
const searching = useLookup(mask === "cep" ? "cep" : mask === "cnpj" ? "cnpj" : mask === "cpfCnpj" ? "auto" : void 0, current, onLookup);
|
|
1667
|
-
const isPhone = mask === "phone";
|
|
1668
|
-
const [innerDdi, setInnerDdi] = useState(ddiProp ?? "55");
|
|
1669
|
-
const ddi = ddiProp ?? innerDdi;
|
|
1670
|
-
const showDdi = isPhone && !hideDdi;
|
|
1671
|
-
const intl = isPhone && ddi !== "55";
|
|
1672
|
-
const hasUnits = Boolean(units && units.length > 0);
|
|
1673
|
-
const [innerUnit, setInnerUnit] = useState(unitProp ?? units?.[0]?.id ?? "");
|
|
1674
|
-
const unit = hasUnits ? unitProp ?? innerUnit : void 0;
|
|
1675
|
-
const unitMaskName = unit === "percent" ? "percent" : unit === "currency" ? "currency" : void 0;
|
|
1676
|
-
const def = intl ? internationalPhoneMask : hasUnits ? unitMaskName === "percent" ? percentMask(percentMax) : unitMaskName === "currency" ? masks.currency : void 0 : mask ? masks[mask] : void 0;
|
|
1677
|
-
const maskKey = !def ? void 0 : intl ? "phone-intl" : hasUnits ? `unit-${unitMaskName}-${percentMax ?? ""}` : mask;
|
|
1678
|
-
useEffect(() => {
|
|
1679
|
-
if (!maskKey || !def || !inputRef.current) return;
|
|
1680
|
-
const m = IMask(inputRef.current, def.options);
|
|
1681
|
-
maskRef.current = m;
|
|
1682
|
-
m.on("accept", () => {
|
|
1683
|
-
setInner(m.value);
|
|
1684
|
-
cb.current.onChange?.(m.value);
|
|
1685
|
-
cb.current.onValueChange?.(m.unmaskedValue, m.value);
|
|
1686
|
-
if (mask === "currency" || unitMaskName === "currency") cb.current.onCentsChange?.(toCents(m.value));
|
|
1687
|
-
});
|
|
1688
|
-
return () => {
|
|
1689
|
-
m.destroy();
|
|
1690
|
-
maskRef.current = null;
|
|
1691
|
-
};
|
|
1692
|
-
}, [maskKey]);
|
|
1693
|
-
useEffect(() => {
|
|
1694
|
-
const m = maskRef.current;
|
|
1695
|
-
if (m && value !== void 0 && value !== m.value) m.value = value;
|
|
1696
|
-
}, [value]);
|
|
1697
|
-
const isPassword = type === "password";
|
|
1698
|
-
const country = ddiOptions.find((c) => c.ddi === ddi);
|
|
1699
|
-
const isSecret = variant === "secret";
|
|
1700
|
-
const { id: fieldId, "aria-describedby": fieldDescribedBy, "aria-required": fieldRequired } = props;
|
|
1701
|
-
const resetValue = () => {
|
|
1702
|
-
if (maskRef.current) maskRef.current.value = "";
|
|
1703
|
-
setInner("");
|
|
1704
|
-
setSecretDraft("");
|
|
1705
|
-
onChange?.("");
|
|
1706
|
-
onValueChange?.("", "");
|
|
1707
|
-
onCentsChange?.(null);
|
|
1708
|
-
};
|
|
1709
|
-
const clear = () => {
|
|
1710
|
-
resetValue();
|
|
1711
|
-
inputRef.current?.focus();
|
|
1712
|
-
};
|
|
1713
|
-
const changeUnit = (id) => {
|
|
1714
|
-
setInnerUnit(id);
|
|
1715
|
-
onUnitChange?.(id);
|
|
1716
|
-
resetValue();
|
|
1717
|
-
};
|
|
1718
|
-
if (isSecret && !isEditing) return /* @__PURE__ */ jsxs("div", {
|
|
1719
|
-
"data-slot": "control",
|
|
1720
|
-
"data-rendra": "CAMP-001",
|
|
1721
|
-
className: cn(controlFrame({
|
|
1722
|
-
size,
|
|
1723
|
-
invalid
|
|
1724
|
-
}), className),
|
|
1725
|
-
children: [
|
|
1726
|
-
/* @__PURE__ */ jsx("span", {
|
|
1727
|
-
className: "min-w-0 flex-1 truncate font-mono text-sm text-muted-foreground",
|
|
1728
|
-
children: hasValue ? maskedHint ?? "••••••••" : "Nenhum valor salvo"
|
|
1729
|
-
}),
|
|
1730
|
-
/* @__PURE__ */ jsx(Button, {
|
|
1731
|
-
type: "button",
|
|
1732
|
-
variant: "ghost",
|
|
1733
|
-
size: "sm",
|
|
1734
|
-
onClick: onStartEdit,
|
|
1735
|
-
disabled,
|
|
1736
|
-
id: fieldId,
|
|
1737
|
-
"aria-describedby": fieldDescribedBy,
|
|
1738
|
-
"aria-required": fieldRequired,
|
|
1739
|
-
children: "Trocar"
|
|
1740
|
-
}),
|
|
1741
|
-
hasValue && onRemove && /* @__PURE__ */ jsx(Button, {
|
|
1742
|
-
type: "button",
|
|
1743
|
-
variant: "ghost",
|
|
1744
|
-
size: "sm",
|
|
1745
|
-
onClick: onRemove,
|
|
1746
|
-
disabled: disabled || removing,
|
|
1747
|
-
loading: removing,
|
|
1748
|
-
children: "Remover"
|
|
1749
|
-
})
|
|
1750
|
-
]
|
|
1751
|
-
});
|
|
1752
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
1753
|
-
"data-slot": "control",
|
|
1754
|
-
"data-rendra": "CAMP-001",
|
|
1755
|
-
className: cn(controlFrame({
|
|
1756
|
-
size,
|
|
1757
|
-
invalid
|
|
1758
|
-
}), className),
|
|
1759
|
-
children: [
|
|
1760
|
-
showDdi && /* @__PURE__ */ jsxs("span", {
|
|
1761
|
-
className: "relative -ml-1 flex h-full min-w-touch shrink-0 items-center gap-1 border-r pr-2 text-sm font-medium",
|
|
1762
|
-
children: [
|
|
1763
|
-
/* @__PURE__ */ jsxs("span", {
|
|
1764
|
-
"aria-hidden": true,
|
|
1765
|
-
children: ["+", ddi]
|
|
1766
|
-
}),
|
|
1767
|
-
/* @__PURE__ */ jsx(ChevronDown, {
|
|
1768
|
-
className: "size-icon-sm text-muted-foreground",
|
|
1769
|
-
"aria-hidden": true
|
|
1770
|
-
}),
|
|
1771
|
-
/* @__PURE__ */ jsx("select", {
|
|
1772
|
-
"aria-label": `Código do país (DDI): ${country?.name ?? ""} +${ddi}`,
|
|
1773
|
-
value: ddi,
|
|
1774
|
-
disabled,
|
|
1775
|
-
onChange: (e) => {
|
|
1776
|
-
setInnerDdi(e.target.value);
|
|
1777
|
-
onDdiChange?.(e.target.value);
|
|
1778
|
-
},
|
|
1779
|
-
className: "absolute inset-0 cursor-pointer bg-popover text-popover-foreground opacity-0 disabled:cursor-not-allowed",
|
|
1780
|
-
children: ddiOptions.map((c) => /* @__PURE__ */ jsxs("option", {
|
|
1781
|
-
value: c.ddi,
|
|
1782
|
-
className: "bg-popover text-popover-foreground",
|
|
1783
|
-
children: [
|
|
1784
|
-
c.name,
|
|
1785
|
-
" (+",
|
|
1786
|
-
c.ddi,
|
|
1787
|
-
")"
|
|
1788
|
-
]
|
|
1789
|
-
}, c.ddi))
|
|
1790
|
-
})
|
|
1791
|
-
]
|
|
1792
|
-
}),
|
|
1793
|
-
icon && /* @__PURE__ */ jsx("span", {
|
|
1794
|
-
className: "flex shrink-0 text-muted-foreground [&_svg]:size-icon-sm",
|
|
1795
|
-
"aria-hidden": true,
|
|
1796
|
-
children: icon
|
|
1797
|
-
}),
|
|
1798
|
-
/* @__PURE__ */ jsx("input", {
|
|
1799
|
-
ref: inputRef,
|
|
1800
|
-
type: isSecret ? showPassword ? "text" : "password" : isPassword && showPassword ? "text" : type,
|
|
1801
|
-
inputMode: inputMode ?? def?.inputMode,
|
|
1802
|
-
placeholder: placeholder ?? def?.placeholder,
|
|
1803
|
-
disabled,
|
|
1804
|
-
"aria-invalid": invalid || void 0,
|
|
1805
|
-
"aria-busy": searching || void 0,
|
|
1806
|
-
className: cn(controlInput, inputClassName),
|
|
1807
|
-
...isSecret ? {
|
|
1808
|
-
value: secretDraft,
|
|
1809
|
-
onChange: (e) => {
|
|
1810
|
-
setSecretDraft(e.target.value);
|
|
1811
|
-
onChange?.(e.target.value);
|
|
1812
|
-
onValueChange?.(e.target.value, e.target.value);
|
|
1813
|
-
}
|
|
1814
|
-
} : maskKey ? { defaultValue: current } : {
|
|
1815
|
-
value: current,
|
|
1816
|
-
onChange: (e) => {
|
|
1817
|
-
setInner(e.target.value);
|
|
1818
|
-
onChange?.(e.target.value);
|
|
1819
|
-
onValueChange?.(e.target.value, e.target.value);
|
|
1820
|
-
}
|
|
1821
|
-
},
|
|
1822
|
-
...props
|
|
1823
|
-
}, hasUnits ? `unit-${unit}` : void 0),
|
|
1824
|
-
searching && /* @__PURE__ */ jsx(Spinner, {
|
|
1825
|
-
size: "sm",
|
|
1826
|
-
label: "Buscando…",
|
|
1827
|
-
className: "shrink-0 text-muted-foreground"
|
|
1828
|
-
}),
|
|
1829
|
-
hasUnits && /* @__PURE__ */ jsxs("span", {
|
|
1830
|
-
className: "relative -mr-1 flex h-full min-w-touch shrink-0 items-center gap-1 border-l pl-2 text-sm font-medium",
|
|
1831
|
-
children: [
|
|
1832
|
-
/* @__PURE__ */ jsx("span", {
|
|
1833
|
-
"aria-hidden": true,
|
|
1834
|
-
children: units?.find((u) => u.id === unit)?.label ?? unit
|
|
1835
|
-
}),
|
|
1836
|
-
/* @__PURE__ */ jsx(ChevronDown, {
|
|
1837
|
-
className: "size-icon-sm text-muted-foreground",
|
|
1838
|
-
"aria-hidden": true
|
|
1839
|
-
}),
|
|
1840
|
-
/* @__PURE__ */ jsx("select", {
|
|
1841
|
-
"aria-label": `Unidade: ${units?.find((u) => u.id === unit)?.label ?? unit}`,
|
|
1842
|
-
value: unit,
|
|
1843
|
-
disabled,
|
|
1844
|
-
onChange: (e) => changeUnit(e.target.value),
|
|
1845
|
-
className: "absolute inset-0 cursor-pointer bg-popover text-popover-foreground opacity-0 disabled:cursor-not-allowed",
|
|
1846
|
-
children: units?.map((u) => /* @__PURE__ */ jsx("option", {
|
|
1847
|
-
value: u.id,
|
|
1848
|
-
className: "bg-popover text-popover-foreground",
|
|
1849
|
-
children: u.label
|
|
1850
|
-
}, u.id))
|
|
1851
|
-
})
|
|
1852
|
-
]
|
|
1853
|
-
}),
|
|
1854
|
-
!hasUnits && suffix && /* @__PURE__ */ jsx("span", {
|
|
1855
|
-
className: "shrink-0 text-sm text-muted-foreground",
|
|
1856
|
-
children: suffix
|
|
1857
|
-
}),
|
|
1858
|
-
clearable && (isSecret ? secretDraft : current) && !disabled && /* @__PURE__ */ jsx("button", {
|
|
1859
|
-
type: "button",
|
|
1860
|
-
onClick: clear,
|
|
1861
|
-
"aria-label": "Limpar campo",
|
|
1862
|
-
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",
|
|
1863
|
-
children: /* @__PURE__ */ jsx(X, { "aria-hidden": true })
|
|
1864
|
-
}),
|
|
1865
|
-
(isPassword || isSecret) && /* @__PURE__ */ jsx("button", {
|
|
1866
|
-
type: "button",
|
|
1867
|
-
onClick: () => setShowPassword((s) => !s),
|
|
1868
|
-
"aria-label": showPassword ? "Ocultar senha" : "Mostrar senha",
|
|
1869
|
-
"aria-pressed": showPassword,
|
|
1870
|
-
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",
|
|
1871
|
-
children: showPassword ? /* @__PURE__ */ jsx(EyeOff, { "aria-hidden": true }) : /* @__PURE__ */ jsx(Eye, { "aria-hidden": true })
|
|
1872
|
-
}),
|
|
1873
|
-
isSecret && /* @__PURE__ */ jsx(Button, {
|
|
1874
|
-
type: "button",
|
|
1875
|
-
variant: "ghost",
|
|
1876
|
-
size: "sm",
|
|
1877
|
-
onClick: onCancelEdit,
|
|
1878
|
-
disabled,
|
|
1879
|
-
children: "Cancelar"
|
|
1880
|
-
})
|
|
1881
|
-
]
|
|
1882
|
-
});
|
|
1883
|
-
});
|
|
1884
|
-
//#endregion
|
|
1885
936
|
//#region src/components/ui/popover.tsx
|
|
1886
937
|
var PopoverOpenContext = createContext(null);
|
|
1887
938
|
function AnimatedRoot({ open, defaultOpen, onOpenChange, ...rest }) {
|
|
@@ -3474,226 +2525,12 @@ function applyPalette(seeds, doc = document) {
|
|
|
3474
2525
|
const attr = "data-palette-runtime";
|
|
3475
2526
|
let style = doc.head.querySelector(`style[${attr}="${seeds.id}"]`);
|
|
3476
2527
|
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 { AnimatePresence, animate, m, useDragControls } = useMotionOn();
|
|
3499
|
-
const presets = useMotionPresets();
|
|
3500
|
-
const ready = useLayoutReady();
|
|
3501
|
-
const controls = useDragControls();
|
|
3502
|
-
const sheetRef = useRef(null);
|
|
3503
|
-
const dimRef = useRef(null);
|
|
3504
|
-
const height = useRef(1);
|
|
3505
|
-
return /* @__PURE__ */ jsxs(Dialog.Root, {
|
|
3506
|
-
open,
|
|
3507
|
-
onOpenChange,
|
|
3508
|
-
children: [/* @__PURE__ */ jsx(Anchor, {
|
|
3509
|
-
adornment,
|
|
3510
|
-
children: /* @__PURE__ */ jsx(Dialog.Trigger, {
|
|
3511
|
-
asChild: true,
|
|
3512
|
-
children: trigger
|
|
3513
|
-
})
|
|
3514
|
-
}), /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsxs(Dialog.Portal, {
|
|
3515
|
-
forceMount: true,
|
|
3516
|
-
children: [/* @__PURE__ */ jsx(Dialog.Overlay, {
|
|
3517
|
-
forceMount: true,
|
|
3518
|
-
asChild: true,
|
|
3519
|
-
children: /* @__PURE__ */ jsx(m.div, {
|
|
3520
|
-
className: "fixed inset-0 z-40",
|
|
3521
|
-
...presets.fade,
|
|
3522
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
3523
|
-
ref: dimRef,
|
|
3524
|
-
className: "absolute inset-0 bg-overlay"
|
|
3525
|
-
})
|
|
3526
|
-
})
|
|
3527
|
-
}), /* @__PURE__ */ jsx(Dialog.Content, {
|
|
3528
|
-
forceMount: true,
|
|
3529
|
-
asChild: true,
|
|
3530
|
-
"aria-describedby": void 0,
|
|
3531
|
-
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",
|
|
3532
|
-
children: /* @__PURE__ */ jsxs(m.div, {
|
|
3533
|
-
ref: sheetRef,
|
|
3534
|
-
...presets.sheet("bottom"),
|
|
3535
|
-
drag: ready ? "y" : false,
|
|
3536
|
-
dragControls: controls,
|
|
3537
|
-
dragListener: false,
|
|
3538
|
-
dragConstraints: { top: 0 },
|
|
3539
|
-
dragElastic: {
|
|
3540
|
-
top: .2,
|
|
3541
|
-
bottom: 0
|
|
3542
|
-
},
|
|
3543
|
-
dragSnapToOrigin: true,
|
|
3544
|
-
dragTransition: presets.sheetBounce,
|
|
3545
|
-
onDragStart: () => {
|
|
3546
|
-
height.current = sheetRef.current?.offsetHeight || 1;
|
|
3547
|
-
},
|
|
3548
|
-
onDrag: (_, info) => {
|
|
3549
|
-
const dim = dimRef.current;
|
|
3550
|
-
if (dim) dim.style.opacity = String(1 - Math.min(1, Math.max(0, info.offset.y / height.current)));
|
|
3551
|
-
},
|
|
3552
|
-
onDragEnd: (_, info) => {
|
|
3553
|
-
if (info.offset.y > height.current * DISMISS_FRACTION || info.velocity.y > DISMISS_VELOCITY) {
|
|
3554
|
-
onOpenChange(false);
|
|
3555
|
-
return;
|
|
3556
|
-
}
|
|
3557
|
-
if (dimRef.current) animate(dimRef.current, { opacity: 1 }, presets.springSheet);
|
|
3558
|
-
},
|
|
3559
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
3560
|
-
"data-sheet-handle": true,
|
|
3561
|
-
onPointerDown: (e) => controls.start(e),
|
|
3562
|
-
className: "touch-none",
|
|
3563
|
-
children: head
|
|
3564
|
-
}), rest]
|
|
3565
|
-
})
|
|
3566
|
-
})]
|
|
3567
|
-
}, "sheet") })]
|
|
3568
|
-
});
|
|
3569
|
-
}
|
|
3570
|
-
function Anchor({ adornment, children }) {
|
|
3571
|
-
if (!adornment) return children;
|
|
3572
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3573
|
-
className: "relative w-full min-w-0",
|
|
3574
|
-
children: [children, adornment]
|
|
3575
|
-
});
|
|
3576
|
-
}
|
|
3577
|
-
function PickerPanel({ open, onOpenChange, trigger, title, header, children, footer, width = "trigger", adornment, align = "start" }) {
|
|
3578
|
-
const { isMobile } = useBreakpoint();
|
|
3579
|
-
const lib = useMotionLib();
|
|
3580
|
-
const presets = useMotionPresets();
|
|
3581
|
-
const on = lib !== null;
|
|
3582
|
-
const sheetHead = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
3583
|
-
className: "flex shrink-0 flex-col items-center pt-2",
|
|
3584
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
3585
|
-
"aria-hidden": true,
|
|
3586
|
-
className: "h-1 w-12 rounded-full bg-border"
|
|
3587
|
-
})
|
|
3588
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3589
|
-
className: "flex shrink-0 items-center justify-between gap-2 pr-2 pl-4",
|
|
3590
|
-
children: [/* @__PURE__ */ jsx(Dialog.Title, {
|
|
3591
|
-
className: "truncate text-base font-semibold",
|
|
3592
|
-
children: title
|
|
3593
|
-
}), /* @__PURE__ */ jsx(Dialog.Close, {
|
|
3594
|
-
"aria-label": "Fechar",
|
|
3595
|
-
className: "flex size-touch items-center justify-center rounded-item text-muted-foreground hover:bg-accent",
|
|
3596
|
-
children: /* @__PURE__ */ jsx(X, {
|
|
3597
|
-
className: "size-icon-md",
|
|
3598
|
-
"aria-hidden": true
|
|
3599
|
-
})
|
|
3600
|
-
})]
|
|
3601
|
-
})] });
|
|
3602
|
-
const sheetRest = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3603
|
-
header && /* @__PURE__ */ jsx("div", {
|
|
3604
|
-
className: "shrink-0 border-b px-4 pb-3",
|
|
3605
|
-
children: header
|
|
3606
|
-
}),
|
|
3607
|
-
/* @__PURE__ */ jsx("div", {
|
|
3608
|
-
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-2",
|
|
3609
|
-
children
|
|
3610
|
-
}),
|
|
3611
|
-
footer && /* @__PURE__ */ jsx("div", {
|
|
3612
|
-
className: "shrink-0 border-t px-4 pt-3 pb-safe",
|
|
3613
|
-
children: footer
|
|
3614
|
-
})
|
|
3615
|
-
] });
|
|
3616
|
-
const sheetBody = /* @__PURE__ */ jsxs(Fragment$1, { children: [sheetHead, sheetRest] });
|
|
3617
|
-
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");
|
|
3618
|
-
const panelBody = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3619
|
-
header && /* @__PURE__ */ jsx("div", {
|
|
3620
|
-
className: "shrink-0 border-b p-2",
|
|
3621
|
-
children: header
|
|
3622
|
-
}),
|
|
3623
|
-
/* @__PURE__ */ jsx("div", {
|
|
3624
|
-
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-1",
|
|
3625
|
-
children
|
|
3626
|
-
}),
|
|
3627
|
-
footer && /* @__PURE__ */ jsx("div", {
|
|
3628
|
-
className: "shrink-0 border-t p-2",
|
|
3629
|
-
children: footer
|
|
3630
|
-
})
|
|
3631
|
-
] });
|
|
3632
|
-
if (on && isMobile) return /* @__PURE__ */ jsx(MobileSheet, {
|
|
3633
|
-
open,
|
|
3634
|
-
onOpenChange,
|
|
3635
|
-
trigger,
|
|
3636
|
-
adornment,
|
|
3637
|
-
head: sheetHead,
|
|
3638
|
-
rest: sheetRest
|
|
3639
|
-
});
|
|
3640
|
-
if (on) return /* @__PURE__ */ jsxs(Popover$1.Root, {
|
|
3641
|
-
open,
|
|
3642
|
-
onOpenChange,
|
|
3643
|
-
children: [/* @__PURE__ */ jsx(Anchor, {
|
|
3644
|
-
adornment,
|
|
3645
|
-
children: /* @__PURE__ */ jsx(Popover$1.Trigger, {
|
|
3646
|
-
asChild: true,
|
|
3647
|
-
children: trigger
|
|
3648
|
-
})
|
|
3649
|
-
}), /* @__PURE__ */ jsx(lib.AnimatePresence, { children: open && /* @__PURE__ */ jsx(Popover$1.Portal, {
|
|
3650
|
-
forceMount: true,
|
|
3651
|
-
children: /* @__PURE__ */ jsx(Popover$1.Content, {
|
|
3652
|
-
forceMount: true,
|
|
3653
|
-
asChild: true,
|
|
3654
|
-
align,
|
|
3655
|
-
sideOffset: 6,
|
|
3656
|
-
collisionPadding: 16,
|
|
3657
|
-
className: panelCls,
|
|
3658
|
-
children: /* @__PURE__ */ jsx(lib.m.div, {
|
|
3659
|
-
...presets.open(),
|
|
3660
|
-
children: panelBody
|
|
3661
|
-
})
|
|
3662
|
-
})
|
|
3663
|
-
}, "panel") })]
|
|
3664
|
-
});
|
|
3665
|
-
if (isMobile) return /* @__PURE__ */ jsxs(Dialog.Root, {
|
|
3666
|
-
open,
|
|
3667
|
-
onOpenChange,
|
|
3668
|
-
children: [/* @__PURE__ */ jsx(Anchor, {
|
|
3669
|
-
adornment,
|
|
3670
|
-
children: /* @__PURE__ */ jsx(Dialog.Trigger, {
|
|
3671
|
-
asChild: true,
|
|
3672
|
-
children: trigger
|
|
3673
|
-
})
|
|
3674
|
-
}), /* @__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, {
|
|
3675
|
-
"aria-describedby": void 0,
|
|
3676
|
-
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",
|
|
3677
|
-
children: sheetBody
|
|
3678
|
-
})] })]
|
|
3679
|
-
});
|
|
3680
|
-
return /* @__PURE__ */ jsxs(Popover$1.Root, {
|
|
3681
|
-
open,
|
|
3682
|
-
onOpenChange,
|
|
3683
|
-
children: [/* @__PURE__ */ jsx(Anchor, {
|
|
3684
|
-
adornment,
|
|
3685
|
-
children: /* @__PURE__ */ jsx(Popover$1.Trigger, {
|
|
3686
|
-
asChild: true,
|
|
3687
|
-
children: trigger
|
|
3688
|
-
})
|
|
3689
|
-
}), /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(Popover$1.Content, {
|
|
3690
|
-
align,
|
|
3691
|
-
sideOffset: 6,
|
|
3692
|
-
collisionPadding: 16,
|
|
3693
|
-
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"),
|
|
3694
|
-
children: panelBody
|
|
3695
|
-
}) })]
|
|
3696
|
-
});
|
|
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;
|
|
3697
2534
|
}
|
|
3698
2535
|
//#endregion
|
|
3699
2536
|
//#region src/components/ui/color-picker.tsx
|
|
@@ -3790,82 +2627,6 @@ var ColorPicker = forwardRef(function ColorPicker({ value, onChange, swatches =
|
|
|
3790
2627
|
});
|
|
3791
2628
|
});
|
|
3792
2629
|
//#endregion
|
|
3793
|
-
//#region src/components/ui/drawer.tsx
|
|
3794
|
-
var sizes = {
|
|
3795
|
-
"30": "md:w-sheet-30",
|
|
3796
|
-
"40": "md:w-sheet-40",
|
|
3797
|
-
"50": "md:w-sheet-50",
|
|
3798
|
-
"75": "md:w-sheet-75",
|
|
3799
|
-
full: "md:w-full",
|
|
3800
|
-
sm: "md:w-sheet-30",
|
|
3801
|
-
md: "md:w-sheet-30",
|
|
3802
|
-
lg: "md:w-sheet-50",
|
|
3803
|
-
xl: "md:w-sheet-75"
|
|
3804
|
-
};
|
|
3805
|
-
var overlayCls = "fixed inset-0 z-50 bg-overlay";
|
|
3806
|
-
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";
|
|
3807
|
-
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." }) {
|
|
3808
|
-
const [confirming, setConfirming] = useState(false);
|
|
3809
|
-
const requestClose = () => dirty ? setConfirming(true) : onOpenChange(false);
|
|
3810
|
-
const lib = useMotionLib();
|
|
3811
|
-
const presets = useMotionPresets();
|
|
3812
|
-
const keepOpenIfDirty = (e) => {
|
|
3813
|
-
if (dirty) {
|
|
3814
|
-
e.preventDefault();
|
|
3815
|
-
setConfirming(true);
|
|
3816
|
-
}
|
|
3817
|
-
};
|
|
3818
|
-
const shell = /* @__PURE__ */ jsx(OverlayShell, {
|
|
3819
|
-
title,
|
|
3820
|
-
description,
|
|
3821
|
-
icon,
|
|
3822
|
-
footer,
|
|
3823
|
-
onRequestClose: requestClose,
|
|
3824
|
-
children
|
|
3825
|
-
});
|
|
3826
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Dialog.Root, {
|
|
3827
|
-
open,
|
|
3828
|
-
onOpenChange: (o) => o ? onOpenChange(true) : requestClose(),
|
|
3829
|
-
children: lib ? /* @__PURE__ */ jsx(lib.AnimatePresence, { children: open && /* @__PURE__ */ jsxs(Dialog.Portal, {
|
|
3830
|
-
forceMount: true,
|
|
3831
|
-
children: [/* @__PURE__ */ jsx(Dialog.Overlay, {
|
|
3832
|
-
forceMount: true,
|
|
3833
|
-
asChild: true,
|
|
3834
|
-
children: /* @__PURE__ */ jsx(lib.m.div, {
|
|
3835
|
-
className: overlayCls,
|
|
3836
|
-
...presets.fade
|
|
3837
|
-
})
|
|
3838
|
-
}), /* @__PURE__ */ jsx(Dialog.Content, {
|
|
3839
|
-
forceMount: true,
|
|
3840
|
-
asChild: true,
|
|
3841
|
-
onEscapeKeyDown: keepOpenIfDirty,
|
|
3842
|
-
onPointerDownOutside: keepOpenIfDirty,
|
|
3843
|
-
"data-rendra": "GAV-001",
|
|
3844
|
-
className: cn(panelCls, sizes[size]),
|
|
3845
|
-
children: /* @__PURE__ */ jsx(lib.m.div, {
|
|
3846
|
-
...presets.sheet("right"),
|
|
3847
|
-
children: shell
|
|
3848
|
-
})
|
|
3849
|
-
})]
|
|
3850
|
-
}, "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, {
|
|
3851
|
-
onEscapeKeyDown: keepOpenIfDirty,
|
|
3852
|
-
onPointerDownOutside: keepOpenIfDirty,
|
|
3853
|
-
"data-rendra": "GAV-001",
|
|
3854
|
-
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]),
|
|
3855
|
-
children: shell
|
|
3856
|
-
})] })
|
|
3857
|
-
}), /* @__PURE__ */ jsx(Modal, {
|
|
3858
|
-
open: confirming,
|
|
3859
|
-
onOpenChange: setConfirming,
|
|
3860
|
-
type: "destructive",
|
|
3861
|
-
title: discardTitle,
|
|
3862
|
-
description: discardDescription,
|
|
3863
|
-
confirmLabel: "Descartar",
|
|
3864
|
-
cancelLabel: "Continuar editando",
|
|
3865
|
-
onConfirm: () => onOpenChange(false)
|
|
3866
|
-
})] });
|
|
3867
|
-
}
|
|
3868
|
-
//#endregion
|
|
3869
2630
|
//#region src/components/ui/switch.tsx
|
|
3870
2631
|
/** Switch único, com rótulo e descrição à esquerda e a chave à direita. */
|
|
3871
2632
|
function Switch({ checked, defaultChecked, onCheckedChange, label, description, disabled, id, name, className, ...aria }) {
|
|
@@ -3936,7 +2697,7 @@ function Switch({ checked, defaultChecked, onCheckedChange, label, description,
|
|
|
3936
2697
|
}
|
|
3937
2698
|
//#endregion
|
|
3938
2699
|
//#region src/components/ui/data-toolbar.tsx
|
|
3939
|
-
function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips = [], sort, columns, actions, primaryAction, selectionBar }) {
|
|
2700
|
+
function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips = [], sort, columns, actions, summary, primaryAction, selectionBar }) {
|
|
3940
2701
|
const { isMobile } = useBreakpoint();
|
|
3941
2702
|
const [drawer, setDrawer] = useState(false);
|
|
3942
2703
|
const hasPanel = Boolean(filters || sort || columns?.length);
|
|
@@ -3974,49 +2735,57 @@ function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips =
|
|
|
3974
2735
|
children: selectionBar
|
|
3975
2736
|
}) : /* @__PURE__ */ jsxs("div", {
|
|
3976
2737
|
className: "flex flex-col gap-3 md:flex-row md:items-center",
|
|
3977
|
-
children: [
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
children:
|
|
4014
|
-
})
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
2738
|
+
children: [
|
|
2739
|
+
search && /* @__PURE__ */ jsx(Input, {
|
|
2740
|
+
icon: /* @__PURE__ */ jsx(Search, {}),
|
|
2741
|
+
clearable: true,
|
|
2742
|
+
value: search.value,
|
|
2743
|
+
onChange: search.onChange,
|
|
2744
|
+
placeholder: search.placeholder ?? "Buscar",
|
|
2745
|
+
"aria-label": search.placeholder ?? "Buscar",
|
|
2746
|
+
type: "search",
|
|
2747
|
+
className: "md:w-3xs lg:w-sm"
|
|
2748
|
+
}),
|
|
2749
|
+
summary && /* @__PURE__ */ jsx("div", {
|
|
2750
|
+
"data-toolbar-summary": true,
|
|
2751
|
+
className: "flex flex-col gap-1 text-sm",
|
|
2752
|
+
children: summary
|
|
2753
|
+
}),
|
|
2754
|
+
isMobile ? /* @__PURE__ */ jsxs(Fragment$1, { children: [(hasPanel || primaryAction) && /* @__PURE__ */ jsxs("div", {
|
|
2755
|
+
className: cn("grid gap-3", hasPanel && primaryAction ? "grid-actions-2" : "grid-cols-1"),
|
|
2756
|
+
children: [hasPanel && filterButton(() => setDrawer(true)), primaryAction]
|
|
2757
|
+
}), actions && /* @__PURE__ */ jsx("div", {
|
|
2758
|
+
className: "flex flex-wrap gap-3 *:flex-1",
|
|
2759
|
+
children: actions
|
|
2760
|
+
})] }) : /* @__PURE__ */ jsxs("div", {
|
|
2761
|
+
className: "flex flex-wrap items-center gap-2 md:ml-auto",
|
|
2762
|
+
children: [
|
|
2763
|
+
actions,
|
|
2764
|
+
columnsMenu,
|
|
2765
|
+
sort,
|
|
2766
|
+
filters && /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
2767
|
+
asChild: true,
|
|
2768
|
+
children: filterButton()
|
|
2769
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
2770
|
+
align: "end",
|
|
2771
|
+
className: "flex flex-col",
|
|
2772
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2773
|
+
className: "max-h-command overflow-y-auto p-4",
|
|
2774
|
+
children: filters
|
|
2775
|
+
}), onClearFilters && filterCount > 0 && /* @__PURE__ */ jsx("div", {
|
|
2776
|
+
className: "border-t p-2",
|
|
2777
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
2778
|
+
variant: "ghost",
|
|
2779
|
+
size: "sm",
|
|
2780
|
+
onClick: onClearFilters,
|
|
2781
|
+
children: "Limpar filtros"
|
|
2782
|
+
})
|
|
2783
|
+
})]
|
|
2784
|
+
})] }),
|
|
2785
|
+
primaryAction
|
|
2786
|
+
]
|
|
2787
|
+
})
|
|
2788
|
+
]
|
|
4020
2789
|
}),
|
|
4021
2790
|
chips.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
4022
2791
|
className: "flex flex-wrap items-center gap-2",
|
|
@@ -4087,121 +2856,6 @@ function DataToolbar({ search, filters, filterCount = 0, onClearFilters, chips =
|
|
|
4087
2856
|
});
|
|
4088
2857
|
}
|
|
4089
2858
|
//#endregion
|
|
4090
|
-
//#region src/components/layout/tokens.ts
|
|
4091
|
-
var gapClass = {
|
|
4092
|
-
"0": "gap-0",
|
|
4093
|
-
"1": "gap-1",
|
|
4094
|
-
"2": "gap-2",
|
|
4095
|
-
"3": "gap-3",
|
|
4096
|
-
"4": "gap-4",
|
|
4097
|
-
"6": "gap-6",
|
|
4098
|
-
"8": "gap-8",
|
|
4099
|
-
"12": "gap-12",
|
|
4100
|
-
"16": "gap-16",
|
|
4101
|
-
"24": "gap-24",
|
|
4102
|
-
section: "gap-8 md:gap-12",
|
|
4103
|
-
fields: "gap-x-4 gap-y-4 md:gap-x-6"
|
|
4104
|
-
};
|
|
4105
|
-
/**
|
|
4106
|
-
* Grade de formulário, pela largura do próprio bloco (container query), não da tela:
|
|
4107
|
-
* 1 coluna estreito, 6 colunas a partir de 28rem, 12 colunas a partir de 48rem.
|
|
4108
|
-
* No largo, o padrão é 3 campos por linha (md = 4/12). Nunca 2 por linha por padrão.
|
|
4109
|
-
*/
|
|
4110
|
-
var fieldGridClass = "grid grid-cols-1 @md:grid-cols-6 @3xl:grid-cols-12";
|
|
4111
|
-
/** Largura do Field na grade de formulário (no largo, em 12 colunas). */
|
|
4112
|
-
var fieldSpanClass = {
|
|
4113
|
-
/** 2/12, cerca de 17%: UF, número, DDD. */
|
|
4114
|
-
xs: "@md:col-span-2 @3xl:col-span-2",
|
|
4115
|
-
/** 3/12 = 25%: CEP, CNPJ, CPF, datas curtas. */
|
|
4116
|
-
sm: "@md:col-span-2 @3xl:col-span-3",
|
|
4117
|
-
/** 4/12 = 33%: o padrão, 3 campos por linha. */
|
|
4118
|
-
md: "@md:col-span-3 @3xl:col-span-4",
|
|
4119
|
-
/** 6/12 = 50%. */
|
|
4120
|
-
lg: "@md:col-span-3 @3xl:col-span-6",
|
|
4121
|
-
/** 8/12 = 67%: nome, logradouro longo. */
|
|
4122
|
-
xl: "@md:col-span-6 @3xl:col-span-8",
|
|
4123
|
-
/** Linha inteira. */
|
|
4124
|
-
full: "@md:col-span-6 @3xl:col-span-12"
|
|
4125
|
-
};
|
|
4126
|
-
var alignClass = {
|
|
4127
|
-
start: "items-start",
|
|
4128
|
-
center: "items-center",
|
|
4129
|
-
end: "items-end",
|
|
4130
|
-
stretch: "items-stretch",
|
|
4131
|
-
baseline: "items-baseline"
|
|
4132
|
-
};
|
|
4133
|
-
var justifyClass = {
|
|
4134
|
-
start: "justify-start",
|
|
4135
|
-
center: "justify-center",
|
|
4136
|
-
end: "justify-end",
|
|
4137
|
-
between: "justify-between"
|
|
4138
|
-
};
|
|
4139
|
-
//#endregion
|
|
4140
|
-
//#region src/components/ui/field.tsx
|
|
4141
|
-
function Label({ className, required, children, ...props }) {
|
|
4142
|
-
return /* @__PURE__ */ jsxs(Label$1.Root, {
|
|
4143
|
-
"data-rendra": "FLD-002",
|
|
4144
|
-
className: cn("text-label text-label-foreground label-case", className),
|
|
4145
|
-
...props,
|
|
4146
|
-
children: [
|
|
4147
|
-
children,
|
|
4148
|
-
required && /* @__PURE__ */ jsxs("span", {
|
|
4149
|
-
className: "text-destructive",
|
|
4150
|
-
"aria-hidden": true,
|
|
4151
|
-
children: [" ", "*"]
|
|
4152
|
-
}),
|
|
4153
|
-
required && /* @__PURE__ */ jsx("span", {
|
|
4154
|
-
className: "sr-only",
|
|
4155
|
-
children: " (obrigatório)"
|
|
4156
|
-
})
|
|
4157
|
-
]
|
|
4158
|
-
});
|
|
4159
|
-
}
|
|
4160
|
-
var FieldContext = createContext(null);
|
|
4161
|
-
/** Liga um controle ao Field mais próximo (id, aria-describedby, aria-invalid). */
|
|
4162
|
-
function useFieldControl() {
|
|
4163
|
-
return useContext(FieldContext);
|
|
4164
|
-
}
|
|
4165
|
-
function Field({ label, required, help, error, span = "md", newRow, reserveMessage = false, id, className, children }) {
|
|
4166
|
-
const auto = useId();
|
|
4167
|
-
const controlId = id ?? `campo${auto}`;
|
|
4168
|
-
const messageId = `${controlId}-mensagem`;
|
|
4169
|
-
const invalid = Boolean(error);
|
|
4170
|
-
const message = error ?? help;
|
|
4171
|
-
const child = isValidElement(children) && typeof children.type !== "string" ? cloneElement(children, {
|
|
4172
|
-
id: children.props.id ?? controlId,
|
|
4173
|
-
...invalid ? { invalid: children.props.invalid ?? true } : {},
|
|
4174
|
-
"aria-describedby": message ? messageId : void 0,
|
|
4175
|
-
"aria-required": required || void 0
|
|
4176
|
-
}) : children;
|
|
4177
|
-
return /* @__PURE__ */ jsx(FieldContext.Provider, {
|
|
4178
|
-
value: {
|
|
4179
|
-
id: controlId,
|
|
4180
|
-
describedBy: message ? messageId : "",
|
|
4181
|
-
invalid
|
|
4182
|
-
},
|
|
4183
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
4184
|
-
"data-slot": "field",
|
|
4185
|
-
"data-rendra": "FLD-001",
|
|
4186
|
-
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),
|
|
4187
|
-
children: [
|
|
4188
|
-
label && /* @__PURE__ */ jsx(Label, {
|
|
4189
|
-
htmlFor: controlId,
|
|
4190
|
-
required,
|
|
4191
|
-
children: label
|
|
4192
|
-
}),
|
|
4193
|
-
child,
|
|
4194
|
-
(reserveMessage || message) && /* @__PURE__ */ jsx("p", {
|
|
4195
|
-
id: messageId,
|
|
4196
|
-
role: invalid ? "alert" : void 0,
|
|
4197
|
-
className: cn("-mt-1 min-h-4 text-help", invalid ? "font-medium text-destructive" : "text-help-foreground"),
|
|
4198
|
-
children: message
|
|
4199
|
-
})
|
|
4200
|
-
]
|
|
4201
|
-
})
|
|
4202
|
-
});
|
|
4203
|
-
}
|
|
4204
|
-
//#endregion
|
|
4205
2859
|
//#region src/components/ui/date-picker.tsx
|
|
4206
2860
|
var fmtDate = (d) => format(d, "dd/MM/yyyy");
|
|
4207
2861
|
var fmtTime = (d) => format(d, "HH:mm");
|
|
@@ -4584,318 +3238,6 @@ function Slider({ value, defaultValue = [50], onChange, min = 0, max = 100, step
|
|
|
4584
3238
|
});
|
|
4585
3239
|
}
|
|
4586
3240
|
//#endregion
|
|
4587
|
-
//#region src/components/ui/select.tsx
|
|
4588
|
-
/** Acima deste número de opções, o "Selecionar todos" aparece sem a prop `selectAll`. */
|
|
4589
|
-
var SELECT_ALL_AUTO_MIN = 5;
|
|
4590
|
-
/**
|
|
4591
|
-
* Select único do sistema. Busca, múltiplo, selecionar todos, contador, criar opção,
|
|
4592
|
-
* busca remota e carregamento são props. No mobile abre como bottom sheet.
|
|
4593
|
-
*/
|
|
4594
|
-
var Select = forwardRef(function Select(props, ref) {
|
|
4595
|
-
const { options: staticOptions = [], placeholder = "Selecione", label, size, invalid, disabled, searchable, creatable, onCreate, loadOptions, loading, clearable, emptyText = "Nenhuma opção encontrada.", id, className } = props;
|
|
4596
|
-
const multiple = props.multiple === true;
|
|
4597
|
-
const { isMobile } = useBreakpoint();
|
|
4598
|
-
const [open, setOpen] = useState(false);
|
|
4599
|
-
const listId = `${useId()}-lista`;
|
|
4600
|
-
const [query, setQuery] = useState("");
|
|
4601
|
-
const [remote, setRemote] = useState(null);
|
|
4602
|
-
const [remoteLoading, setRemoteLoading] = useState(false);
|
|
4603
|
-
const [created, setCreated] = useState([]);
|
|
4604
|
-
const [innerSingle, setInnerSingle] = useState(null);
|
|
4605
|
-
const [innerMulti, setInnerMulti] = useState([]);
|
|
4606
|
-
const [draft, setDraft] = useState([]);
|
|
4607
|
-
const selectedSingle = multiple ? null : props.value ?? innerSingle;
|
|
4608
|
-
const selectedMulti = multiple ? props.value ?? innerMulti : [];
|
|
4609
|
-
const seq = useRef(0);
|
|
4610
|
-
useEffect(() => {
|
|
4611
|
-
if (!loadOptions || !open) return;
|
|
4612
|
-
const n = ++seq.current;
|
|
4613
|
-
setRemoteLoading(true);
|
|
4614
|
-
const t = window.setTimeout(async () => {
|
|
4615
|
-
const res = await loadOptions(query);
|
|
4616
|
-
if (n === seq.current) {
|
|
4617
|
-
setRemote(res);
|
|
4618
|
-
setRemoteLoading(false);
|
|
4619
|
-
}
|
|
4620
|
-
}, 250);
|
|
4621
|
-
return () => window.clearTimeout(t);
|
|
4622
|
-
}, [
|
|
4623
|
-
loadOptions,
|
|
4624
|
-
query,
|
|
4625
|
-
open
|
|
4626
|
-
]);
|
|
4627
|
-
const all = useMemo(() => {
|
|
4628
|
-
const base = remote ?? staticOptions;
|
|
4629
|
-
const map = /* @__PURE__ */ new Map();
|
|
4630
|
-
[...base, ...created].forEach((o) => map.set(o.value, o));
|
|
4631
|
-
return [...map.values()];
|
|
4632
|
-
}, [
|
|
4633
|
-
remote,
|
|
4634
|
-
staticOptions,
|
|
4635
|
-
created
|
|
4636
|
-
]);
|
|
4637
|
-
const byValue = (v) => all.find((o) => o.value === v);
|
|
4638
|
-
const isSearchable = searchable || creatable || Boolean(loadOptions);
|
|
4639
|
-
const busy = loading || remoteLoading;
|
|
4640
|
-
const multiValue = isMobile && multiple ? draft : selectedMulti;
|
|
4641
|
-
const commitSingle = (v) => {
|
|
4642
|
-
setInnerSingle(v);
|
|
4643
|
-
props.onChange?.(v);
|
|
4644
|
-
};
|
|
4645
|
-
const commitMulti = (v) => {
|
|
4646
|
-
setInnerMulti(v);
|
|
4647
|
-
props.onChange?.(v);
|
|
4648
|
-
};
|
|
4649
|
-
const toggle = (v) => {
|
|
4650
|
-
if (!multiple) {
|
|
4651
|
-
commitSingle(v);
|
|
4652
|
-
setOpen(false);
|
|
4653
|
-
return;
|
|
4654
|
-
}
|
|
4655
|
-
const next = multiValue.includes(v) ? multiValue.filter((x) => x !== v) : [...multiValue, v];
|
|
4656
|
-
if (isMobile) setDraft(next);
|
|
4657
|
-
else commitMulti(next);
|
|
4658
|
-
};
|
|
4659
|
-
const enabled = all.filter((o) => !o.disabled);
|
|
4660
|
-
const allSelected = enabled.length > 0 && enabled.every((o) => multiValue.includes(o.value));
|
|
4661
|
-
const showSelectAll = multiple && (props.selectAll ?? all.length > SELECT_ALL_AUTO_MIN);
|
|
4662
|
-
const toggleAll = () => {
|
|
4663
|
-
const next = allSelected ? [] : enabled.map((o) => o.value);
|
|
4664
|
-
if (isMobile) setDraft(next);
|
|
4665
|
-
else commitMulti(next);
|
|
4666
|
-
};
|
|
4667
|
-
const create = async () => {
|
|
4668
|
-
const text = query.trim();
|
|
4669
|
-
if (!text) return;
|
|
4670
|
-
const opt = onCreate ? await onCreate(text) : {
|
|
4671
|
-
value: text,
|
|
4672
|
-
label: text
|
|
4673
|
-
};
|
|
4674
|
-
setCreated((c) => [...c, opt]);
|
|
4675
|
-
setQuery("");
|
|
4676
|
-
toggle(opt.value);
|
|
4677
|
-
};
|
|
4678
|
-
const onOpenChange = (o) => {
|
|
4679
|
-
setOpen(o);
|
|
4680
|
-
if (o) setDraft(selectedMulti);
|
|
4681
|
-
else setQuery("");
|
|
4682
|
-
};
|
|
4683
|
-
const hasValue = multiple ? selectedMulti.length > 0 : selectedSingle != null;
|
|
4684
|
-
const maxChips = props.maxChips ?? 2;
|
|
4685
|
-
let display = /* @__PURE__ */ jsx("span", {
|
|
4686
|
-
className: "truncate text-muted-foreground",
|
|
4687
|
-
children: placeholder
|
|
4688
|
-
});
|
|
4689
|
-
if (!multiple && selectedSingle != null) {
|
|
4690
|
-
const o = byValue(selectedSingle);
|
|
4691
|
-
display = /* @__PURE__ */ jsxs("span", {
|
|
4692
|
-
className: "flex min-w-0 items-center gap-2",
|
|
4693
|
-
children: [o?.icon, /* @__PURE__ */ jsx("span", {
|
|
4694
|
-
className: "truncate",
|
|
4695
|
-
children: o?.label ?? selectedSingle
|
|
4696
|
-
})]
|
|
4697
|
-
});
|
|
4698
|
-
} else if (multiple && selectedMulti.length > 0) display = props.showCount ? /* @__PURE__ */ jsxs("span", {
|
|
4699
|
-
className: "truncate",
|
|
4700
|
-
children: [
|
|
4701
|
-
selectedMulti.length,
|
|
4702
|
-
" ",
|
|
4703
|
-
selectedMulti.length === 1 ? "selecionado" : "selecionados"
|
|
4704
|
-
]
|
|
4705
|
-
}) : /* @__PURE__ */ jsxs("span", {
|
|
4706
|
-
className: "flex min-w-0 items-center gap-1 overflow-hidden",
|
|
4707
|
-
children: [selectedMulti.slice(0, maxChips).map((v) => /* @__PURE__ */ jsx("span", {
|
|
4708
|
-
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",
|
|
4709
|
-
children: byValue(v)?.label ?? v
|
|
4710
|
-
}, v)), selectedMulti.length > maxChips && /* @__PURE__ */ jsxs("span", {
|
|
4711
|
-
className: "shrink-0 rounded-item bg-muted px-2 py-1 text-xs leading-none font-medium",
|
|
4712
|
-
children: ["+", selectedMulti.length - maxChips]
|
|
4713
|
-
})]
|
|
4714
|
-
});
|
|
4715
|
-
const showClear = clearable && hasValue && !disabled;
|
|
4716
|
-
const clear = showClear ? /* @__PURE__ */ jsx("button", {
|
|
4717
|
-
type: "button",
|
|
4718
|
-
"aria-label": "Limpar seleção",
|
|
4719
|
-
className: cn(controlAdornmentButton, "absolute top-1/2 right-8 mr-0 -translate-y-1/2 md:mr-0"),
|
|
4720
|
-
onClick: () => multiple ? commitMulti([]) : commitSingle(null),
|
|
4721
|
-
children: /* @__PURE__ */ jsx(X, { "aria-hidden": true })
|
|
4722
|
-
}) : void 0;
|
|
4723
|
-
const trigger = /* @__PURE__ */ jsxs("button", {
|
|
4724
|
-
ref,
|
|
4725
|
-
id,
|
|
4726
|
-
type: "button",
|
|
4727
|
-
role: "combobox",
|
|
4728
|
-
"aria-expanded": open,
|
|
4729
|
-
"aria-controls": listId,
|
|
4730
|
-
"aria-haspopup": "listbox",
|
|
4731
|
-
"aria-invalid": invalid || void 0,
|
|
4732
|
-
"aria-describedby": props["aria-describedby"],
|
|
4733
|
-
"aria-label": id ? void 0 : label,
|
|
4734
|
-
disabled,
|
|
4735
|
-
"data-rendra": "SEL-001",
|
|
4736
|
-
onKeyDown: (e) => e.stopPropagation(),
|
|
4737
|
-
className: cn(controlFrame({
|
|
4738
|
-
size,
|
|
4739
|
-
invalid
|
|
4740
|
-
}), "cursor-pointer text-left disabled:cursor-not-allowed disabled:opacity-60", className),
|
|
4741
|
-
children: [
|
|
4742
|
-
/* @__PURE__ */ jsx("span", {
|
|
4743
|
-
className: "flex min-w-0 flex-1 items-center",
|
|
4744
|
-
children: display
|
|
4745
|
-
}),
|
|
4746
|
-
showClear && /* @__PURE__ */ jsx("span", {
|
|
4747
|
-
"aria-hidden": true,
|
|
4748
|
-
className: cn("size-control-sm shrink-0 md:size-8", "-mr-1")
|
|
4749
|
-
}),
|
|
4750
|
-
/* @__PURE__ */ jsx(ChevronDown, {
|
|
4751
|
-
"aria-hidden": true,
|
|
4752
|
-
className: cn("size-icon-sm shrink-0 text-muted-foreground transition-transform duration-(--rendra-duration-base) ease-move", open && "rotate-180")
|
|
4753
|
-
})
|
|
4754
|
-
]
|
|
4755
|
-
});
|
|
4756
|
-
const groups = all.reduce((acc, o) => {
|
|
4757
|
-
(acc[o.group ?? ""] ??= []).push(o);
|
|
4758
|
-
return acc;
|
|
4759
|
-
}, {});
|
|
4760
|
-
const q = query.trim().toLowerCase();
|
|
4761
|
-
const showCreate = creatable && q && !all.some((o) => o.label.toLowerCase() === q);
|
|
4762
|
-
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";
|
|
4763
|
-
const checkbox = (checked) => /* @__PURE__ */ jsx("span", {
|
|
4764
|
-
"aria-hidden": true,
|
|
4765
|
-
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"),
|
|
4766
|
-
children: checked && /* @__PURE__ */ jsx(Check, {
|
|
4767
|
-
className: "size-3",
|
|
4768
|
-
strokeWidth: 3
|
|
4769
|
-
})
|
|
4770
|
-
});
|
|
4771
|
-
const list = /* @__PURE__ */ jsxs(Command.List, {
|
|
4772
|
-
id: listId,
|
|
4773
|
-
"aria-label": label ?? placeholder,
|
|
4774
|
-
children: [
|
|
4775
|
-
busy && /* @__PURE__ */ jsx(Command.Loading, { children: /* @__PURE__ */ jsxs("div", {
|
|
4776
|
-
className: "flex items-center gap-2 px-3 py-4 text-sm text-muted-foreground",
|
|
4777
|
-
children: [/* @__PURE__ */ jsx(Spinner, { size: "sm" }), "Carregando opções..."]
|
|
4778
|
-
}) }),
|
|
4779
|
-
!busy && /* @__PURE__ */ jsx(Command.Empty, {
|
|
4780
|
-
className: "px-3 py-6 text-center text-sm text-muted-foreground",
|
|
4781
|
-
children: emptyText
|
|
4782
|
-
}),
|
|
4783
|
-
showCreate && /* @__PURE__ */ jsxs(Command.Item, {
|
|
4784
|
-
value: `__criar__${query}`,
|
|
4785
|
-
onSelect: create,
|
|
4786
|
-
className: itemClass,
|
|
4787
|
-
children: [/* @__PURE__ */ jsx(Plus, {
|
|
4788
|
-
className: "size-icon-sm shrink-0 text-primary-text",
|
|
4789
|
-
"aria-hidden": true
|
|
4790
|
-
}), /* @__PURE__ */ jsxs("span", {
|
|
4791
|
-
className: "truncate",
|
|
4792
|
-
children: ["Criar ", /* @__PURE__ */ jsxs("strong", {
|
|
4793
|
-
className: "font-semibold",
|
|
4794
|
-
children: [
|
|
4795
|
-
"“",
|
|
4796
|
-
query.trim(),
|
|
4797
|
-
"”"
|
|
4798
|
-
]
|
|
4799
|
-
})]
|
|
4800
|
-
})]
|
|
4801
|
-
}),
|
|
4802
|
-
showSelectAll && !q && enabled.length > 0 && /* @__PURE__ */ jsxs(Command.Item, {
|
|
4803
|
-
value: "__todos__",
|
|
4804
|
-
onSelect: toggleAll,
|
|
4805
|
-
className: cn(itemClass, "font-medium"),
|
|
4806
|
-
children: [checkbox(allSelected), allSelected ? "Desmarcar todos" : "Selecionar todos"]
|
|
4807
|
-
}),
|
|
4808
|
-
Object.entries(groups).map(([group, opts]) => /* @__PURE__ */ jsx(Command.Group, {
|
|
4809
|
-
heading: group || void 0,
|
|
4810
|
-
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",
|
|
4811
|
-
children: opts.map((o) => {
|
|
4812
|
-
const checked = multiple ? multiValue.includes(o.value) : selectedSingle === o.value;
|
|
4813
|
-
return /* @__PURE__ */ jsxs(Command.Item, {
|
|
4814
|
-
value: `${o.label} ${o.description ?? ""} ${o.value}`,
|
|
4815
|
-
disabled: o.disabled,
|
|
4816
|
-
onSelect: () => toggle(o.value),
|
|
4817
|
-
"aria-selected": checked,
|
|
4818
|
-
className: itemClass,
|
|
4819
|
-
children: [
|
|
4820
|
-
multiple && checkbox(checked),
|
|
4821
|
-
o.icon && /* @__PURE__ */ jsx("span", {
|
|
4822
|
-
className: "flex shrink-0 [&_svg]:size-icon-sm",
|
|
4823
|
-
children: o.icon
|
|
4824
|
-
}),
|
|
4825
|
-
/* @__PURE__ */ jsxs("span", {
|
|
4826
|
-
className: "flex min-w-0 flex-1 flex-col",
|
|
4827
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
4828
|
-
className: cn("truncate", checked && !multiple && "font-medium"),
|
|
4829
|
-
children: o.label
|
|
4830
|
-
}), o.description && /* @__PURE__ */ jsx("span", {
|
|
4831
|
-
className: "truncate text-xs text-muted-foreground",
|
|
4832
|
-
children: o.description
|
|
4833
|
-
})]
|
|
4834
|
-
}),
|
|
4835
|
-
!multiple && checked && /* @__PURE__ */ jsx(Check, {
|
|
4836
|
-
className: "size-icon-sm shrink-0 text-primary-text",
|
|
4837
|
-
"aria-hidden": true
|
|
4838
|
-
})
|
|
4839
|
-
]
|
|
4840
|
-
}, o.value);
|
|
4841
|
-
})
|
|
4842
|
-
}, group || "sem-grupo"))
|
|
4843
|
-
]
|
|
4844
|
-
});
|
|
4845
|
-
const search = isSearchable ? /* @__PURE__ */ jsxs("div", {
|
|
4846
|
-
className: cn(controlFrame({ size: "md" }), "bg-background"),
|
|
4847
|
-
children: [/* @__PURE__ */ jsx(Search, {
|
|
4848
|
-
className: "size-icon-sm shrink-0 text-muted-foreground",
|
|
4849
|
-
"aria-hidden": true
|
|
4850
|
-
}), /* @__PURE__ */ jsx(Command.Input, {
|
|
4851
|
-
value: query,
|
|
4852
|
-
onValueChange: setQuery,
|
|
4853
|
-
placeholder: creatable ? "Buscar ou criar..." : "Buscar...",
|
|
4854
|
-
className: "h-full min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground"
|
|
4855
|
-
})]
|
|
4856
|
-
}) : null;
|
|
4857
|
-
const count = multiValue.length;
|
|
4858
|
-
const footer = multiple && (isMobile || count > 0) ? /* @__PURE__ */ jsxs("div", {
|
|
4859
|
-
className: "grid grid-actions-2 gap-3",
|
|
4860
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
4861
|
-
variant: "outline",
|
|
4862
|
-
onClick: () => isMobile ? setDraft([]) : commitMulti([]),
|
|
4863
|
-
disabled: count === 0,
|
|
4864
|
-
children: "Limpar"
|
|
4865
|
-
}), isMobile ? /* @__PURE__ */ jsxs(Button, {
|
|
4866
|
-
onClick: () => {
|
|
4867
|
-
commitMulti(draft);
|
|
4868
|
-
setOpen(false);
|
|
4869
|
-
},
|
|
4870
|
-
children: ["Aplicar", count ? ` (${count})` : ""]
|
|
4871
|
-
}) : /* @__PURE__ */ jsxs(Button, {
|
|
4872
|
-
variant: "secondary",
|
|
4873
|
-
onClick: () => setOpen(false),
|
|
4874
|
-
children: [
|
|
4875
|
-
"Pronto (",
|
|
4876
|
-
count,
|
|
4877
|
-
")"
|
|
4878
|
-
]
|
|
4879
|
-
})]
|
|
4880
|
-
}) : void 0;
|
|
4881
|
-
return /* @__PURE__ */ jsx(Command, {
|
|
4882
|
-
shouldFilter: !loadOptions,
|
|
4883
|
-
loop: true,
|
|
4884
|
-
className: "contents",
|
|
4885
|
-
label: label ?? placeholder,
|
|
4886
|
-
children: /* @__PURE__ */ jsx(PickerPanel, {
|
|
4887
|
-
open,
|
|
4888
|
-
onOpenChange,
|
|
4889
|
-
trigger,
|
|
4890
|
-
adornment: clear,
|
|
4891
|
-
title: label ?? placeholder,
|
|
4892
|
-
header: search,
|
|
4893
|
-
footer,
|
|
4894
|
-
children: list
|
|
4895
|
-
})
|
|
4896
|
-
});
|
|
4897
|
-
});
|
|
4898
|
-
//#endregion
|
|
4899
3241
|
//#region src/components/ui/tabs.tsx
|
|
4900
3242
|
/** Contador de instâncias, só para o `layoutId` do indicador (ver `indicatorId`). */
|
|
4901
3243
|
var tabsCreated = 0;
|
|
@@ -5458,33 +3800,6 @@ function ImageViewer({ images, index, onIndexChange }) {
|
|
|
5458
3800
|
});
|
|
5459
3801
|
}
|
|
5460
3802
|
//#endregion
|
|
5461
|
-
//#region src/hooks/use-fill-height.ts
|
|
5462
|
-
/**
|
|
5463
|
-
* Mede o espaço que sobra na área de conteúdo (o <main>) abaixo do elemento e grava em
|
|
5464
|
-
* --board-h. Com a classe h-board, o elemento ocupa exatamente essa altura: a página não
|
|
5465
|
-
* rola e a rolagem acontece dentro dele (kanban, chat).
|
|
5466
|
-
*/
|
|
5467
|
-
function useFillHeight() {
|
|
5468
|
-
const ref = useRef(null);
|
|
5469
|
-
useLayoutEffect(() => {
|
|
5470
|
-
const el = ref.current;
|
|
5471
|
-
if (!el) return;
|
|
5472
|
-
const main = el.closest("main");
|
|
5473
|
-
const measure = () => {
|
|
5474
|
-
const h = el.getBoundingClientRect().height;
|
|
5475
|
-
const page = main?.firstElementChild;
|
|
5476
|
-
const room = main && page ? main.clientHeight - (page.getBoundingClientRect().height - h) : window.innerHeight - el.getBoundingClientRect().top;
|
|
5477
|
-
el.style.setProperty("--board-h", `${Math.max(320, Math.floor(room))}px`);
|
|
5478
|
-
};
|
|
5479
|
-
measure();
|
|
5480
|
-
const ro = new ResizeObserver(measure);
|
|
5481
|
-
ro.observe(document.documentElement);
|
|
5482
|
-
if (main) ro.observe(main);
|
|
5483
|
-
return () => ro.disconnect();
|
|
5484
|
-
}, []);
|
|
5485
|
-
return ref;
|
|
5486
|
-
}
|
|
5487
|
-
//#endregion
|
|
5488
3803
|
//#region src/components/ui/kanban.tsx
|
|
5489
3804
|
/** Marca o fim da lista: ao aparecer na rolagem da etapa, pede mais cards. */
|
|
5490
3805
|
function LoadMore({ onVisible }) {
|
|
@@ -5527,10 +3842,239 @@ var targetIconTone = {
|
|
|
5527
3842
|
info: "text-info",
|
|
5528
3843
|
outline: "text-foreground"
|
|
5529
3844
|
};
|
|
5530
|
-
|
|
5531
|
-
|
|
3845
|
+
/** Fundo claro de cada destino do rodapé flutuante, pela cor da ação. */
|
|
3846
|
+
var targetSoft = {
|
|
3847
|
+
neutral: "bg-muted",
|
|
3848
|
+
primary: "bg-primary-soft",
|
|
3849
|
+
success: "bg-success-soft",
|
|
3850
|
+
warning: "bg-warning-soft",
|
|
3851
|
+
error: "bg-destructive-soft",
|
|
3852
|
+
info: "bg-info-soft",
|
|
3853
|
+
outline: "bg-card"
|
|
3854
|
+
};
|
|
3855
|
+
/** Destino realçado (card por cima): fundo forte com o `-foreground` dele em tudo. */
|
|
3856
|
+
var targetStrong = {
|
|
3857
|
+
neutral: "bg-muted text-foreground",
|
|
3858
|
+
primary: "bg-primary text-primary-foreground",
|
|
3859
|
+
success: "bg-success text-success-foreground",
|
|
3860
|
+
warning: "bg-warning text-warning-foreground",
|
|
3861
|
+
error: "bg-destructive text-destructive-foreground",
|
|
3862
|
+
info: "bg-info text-info-foreground",
|
|
3863
|
+
outline: "bg-muted text-foreground"
|
|
3864
|
+
};
|
|
3865
|
+
/**
|
|
3866
|
+
* Situação do card a partir da próxima atividade e da cadência da etapa. Compara por dia de
|
|
3867
|
+
* calendário; `referenceDate` é o "hoje" (injetável para teste).
|
|
3868
|
+
*/
|
|
3869
|
+
function getKanbanCardStatus(card, column, referenceDate) {
|
|
3870
|
+
const daysInColumn = card.enteredColumnAt ? differenceInCalendarDays(referenceDate, card.enteredColumnAt) : null;
|
|
3871
|
+
const cadenceOverdue = column?.cadenceDays !== void 0 && daysInColumn !== null && daysInColumn > column.cadenceDays;
|
|
3872
|
+
const ahead = card.activity ? differenceInCalendarDays(card.activity.at, referenceDate) : null;
|
|
3873
|
+
const activity = ahead === null ? "none" : ahead < 0 ? "late" : ahead === 0 ? "today" : "onTime";
|
|
3874
|
+
return {
|
|
3875
|
+
background: cadenceOverdue && (activity === "late" || activity === "none") ? "critical" : cadenceOverdue ? "cadenceOverdue" : activity === "none" ? "noActivity" : "normal",
|
|
3876
|
+
activity,
|
|
3877
|
+
daysInColumn,
|
|
3878
|
+
daysLate: ahead !== null && ahead < 0 ? -ahead : 0
|
|
3879
|
+
};
|
|
3880
|
+
}
|
|
3881
|
+
/** Classes literais completas (nada de classe montada por string). */
|
|
3882
|
+
var statusBackground = {
|
|
3883
|
+
critical: "bg-critical-soft",
|
|
3884
|
+
cadenceOverdue: "bg-destructive-soft",
|
|
3885
|
+
noActivity: "bg-warning-soft",
|
|
3886
|
+
normal: "bg-card"
|
|
3887
|
+
};
|
|
3888
|
+
var activityIcon = {
|
|
3889
|
+
onTime: {
|
|
3890
|
+
icon: CalendarDays,
|
|
3891
|
+
circle: "bg-info-soft text-info-soft-foreground"
|
|
3892
|
+
},
|
|
3893
|
+
today: {
|
|
3894
|
+
icon: CalendarClock,
|
|
3895
|
+
circle: "bg-warning-mid text-warning-mid-foreground"
|
|
3896
|
+
},
|
|
3897
|
+
late: {
|
|
3898
|
+
icon: CalendarX2,
|
|
3899
|
+
circle: "bg-destructive text-destructive-foreground"
|
|
3900
|
+
},
|
|
3901
|
+
none: {
|
|
3902
|
+
icon: CalendarDays,
|
|
3903
|
+
circle: "border border-dashed border-muted-foreground text-muted-foreground"
|
|
3904
|
+
}
|
|
3905
|
+
};
|
|
3906
|
+
function plural(n, one, many) {
|
|
3907
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
3908
|
+
}
|
|
3909
|
+
function situationText(status) {
|
|
3910
|
+
if (status.activity === "onTime") return "Em dia";
|
|
3911
|
+
if (status.activity === "today") return "Vence hoje";
|
|
3912
|
+
if (status.activity === "late") return `Atrasada há ${plural(status.daysLate, "dia", "dias")}`;
|
|
3913
|
+
return "Sem atividade agendada";
|
|
3914
|
+
}
|
|
3915
|
+
/** Texto para o leitor de tela: a cor do fundo nunca é a única informação. */
|
|
3916
|
+
function backgroundLabel(status) {
|
|
3917
|
+
if (status.background === "critical") return `Situação: crítico, cadência vencida e ${status.activity === "late" ? "atividade atrasada" : "sem próxima atividade"}`;
|
|
3918
|
+
if (status.background === "cadenceOverdue") return "Situação: cadência vencida";
|
|
3919
|
+
if (status.background === "noActivity") return "Situação: sem atividade";
|
|
3920
|
+
return null;
|
|
3921
|
+
}
|
|
3922
|
+
function whenText(at, status) {
|
|
3923
|
+
return status.activity === "today" ? `Hoje às ${format(at, "HH:mm")}` : `${format(at, "dd/MM/yyyy")} às ${format(at, "HH:mm")}`;
|
|
3924
|
+
}
|
|
3925
|
+
var baseFields = [
|
|
3926
|
+
{
|
|
3927
|
+
id: "tags",
|
|
3928
|
+
label: "Tags"
|
|
3929
|
+
},
|
|
3930
|
+
{
|
|
3931
|
+
id: "document",
|
|
3932
|
+
label: "CNPJ ou CPF"
|
|
3933
|
+
},
|
|
3934
|
+
{
|
|
3935
|
+
id: "description",
|
|
3936
|
+
label: "Descrição"
|
|
3937
|
+
},
|
|
3938
|
+
{
|
|
3939
|
+
id: "contact",
|
|
3940
|
+
label: "Contato"
|
|
3941
|
+
},
|
|
3942
|
+
{
|
|
3943
|
+
id: "phone",
|
|
3944
|
+
label: "Telefone"
|
|
3945
|
+
},
|
|
3946
|
+
{
|
|
3947
|
+
id: "email",
|
|
3948
|
+
label: "E-mail"
|
|
3949
|
+
},
|
|
3950
|
+
{
|
|
3951
|
+
id: "activity",
|
|
3952
|
+
label: "Atividade"
|
|
3953
|
+
},
|
|
3954
|
+
{
|
|
3955
|
+
id: "assignee",
|
|
3956
|
+
label: "Responsável"
|
|
3957
|
+
}
|
|
3958
|
+
];
|
|
3959
|
+
/** Lê os campos escondidos; qualquer falha do armazenamento cai no padrão (tudo visível). */
|
|
3960
|
+
function readHidden(storageKey) {
|
|
3961
|
+
if (!storageKey) return {};
|
|
3962
|
+
try {
|
|
3963
|
+
const raw = localStorage.getItem(storageKey);
|
|
3964
|
+
const list = raw ? JSON.parse(raw) : [];
|
|
3965
|
+
return Array.isArray(list) ? Object.fromEntries(list.filter((f) => typeof f === "string").map((f) => [f, true])) : {};
|
|
3966
|
+
} catch {
|
|
3967
|
+
return {};
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
function writeHidden(storageKey, hidden) {
|
|
3971
|
+
if (!storageKey) return;
|
|
3972
|
+
try {
|
|
3973
|
+
localStorage.setItem(storageKey, JSON.stringify(Object.keys(hidden).filter((k) => hidden[k])));
|
|
3974
|
+
} catch {}
|
|
3975
|
+
}
|
|
3976
|
+
var HINT_CLOSE_DELAY = 150;
|
|
3977
|
+
/**
|
|
3978
|
+
* Calendário do card: ícone de situação, data ao lado e hint (tipo, quando, com quem,
|
|
3979
|
+
* responsável e situação). Abre por clique, toque, foco por teclado e mouse; o gatilho é um
|
|
3980
|
+
* botão fora do botão de clique do card.
|
|
3981
|
+
*/
|
|
3982
|
+
function ActivityHint({ card, status }) {
|
|
3983
|
+
const [open, setOpen] = useState(false);
|
|
3984
|
+
const pressed = useRef(false);
|
|
3985
|
+
const holding = useRef(false);
|
|
3986
|
+
const triggerRef = useRef(null);
|
|
3987
|
+
const lastPointer = useRef("");
|
|
3988
|
+
const timer = useRef(void 0);
|
|
3989
|
+
const { icon: Icon, circle } = activityIcon[status.activity];
|
|
3990
|
+
const activity = card.activity;
|
|
3991
|
+
const visible = activity ? status.activity === "today" ? `Hoje ${format(activity.at, "HH:mm")}` : format(activity.at, "dd/MM/yyyy") : "Sem atividade";
|
|
3992
|
+
const cancelClose = () => clearTimeout(timer.current);
|
|
3993
|
+
const scheduleClose = () => {
|
|
3994
|
+
cancelClose();
|
|
3995
|
+
timer.current = setTimeout(() => {
|
|
3996
|
+
if (!holding.current) setOpen(false);
|
|
3997
|
+
}, HINT_CLOSE_DELAY);
|
|
3998
|
+
};
|
|
3999
|
+
useEffect(() => cancelClose, []);
|
|
4000
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
|
4001
|
+
open,
|
|
4002
|
+
onOpenChange: (next) => !next && !holding.current && setOpen(false),
|
|
4003
|
+
children: [/* @__PURE__ */ jsx(PopoverAnchor, {
|
|
4004
|
+
asChild: true,
|
|
4005
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
4006
|
+
ref: triggerRef,
|
|
4007
|
+
type: "button",
|
|
4008
|
+
"aria-haspopup": "dialog",
|
|
4009
|
+
"aria-expanded": open,
|
|
4010
|
+
"aria-label": `${visible}. ${situationText(status)}`,
|
|
4011
|
+
className: "relative z-10 -ml-1 inline-flex cursor-pointer items-center gap-1 rounded-item px-1 tabular-nums outline-none focus-visible:ring-2 focus-visible:ring-ring max-md:min-h-touch",
|
|
4012
|
+
onPointerDown: (e) => {
|
|
4013
|
+
cancelClose();
|
|
4014
|
+
pressed.current = true;
|
|
4015
|
+
holding.current = true;
|
|
4016
|
+
window.addEventListener("pointerup", () => holding.current = false, { once: true });
|
|
4017
|
+
window.addEventListener("pointercancel", () => holding.current = false, { once: true });
|
|
4018
|
+
lastPointer.current = e.pointerType;
|
|
4019
|
+
},
|
|
4020
|
+
onPointerEnter: (e) => {
|
|
4021
|
+
if (e.pointerType !== "mouse") return;
|
|
4022
|
+
cancelClose();
|
|
4023
|
+
setOpen(true);
|
|
4024
|
+
},
|
|
4025
|
+
onPointerLeave: (e) => e.pointerType === "mouse" && scheduleClose(),
|
|
4026
|
+
onFocus: () => {
|
|
4027
|
+
if (!pressed.current) setOpen(true);
|
|
4028
|
+
},
|
|
4029
|
+
onBlur: () => {
|
|
4030
|
+
pressed.current = false;
|
|
4031
|
+
if (!holding.current) setOpen(false);
|
|
4032
|
+
},
|
|
4033
|
+
onClick: (e) => {
|
|
4034
|
+
e.preventDefault();
|
|
4035
|
+
e.stopPropagation();
|
|
4036
|
+
pressed.current = false;
|
|
4037
|
+
const byMouse = lastPointer.current === "mouse";
|
|
4038
|
+
lastPointer.current = "";
|
|
4039
|
+
setOpen((o) => byMouse || !o);
|
|
4040
|
+
},
|
|
4041
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4042
|
+
"aria-hidden": true,
|
|
4043
|
+
className: cn("flex size-6 shrink-0 items-center justify-center rounded-full", circle),
|
|
4044
|
+
children: /* @__PURE__ */ jsx(Icon, { className: "size-3" })
|
|
4045
|
+
}), visible]
|
|
4046
|
+
})
|
|
4047
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
4048
|
+
width: "sm",
|
|
4049
|
+
align: "start",
|
|
4050
|
+
className: "flex flex-col gap-1 p-3 text-xs",
|
|
4051
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
4052
|
+
onInteractOutside: (e) => {
|
|
4053
|
+
if (triggerRef.current?.contains(e.target)) e.preventDefault();
|
|
4054
|
+
},
|
|
4055
|
+
onPointerEnter: cancelClose,
|
|
4056
|
+
onPointerLeave: scheduleClose,
|
|
4057
|
+
children: [
|
|
4058
|
+
activity ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("p", {
|
|
4059
|
+
className: "text-sm font-medium",
|
|
4060
|
+
children: [
|
|
4061
|
+
activity.type,
|
|
4062
|
+
" · ",
|
|
4063
|
+
whenText(activity.at, status)
|
|
4064
|
+
]
|
|
4065
|
+
}), activity.with && /* @__PURE__ */ jsxs("p", { children: ["Com: ", activity.with] })] }) : null,
|
|
4066
|
+
card.assignee && /* @__PURE__ */ jsxs("p", { children: ["Responsável: ", card.assignee] }),
|
|
4067
|
+
/* @__PURE__ */ jsx("p", {
|
|
4068
|
+
className: "font-medium",
|
|
4069
|
+
children: situationText(status)
|
|
4070
|
+
})
|
|
4071
|
+
]
|
|
4072
|
+
})]
|
|
4073
|
+
});
|
|
4074
|
+
}
|
|
4075
|
+
function CardBody({ card, show, withHandle }) {
|
|
5532
4076
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
5533
|
-
card.tags && card.tags.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
4077
|
+
show("tags") && card.tags && card.tags.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
5534
4078
|
className: "flex flex-wrap gap-1",
|
|
5535
4079
|
children: card.tags.map((t) => /* @__PURE__ */ jsx(Badge, {
|
|
5536
4080
|
tone: t.tone ?? "neutral",
|
|
@@ -5542,19 +4086,19 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
|
|
|
5542
4086
|
children: [/* @__PURE__ */ jsx("span", {
|
|
5543
4087
|
className: "line-clamp-2 text-sm font-medium",
|
|
5544
4088
|
children: card.title
|
|
5545
|
-
}), card.subtitle && /* @__PURE__ */ jsx("span", {
|
|
4089
|
+
}), show("document") && card.subtitle && /* @__PURE__ */ jsx("span", {
|
|
5546
4090
|
className: "text-xs text-muted-foreground tabular-nums",
|
|
5547
4091
|
children: card.subtitle
|
|
5548
4092
|
})]
|
|
5549
4093
|
}),
|
|
5550
|
-
card.description && /* @__PURE__ */ jsx("span", {
|
|
4094
|
+
show("description") && card.description && /* @__PURE__ */ jsx("span", {
|
|
5551
4095
|
className: "line-clamp-2 text-xs text-muted-foreground",
|
|
5552
4096
|
children: card.description
|
|
5553
4097
|
}),
|
|
5554
4098
|
card.contact && /* @__PURE__ */ jsxs("span", {
|
|
5555
4099
|
className: "flex flex-col gap-1 text-xs text-muted-foreground",
|
|
5556
4100
|
children: [
|
|
5557
|
-
card.contact.name && /* @__PURE__ */ jsxs("span", {
|
|
4101
|
+
show("contact") && card.contact.name && /* @__PURE__ */ jsxs("span", {
|
|
5558
4102
|
className: "flex min-w-0 items-center gap-1 text-foreground",
|
|
5559
4103
|
children: [/* @__PURE__ */ jsx(User, {
|
|
5560
4104
|
className: "size-3 shrink-0",
|
|
@@ -5564,7 +4108,7 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
|
|
|
5564
4108
|
children: card.contact.name
|
|
5565
4109
|
})]
|
|
5566
4110
|
}),
|
|
5567
|
-
card.contact.phone && /* @__PURE__ */ jsxs("span", {
|
|
4111
|
+
show("phone") && card.contact.phone && /* @__PURE__ */ jsxs("span", {
|
|
5568
4112
|
className: "flex min-w-0 items-center gap-1 tabular-nums",
|
|
5569
4113
|
children: [/* @__PURE__ */ jsx(Phone, {
|
|
5570
4114
|
className: "size-3 shrink-0",
|
|
@@ -5574,7 +4118,7 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
|
|
|
5574
4118
|
children: card.contact.phone
|
|
5575
4119
|
})]
|
|
5576
4120
|
}),
|
|
5577
|
-
card.contact.email && /* @__PURE__ */ jsxs("span", {
|
|
4121
|
+
show("email") && card.contact.email && /* @__PURE__ */ jsxs("span", {
|
|
5578
4122
|
className: "flex min-w-0 items-center gap-1",
|
|
5579
4123
|
children: [/* @__PURE__ */ jsx(Mail, {
|
|
5580
4124
|
className: "size-3 shrink-0",
|
|
@@ -5585,50 +4129,96 @@ function CardBody({ card, valueFields = [], formatValue, withHandle }) {
|
|
|
5585
4129
|
})]
|
|
5586
4130
|
})
|
|
5587
4131
|
]
|
|
5588
|
-
}),
|
|
5589
|
-
shown.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
5590
|
-
className: "grid grid-cols-2 divide-x rounded-block bg-muted text-xs",
|
|
5591
|
-
children: shown.map((f) => /* @__PURE__ */ jsxs("span", {
|
|
5592
|
-
className: "flex min-w-0 flex-col px-2 py-1",
|
|
5593
|
-
children: [/* @__PURE__ */ jsxs("span", {
|
|
5594
|
-
className: "text-muted-foreground",
|
|
5595
|
-
children: [f.label, ":"]
|
|
5596
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
5597
|
-
className: "truncate font-semibold text-foreground tabular-nums",
|
|
5598
|
-
children: formatValue(card.values?.[f.key] ?? 0)
|
|
5599
|
-
})]
|
|
5600
|
-
}, f.key))
|
|
5601
|
-
}),
|
|
5602
|
-
(card.assignee || card.dueDate || card.meta) && /* @__PURE__ */ jsxs("span", {
|
|
5603
|
-
className: "flex items-center gap-2 border-t pt-2 text-xs text-muted-foreground",
|
|
5604
|
-
children: [
|
|
5605
|
-
card.dueDate && /* @__PURE__ */ jsxs("span", {
|
|
5606
|
-
className: "inline-flex items-center gap-1 tabular-nums",
|
|
5607
|
-
children: [/* @__PURE__ */ jsx(CalendarDays, {
|
|
5608
|
-
className: "size-3",
|
|
5609
|
-
"aria-hidden": true
|
|
5610
|
-
}), format(card.dueDate, "dd/MM/yyyy")]
|
|
5611
|
-
}),
|
|
5612
|
-
card.meta && /* @__PURE__ */ jsx("span", {
|
|
5613
|
-
className: "font-medium text-foreground tabular-nums",
|
|
5614
|
-
children: card.meta
|
|
5615
|
-
}),
|
|
5616
|
-
card.assignee && /* @__PURE__ */ jsx("span", {
|
|
5617
|
-
className: "ml-auto",
|
|
5618
|
-
title: card.assignee,
|
|
5619
|
-
children: /* @__PURE__ */ jsx(Avatar, {
|
|
5620
|
-
name: card.assignee,
|
|
5621
|
-
size: "sm"
|
|
5622
|
-
})
|
|
5623
|
-
})
|
|
5624
|
-
]
|
|
5625
4132
|
})
|
|
5626
4133
|
] });
|
|
5627
4134
|
}
|
|
4135
|
+
/**
|
|
4136
|
+
* Rodapé do card, fora do botão de clique: linha de calendário, meta e responsável e, depois
|
|
4137
|
+
* de uma divisória, os valores empilhados. Sem `renderCard` apenas.
|
|
4138
|
+
*/
|
|
4139
|
+
function cardFooter({ card, status, show, valueFields, formatValue }) {
|
|
4140
|
+
const calendar = show("activity") ? status ? /* @__PURE__ */ jsx(ActivityHint, {
|
|
4141
|
+
card,
|
|
4142
|
+
status
|
|
4143
|
+
}) : card.dueDate && /* @__PURE__ */ jsxs("span", {
|
|
4144
|
+
className: "inline-flex items-center gap-1 tabular-nums",
|
|
4145
|
+
children: [/* @__PURE__ */ jsx(CalendarDays, {
|
|
4146
|
+
className: "size-3",
|
|
4147
|
+
"aria-hidden": true
|
|
4148
|
+
}), format(card.dueDate, "dd/MM/yyyy")]
|
|
4149
|
+
}) : null;
|
|
4150
|
+
const assignee = show("assignee") ? card.assignee : void 0;
|
|
4151
|
+
const values = valueFields.slice(0, 2).filter((f) => show(`value:${f.key}`));
|
|
4152
|
+
const hasRow = Boolean(calendar || assignee || card.meta);
|
|
4153
|
+
if (!hasRow && values.length === 0) return null;
|
|
4154
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [hasRow && /* @__PURE__ */ jsxs("span", {
|
|
4155
|
+
className: "flex items-center gap-2 border-t pt-2 text-xs text-muted-foreground",
|
|
4156
|
+
children: [
|
|
4157
|
+
calendar,
|
|
4158
|
+
card.meta && /* @__PURE__ */ jsx("span", {
|
|
4159
|
+
className: "font-medium text-foreground tabular-nums",
|
|
4160
|
+
children: card.meta
|
|
4161
|
+
}),
|
|
4162
|
+
assignee && /* @__PURE__ */ jsx("span", {
|
|
4163
|
+
className: "ml-auto",
|
|
4164
|
+
title: assignee,
|
|
4165
|
+
children: /* @__PURE__ */ jsx(Avatar, {
|
|
4166
|
+
name: assignee,
|
|
4167
|
+
size: "sm"
|
|
4168
|
+
})
|
|
4169
|
+
})
|
|
4170
|
+
]
|
|
4171
|
+
}), values.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
4172
|
+
className: "flex flex-col gap-1 border-t pt-2 text-xs",
|
|
4173
|
+
children: values.map((f) => /* @__PURE__ */ jsxs("span", {
|
|
4174
|
+
className: "flex items-baseline justify-between gap-2",
|
|
4175
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
4176
|
+
className: "text-muted-foreground",
|
|
4177
|
+
children: [f.label, ":"]
|
|
4178
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
4179
|
+
className: "truncate font-semibold text-foreground tabular-nums",
|
|
4180
|
+
children: formatValue(card.values?.[f.key] ?? 0)
|
|
4181
|
+
})]
|
|
4182
|
+
}, f.key))
|
|
4183
|
+
})] });
|
|
4184
|
+
}
|
|
4185
|
+
/** Sem acento e sem diferença de maiúscula, para a busca. */
|
|
4186
|
+
function normalize(text) {
|
|
4187
|
+
const marks = new RegExp(`[${String.fromCharCode(768)}-${String.fromCharCode(879)}]`, "g");
|
|
4188
|
+
return text.normalize("NFD").replace(marks, "").toLowerCase();
|
|
4189
|
+
}
|
|
4190
|
+
/**
|
|
4191
|
+
* Posição, na lista completa da coluna, de um índice da lista desenhada (que pode ser só uma
|
|
4192
|
+
* parte dela, por busca, filtro ou paginação). Fim da lista desenhada = logo depois do último
|
|
4193
|
+
* card desenhado; sem card desenhado = fim da lista completa.
|
|
4194
|
+
*/
|
|
4195
|
+
function toFullIndex(full, drawn, drawnIndex) {
|
|
4196
|
+
if (drawn.length === 0) return full.length;
|
|
4197
|
+
if (drawnIndex < drawn.length) return full.indexOf(drawn[drawnIndex]);
|
|
4198
|
+
return full.indexOf(drawn[drawn.length - 1]) + 1;
|
|
4199
|
+
}
|
|
4200
|
+
var situationOptions = [
|
|
4201
|
+
{
|
|
4202
|
+
value: "critical",
|
|
4203
|
+
label: "Crítico"
|
|
4204
|
+
},
|
|
4205
|
+
{
|
|
4206
|
+
value: "cadenceOverdue",
|
|
4207
|
+
label: "Cadência vencida"
|
|
4208
|
+
},
|
|
4209
|
+
{
|
|
4210
|
+
value: "noActivity",
|
|
4211
|
+
label: "Sem atividade"
|
|
4212
|
+
},
|
|
4213
|
+
{
|
|
4214
|
+
value: "late",
|
|
4215
|
+
label: "Atividade atrasada"
|
|
4216
|
+
}
|
|
4217
|
+
];
|
|
5628
4218
|
function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard, valueFields, formatValue = (n) => n.toLocaleString("pt-BR", {
|
|
5629
4219
|
style: "currency",
|
|
5630
4220
|
currency: "BRL"
|
|
5631
|
-
}), pageSize = 20, visibleColumns = 5, onLoadMore, hasMore, dropTargets, onDropTarget, className, ...aria }) {
|
|
4221
|
+
}), pageSize = 20, visibleColumns = 5, onLoadMore, hasMore, dropTargets, onDropTarget, referenceDate, toolbar, onNewCard, storageKey, className, ...aria }) {
|
|
5632
4222
|
const code = resolveCatalogCode("Kanban", { hasDropTargets: Boolean(dropTargets?.length) });
|
|
5633
4223
|
const { isMobile } = useBreakpoint();
|
|
5634
4224
|
const motion = useMotionMode();
|
|
@@ -5653,18 +4243,66 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
5653
4243
|
const [active, setActive] = useState(columns[0]?.id ?? "");
|
|
5654
4244
|
const [dragging, setDragging] = useState(null);
|
|
5655
4245
|
const [over, setOver] = useState(null);
|
|
4246
|
+
const [overTarget, setOverTarget] = useState(null);
|
|
5656
4247
|
const [touchDrag, setTouchDrag] = useState(null);
|
|
4248
|
+
const [pendingDrop, setPendingDrop] = useState(null);
|
|
4249
|
+
const [reason, setReason] = useState("");
|
|
4250
|
+
const [query, setQuery] = useState("");
|
|
4251
|
+
const [assigneeFilter, setAssigneeFilter] = useState(null);
|
|
4252
|
+
const [situationFilter, setSituationFilter] = useState(null);
|
|
4253
|
+
const [customizing, setCustomizing] = useState(false);
|
|
4254
|
+
const [hidden, setHidden] = useState(() => readHidden(storageKey));
|
|
4255
|
+
const changeHidden = (next) => {
|
|
4256
|
+
setHidden(next);
|
|
4257
|
+
writeHidden(storageKey, next);
|
|
4258
|
+
};
|
|
4259
|
+
const show = (field) => !hidden[field];
|
|
4260
|
+
const today = referenceDate ?? /* @__PURE__ */ new Date();
|
|
4261
|
+
const statusEnabled = columns.some((c) => c.cadenceDays !== void 0) || cards.some((c) => c.activity);
|
|
4262
|
+
const statusOf = (card) => statusEnabled ? getKanbanCardStatus(card, columns.find((c) => c.id === card.columnId), today) : null;
|
|
4263
|
+
const filtering = toolbar && (query.trim() !== "" || assigneeFilter || situationFilter);
|
|
4264
|
+
const matches = (card) => {
|
|
4265
|
+
const q = normalize(query.trim());
|
|
4266
|
+
if (q && ![
|
|
4267
|
+
card.title,
|
|
4268
|
+
card.subtitle,
|
|
4269
|
+
card.contact?.name
|
|
4270
|
+
].some((t) => t && normalize(t).includes(q))) return false;
|
|
4271
|
+
if (assigneeFilter && card.assignee !== assigneeFilter) return false;
|
|
4272
|
+
if (situationFilter) {
|
|
4273
|
+
const status = statusOf(card);
|
|
4274
|
+
if (!status) return false;
|
|
4275
|
+
if (situationFilter === "late" ? status.activity !== "late" : status.background !== situationFilter) return false;
|
|
4276
|
+
}
|
|
4277
|
+
return true;
|
|
4278
|
+
};
|
|
4279
|
+
const visibleCards = filtering ? cards.filter(matches) : cards;
|
|
4280
|
+
/** Lista completa da coluna: a única fonte do índice que sai em `onCardMove`. */
|
|
5657
4281
|
const inColumn = (id) => cards.filter((c) => c.columnId === id);
|
|
4282
|
+
/** Lista visível (busca e filtros): cards desenhados, contagem, totais, paginação e abas. */
|
|
4283
|
+
const visibleInColumn = (id) => visibleCards.filter((c) => c.columnId === id);
|
|
5658
4284
|
const drop = (columnId, index) => {
|
|
5659
|
-
if (dragging)
|
|
4285
|
+
if (dragging) {
|
|
4286
|
+
const drawn = visibleInColumn(columnId).slice(0, limitOf(columnId));
|
|
4287
|
+
onCardMove?.(dragging, columnId, toFullIndex(inColumn(columnId), drawn, index));
|
|
4288
|
+
}
|
|
5660
4289
|
setDragging(null);
|
|
5661
4290
|
setOver(null);
|
|
4291
|
+
setOverTarget(null);
|
|
5662
4292
|
};
|
|
5663
4293
|
const draggingCardId = dragging ?? touchDrag?.cardId ?? null;
|
|
5664
4294
|
const showTargetBar = Boolean(dropTargets?.length) && draggingCardId !== null;
|
|
5665
4295
|
const dropOnTarget = (cardId, targetId) => {
|
|
5666
4296
|
const target = dropTargets?.find((t) => t.id === targetId);
|
|
5667
4297
|
if (!target || target.disabled) return;
|
|
4298
|
+
if (target.confirm) {
|
|
4299
|
+
setReason(target.confirm.reasons?.[0]?.value ?? "");
|
|
4300
|
+
setPendingDrop({
|
|
4301
|
+
cardId,
|
|
4302
|
+
targetId
|
|
4303
|
+
});
|
|
4304
|
+
return;
|
|
4305
|
+
}
|
|
5668
4306
|
onDropTarget?.(cardId, targetId);
|
|
5669
4307
|
};
|
|
5670
4308
|
const startTouchDrag = (card, e) => {
|
|
@@ -5742,43 +4380,60 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
5742
4380
|
]
|
|
5743
4381
|
})] });
|
|
5744
4382
|
};
|
|
5745
|
-
/**
|
|
4383
|
+
/** Rodapé flutuante de destinos, mostrado durante o arraste (mouse ou toque). */
|
|
4384
|
+
const highlightedTarget = overTarget ?? touchDrag?.overTargetId ?? null;
|
|
5746
4385
|
const targetBar = showTargetBar && /* @__PURE__ */ jsx("div", {
|
|
5747
4386
|
"aria-label": "Soltar em",
|
|
5748
|
-
className: "fixed inset-x-4 bottom-4 z-30
|
|
5749
|
-
children: dropTargets.map((t) =>
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
}
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
}
|
|
5776
|
-
t.disabled
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
4387
|
+
className: "fixed inset-x-4 bottom-4 z-30 grid grid-cols-2 gap-2 rounded-surface border bg-card p-2 shadow-lg md:flex md:justify-center md:overflow-x-auto",
|
|
4388
|
+
children: dropTargets.map((t) => {
|
|
4389
|
+
const tone = t.tone ?? "neutral";
|
|
4390
|
+
const highlighted = !t.disabled && highlightedTarget === t.id;
|
|
4391
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4392
|
+
"data-kanban-target": t.id,
|
|
4393
|
+
"data-over": highlighted ? "true" : void 0,
|
|
4394
|
+
onDragEnter: () => {
|
|
4395
|
+
if (dragging && !t.disabled) setOverTarget(t.id);
|
|
4396
|
+
},
|
|
4397
|
+
onDragOver: (e) => {
|
|
4398
|
+
if (dragging && !t.disabled) {
|
|
4399
|
+
e.preventDefault();
|
|
4400
|
+
setOverTarget(t.id);
|
|
4401
|
+
}
|
|
4402
|
+
},
|
|
4403
|
+
onDragLeave: (e) => {
|
|
4404
|
+
if (e.relatedTarget instanceof Node && e.currentTarget.contains(e.relatedTarget)) return;
|
|
4405
|
+
setOverTarget((id) => id === t.id ? null : id);
|
|
4406
|
+
},
|
|
4407
|
+
onDrop: (e) => {
|
|
4408
|
+
e.preventDefault();
|
|
4409
|
+
setOverTarget(null);
|
|
4410
|
+
if (dragging) {
|
|
4411
|
+
dropOnTarget(dragging, t.id);
|
|
4412
|
+
setDragging(null);
|
|
4413
|
+
}
|
|
4414
|
+
},
|
|
4415
|
+
className: cn("flex min-w-24 flex-col items-center gap-1 rounded-block border p-2 text-center text-xs transition-colors", t.disabled ? "cursor-not-allowed bg-muted opacity-50" : highlighted ? cn(targetStrong[tone], "ring-2 ring-ring") : targetSoft[tone]),
|
|
4416
|
+
children: [
|
|
4417
|
+
t.icon && /* @__PURE__ */ jsx("span", {
|
|
4418
|
+
"aria-hidden": true,
|
|
4419
|
+
className: highlighted ? void 0 : targetIconTone[tone],
|
|
4420
|
+
children: t.icon
|
|
4421
|
+
}),
|
|
4422
|
+
/* @__PURE__ */ jsx("span", {
|
|
4423
|
+
className: "font-medium",
|
|
4424
|
+
children: t.label
|
|
4425
|
+
}),
|
|
4426
|
+
t.hint && !t.disabled && /* @__PURE__ */ jsx("span", {
|
|
4427
|
+
className: highlighted ? void 0 : "text-muted-foreground",
|
|
4428
|
+
children: t.hint
|
|
4429
|
+
}),
|
|
4430
|
+
t.disabled && t.disabledReason && /* @__PURE__ */ jsx("span", {
|
|
4431
|
+
className: "text-muted-foreground",
|
|
4432
|
+
children: t.disabledReason
|
|
4433
|
+
})
|
|
4434
|
+
]
|
|
4435
|
+
}, t.id);
|
|
4436
|
+
})
|
|
5782
4437
|
});
|
|
5783
4438
|
const canTouchDrag = Boolean(onCardMove) || Boolean(dropTargets?.length && onDropTarget);
|
|
5784
4439
|
const showHandle = isMobile && canTouchDrag;
|
|
@@ -5792,7 +4447,10 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
5792
4447
|
const dragEnd = () => {
|
|
5793
4448
|
setDragging(null);
|
|
5794
4449
|
setOver(null);
|
|
4450
|
+
setOverTarget(null);
|
|
5795
4451
|
};
|
|
4452
|
+
const status = statusOf(card);
|
|
4453
|
+
const label = status && backgroundLabel(status);
|
|
5796
4454
|
const common = {
|
|
5797
4455
|
"data-kanban-card": card.id,
|
|
5798
4456
|
draggable: !isMobile && Boolean(onCardMove),
|
|
@@ -5812,27 +4470,37 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
5812
4470
|
e.stopPropagation();
|
|
5813
4471
|
if (over) drop(over.column, over.index);
|
|
5814
4472
|
},
|
|
5815
|
-
className: cn("relative flex rounded-block border bg-card p-3 shadow-sm transition-[box-shadow,opacity]", !isMobile && onCardMove && "cursor-grab active:cursor-grabbing", (dragging === card.id || touchDrag?.cardId === card.id) && "opacity-50", over?.column === card.columnId && over.index === index && dragging !== card.id && "ring-2 ring-ring ring-offset-2 ring-offset-muted")
|
|
4473
|
+
className: cn("relative flex rounded-block border", status ? statusBackground[status.background] : "bg-card", "p-3 shadow-sm transition-[box-shadow,opacity]", !isMobile && onCardMove && "cursor-grab active:cursor-grabbing", (dragging === card.id || touchDrag?.cardId === card.id) && "opacity-50", over?.column === card.columnId && over.index === index && dragging !== card.id && "ring-2 ring-ring ring-offset-2 ring-offset-muted")
|
|
5816
4474
|
};
|
|
4475
|
+
const content = renderCard ? renderCard(card) : /* @__PURE__ */ jsx(CardBody, {
|
|
4476
|
+
card,
|
|
4477
|
+
show,
|
|
4478
|
+
withHandle: showHandle
|
|
4479
|
+
});
|
|
4480
|
+
const footer = renderCard ? null : cardFooter({
|
|
4481
|
+
card,
|
|
4482
|
+
status,
|
|
4483
|
+
show,
|
|
4484
|
+
valueFields: valueFields ?? [],
|
|
4485
|
+
formatValue
|
|
4486
|
+
});
|
|
4487
|
+
const main = onCardClick ? /* @__PURE__ */ jsx("button", {
|
|
4488
|
+
type: "button",
|
|
4489
|
+
onClick: () => onCardClick(card),
|
|
4490
|
+
className: footer ? "flex min-w-0 cursor-pointer flex-col gap-2 rounded-block text-left outline-none after:absolute after:inset-0 focus-visible:ring-2 focus-visible:ring-ring" : "flex min-w-0 flex-1 cursor-pointer flex-col gap-2 rounded-block text-left outline-none after:absolute after:inset-0 focus-visible:ring-2 focus-visible:ring-ring",
|
|
4491
|
+
children: content
|
|
4492
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
4493
|
+
className: footer ? "flex min-w-0 flex-col gap-2" : "flex min-w-0 flex-1 flex-col gap-2",
|
|
4494
|
+
children: content
|
|
4495
|
+
});
|
|
5817
4496
|
const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
5818
|
-
|
|
5819
|
-
type: "button",
|
|
5820
|
-
onClick: () => onCardClick(card),
|
|
5821
|
-
className: "flex min-w-0 flex-1 cursor-pointer flex-col gap-2 rounded-block text-left outline-none after:absolute after:inset-0 focus-visible:ring-2 focus-visible:ring-ring",
|
|
5822
|
-
children: renderCard ? renderCard(card) : /* @__PURE__ */ jsx(CardBody, {
|
|
5823
|
-
card,
|
|
5824
|
-
valueFields,
|
|
5825
|
-
formatValue,
|
|
5826
|
-
withHandle: showHandle
|
|
5827
|
-
})
|
|
5828
|
-
}) : /* @__PURE__ */ jsx("div", {
|
|
4497
|
+
footer ? /* @__PURE__ */ jsxs("div", {
|
|
5829
4498
|
className: "flex min-w-0 flex-1 flex-col gap-2",
|
|
5830
|
-
children:
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
})
|
|
4499
|
+
children: [main, footer]
|
|
4500
|
+
}) : main,
|
|
4501
|
+
label && /* @__PURE__ */ jsx("span", {
|
|
4502
|
+
className: "sr-only",
|
|
4503
|
+
children: label
|
|
5836
4504
|
}),
|
|
5837
4505
|
showHandle && /* @__PURE__ */ jsx("button", {
|
|
5838
4506
|
type: "button",
|
|
@@ -5880,53 +4548,79 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
5880
4548
|
children: body
|
|
5881
4549
|
}, card.id);
|
|
5882
4550
|
};
|
|
5883
|
-
const
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
4551
|
+
const totalFields = (valueFields ?? []).slice(0, 2);
|
|
4552
|
+
const sumOf = (list, key) => list.reduce((sum, c) => sum + (c.values?.[key] ?? 0), 0);
|
|
4553
|
+
const boardCards = visibleCards.filter((c) => columns.some((col) => col.id === c.columnId));
|
|
4554
|
+
const totals = (col) => totalFields.map((f) => {
|
|
4555
|
+
const total = sumOf(visibleInColumn(col.id), f.key);
|
|
4556
|
+
const board = sumOf(boardCards, f.key);
|
|
4557
|
+
return {
|
|
4558
|
+
...f,
|
|
4559
|
+
total,
|
|
4560
|
+
percent: board === 0 ? 0 : Math.round(total / board * 100)
|
|
4561
|
+
};
|
|
4562
|
+
});
|
|
5887
4563
|
const columnHeader = (col, count) => /* @__PURE__ */ jsxs("div", {
|
|
5888
4564
|
className: "flex flex-col gap-2 px-1",
|
|
5889
|
-
children: [
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
"
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
className: "
|
|
5918
|
-
children: [
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
4565
|
+
children: [
|
|
4566
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4567
|
+
className: "flex items-center gap-2",
|
|
4568
|
+
children: [
|
|
4569
|
+
/* @__PURE__ */ jsx("span", {
|
|
4570
|
+
"aria-hidden": true,
|
|
4571
|
+
className: cn("size-2 rounded-full", dotTone[col.tone ?? "neutral"])
|
|
4572
|
+
}),
|
|
4573
|
+
/* @__PURE__ */ jsx("h3", {
|
|
4574
|
+
className: "min-w-0 flex-1 truncate text-sm font-semibold",
|
|
4575
|
+
children: col.title
|
|
4576
|
+
}),
|
|
4577
|
+
/* @__PURE__ */ jsx(Badge, {
|
|
4578
|
+
tone: col.limit && count > col.limit ? "warning" : "neutral",
|
|
4579
|
+
children: col.limit ? `${count}/${col.limit}` : count
|
|
4580
|
+
}),
|
|
4581
|
+
onAddCard && /* @__PURE__ */ jsx(Button, {
|
|
4582
|
+
variant: "ghost",
|
|
4583
|
+
size: "sm",
|
|
4584
|
+
iconOnly: true,
|
|
4585
|
+
"aria-label": `Adicionar card em ${col.title}`,
|
|
4586
|
+
onClick: () => onAddCard(col.id),
|
|
4587
|
+
className: "-my-1 -mr-1 rounded-full",
|
|
4588
|
+
children: /* @__PURE__ */ jsx(Plus, {})
|
|
4589
|
+
})
|
|
4590
|
+
]
|
|
4591
|
+
}),
|
|
4592
|
+
col.cadenceDays !== void 0 && /* @__PURE__ */ jsxs("p", {
|
|
4593
|
+
className: "text-xs text-muted-foreground",
|
|
4594
|
+
children: ["Cadência: ", plural(col.cadenceDays, "dia", "dias")]
|
|
4595
|
+
}),
|
|
4596
|
+
valueFields && valueFields.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
4597
|
+
className: "grid grid-cols-2 divide-x rounded-block bg-card text-xs",
|
|
4598
|
+
children: totals(col).map((t) => /* @__PURE__ */ jsxs("span", {
|
|
4599
|
+
className: "flex min-w-0 flex-col px-2 py-1",
|
|
4600
|
+
children: [
|
|
4601
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4602
|
+
className: "text-muted-foreground",
|
|
4603
|
+
children: ["Total ", t.label]
|
|
4604
|
+
}),
|
|
4605
|
+
/* @__PURE__ */ jsx("span", {
|
|
4606
|
+
className: "truncate font-semibold tabular-nums",
|
|
4607
|
+
children: formatValue(t.total)
|
|
4608
|
+
}),
|
|
4609
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4610
|
+
className: "text-muted-foreground tabular-nums",
|
|
4611
|
+
children: [
|
|
4612
|
+
"(",
|
|
4613
|
+
t.percent,
|
|
4614
|
+
"%)"
|
|
4615
|
+
]
|
|
4616
|
+
})
|
|
4617
|
+
]
|
|
4618
|
+
}, t.key))
|
|
4619
|
+
})
|
|
4620
|
+
]
|
|
5927
4621
|
});
|
|
5928
4622
|
const columnList = (col) => {
|
|
5929
|
-
const all =
|
|
4623
|
+
const all = visibleInColumn(col.id);
|
|
5930
4624
|
const list = all.slice(0, limitOf(col.id));
|
|
5931
4625
|
const more = all.length > list.length || Boolean(hasMore?.(col.id));
|
|
5932
4626
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -5964,32 +4658,213 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
5964
4658
|
}, String(ready))
|
|
5965
4659
|
});
|
|
5966
4660
|
};
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
4661
|
+
const assignees = [...new Set(cards.map((c) => c.assignee).filter((a) => !!a))].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
4662
|
+
const filterCount = (assigneeFilter ? 1 : 0) + (situationFilter ? 1 : 0);
|
|
4663
|
+
const hasFilters = assignees.length > 0 || statusEnabled;
|
|
4664
|
+
const toolbarNode = toolbar && /* @__PURE__ */ jsx(DataToolbar, {
|
|
4665
|
+
search: {
|
|
4666
|
+
value: query,
|
|
4667
|
+
onChange: setQuery,
|
|
4668
|
+
placeholder: "Buscar card"
|
|
4669
|
+
},
|
|
4670
|
+
filters: hasFilters ? /* @__PURE__ */ jsxs("div", {
|
|
4671
|
+
className: "flex flex-col gap-4",
|
|
4672
|
+
children: [assignees.length > 0 && /* @__PURE__ */ jsx(Field, {
|
|
4673
|
+
label: "Responsável",
|
|
4674
|
+
span: "full",
|
|
4675
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
4676
|
+
placeholder: "Todos",
|
|
4677
|
+
clearable: true,
|
|
4678
|
+
options: assignees.map((a) => ({
|
|
4679
|
+
value: a,
|
|
4680
|
+
label: a
|
|
4681
|
+
})),
|
|
4682
|
+
value: assigneeFilter,
|
|
4683
|
+
onChange: setAssigneeFilter
|
|
4684
|
+
})
|
|
4685
|
+
}), statusEnabled && /* @__PURE__ */ jsx(Field, {
|
|
4686
|
+
label: "Situação",
|
|
4687
|
+
span: "full",
|
|
4688
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
4689
|
+
placeholder: "Todas",
|
|
4690
|
+
clearable: true,
|
|
4691
|
+
options: situationOptions,
|
|
4692
|
+
value: situationFilter,
|
|
4693
|
+
onChange: setSituationFilter
|
|
4694
|
+
})
|
|
4695
|
+
})]
|
|
4696
|
+
}) : void 0,
|
|
4697
|
+
filterCount,
|
|
4698
|
+
onClearFilters: () => {
|
|
4699
|
+
setAssigneeFilter(null);
|
|
4700
|
+
setSituationFilter(null);
|
|
4701
|
+
},
|
|
4702
|
+
summary: totalFields.length > 0 ? totalFields.map((f) => /* @__PURE__ */ jsxs("span", {
|
|
4703
|
+
className: "flex items-baseline gap-1",
|
|
4704
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
4705
|
+
className: "text-muted-foreground",
|
|
4706
|
+
children: [
|
|
4707
|
+
"Total ",
|
|
4708
|
+
f.label,
|
|
4709
|
+
":"
|
|
4710
|
+
]
|
|
4711
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
4712
|
+
className: "font-semibold tabular-nums",
|
|
4713
|
+
children: formatValue(sumOf(boardCards, f.key))
|
|
4714
|
+
})]
|
|
4715
|
+
}, f.key)) : void 0,
|
|
4716
|
+
actions: /* @__PURE__ */ jsx(Button, {
|
|
4717
|
+
variant: "outline",
|
|
4718
|
+
icon: /* @__PURE__ */ jsx(Settings2, {}),
|
|
4719
|
+
onClick: () => setCustomizing(true),
|
|
4720
|
+
children: "Customizar"
|
|
4721
|
+
}),
|
|
4722
|
+
primaryAction: onNewCard ? /* @__PURE__ */ jsx(Button, {
|
|
4723
|
+
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
4724
|
+
onClick: () => onNewCard(),
|
|
4725
|
+
children: "Novo card"
|
|
4726
|
+
}) : void 0
|
|
4727
|
+
});
|
|
4728
|
+
const customizeFields = [...baseFields.map((f) => ({
|
|
4729
|
+
id: f.id,
|
|
4730
|
+
label: f.label
|
|
4731
|
+
})), ...totalFields.map((f) => ({
|
|
4732
|
+
id: `value:${f.key}`,
|
|
4733
|
+
label: f.label
|
|
4734
|
+
}))];
|
|
4735
|
+
const customizeDrawer = toolbar && /* @__PURE__ */ jsx(Drawer, {
|
|
4736
|
+
open: customizing,
|
|
4737
|
+
onOpenChange: setCustomizing,
|
|
4738
|
+
title: "Customizar",
|
|
4739
|
+
icon: /* @__PURE__ */ jsx(Settings2, {}),
|
|
4740
|
+
footer: /* @__PURE__ */ jsx(ActionBar, {
|
|
4741
|
+
cancel: {
|
|
4742
|
+
label: "Restaurar",
|
|
4743
|
+
onClick: () => changeHidden({})
|
|
4744
|
+
},
|
|
4745
|
+
primary: {
|
|
4746
|
+
label: "Pronto",
|
|
4747
|
+
onClick: () => setCustomizing(false)
|
|
4748
|
+
}
|
|
4749
|
+
}),
|
|
4750
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
4751
|
+
className: "flex flex-col gap-1",
|
|
4752
|
+
children: customizeFields.map((f) => /* @__PURE__ */ jsx(Checkbox, {
|
|
4753
|
+
label: f.label,
|
|
4754
|
+
checked: show(f.id),
|
|
4755
|
+
onCheckedChange: (checked) => changeHidden({
|
|
4756
|
+
...hidden,
|
|
4757
|
+
[f.id]: !checked
|
|
4758
|
+
})
|
|
4759
|
+
}, f.id))
|
|
4760
|
+
})
|
|
5991
4761
|
});
|
|
5992
|
-
|
|
4762
|
+
const pendingTarget = pendingDrop && dropTargets?.find((t) => t.id === pendingDrop.targetId);
|
|
4763
|
+
const pendingCard = pendingDrop && cards.find((c) => c.id === pendingDrop.cardId);
|
|
4764
|
+
useEffect(() => {
|
|
4765
|
+
if (pendingDrop && !pendingCard) setPendingDrop(null);
|
|
4766
|
+
}, [pendingDrop, pendingCard]);
|
|
4767
|
+
const confirmation = pendingDrop && pendingTarget?.confirm && pendingCard ? /* @__PURE__ */ jsxs(Modal, {
|
|
4768
|
+
open: true,
|
|
4769
|
+
onOpenChange: (next) => !next && setPendingDrop(null),
|
|
4770
|
+
type: pendingTarget.confirm.destructive ? "destructive" : "confirm",
|
|
4771
|
+
title: pendingTarget.confirm.title,
|
|
4772
|
+
description: pendingTarget.confirm.description,
|
|
4773
|
+
confirmLabel: pendingTarget.confirm.confirmLabel ?? pendingTarget.label,
|
|
4774
|
+
onConfirm: () => onDropTarget?.(pendingDrop.cardId, pendingDrop.targetId, reason || void 0),
|
|
4775
|
+
children: [/* @__PURE__ */ jsxs("dl", {
|
|
4776
|
+
className: "flex w-full flex-col gap-1 rounded-block bg-muted p-3 text-left text-sm",
|
|
4777
|
+
children: [
|
|
4778
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4779
|
+
className: "flex justify-between gap-2",
|
|
4780
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
4781
|
+
className: "text-muted-foreground",
|
|
4782
|
+
children: "Empresa"
|
|
4783
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
4784
|
+
className: "font-medium",
|
|
4785
|
+
children: pendingCard.title
|
|
4786
|
+
})]
|
|
4787
|
+
}),
|
|
4788
|
+
pendingCard.subtitle && /* @__PURE__ */ jsxs("div", {
|
|
4789
|
+
className: "flex justify-between gap-2",
|
|
4790
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
4791
|
+
className: "text-muted-foreground",
|
|
4792
|
+
children: "Documento"
|
|
4793
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
4794
|
+
className: "tabular-nums",
|
|
4795
|
+
children: pendingCard.subtitle
|
|
4796
|
+
})]
|
|
4797
|
+
}),
|
|
4798
|
+
/* @__PURE__ */ jsxs("div", {
|
|
4799
|
+
className: "flex justify-between gap-2",
|
|
4800
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
4801
|
+
className: "text-muted-foreground",
|
|
4802
|
+
children: "Etapa"
|
|
4803
|
+
}), /* @__PURE__ */ jsx("dd", { children: columns.find((c) => c.id === pendingCard.columnId)?.title })]
|
|
4804
|
+
}),
|
|
4805
|
+
totalFields.map((f) => /* @__PURE__ */ jsxs("div", {
|
|
4806
|
+
className: "flex justify-between gap-2",
|
|
4807
|
+
children: [/* @__PURE__ */ jsxs("dt", {
|
|
4808
|
+
className: "text-muted-foreground",
|
|
4809
|
+
children: [f.label, ":"]
|
|
4810
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
4811
|
+
className: "font-semibold tabular-nums",
|
|
4812
|
+
children: formatValue(pendingCard.values?.[f.key] ?? 0)
|
|
4813
|
+
})]
|
|
4814
|
+
}, f.key))
|
|
4815
|
+
]
|
|
4816
|
+
}), pendingTarget.confirm.reasons && /* @__PURE__ */ jsxs("div", {
|
|
4817
|
+
className: "flex w-full flex-col gap-1 text-left",
|
|
4818
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4819
|
+
className: "text-sm font-medium",
|
|
4820
|
+
children: "Motivo"
|
|
4821
|
+
}), /* @__PURE__ */ jsx(Select, {
|
|
4822
|
+
label: "Motivo",
|
|
4823
|
+
options: pendingTarget.confirm.reasons,
|
|
4824
|
+
value: reason,
|
|
4825
|
+
onChange: (value) => setReason(value ?? "")
|
|
4826
|
+
})]
|
|
4827
|
+
})]
|
|
4828
|
+
}) : null;
|
|
4829
|
+
if (isMobile) {
|
|
4830
|
+
const board = /* @__PURE__ */ jsxs("div", {
|
|
4831
|
+
ref: boardRef,
|
|
4832
|
+
className: cn("flex h-board min-w-0 flex-col gap-3", className),
|
|
4833
|
+
"aria-label": aria["aria-label"],
|
|
4834
|
+
"data-rendra": code,
|
|
4835
|
+
children: [
|
|
4836
|
+
targetBar,
|
|
4837
|
+
/* @__PURE__ */ jsx(Tabs, {
|
|
4838
|
+
variant: "pill",
|
|
4839
|
+
"aria-label": "Colunas",
|
|
4840
|
+
value: active,
|
|
4841
|
+
onChange: setActive,
|
|
4842
|
+
items: columns.map((col) => ({
|
|
4843
|
+
value: col.id,
|
|
4844
|
+
label: col.title,
|
|
4845
|
+
count: visibleInColumn(col.id).length,
|
|
4846
|
+
content: null
|
|
4847
|
+
}))
|
|
4848
|
+
}),
|
|
4849
|
+
columns.filter((col) => col.id === active).map((col) => /* @__PURE__ */ jsxs("div", {
|
|
4850
|
+
className: "flex min-h-0 flex-1 flex-col gap-2 rounded-surface bg-muted p-2",
|
|
4851
|
+
children: [columnHeader(col, visibleInColumn(col.id).length), columnList(col)]
|
|
4852
|
+
}, col.id))
|
|
4853
|
+
]
|
|
4854
|
+
});
|
|
4855
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4856
|
+
toolbar ? /* @__PURE__ */ jsxs("div", {
|
|
4857
|
+
className: "flex min-w-0 flex-col gap-3",
|
|
4858
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
4859
|
+
className: "rounded-surface border bg-card",
|
|
4860
|
+
children: toolbarNode
|
|
4861
|
+
}), board]
|
|
4862
|
+
}) : board,
|
|
4863
|
+
customizeDrawer,
|
|
4864
|
+
confirmation
|
|
4865
|
+
] });
|
|
4866
|
+
}
|
|
4867
|
+
const board = /* @__PURE__ */ jsxs("section", {
|
|
5993
4868
|
ref: boardRef,
|
|
5994
4869
|
"aria-label": aria["aria-label"] ?? "Quadro kanban",
|
|
5995
4870
|
"data-rendra": code,
|
|
@@ -6000,10 +4875,21 @@ function Kanban({ columns, cards, onCardMove, onCardClick, onAddCard, renderCard
|
|
|
6000
4875
|
className: "flex min-h-0 w-kanban-col flex-col gap-2 rounded-surface bg-muted p-2",
|
|
6001
4876
|
children: [/* @__PURE__ */ jsx("div", {
|
|
6002
4877
|
className: "pt-1",
|
|
6003
|
-
children: columnHeader(col,
|
|
4878
|
+
children: columnHeader(col, visibleInColumn(col.id).length)
|
|
6004
4879
|
}), columnList(col)]
|
|
6005
4880
|
}, col.id))]
|
|
6006
4881
|
});
|
|
4882
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4883
|
+
toolbar ? /* @__PURE__ */ jsxs("div", {
|
|
4884
|
+
className: "flex min-w-0 flex-col gap-4",
|
|
4885
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
4886
|
+
className: "rounded-surface border bg-card",
|
|
4887
|
+
children: toolbarNode
|
|
4888
|
+
}), board]
|
|
4889
|
+
}) : board,
|
|
4890
|
+
customizeDrawer,
|
|
4891
|
+
confirmation
|
|
4892
|
+
] });
|
|
6007
4893
|
}
|
|
6008
4894
|
/** Move um card na lista (para usar no onCardMove): devolve a lista nova. */
|
|
6009
4895
|
function moveKanbanCard(cards, cardId, toColumnId, toIndex) {
|
|
@@ -8397,95 +7283,6 @@ var Textarea = forwardRef(function Textarea({ invalid, counter, value, defaultVa
|
|
|
8397
7283
|
});
|
|
8398
7284
|
});
|
|
8399
7285
|
//#endregion
|
|
8400
|
-
//#region src/components/ui/timeline.tsx
|
|
8401
|
-
var dot = {
|
|
8402
|
-
neutral: "bg-muted text-muted-foreground",
|
|
8403
|
-
info: "bg-info-soft text-info-soft-foreground",
|
|
8404
|
-
success: "bg-success-soft text-success-soft-foreground",
|
|
8405
|
-
warning: "bg-warning-soft text-warning-soft-foreground",
|
|
8406
|
-
error: "bg-destructive-soft text-destructive-soft-foreground"
|
|
8407
|
-
};
|
|
8408
|
-
var statusTone = {
|
|
8409
|
-
succeeded: "success",
|
|
8410
|
-
failed: "error",
|
|
8411
|
-
skipped: "neutral"
|
|
8412
|
-
};
|
|
8413
|
-
var statusIcon = {
|
|
8414
|
-
succeeded: CheckCircle2,
|
|
8415
|
-
failed: XCircle,
|
|
8416
|
-
skipped: SkipForward
|
|
8417
|
-
};
|
|
8418
|
-
var statusLabel$1 = {
|
|
8419
|
-
succeeded: "Concluído",
|
|
8420
|
-
failed: "Falhou",
|
|
8421
|
-
skipped: "Ignorado"
|
|
8422
|
-
};
|
|
8423
|
-
var statusTextTone = {
|
|
8424
|
-
succeeded: "text-success-soft-foreground",
|
|
8425
|
-
failed: "text-destructive-soft-foreground",
|
|
8426
|
-
skipped: "text-muted-foreground"
|
|
8427
|
-
};
|
|
8428
|
-
/** Linha do tempo única, com eventos em ordem e tom semântico por evento. */
|
|
8429
|
-
function Timeline({ events, className }) {
|
|
8430
|
-
const lib = useMotionLib();
|
|
8431
|
-
const on = lib !== null;
|
|
8432
|
-
const presets = useMotionPresets();
|
|
8433
|
-
const Item = on ? lib.m.li : "li";
|
|
8434
|
-
const enter = presets.slide("bottom", "short");
|
|
8435
|
-
return /* @__PURE__ */ jsx("ol", {
|
|
8436
|
-
"data-rendra": "TLN-001",
|
|
8437
|
-
className: cn("@container flex flex-col", className),
|
|
8438
|
-
children: events.map((e, i) => {
|
|
8439
|
-
const StatusIcon = e.status ? statusIcon[e.status] : null;
|
|
8440
|
-
const tone = e.tone ?? (e.status ? statusTone[e.status] : "neutral");
|
|
8441
|
-
return /* @__PURE__ */ jsxs(Item, {
|
|
8442
|
-
className: "relative flex gap-3 pb-6 last:pb-0",
|
|
8443
|
-
...on ? {
|
|
8444
|
-
...enter,
|
|
8445
|
-
transition: {
|
|
8446
|
-
...enter.transition,
|
|
8447
|
-
...presets.stagger(i)
|
|
8448
|
-
}
|
|
8449
|
-
} : {},
|
|
8450
|
-
children: [
|
|
8451
|
-
i < events.length - 1 && /* @__PURE__ */ jsx("span", {
|
|
8452
|
-
"aria-hidden": true,
|
|
8453
|
-
className: "absolute top-8 bottom-0 left-4 w-px -translate-x-1/2 bg-border"
|
|
8454
|
-
}),
|
|
8455
|
-
/* @__PURE__ */ jsx("span", {
|
|
8456
|
-
"aria-hidden": true,
|
|
8457
|
-
className: cn("relative flex size-8 shrink-0 items-center justify-center rounded-full [&_svg]:size-icon-sm", dot[tone]),
|
|
8458
|
-
children: e.icon ?? (StatusIcon && /* @__PURE__ */ jsx(StatusIcon, {})) ?? /* @__PURE__ */ jsx("span", { className: "size-2 rounded-full bg-current" })
|
|
8459
|
-
}),
|
|
8460
|
-
/* @__PURE__ */ jsxs("div", {
|
|
8461
|
-
className: "flex min-w-0 flex-1 flex-col gap-1 pt-1",
|
|
8462
|
-
children: [
|
|
8463
|
-
/* @__PURE__ */ jsxs("div", {
|
|
8464
|
-
className: "flex min-w-0 flex-col gap-1 @sm:flex-row @sm:items-baseline @sm:justify-between @sm:gap-3",
|
|
8465
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
8466
|
-
className: "text-sm font-medium wrap-break-word",
|
|
8467
|
-
children: e.title
|
|
8468
|
-
}), /* @__PURE__ */ jsx("time", {
|
|
8469
|
-
className: "shrink-0 text-xs text-muted-foreground tabular-nums",
|
|
8470
|
-
children: e.date
|
|
8471
|
-
})]
|
|
8472
|
-
}),
|
|
8473
|
-
e.description && /* @__PURE__ */ jsx("p", {
|
|
8474
|
-
className: "text-sm wrap-break-word text-muted-foreground",
|
|
8475
|
-
children: e.description
|
|
8476
|
-
}),
|
|
8477
|
-
e.status && StatusIcon && /* @__PURE__ */ jsxs("span", {
|
|
8478
|
-
className: cn("inline-flex w-fit items-center gap-1 text-xs font-medium [&_svg]:size-icon-sm", statusTextTone[e.status]),
|
|
8479
|
-
children: [/* @__PURE__ */ jsx(StatusIcon, {}), statusLabel$1[e.status]]
|
|
8480
|
-
})
|
|
8481
|
-
]
|
|
8482
|
-
})
|
|
8483
|
-
]
|
|
8484
|
-
}, e.id);
|
|
8485
|
-
})
|
|
8486
|
-
});
|
|
8487
|
-
}
|
|
8488
|
-
//#endregion
|
|
8489
7286
|
//#region src/components/ui/toast.tsx
|
|
8490
7287
|
var tone = {
|
|
8491
7288
|
success: "border-success/25",
|
|
@@ -11339,6 +10136,6 @@ function createTheme(input) {
|
|
|
11339
10136
|
};
|
|
11340
10137
|
}
|
|
11341
10138
|
//#endregion
|
|
11342
|
-
export { Accordion, ActionBar, Alert, AppShell, Avatar, AvatarGroup, Badge, BrandFeedbackIcon, BrandLogo, BrandProvider, Breadcrumb, Button, ButtonGroup, CATALOG, CATALOG_EXCLUDED_FILES, COMPONENT_CODE_PATTERN, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChannelBadge, ChatComposer, ChatThread, Checkbox, CheckboxGroup, Checklist, ColorPicker, Container, ConversationList, DEFAULT_DDI, DataToolbar, DatePicker, Drawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorPage, Field, Form, FormField, FormSection, Grid, ImageCropper, ImageViewer, InfoHint, Inline, Input, Kanban, Label, List, Modal, OtpInput, PageHeader, Pagination, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QR_MAX_VERSION, QrCode, QrEncodingError, RENDRA_CREDIT_HREF, RENDRA_CREDIT_TEXT, RadioGroup, Rating, RendraCredit, RendraProvider, RepeatableField, Section, Select, Separator, Skeleton, Slider, Spinner, Stack, StatCard, Stepper, Switch, TABLE_PAGE_SIZE, TOKEN_KEYS, Table, Tabs, Textarea, Timeline, Toaster, Tooltip, TooltipProvider, Upload, Wizard, applyPalette, applyTheme, assertCatalogIntegrity, bindPointerDrag, breakpoints, buildDataCodewords, buttonVariants, catalogByComponent, chatChannels, cn, computeCropGeometry, computeFormatBits, computeMaskPenalty, computeVersionBits, contrast, contrastRatio, controlAdornmentButton, controlAdornmentSpace, controlFrame, controlInput, createPalette, createTheme, defaultShellLayout, encodeQrMatrix, feedbackLabels, filesMissingCatalogEntry, findComponentsWithMultipleDefaults, findComponentsWithoutDefault, findDragTarget, findDuplicateCodes, findInvalidFormatCodes, findPresetCollisions, formatCents, formatCurrency, getCatalogEntry, getReducedMotion, internationalPhoneMask, isValidCnpj, isValidCpf, isValidDateBR, layoutOptions, lookupCep, lookupCnpj, masks, moveKanbanCard, parseLocaleNumber, percentMask, phoneCountries, qrMatrixToSvgPath, readCodewordsForTest, readVar, reedSolomonComputeDivisor, reedSolomonComputeRemainder, reedSolomonEncode, reedSolomonMultiply, resolveCatalogCode, resolveDropIndex, shapeLabels, subscribeReducedMotion, toCents, toE164, toast, useBrand, useBreakpoint, useCurrentPath, useDebouncedValue, useFieldControl, useFillHeight, useLookup, usePrefersReducedMotion, useRendraBreadcrumbs, useRendraLink, useRendraNavigate, useSortable, zBR };
|
|
10139
|
+
export { Accordion, ActionBar, Alert, AppShell, Avatar, AvatarGroup, Badge, BrandFeedbackIcon, BrandLogo, BrandProvider, Breadcrumb, Button, ButtonGroup, CATALOG, CATALOG_EXCLUDED_FILES, COMPONENT_CODE_PATTERN, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChannelBadge, ChatComposer, ChatThread, Checkbox, CheckboxGroup, Checklist, ColorPicker, Container, ConversationList, DEFAULT_DDI, DataToolbar, DatePicker, Drawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorPage, Field, Form, FormField, FormSection, Grid, ImageCropper, ImageViewer, InfoHint, Inline, Input, Kanban, Label, List, Modal, OtpInput, PageHeader, Pagination, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, QR_MAX_VERSION, QrCode, QrEncodingError, RENDRA_CREDIT_HREF, RENDRA_CREDIT_TEXT, RadioGroup, Rating, RendraCredit, RendraProvider, RepeatableField, Section, Select, Separator, Skeleton, Slider, Spinner, Stack, StatCard, Stepper, Switch, TABLE_PAGE_SIZE, TOKEN_KEYS, Table, Tabs, Textarea, Timeline, Toaster, Tooltip, TooltipProvider, Upload, Wizard, applyPalette, applyTheme, assertCatalogIntegrity, bindPointerDrag, breakpoints, buildDataCodewords, buttonVariants, catalogByComponent, chatChannels, cn, computeCropGeometry, computeFormatBits, computeMaskPenalty, computeVersionBits, contrast, contrastRatio, controlAdornmentButton, controlAdornmentSpace, controlFrame, controlInput, createPalette, createTheme, defaultShellLayout, encodeQrMatrix, feedbackLabels, filesMissingCatalogEntry, findComponentsWithMultipleDefaults, findComponentsWithoutDefault, findDragTarget, findDuplicateCodes, findInvalidFormatCodes, findPresetCollisions, formatCents, formatCurrency, getCatalogEntry, getKanbanCardStatus, getReducedMotion, internationalPhoneMask, isValidCnpj, isValidCpf, isValidDateBR, layoutOptions, lookupCep, lookupCnpj, masks, moveKanbanCard, parseLocaleNumber, percentMask, phoneCountries, qrMatrixToSvgPath, readCodewordsForTest, readVar, reedSolomonComputeDivisor, reedSolomonComputeRemainder, reedSolomonEncode, reedSolomonMultiply, resolveCatalogCode, resolveDropIndex, shapeLabels, subscribeReducedMotion, toCents, toE164, toast, useBrand, useBreakpoint, useCurrentPath, useDebouncedValue, useFieldControl, useFillHeight, useLookup, usePrefersReducedMotion, useRendraBreadcrumbs, useRendraLink, useRendraNavigate, useSortable, zBR };
|
|
11343
10140
|
|
|
11344
10141
|
//# sourceMappingURL=index.js.map
|