@strategicos/ui 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/components/breadcrumb.d.ts +30 -0
- package/dist/components/breadcrumb.d.ts.map +1 -0
- package/dist/components/breadcrumb.js +43 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/multi-select.d.ts +4 -1
- package/dist/components/multi-select.d.ts.map +1 -1
- package/dist/components/multi-select.js +2 -2
- package/dist/components/multi-select.js.map +1 -1
- package/package.json +1 -1
- package/src/components/breadcrumb.tsx +100 -0
- package/src/components/multi-select.tsx +6 -2
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ import { cn } from "@strategicos/ui/utils"
|
|
|
15
15
|
|
|
16
16
|
## Componentes
|
|
17
17
|
|
|
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`
|
|
18
|
+
`accordion` · `alert` · `alert-dialog` · `avatar` · `badge` · `breadcrumb` · `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
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Caminho até a tela atual: os níveis anteriores em tom apagado (links,
|
|
4
|
+
* quando dá para voltar a eles) e o atual em destaque, separados por "/".
|
|
5
|
+
*
|
|
6
|
+
* <Breadcrumb>
|
|
7
|
+
* <BreadcrumbList>
|
|
8
|
+
* <BreadcrumbItem>
|
|
9
|
+
* <BreadcrumbLink asChild><Link href="/configuracoes">Configurações</Link></BreadcrumbLink>
|
|
10
|
+
* </BreadcrumbItem>
|
|
11
|
+
* <BreadcrumbSeparator />
|
|
12
|
+
* <BreadcrumbItem>
|
|
13
|
+
* <BreadcrumbPage>Empresa</BreadcrumbPage>
|
|
14
|
+
* </BreadcrumbItem>
|
|
15
|
+
* </BreadcrumbList>
|
|
16
|
+
* </Breadcrumb>
|
|
17
|
+
*
|
|
18
|
+
* Só o nível atual (`BreadcrumbPage`) encolhe com reticências; os anteriores
|
|
19
|
+
* mantêm o texto inteiro. Um nível sem link é texto puro dentro do item.
|
|
20
|
+
*/
|
|
21
|
+
declare function Breadcrumb({ "aria-label": ariaLabel, ...props }: React.ComponentProps<"nav">): React.JSX.Element;
|
|
22
|
+
declare function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">): React.JSX.Element;
|
|
23
|
+
declare function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
|
|
24
|
+
declare function BreadcrumbLink({ asChild, className, ...props }: React.ComponentProps<"a"> & {
|
|
25
|
+
asChild?: boolean;
|
|
26
|
+
}): React.JSX.Element;
|
|
27
|
+
declare function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
28
|
+
declare function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
|
|
29
|
+
export { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, };
|
|
30
|
+
//# sourceMappingURL=breadcrumb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breadcrumb.d.ts","sourceRoot":"","sources":["../../src/components/breadcrumb.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAS,UAAU,CAAC,EAAE,YAAY,EAAE,SAAqB,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAEjG;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,qBAQ1E;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,qBAQ1E;AAED,iBAAS,cAAc,CAAC,EACtB,OAAe,EACf,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,qBAanD;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,qBAS5E;AAED,iBAAS,mBAAmB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,qBAYzF;AAED,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,mBAAmB,GACpB,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Slot } from "radix-ui";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
/**
|
|
5
|
+
* Caminho até a tela atual: os níveis anteriores em tom apagado (links,
|
|
6
|
+
* quando dá para voltar a eles) e o atual em destaque, separados por "/".
|
|
7
|
+
*
|
|
8
|
+
* <Breadcrumb>
|
|
9
|
+
* <BreadcrumbList>
|
|
10
|
+
* <BreadcrumbItem>
|
|
11
|
+
* <BreadcrumbLink asChild><Link href="/configuracoes">Configurações</Link></BreadcrumbLink>
|
|
12
|
+
* </BreadcrumbItem>
|
|
13
|
+
* <BreadcrumbSeparator />
|
|
14
|
+
* <BreadcrumbItem>
|
|
15
|
+
* <BreadcrumbPage>Empresa</BreadcrumbPage>
|
|
16
|
+
* </BreadcrumbItem>
|
|
17
|
+
* </BreadcrumbList>
|
|
18
|
+
* </Breadcrumb>
|
|
19
|
+
*
|
|
20
|
+
* Só o nível atual (`BreadcrumbPage`) encolhe com reticências; os anteriores
|
|
21
|
+
* mantêm o texto inteiro. Um nível sem link é texto puro dentro do item.
|
|
22
|
+
*/
|
|
23
|
+
function Breadcrumb({ "aria-label": ariaLabel = "Caminho", ...props }) {
|
|
24
|
+
return _jsx("nav", { "data-slot": "breadcrumb", "aria-label": ariaLabel, ...props });
|
|
25
|
+
}
|
|
26
|
+
function BreadcrumbList({ className, ...props }) {
|
|
27
|
+
return (_jsx("ol", { "data-slot": "breadcrumb-list", className: cn("flex min-w-0 items-center gap-1.5 text-sm text-muted-foreground", className), ...props }));
|
|
28
|
+
}
|
|
29
|
+
function BreadcrumbItem({ className, ...props }) {
|
|
30
|
+
return (_jsx("li", { "data-slot": "breadcrumb-item", className: cn("inline-flex min-w-0 items-center gap-1.5", className), ...props }));
|
|
31
|
+
}
|
|
32
|
+
function BreadcrumbLink({ asChild = false, className, ...props }) {
|
|
33
|
+
const Comp = asChild ? Slot.Root : "a";
|
|
34
|
+
return (_jsx(Comp, { "data-slot": "breadcrumb-link", className: cn("rounded-sm whitespace-nowrap transition-colors outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50", className), ...props }));
|
|
35
|
+
}
|
|
36
|
+
function BreadcrumbPage({ className, ...props }) {
|
|
37
|
+
return (_jsx("span", { "data-slot": "breadcrumb-page", "aria-current": "page", className: cn("min-w-0 truncate font-medium text-foreground", className), ...props }));
|
|
38
|
+
}
|
|
39
|
+
function BreadcrumbSeparator({ children, className, ...props }) {
|
|
40
|
+
return (_jsx("li", { "data-slot": "breadcrumb-separator", role: "presentation", "aria-hidden": "true", className: cn("shrink-0 text-muted-foreground/60 [&>svg]:size-3.5", className), ...props, children: children ?? "/" }));
|
|
41
|
+
}
|
|
42
|
+
export { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator, };
|
|
43
|
+
//# sourceMappingURL=breadcrumb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breadcrumb.js","sourceRoot":"","sources":["../../src/components/breadcrumb.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AAEpC;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,UAAU,CAAC,EAAE,YAAY,EAAE,SAAS,GAAG,SAAS,EAAE,GAAG,KAAK,EAA+B;IAChG,OAAO,2BAAe,YAAY,gBAAa,SAAS,KAAM,KAAK,GAAI,CAAA;AACzE,CAAC;AAED,SAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA8B;IACzE,OAAO,CACL,0BACY,iBAAiB,EAC3B,SAAS,EAAE,EAAE,CAAC,iEAAiE,EAAE,SAAS,CAAC,KACvF,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA8B;IACzE,OAAO,CACL,0BACY,iBAAiB,EAC3B,SAAS,EAAE,EAAE,CAAC,0CAA0C,EAAE,SAAS,CAAC,KAChE,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,cAAc,CAAC,EACtB,OAAO,GAAG,KAAK,EACf,SAAS,EACT,GAAG,KAAK,EAC0C;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAA;IAEtC,OAAO,CACL,KAAC,IAAI,iBACO,iBAAiB,EAC3B,SAAS,EAAE,EAAE,CACX,mIAAmI,EACnI,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAgC;IAC3E,OAAO,CACL,4BACY,iBAAiB,kBACd,MAAM,EACnB,SAAS,EAAE,EAAE,CAAC,8CAA8C,EAAE,SAAS,CAAC,KACpE,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAA8B;IACxF,OAAO,CACL,0BACY,sBAAsB,EAChC,IAAI,EAAC,cAAc,iBACP,MAAM,EAClB,SAAS,EAAE,EAAE,CAAC,oDAAoD,EAAE,SAAS,CAAC,KAC1E,KAAK,YAER,QAAQ,IAAI,GAAG,GACb,CACN,CAAA;AACH,CAAC;AAED,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,mBAAmB,GACpB,CAAA"}
|
|
@@ -21,7 +21,7 @@ export type MultiSelectOption = {
|
|
|
21
21
|
* Teclado: digite para filtrar, ↑/↓ para andar, Enter para marcar/desmarcar,
|
|
22
22
|
* Esc para fechar. Dentro de um <Field>, o gatilho recebe o id e os aria-*.
|
|
23
23
|
*/
|
|
24
|
-
declare function MultiSelect({ options, value, onValueChange, placeholder, searchPlaceholder, emptyText, maxDisplayed, searchable, size, disabled, className, contentClassName, ...props }: {
|
|
24
|
+
declare function MultiSelect({ options, value, onValueChange, placeholder, searchPlaceholder, emptyText, maxDisplayed, searchable, size, disabled, className, contentClassName, onOpenChange, ...props }: {
|
|
25
25
|
options: MultiSelectOption[];
|
|
26
26
|
value: string[];
|
|
27
27
|
onValueChange: (value: string[]) => void;
|
|
@@ -35,6 +35,9 @@ declare function MultiSelect({ options, value, onValueChange, placeholder, searc
|
|
|
35
35
|
disabled?: boolean;
|
|
36
36
|
className?: string;
|
|
37
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;
|
|
38
41
|
id?: string;
|
|
39
42
|
"aria-label"?: string;
|
|
40
43
|
"aria-describedby"?: string;
|
|
@@ -1 +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,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,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"}
|
|
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"}
|
|
@@ -19,7 +19,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
|
|
|
19
19
|
* Teclado: digite para filtrar, ↑/↓ para andar, Enter para marcar/desmarcar,
|
|
20
20
|
* Esc para fechar. Dentro de um <Field>, o gatilho recebe o id e os aria-*.
|
|
21
21
|
*/
|
|
22
|
-
function MultiSelect({ options, value, onValueChange, placeholder = "Selecione", searchPlaceholder = "Buscar…", emptyText = "Nada encontrado.", maxDisplayed = 2, searchable = true, size = "default", disabled = false, className, contentClassName, ...props }) {
|
|
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
23
|
const controlProps = useFieldControl(props, { withRequired: false });
|
|
24
24
|
const [open, setOpen] = React.useState(false);
|
|
25
25
|
const [query, setQuery] = React.useState("");
|
|
@@ -61,7 +61,7 @@ function MultiSelect({ options, value, onValueChange, placeholder = "Selecione",
|
|
|
61
61
|
return (_jsxs(Popover, { open: open, onOpenChange: o => { setOpen(o); if (!o) {
|
|
62
62
|
setQuery("");
|
|
63
63
|
setActive(0);
|
|
64
|
-
} }, 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, "
|
|
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
65
|
const isSelected = selected.has(o.value);
|
|
66
66
|
const isActive = selectable[active]?.value === o.value;
|
|
67
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)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi-select.js","sourceRoot":"","sources":["../../src/components/multi-select.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAErE,OAAO,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAA;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAYtE;;;;;;;;;;;;GAYG;AACH,SAAS,WAAW,CAAC,EACnB,OAAO,EACP,KAAK,EACL,aAAa,EACb,WAAW,GAAG,WAAW,EACzB,iBAAiB,GAAG,SAAS,EAC7B,SAAS,GAAG,kBAAkB,EAC9B,YAAY,GAAG,CAAC,EAChB,UAAU,GAAG,IAAI,EACjB,IAAI,GAAG,SAAS,EAChB,QAAQ,GAAG,KAAK,EAChB,SAAS,EACT,gBAAgB,EAChB,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"multi-select.js","sourceRoot":"","sources":["../../src/components/multi-select.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Slot } from "radix-ui"
|
|
3
|
+
|
|
4
|
+
import { cn } from "../lib/utils.js"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Caminho até a tela atual: os níveis anteriores em tom apagado (links,
|
|
8
|
+
* quando dá para voltar a eles) e o atual em destaque, separados por "/".
|
|
9
|
+
*
|
|
10
|
+
* <Breadcrumb>
|
|
11
|
+
* <BreadcrumbList>
|
|
12
|
+
* <BreadcrumbItem>
|
|
13
|
+
* <BreadcrumbLink asChild><Link href="/configuracoes">Configurações</Link></BreadcrumbLink>
|
|
14
|
+
* </BreadcrumbItem>
|
|
15
|
+
* <BreadcrumbSeparator />
|
|
16
|
+
* <BreadcrumbItem>
|
|
17
|
+
* <BreadcrumbPage>Empresa</BreadcrumbPage>
|
|
18
|
+
* </BreadcrumbItem>
|
|
19
|
+
* </BreadcrumbList>
|
|
20
|
+
* </Breadcrumb>
|
|
21
|
+
*
|
|
22
|
+
* Só o nível atual (`BreadcrumbPage`) encolhe com reticências; os anteriores
|
|
23
|
+
* mantêm o texto inteiro. Um nível sem link é texto puro dentro do item.
|
|
24
|
+
*/
|
|
25
|
+
function Breadcrumb({ "aria-label": ariaLabel = "Caminho", ...props }: React.ComponentProps<"nav">) {
|
|
26
|
+
return <nav data-slot="breadcrumb" aria-label={ariaLabel} {...props} />
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
|
30
|
+
return (
|
|
31
|
+
<ol
|
|
32
|
+
data-slot="breadcrumb-list"
|
|
33
|
+
className={cn("flex min-w-0 items-center gap-1.5 text-sm text-muted-foreground", className)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
|
|
40
|
+
return (
|
|
41
|
+
<li
|
|
42
|
+
data-slot="breadcrumb-item"
|
|
43
|
+
className={cn("inline-flex min-w-0 items-center gap-1.5", className)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function BreadcrumbLink({
|
|
50
|
+
asChild = false,
|
|
51
|
+
className,
|
|
52
|
+
...props
|
|
53
|
+
}: React.ComponentProps<"a"> & { asChild?: boolean }) {
|
|
54
|
+
const Comp = asChild ? Slot.Root : "a"
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Comp
|
|
58
|
+
data-slot="breadcrumb-link"
|
|
59
|
+
className={cn(
|
|
60
|
+
"rounded-sm whitespace-nowrap transition-colors outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50",
|
|
61
|
+
className
|
|
62
|
+
)}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
|
69
|
+
return (
|
|
70
|
+
<span
|
|
71
|
+
data-slot="breadcrumb-page"
|
|
72
|
+
aria-current="page"
|
|
73
|
+
className={cn("min-w-0 truncate font-medium text-foreground", className)}
|
|
74
|
+
{...props}
|
|
75
|
+
/>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<"li">) {
|
|
80
|
+
return (
|
|
81
|
+
<li
|
|
82
|
+
data-slot="breadcrumb-separator"
|
|
83
|
+
role="presentation"
|
|
84
|
+
aria-hidden="true"
|
|
85
|
+
className={cn("shrink-0 text-muted-foreground/60 [&>svg]:size-3.5", className)}
|
|
86
|
+
{...props}
|
|
87
|
+
>
|
|
88
|
+
{children ?? "/"}
|
|
89
|
+
</li>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
Breadcrumb,
|
|
95
|
+
BreadcrumbList,
|
|
96
|
+
BreadcrumbItem,
|
|
97
|
+
BreadcrumbLink,
|
|
98
|
+
BreadcrumbPage,
|
|
99
|
+
BreadcrumbSeparator,
|
|
100
|
+
}
|
|
@@ -44,6 +44,7 @@ function MultiSelect({
|
|
|
44
44
|
disabled = false,
|
|
45
45
|
className,
|
|
46
46
|
contentClassName,
|
|
47
|
+
onOpenChange,
|
|
47
48
|
...props
|
|
48
49
|
}: {
|
|
49
50
|
options: MultiSelectOption[]
|
|
@@ -59,6 +60,9 @@ function MultiSelect({
|
|
|
59
60
|
disabled?: boolean
|
|
60
61
|
className?: string
|
|
61
62
|
contentClassName?: string
|
|
63
|
+
/** Avisa quando a lista abre e fecha. Útil para gravar a seleção uma vez só,
|
|
64
|
+
* ao fechar, em vez de a cada clique. */
|
|
65
|
+
onOpenChange?: (open: boolean) => void
|
|
62
66
|
id?: string
|
|
63
67
|
"aria-label"?: string
|
|
64
68
|
"aria-describedby"?: string
|
|
@@ -96,7 +100,7 @@ function MultiSelect({
|
|
|
96
100
|
const selectedOptions = options.filter(o => selected.has(o.value))
|
|
97
101
|
|
|
98
102
|
return (
|
|
99
|
-
<Popover open={open} onOpenChange={o => { setOpen(o); if (!o) { setQuery(""); setActive(0) } }}>
|
|
103
|
+
<Popover open={open} onOpenChange={o => { setOpen(o); if (!o) { setQuery(""); setActive(0) }; onOpenChange?.(o) }}>
|
|
100
104
|
<PopoverTrigger asChild disabled={disabled}>
|
|
101
105
|
<button
|
|
102
106
|
type="button"
|
|
@@ -121,7 +125,7 @@ function MultiSelect({
|
|
|
121
125
|
</Badge>
|
|
122
126
|
))
|
|
123
127
|
) : (
|
|
124
|
-
<span className="truncate">{selectedOptions.length}
|
|
128
|
+
<span className="truncate">{selectedOptions.length} selecionado{selectedOptions.length === 1 ? "" : "s"}</span>
|
|
125
129
|
)}
|
|
126
130
|
</span>
|
|
127
131
|
<ChevronDownIcon className="size-4 shrink-0 opacity-70" />
|