@strategicos/ui 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +16 -1
  2. package/dist/components/accordion.d.ts +10 -0
  3. package/dist/components/accordion.d.ts.map +1 -0
  4. package/dist/components/accordion.js +21 -0
  5. package/dist/components/accordion.js.map +1 -0
  6. package/dist/components/badge.d.ts +1 -1
  7. package/dist/components/button.d.ts +1 -1
  8. package/dist/components/chip.d.ts +40 -0
  9. package/dist/components/chip.d.ts.map +1 -0
  10. package/dist/components/chip.js +23 -0
  11. package/dist/components/chip.js.map +1 -0
  12. package/dist/components/dropzone.d.ts +38 -0
  13. package/dist/components/dropzone.d.ts.map +1 -0
  14. package/dist/components/dropzone.js +67 -0
  15. package/dist/components/dropzone.js.map +1 -0
  16. package/dist/components/empty-state.d.ts +24 -0
  17. package/dist/components/empty-state.d.ts.map +1 -0
  18. package/dist/components/empty-state.js +21 -0
  19. package/dist/components/empty-state.js.map +1 -0
  20. package/dist/components/multi-select.d.ts +47 -0
  21. package/dist/components/multi-select.d.ts.map +1 -0
  22. package/dist/components/multi-select.js +72 -0
  23. package/dist/components/multi-select.js.map +1 -0
  24. package/dist/components/popover.d.ts +10 -0
  25. package/dist/components/popover.d.ts.map +1 -0
  26. package/dist/components/popover.js +20 -0
  27. package/dist/components/popover.js.map +1 -0
  28. package/dist/components/progress.d.ts +18 -0
  29. package/dist/components/progress.d.ts.map +1 -0
  30. package/dist/components/progress.js +18 -0
  31. package/dist/components/progress.js.map +1 -0
  32. package/dist/components/segmented-control.d.ts +37 -0
  33. package/dist/components/segmented-control.d.ts.map +1 -0
  34. package/dist/components/segmented-control.js +26 -0
  35. package/dist/components/segmented-control.js.map +1 -0
  36. package/dist/components/stat.d.ts +27 -0
  37. package/dist/components/stat.d.ts.map +1 -0
  38. package/dist/components/stat.js +23 -0
  39. package/dist/components/stat.js.map +1 -0
  40. package/dist/components/tabs.d.ts +2 -2
  41. package/package.json +1 -1
  42. package/src/components/accordion.tsx +55 -0
  43. package/src/components/chip.tsx +111 -0
  44. package/src/components/dropzone.tsx +124 -0
  45. package/src/components/empty-state.tsx +56 -0
  46. package/src/components/multi-select.tsx +210 -0
  47. package/src/components/popover.tsx +44 -0
  48. package/src/components/progress.tsx +50 -0
  49. package/src/components/segmented-control.tsx +89 -0
  50. package/src/components/stat.tsx +65 -0
package/README.md CHANGED
@@ -15,7 +15,7 @@ import { cn } from "@strategicos/ui/utils"
15
15
 
16
16
  ## Componentes
17
17
 
18
- `alert` · `alert-dialog` · `avatar` · `badge` · `button` · `card` · `checkbox` · `dialog` · `dropdown-menu` · `field` · `input` · `label` · `page-header` · `pagination` · `password-input` · `select` · `separator` · `sheet` · `sidebar` · `skeleton` · `sonner` · `switch` · `table` · `tabs` · `textarea` · `tooltip`
18
+ `accordion` · `alert` · `alert-dialog` · `avatar` · `badge` · `button` · `card` · `checkbox` · `chip` · `dialog` · `dropdown-menu` · `dropzone` · `empty-state` · `field` · `input` · `label` · `multi-select` · `page-header` · `pagination` · `password-input` · `popover` · `progress` · `segmented-control` · `select` · `separator` · `sheet` · `sidebar` · `skeleton` · `sonner` · `stat` · `switch` · `table` · `tabs` · `textarea` · `tooltip`
19
19
 
20
20
  Utilitários: `@strategicos/ui/utils` (`cn`) e `@strategicos/ui/hooks/use-mobile` (`useIsMobile`).
21
21
 
@@ -46,6 +46,21 @@ import { Input } from "@strategicos/ui/input"
46
46
  - `PasswordInput` traz o botão de mostrar/ocultar a senha.
47
47
  - `Textarea autosize` cresce com o texto. Limite a altura com `max-h-*`.
48
48
 
49
+ ## Quando usar cada um
50
+
51
+ | Situação | Componente |
52
+ |---|---|
53
+ | Trocar o modo de ver o mesmo conteúdo (Lista \| Quadro, 30d \| 60d) | `SegmentedControl` |
54
+ | Navegar entre conteúdos diferentes | `Tabs` |
55
+ | Filtros em pílula (categoria, status), um ou vários | `ChipGroup` + `Chip` |
56
+ | Escolher vários itens com busca | `MultiSelect` |
57
+ | Indicador numérico (KPI) | `Stat` |
58
+ | Barra de progresso | `Progress` |
59
+ | Área de envio de arquivos | `Dropzone` |
60
+ | Seções que abrem e fecham | `Accordion` |
61
+ | Lista ou área sem conteúdo | `EmptyState` |
62
+ | Painel flutuante genérico | `Popover` |
63
+
49
64
  ## Celular
50
65
 
51
66
  - `DialogContent` ocupa a tela inteira abaixo de `sm` (640px). Para diálogos curtos que devem continuar centralizados, use `mobile="centered"`. O `AlertDialog` é sempre centralizado.
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { Accordion as AccordionPrimitive } from "radix-ui";
3
+ /** Seções que abrem e fecham (Radix Accordion), no estilo do Accordion do
4
+ * Mantine: itens separados por fio, chevron à direita. */
5
+ declare function Accordion(props: React.ComponentProps<typeof AccordionPrimitive.Root>): React.JSX.Element;
6
+ declare function AccordionItem({ className, ...props }: React.ComponentProps<typeof AccordionPrimitive.Item>): React.JSX.Element;
7
+ declare function AccordionTrigger({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Trigger>): React.JSX.Element;
8
+ declare function AccordionContent({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Content>): React.JSX.Element;
9
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
10
+ //# sourceMappingURL=accordion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../src/components/accordion.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,SAAS,IAAI,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAK1D;2DAC2D;AAC3D,iBAAS,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,IAAI,CAAC,qBAE7E;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,IAAI,CAAC,qBAQnG;AAED,iBAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,OAAO,CAAC,qBAgBnH;AAED,iBAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,kBAAkB,CAAC,OAAO,CAAC,qBAUnH;AAED,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAA"}
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Accordion as AccordionPrimitive } from "radix-ui";
4
+ import { ChevronDownIcon } from "lucide-react";
5
+ import { cn } from "../lib/utils.js";
6
+ /** Seções que abrem e fecham (Radix Accordion), no estilo do Accordion do
7
+ * Mantine: itens separados por fio, chevron à direita. */
8
+ function Accordion(props) {
9
+ return _jsx(AccordionPrimitive.Root, { "data-slot": "accordion", ...props });
10
+ }
11
+ function AccordionItem({ className, ...props }) {
12
+ return (_jsx(AccordionPrimitive.Item, { "data-slot": "accordion-item", className: cn("border-b border-border last:border-b-0", className), ...props }));
13
+ }
14
+ function AccordionTrigger({ className, children, ...props }) {
15
+ return (_jsx(AccordionPrimitive.Header, { className: "flex", children: _jsxs(AccordionPrimitive.Trigger, { "data-slot": "accordion-trigger", className: cn("group/accordion flex flex-1 cursor-pointer items-center justify-between gap-4 py-3 text-left text-sm font-medium text-foreground transition-colors outline-none hover:text-foreground/80 focus-visible:ring-2 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 [&_svg]:shrink-0", className), ...props, children: [children, _jsx(ChevronDownIcon, { className: "size-4 text-muted-foreground transition-transform duration-200 group-data-[state=open]/accordion:rotate-180" })] }) }));
16
+ }
17
+ function AccordionContent({ className, children, ...props }) {
18
+ return (_jsx(AccordionPrimitive.Content, { "data-slot": "accordion-content", className: "overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down", ...props, children: _jsx("div", { className: cn("pb-4", className), children: children }) }));
19
+ }
20
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
21
+ //# sourceMappingURL=accordion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../src/components/accordion.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAGZ,OAAO,EAAE,SAAS,IAAI,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAEpC;2DAC2D;AAC3D,SAAS,SAAS,CAAC,KAA2D;IAC5E,OAAO,KAAC,kBAAkB,CAAC,IAAI,iBAAW,WAAW,KAAK,KAAK,GAAI,CAAA;AACrE,CAAC;AAED,SAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAwD;IAClG,OAAO,CACL,KAAC,kBAAkB,CAAC,IAAI,iBACZ,gBAAgB,EAC1B,SAAS,EAAE,EAAE,CAAC,wCAAwC,EAAE,SAAS,CAAC,KAC9D,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAA2D;IAClH,OAAO,CACL,KAAC,kBAAkB,CAAC,MAAM,IAAC,SAAS,EAAC,MAAM,YACzC,MAAC,kBAAkB,CAAC,OAAO,iBACf,mBAAmB,EAC7B,SAAS,EAAE,EAAE,CACX,2SAA2S,EAC3S,SAAS,CACV,KACG,KAAK,aAER,QAAQ,EACT,KAAC,eAAe,IAAC,SAAS,EAAC,6GAA6G,GAAG,IAChH,GACH,CAC7B,CAAA;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAA2D;IAClH,OAAO,CACL,KAAC,kBAAkB,CAAC,OAAO,iBACf,mBAAmB,EAC7B,SAAS,EAAC,2GAA2G,KACjH,KAAK,YAET,cAAK,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,YAAG,QAAQ,GAAO,GAC5B,CAC9B,CAAA;AACH,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const badgeVariants: (props?: ({
4
- variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" | "link" | "info" | "success" | "warning" | null | undefined;
4
+ variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | "info" | "success" | "warning" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
7
7
  asChild?: boolean;
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const buttonVariants: (props?: ({
4
- variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" | "link" | null | undefined;
4
+ variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | null | undefined;
5
5
  size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
7
  declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
@@ -0,0 +1,40 @@
1
+ import * as React from "react";
2
+ import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
3
+ /**
4
+ * Pílulas selecionáveis, como o Chip do Mantine: filtros por categoria, status
5
+ * e afins. Selecionada, a pílula ganha o fundo claro da cor primária e um ✓.
6
+ *
7
+ * <ChipGroup type="single" value={categoria} onValueChange={setCategoria}>
8
+ * <Chip value="todas">Todas</Chip>
9
+ * <Chip value="legislacao">Legislação</Chip>
10
+ * </ChipGroup>
11
+ *
12
+ * <ChipGroup type="multiple" value={status} onValueChange={setStatus}>
13
+ * <Chip value="todo" count={8}>A fazer</Chip>
14
+ * </ChipGroup>
15
+ *
16
+ * Em `single`, clicar na selecionada não a desmarca (sempre há uma ativa).
17
+ * Os valores não podem ser vazios: o Radix trata "" como "nada selecionado".
18
+ * `scrollable` deixa o grupo numa linha só, rolando na horizontal no celular.
19
+ */
20
+ type ChipGroupProps = {
21
+ type: "single";
22
+ value: string;
23
+ onValueChange: (value: string) => void;
24
+ } | {
25
+ type: "multiple";
26
+ value: string[];
27
+ onValueChange: (value: string[]) => void;
28
+ };
29
+ declare function ChipGroup({ className, children, scrollable, "aria-label": ariaLabel, ...props }: ChipGroupProps & {
30
+ className?: string;
31
+ children: React.ReactNode;
32
+ scrollable?: boolean;
33
+ "aria-label"?: string;
34
+ }): React.JSX.Element;
35
+ declare function Chip({ value, count, className, children, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & {
36
+ /** Número exibido depois do rótulo (ex.: quantidade de itens). */
37
+ count?: number;
38
+ }): React.JSX.Element;
39
+ export { ChipGroup, Chip };
40
+ //# sourceMappingURL=chip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chip.d.ts","sourceRoot":"","sources":["../../src/components/chip.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAK9D;;;;;;;;;;;;;;;;GAgBG;AAEH,KAAK,cAAc,GACf;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC,GACD;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CACzC,CAAA;AAEL,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,QAAQ,EACR,UAAkB,EAClB,YAAY,EAAE,SAAS,EACvB,GAAG,KAAK,EACT,EAAE,cAAc,GAAG;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,qBA4BA;AAED,iBAAS,IAAI,CAAC,EACZ,KAAK,EACL,KAAK,EACL,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,IAAI,CAAC,GAAG;IAC1D,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,qBAoBA;AAED,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA"}
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
4
+ import { CheckIcon } from "lucide-react";
5
+ import { cn } from "../lib/utils.js";
6
+ function ChipGroup({ className, children, scrollable = false, "aria-label": ariaLabel, ...props }) {
7
+ const shared = {
8
+ "aria-label": ariaLabel,
9
+ "data-slot": "chip-group",
10
+ className: cn("flex gap-1.5", scrollable ? "no-scrollbar -mx-1 overflow-x-auto px-1 py-0.5" : "flex-wrap", className),
11
+ };
12
+ if (props.type === "single") {
13
+ const { value, onValueChange } = props;
14
+ return (_jsx(ToggleGroupPrimitive.Root, { type: "single", value: value, onValueChange: v => { if (v)
15
+ onValueChange(v); }, ...shared, children: children }));
16
+ }
17
+ return (_jsx(ToggleGroupPrimitive.Root, { type: "multiple", value: props.value, onValueChange: props.onValueChange, ...shared, children: children }));
18
+ }
19
+ function Chip({ value, count, className, children, ...props }) {
20
+ return (_jsxs(ToggleGroupPrimitive.Item, { value: value, "data-slot": "chip", className: cn("group/chip inline-flex h-7.5 shrink-0 cursor-pointer items-center gap-1.5 rounded-full border border-border bg-background px-3 text-sm whitespace-nowrap text-foreground transition-colors outline-none hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[state=on]:border-primary/50 data-[state=on]:bg-primary/10 data-[state=on]:text-primary-strong dark:bg-transparent", className), ...props, children: [_jsx(CheckIcon, { className: "hidden size-3.5 shrink-0 stroke-3 group-data-[state=on]/chip:block" }), children, count !== undefined && (_jsx("span", { className: "text-xs text-muted-foreground tabular-nums group-data-[state=on]/chip:text-primary-strong/80", children: count }))] }));
21
+ }
22
+ export { ChipGroup, Chip };
23
+ //# sourceMappingURL=chip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chip.js","sourceRoot":"","sources":["../../src/components/chip.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAGZ,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAExC,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAgCpC,SAAS,SAAS,CAAC,EACjB,SAAS,EACT,QAAQ,EACR,UAAU,GAAG,KAAK,EAClB,YAAY,EAAE,SAAS,EACvB,GAAG,KAAK,EAMT;IACC,MAAM,MAAM,GAAG;QACb,YAAY,EAAE,SAAS;QACvB,WAAW,EAAE,YAAY;QACzB,SAAS,EAAE,EAAE,CACX,cAAc,EACd,UAAU,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC,CAAC,WAAW,EAC3E,SAAS,CACV;KACF,CAAA;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,KAAK,CAAA;QACtC,OAAO,CACL,KAAC,oBAAoB,CAAC,IAAI,IACxB,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC;gBAAE,aAAa,CAAC,CAAC,CAAC,CAAA,CAAC,CAAC,KAC3C,MAAM,YAET,QAAQ,GACiB,CAC7B,CAAA;IACH,CAAC;IACD,OAAO,CACL,KAAC,oBAAoB,CAAC,IAAI,IAAC,IAAI,EAAC,UAAU,EAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,KAAM,MAAM,YAC1G,QAAQ,GACiB,CAC7B,CAAA;AACH,CAAC;AAED,SAAS,IAAI,CAAC,EACZ,KAAK,EACL,KAAK,EACL,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAIT;IACC,OAAO,CACL,MAAC,oBAAoB,CAAC,IAAI,IACxB,KAAK,EAAE,KAAK,eACF,MAAM,EAChB,SAAS,EAAE,EAAE,CACX,gbAAgb,EAChb,SAAS,CACV,KACG,KAAK,aAET,KAAC,SAAS,IAAC,SAAS,EAAC,oEAAoE,GAAG,EAC3F,QAAQ,EACR,KAAK,KAAK,SAAS,IAAI,CACtB,eAAM,SAAS,EAAC,8FAA8F,YAC3G,KAAK,GACD,CACR,IACyB,CAC7B,CAAA;AACH,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA"}
@@ -0,0 +1,38 @@
1
+ import * as React from "react";
2
+ /**
3
+ * Área de envio de arquivos, como o Dropzone do Mantine: arrastar e soltar, ou
4
+ * clicar (e Enter/Espaço) para abrir o seletor do sistema.
5
+ *
6
+ * <Dropzone
7
+ * accept=".txt,.xml,.zip"
8
+ * maxSize={50 * 1024 * 1024}
9
+ * onDrop={files => enviar(files)}
10
+ * onReject={msg => toast.error(msg)}
11
+ * title="Importar arquivos fiscais"
12
+ * description="SPED (.txt), NF-e (.xml) ou pacote .zip, até 50 MB"
13
+ * />
14
+ *
15
+ * `children` substitui o conteúdo padrão (ícone, título e descrição).
16
+ * A validação de tipo e tamanho é só uma conveniência: o servidor valida de
17
+ * novo.
18
+ */
19
+ declare function Dropzone({ onDrop, onReject, accept, multiple, maxSize, disabled, loading, title, description, icon, className, children, }: {
20
+ onDrop: (files: File[]) => void;
21
+ /** Chamado com uma mensagem quando algum arquivo é recusado (tipo/tamanho). */
22
+ onReject?: (message: string) => void;
23
+ /** Mesmo formato do atributo `accept` do input (ex.: ".pdf,image/*"). */
24
+ accept?: string;
25
+ multiple?: boolean;
26
+ /** Tamanho máximo por arquivo, em bytes. */
27
+ maxSize?: number;
28
+ disabled?: boolean;
29
+ /** Enquanto envia: bloqueia novos envios e mostra o estado ocupado. */
30
+ loading?: boolean;
31
+ title?: React.ReactNode;
32
+ description?: React.ReactNode;
33
+ icon?: React.ReactNode;
34
+ className?: string;
35
+ children?: React.ReactNode;
36
+ }): React.JSX.Element;
37
+ export { Dropzone };
38
+ //# sourceMappingURL=dropzone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropzone.d.ts","sourceRoot":"","sources":["../../src/components/dropzone.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B;;;;;;;;;;;;;;;;GAgBG;AACH,iBAAS,QAAQ,CAAC,EAChB,MAAM,EACN,QAAQ,EACR,MAAM,EACN,QAAgB,EAChB,OAAO,EACP,QAAgB,EAChB,OAAe,EACf,KAAkD,EAClD,WAAW,EACX,IAAI,EACJ,SAAS,EACT,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B,qBAmEA;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,67 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { UploadIcon } from "lucide-react";
5
+ import { cn } from "../lib/utils.js";
6
+ /**
7
+ * Área de envio de arquivos, como o Dropzone do Mantine: arrastar e soltar, ou
8
+ * clicar (e Enter/Espaço) para abrir o seletor do sistema.
9
+ *
10
+ * <Dropzone
11
+ * accept=".txt,.xml,.zip"
12
+ * maxSize={50 * 1024 * 1024}
13
+ * onDrop={files => enviar(files)}
14
+ * onReject={msg => toast.error(msg)}
15
+ * title="Importar arquivos fiscais"
16
+ * description="SPED (.txt), NF-e (.xml) ou pacote .zip, até 50 MB"
17
+ * />
18
+ *
19
+ * `children` substitui o conteúdo padrão (ícone, título e descrição).
20
+ * A validação de tipo e tamanho é só uma conveniência: o servidor valida de
21
+ * novo.
22
+ */
23
+ function Dropzone({ onDrop, onReject, accept, multiple = false, maxSize, disabled = false, loading = false, title = "Arraste arquivos ou clique para escolher", description, icon, className, children, }) {
24
+ const inputRef = React.useRef(null);
25
+ const [dragging, setDragging] = React.useState(false);
26
+ const blocked = disabled || loading;
27
+ function matchesAccept(file) {
28
+ if (!accept)
29
+ return true;
30
+ const name = file.name.toLowerCase();
31
+ return accept.split(",").map(s => s.trim().toLowerCase()).some(rule => {
32
+ if (rule.startsWith("."))
33
+ return name.endsWith(rule);
34
+ if (rule.endsWith("/*"))
35
+ return file.type.startsWith(rule.slice(0, -1));
36
+ return file.type === rule;
37
+ });
38
+ }
39
+ function handleFiles(list) {
40
+ if (!list || list.length === 0 || blocked)
41
+ return;
42
+ const files = Array.from(list).slice(0, multiple ? undefined : 1);
43
+ const ok = [];
44
+ for (const f of files) {
45
+ if (!matchesAccept(f))
46
+ onReject?.(`"${f.name}" não é de um tipo aceito.`);
47
+ else if (maxSize && f.size > maxSize)
48
+ onReject?.(`"${f.name}" passa do limite de ${Math.round(maxSize / 1024 / 1024)} MB.`);
49
+ else
50
+ ok.push(f);
51
+ }
52
+ if (ok.length)
53
+ onDrop(ok);
54
+ }
55
+ return (_jsxs("div", { role: "button", tabIndex: blocked ? -1 : 0, "aria-disabled": blocked || undefined, "aria-busy": loading || undefined, "data-slot": "dropzone", "data-dragging": dragging || undefined, onClick: () => !blocked && inputRef.current?.click(), onKeyDown: e => {
56
+ if (blocked)
57
+ return;
58
+ if (e.key === "Enter" || e.key === " ") {
59
+ e.preventDefault();
60
+ inputRef.current?.click();
61
+ }
62
+ }, onDragOver: e => { e.preventDefault(); if (!blocked)
63
+ setDragging(true); }, onDragLeave: e => { if (!e.currentTarget.contains(e.relatedTarget))
64
+ setDragging(false); }, onDrop: e => { e.preventDefault(); setDragging(false); handleFiles(e.dataTransfer.files); }, className: cn("flex cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed border-border px-6 py-8 text-center transition-colors outline-none hover:border-primary/50 hover:bg-muted/40 focus-visible:ring-2 focus-visible:ring-ring/50 data-dragging:border-primary data-dragging:bg-primary/5 aria-disabled:cursor-not-allowed aria-disabled:opacity-60 aria-disabled:hover:border-border aria-disabled:hover:bg-transparent", className), children: [_jsx("input", { ref: inputRef, type: "file", accept: accept, multiple: multiple, className: "hidden", onChange: e => { handleFiles(e.target.files); e.target.value = ""; } }), children ?? (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex size-10 items-center justify-center rounded-full bg-muted text-muted-foreground [&_svg]:size-5", children: icon ?? _jsx(UploadIcon, {}) }), _jsx("p", { className: "text-sm font-medium text-foreground", children: title }), description && _jsx("p", { className: "text-xs text-muted-foreground", children: description })] }))] }));
65
+ }
66
+ export { Dropzone };
67
+ //# sourceMappingURL=dropzone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropzone.js","sourceRoot":"","sources":["../../src/components/dropzone.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import * as React from "react";
2
+ /**
3
+ * Estado vazio: ícone, título, explicação e uma ação. Para listas sem itens,
4
+ * buscas sem resultado e telas que ainda não têm conteúdo.
5
+ *
6
+ * <EmptyState
7
+ * icon={<FileText />}
8
+ * title="Nenhum documento ainda"
9
+ * description="Crie um documento ou importe uma apresentação para começar."
10
+ * action={<Button><Plus /> Novo documento</Button>}
11
+ * />
12
+ *
13
+ * `bordered` desenha a moldura tracejada, para quando o vazio ocupa o lugar de
14
+ * uma área (lista, quadro) e precisa mostrar o contorno dela.
15
+ */
16
+ declare function EmptyState({ icon, title, description, action, bordered, className, ...props }: Omit<React.ComponentProps<"div">, "title"> & {
17
+ icon?: React.ReactNode;
18
+ title: React.ReactNode;
19
+ description?: React.ReactNode;
20
+ action?: React.ReactNode;
21
+ bordered?: boolean;
22
+ }): React.JSX.Element;
23
+ export { EmptyState };
24
+ //# sourceMappingURL=empty-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty-state.d.ts","sourceRoot":"","sources":["../../src/components/empty-state.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B;;;;;;;;;;;;;GAaG;AACH,iBAAS,UAAU,CAAC,EAClB,IAAI,EACJ,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAgB,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,GAAG;IAC9C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,qBAqBA;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/utils.js";
3
+ /**
4
+ * Estado vazio: ícone, título, explicação e uma ação. Para listas sem itens,
5
+ * buscas sem resultado e telas que ainda não têm conteúdo.
6
+ *
7
+ * <EmptyState
8
+ * icon={<FileText />}
9
+ * title="Nenhum documento ainda"
10
+ * description="Crie um documento ou importe uma apresentação para começar."
11
+ * action={<Button><Plus /> Novo documento</Button>}
12
+ * />
13
+ *
14
+ * `bordered` desenha a moldura tracejada, para quando o vazio ocupa o lugar de
15
+ * uma área (lista, quadro) e precisa mostrar o contorno dela.
16
+ */
17
+ function EmptyState({ icon, title, description, action, bordered = false, className, ...props }) {
18
+ return (_jsxs("div", { "data-slot": "empty-state", className: cn("flex flex-col items-center justify-center gap-2 px-6 py-12 text-center", bordered && "rounded-lg border-2 border-dashed border-border", className), ...props, children: [icon && (_jsx("span", { className: "mb-1 flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground [&_svg]:size-6", children: icon })), _jsx("p", { className: "text-base font-semibold text-foreground", children: title }), description && _jsx("p", { className: "max-w-sm text-sm text-muted-foreground", children: description }), action && _jsx("div", { className: "mt-3 flex flex-wrap items-center justify-center gap-2", children: action })] }));
19
+ }
20
+ export { EmptyState };
21
+ //# sourceMappingURL=empty-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty-state.js","sourceRoot":"","sources":["../../src/components/empty-state.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAEpC;;;;;;;;;;;;;GAaG;AACH,SAAS,UAAU,CAAC,EAClB,IAAI,EACJ,KAAK,EACL,WAAW,EACX,MAAM,EACN,QAAQ,GAAG,KAAK,EAChB,SAAS,EACT,GAAG,KAAK,EAOT;IACC,OAAO,CACL,4BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,wEAAwE,EACxE,QAAQ,IAAI,iDAAiD,EAC7D,SAAS,CACV,KACG,KAAK,aAER,IAAI,IAAI,CACP,eAAM,SAAS,EAAC,0GAA0G,YACvH,IAAI,GACA,CACR,EACD,YAAG,SAAS,EAAC,yCAAyC,YAAE,KAAK,GAAK,EACjE,WAAW,IAAI,YAAG,SAAS,EAAC,wCAAwC,YAAE,WAAW,GAAK,EACtF,MAAM,IAAI,cAAK,SAAS,EAAC,uDAAuD,YAAE,MAAM,GAAO,IAC5F,CACP,CAAA;AACH,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
@@ -0,0 +1,47 @@
1
+ import * as React from "react";
2
+ export type MultiSelectOption = {
3
+ value: string;
4
+ label: string;
5
+ /** Agrupa as opções sob um título (ex.: o eixo de uma ação). */
6
+ group?: string;
7
+ /** Bolinha de cor antes do rótulo. */
8
+ color?: string;
9
+ disabled?: boolean;
10
+ };
11
+ /**
12
+ * Seleção de vários itens com busca, como o MultiSelect do Mantine.
13
+ *
14
+ * <MultiSelect
15
+ * options={eixos.map(e => ({ value: e.id, label: e.name, color: e.color }))}
16
+ * value={selecionados}
17
+ * onValueChange={setSelecionados}
18
+ * placeholder="Todos os eixos"
19
+ * />
20
+ *
21
+ * Teclado: digite para filtrar, ↑/↓ para andar, Enter para marcar/desmarcar,
22
+ * Esc para fechar. Dentro de um <Field>, o gatilho recebe o id e os aria-*.
23
+ */
24
+ declare function MultiSelect({ options, value, onValueChange, placeholder, searchPlaceholder, emptyText, maxDisplayed, searchable, size, disabled, className, contentClassName, onOpenChange, ...props }: {
25
+ options: MultiSelectOption[];
26
+ value: string[];
27
+ onValueChange: (value: string[]) => void;
28
+ placeholder?: string;
29
+ searchPlaceholder?: string;
30
+ emptyText?: string;
31
+ /** Quantos selecionados aparecem como selo antes de virar "N selecionados". */
32
+ maxDisplayed?: number;
33
+ searchable?: boolean;
34
+ size?: "sm" | "default";
35
+ disabled?: boolean;
36
+ className?: string;
37
+ contentClassName?: string;
38
+ /** Avisa quando a lista abre e fecha. Útil para gravar a seleção uma vez só,
39
+ * ao fechar, em vez de a cada clique. */
40
+ onOpenChange?: (open: boolean) => void;
41
+ id?: string;
42
+ "aria-label"?: string;
43
+ "aria-describedby"?: string;
44
+ "aria-invalid"?: React.AriaAttributes["aria-invalid"];
45
+ }): React.JSX.Element;
46
+ export { MultiSelect };
47
+ //# sourceMappingURL=multi-select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-select.d.ts","sourceRoot":"","sources":["../../src/components/multi-select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,iBAAS,WAAW,CAAC,EACnB,OAAO,EACP,KAAK,EACL,aAAa,EACb,WAAyB,EACzB,iBAA6B,EAC7B,SAA8B,EAC9B,YAAgB,EAChB,UAAiB,EACjB,IAAgB,EAChB,QAAgB,EAChB,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,GAAG,KAAK,EACT,EAAE;IACD,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,CAAA;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;8CAC0C;IAC1C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,cAAc,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAA;CACtD,qBA0IA;AAED,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -0,0 +1,72 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { CheckIcon, ChevronDownIcon, SearchIcon } from "lucide-react";
5
+ import { cn } from "../lib/utils.js";
6
+ import { Badge } from "./badge.js";
7
+ import { useFieldControl } from "./field.js";
8
+ import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
9
+ /**
10
+ * Seleção de vários itens com busca, como o MultiSelect do Mantine.
11
+ *
12
+ * <MultiSelect
13
+ * options={eixos.map(e => ({ value: e.id, label: e.name, color: e.color }))}
14
+ * value={selecionados}
15
+ * onValueChange={setSelecionados}
16
+ * placeholder="Todos os eixos"
17
+ * />
18
+ *
19
+ * Teclado: digite para filtrar, ↑/↓ para andar, Enter para marcar/desmarcar,
20
+ * Esc para fechar. Dentro de um <Field>, o gatilho recebe o id e os aria-*.
21
+ */
22
+ function MultiSelect({ options, value, onValueChange, placeholder = "Selecione", searchPlaceholder = "Buscar…", emptyText = "Nada encontrado.", maxDisplayed = 2, searchable = true, size = "default", disabled = false, className, contentClassName, onOpenChange, ...props }) {
23
+ const controlProps = useFieldControl(props, { withRequired: false });
24
+ const [open, setOpen] = React.useState(false);
25
+ const [query, setQuery] = React.useState("");
26
+ const [active, setActive] = React.useState(0);
27
+ const listId = React.useId();
28
+ const selected = new Set(value);
29
+ const q = query.trim().toLowerCase();
30
+ const filtered = q ? options.filter(o => o.label.toLowerCase().includes(q)) : options;
31
+ const selectable = filtered.filter(o => !o.disabled);
32
+ function toggle(v) {
33
+ onValueChange(selected.has(v) ? value.filter(x => x !== v) : [...value, v]);
34
+ }
35
+ function onKeyDown(e) {
36
+ if (e.key === "ArrowDown") {
37
+ e.preventDefault();
38
+ setActive(i => Math.min(i + 1, selectable.length - 1));
39
+ }
40
+ else if (e.key === "ArrowUp") {
41
+ e.preventDefault();
42
+ setActive(i => Math.max(i - 1, 0));
43
+ }
44
+ else if (e.key === "Enter") {
45
+ e.preventDefault();
46
+ const o = selectable[active];
47
+ if (o)
48
+ toggle(o.value);
49
+ }
50
+ }
51
+ // Grupos na ordem em que aparecem nas opções.
52
+ const groups = [];
53
+ for (const o of filtered) {
54
+ const g = groups.find(x => x.name === o.group);
55
+ if (g)
56
+ g.items.push(o);
57
+ else
58
+ groups.push({ name: o.group, items: [o] });
59
+ }
60
+ const selectedOptions = options.filter(o => selected.has(o.value));
61
+ return (_jsxs(Popover, { open: open, onOpenChange: o => { setOpen(o); if (!o) {
62
+ setQuery("");
63
+ setActive(0);
64
+ } ; onOpenChange?.(o); }, children: [_jsx(PopoverTrigger, { asChild: true, disabled: disabled, children: _jsxs("button", { type: "button", role: "combobox", "aria-expanded": open, "aria-controls": listId, "data-slot": "multi-select-trigger", "data-size": size, ...controlProps, className: cn("flex w-full min-w-0 cursor-pointer items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent pr-2.5 pl-3 text-left text-sm transition-colors outline-none focus-visible:border-ring disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive data-[size=default]:h-9 data-[size=sm]:h-7.5 data-[state=open]:border-ring dark:bg-input/30", className), children: [_jsx("span", { className: "flex min-w-0 flex-1 items-center gap-1 overflow-hidden", children: selectedOptions.length === 0 ? (_jsx("span", { className: "truncate text-muted-foreground", children: placeholder })) : selectedOptions.length <= maxDisplayed ? (selectedOptions.map(o => (_jsx(Badge, { variant: "secondary", className: "max-w-[10rem] normal-case", children: _jsx("span", { className: "truncate", children: o.label }) }, o.value)))) : (_jsxs("span", { className: "truncate", children: [selectedOptions.length, " selecionado", selectedOptions.length === 1 ? "" : "s"] })) }), _jsx(ChevronDownIcon, { className: "size-4 shrink-0 opacity-70" })] }) }), _jsxs(PopoverContent, { className: cn("w-(--radix-popover-trigger-width) min-w-60 p-0", contentClassName), onKeyDown: onKeyDown, children: [searchable && (_jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3", children: [_jsx(SearchIcon, { className: "size-4 shrink-0 text-muted-foreground" }), _jsx("input", { autoFocus: true, value: query, onChange: e => { setQuery(e.target.value); setActive(0); }, placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-controls": listId, className: "h-9 w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground" })] })), _jsx("div", { id: listId, role: "listbox", "aria-multiselectable": true, className: "max-h-64 overflow-y-auto overscroll-contain p-1", children: filtered.length === 0 ? (_jsx("p", { className: "px-2.5 py-6 text-center text-sm text-muted-foreground", children: emptyText })) : (groups.map(g => (_jsxs("div", { role: "group", "aria-label": g.name, children: [g.name && _jsx("p", { className: "px-2.5 pt-2 pb-1 text-xs font-medium text-muted-foreground", children: g.name }), g.items.map(o => {
65
+ const isSelected = selected.has(o.value);
66
+ const isActive = selectable[active]?.value === o.value;
67
+ return (_jsxs("div", { role: "option", "aria-selected": isSelected, "aria-disabled": o.disabled || undefined, "data-active": isActive || undefined, onMouseEnter: () => { const i = selectable.indexOf(o); if (i >= 0)
68
+ setActive(i); }, onClick: () => !o.disabled && toggle(o.value), className: "flex cursor-pointer items-center gap-2 rounded-md px-2.5 py-1.5 text-sm select-none data-active:bg-accent aria-disabled:cursor-not-allowed aria-disabled:opacity-50", children: [_jsx("span", { className: cn("flex size-4 shrink-0 items-center justify-center rounded border", isSelected ? "border-primary bg-primary text-primary-foreground" : "border-input"), children: isSelected && _jsx(CheckIcon, { className: "size-3 stroke-3" }) }), o.color && _jsx("span", { className: "size-2 shrink-0 rounded-full", style: { background: o.color } }), _jsx("span", { className: "truncate", children: o.label })] }, o.value));
69
+ })] }, g.name ?? "_")))) }), value.length > 0 && (_jsxs("div", { className: "flex items-center justify-between border-t border-border px-3 py-2 text-xs text-muted-foreground", children: [_jsxs("span", { children: [value.length, " selecionado", value.length === 1 ? "" : "s"] }), _jsx("button", { type: "button", onClick: () => onValueChange([]), className: "cursor-pointer rounded font-medium text-foreground outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring/50", children: "Limpar" })] }))] })] }));
70
+ }
71
+ export { MultiSelect };
72
+ //# sourceMappingURL=multi-select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-select.js","sourceRoot":"","sources":["../../src/components/multi-select.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { Popover as PopoverPrimitive } from "radix-ui";
3
+ /** Painel flutuante ancorado num gatilho (Radix Popover), com a mesma
4
+ * superfície dos menus e do Select. */
5
+ declare function Popover(props: React.ComponentProps<typeof PopoverPrimitive.Root>): React.JSX.Element;
6
+ declare function PopoverTrigger(props: React.ComponentProps<typeof PopoverPrimitive.Trigger>): React.JSX.Element;
7
+ declare function PopoverAnchor(props: React.ComponentProps<typeof PopoverPrimitive.Anchor>): React.JSX.Element;
8
+ declare function PopoverContent({ className, align, sideOffset, ...props }: React.ComponentProps<typeof PopoverPrimitive.Content>): React.JSX.Element;
9
+ export { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };
10
+ //# sourceMappingURL=popover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../src/components/popover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAItD;wCACwC;AACxC,iBAAS,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,IAAI,CAAC,qBAEzE;AAED,iBAAS,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,qBAEnF;AAED,iBAAS,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,MAAM,CAAC,qBAEjF;AAED,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,KAAe,EACf,UAAc,EACd,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,qBAevD;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,CAAA"}
@@ -0,0 +1,20 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Popover as PopoverPrimitive } from "radix-ui";
4
+ import { cn } from "../lib/utils.js";
5
+ /** Painel flutuante ancorado num gatilho (Radix Popover), com a mesma
6
+ * superfície dos menus e do Select. */
7
+ function Popover(props) {
8
+ return _jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
9
+ }
10
+ function PopoverTrigger(props) {
11
+ return _jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
12
+ }
13
+ function PopoverAnchor(props) {
14
+ return _jsx(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
15
+ }
16
+ function PopoverContent({ className, align = "start", sideOffset = 4, ...props }) {
17
+ return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { "data-slot": "popover-content", align: align, sideOffset: sideOffset, className: cn("z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-lg bg-popover p-3 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className), ...props }) }));
18
+ }
19
+ export { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };
20
+ //# sourceMappingURL=popover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover.js","sourceRoot":"","sources":["../../src/components/popover.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAGZ,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAEtD,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAEpC;wCACwC;AACxC,SAAS,OAAO,CAAC,KAAyD;IACxE,OAAO,KAAC,gBAAgB,CAAC,IAAI,iBAAW,SAAS,KAAK,KAAK,GAAI,CAAA;AACjE,CAAC;AAED,SAAS,cAAc,CAAC,KAA4D;IAClF,OAAO,KAAC,gBAAgB,CAAC,OAAO,iBAAW,iBAAiB,KAAK,KAAK,GAAI,CAAA;AAC5E,CAAC;AAED,SAAS,aAAa,CAAC,KAA2D;IAChF,OAAO,KAAC,gBAAgB,CAAC,MAAM,iBAAW,gBAAgB,KAAK,KAAK,GAAI,CAAA;AAC1E,CAAC;AAED,SAAS,cAAc,CAAC,EACtB,SAAS,EACT,KAAK,GAAG,OAAO,EACf,UAAU,GAAG,CAAC,EACd,GAAG,KAAK,EAC8C;IACtD,OAAO,CACL,KAAC,gBAAgB,CAAC,MAAM,cACtB,KAAC,gBAAgB,CAAC,OAAO,iBACb,iBAAiB,EAC3B,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,EAAE,CACX,ycAAyc,EACzc,SAAS,CACV,KACG,KAAK,GACT,GACsB,CAC3B,CAAA;AACH,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,CAAA"}
@@ -0,0 +1,18 @@
1
+ import * as React from "react";
2
+ import { Progress as ProgressPrimitive } from "radix-ui";
3
+ declare const tones: {
4
+ default: string;
5
+ success: string;
6
+ warning: string;
7
+ destructive: string;
8
+ info: string;
9
+ };
10
+ /** Barra de progresso (0–100), como o Progress do Mantine. */
11
+ declare function Progress({ value, tone, size, className, ...props }: Omit<React.ComponentProps<typeof ProgressPrimitive.Root>, "value"> & {
12
+ /** 0 a 100. Valores fora da faixa são limitados. */
13
+ value: number;
14
+ tone?: keyof typeof tones;
15
+ size?: "sm" | "default" | "lg";
16
+ }): React.JSX.Element;
17
+ export { Progress };
18
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/components/progress.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAIxD,QAAA,MAAM,KAAK;;;;;;CAMV,CAAA;AAED,8DAA8D;AAC9D,iBAAS,QAAQ,CAAC,EAChB,KAAK,EACL,IAAgB,EAChB,IAAgB,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,GAAG;IACtE,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,OAAO,KAAK,CAAA;IACzB,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAA;CAC/B,qBAoBA;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Progress as ProgressPrimitive } from "radix-ui";
4
+ import { cn } from "../lib/utils.js";
5
+ const tones = {
6
+ default: "bg-primary",
7
+ success: "bg-success",
8
+ warning: "bg-warning",
9
+ destructive: "bg-destructive",
10
+ info: "bg-info",
11
+ };
12
+ /** Barra de progresso (0–100), como o Progress do Mantine. */
13
+ function Progress({ value, tone = "default", size = "default", className, ...props }) {
14
+ const pct = Math.max(0, Math.min(100, value));
15
+ return (_jsx(ProgressPrimitive.Root, { "data-slot": "progress", value: pct, className: cn("relative w-full overflow-hidden rounded-full bg-muted", size === "sm" ? "h-1" : size === "lg" ? "h-3" : "h-2", className), ...props, children: _jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: cn("h-full rounded-full transition-[width] duration-300", tones[tone]), style: { width: `${pct}%` } }) }));
16
+ }
17
+ export { Progress };
18
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/components/progress.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAGZ,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAExD,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAEpC,MAAM,KAAK,GAAG;IACZ,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,YAAY;IACrB,WAAW,EAAE,gBAAgB;IAC7B,IAAI,EAAE,SAAS;CAChB,CAAA;AAED,8DAA8D;AAC9D,SAAS,QAAQ,CAAC,EAChB,KAAK,EACL,IAAI,GAAG,SAAS,EAChB,IAAI,GAAG,SAAS,EAChB,SAAS,EACT,GAAG,KAAK,EAMT;IACC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;IAC7C,OAAO,CACL,KAAC,iBAAiB,CAAC,IAAI,iBACX,UAAU,EACpB,KAAK,EAAE,GAAG,EACV,SAAS,EAAE,EAAE,CACX,uDAAuD,EACvD,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EACrD,SAAS,CACV,KACG,KAAK,YAET,KAAC,iBAAiB,CAAC,SAAS,iBAChB,oBAAoB,EAC9B,SAAS,EAAE,EAAE,CAAC,qDAAqD,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,EACjF,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE,GAC3B,GACqB,CAC1B,CAAA;AACH,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}