@strategicos/ui 0.6.1 → 0.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 +36 -2
- package/THIRD_PARTY_NOTICES.md +187 -0
- 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/calendar.d.ts +24 -0
- package/dist/components/calendar.d.ts.map +1 -0
- package/dist/components/calendar.js +81 -0
- package/dist/components/calendar.js.map +1 -0
- package/dist/components/combobox.d.ts +73 -0
- package/dist/components/combobox.d.ts.map +1 -0
- package/dist/components/combobox.js +193 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/date-picker.d.ts +78 -0
- package/dist/components/date-picker.d.ts.map +1 -0
- package/dist/components/date-picker.js +142 -0
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/multi-select.d.ts.map +1 -1
- package/dist/components/multi-select.js +2 -1
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/select.d.ts +16 -1
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +24 -2
- package/dist/components/select.js.map +1 -1
- package/package.json +2 -1
- package/src/components/breadcrumb.tsx +100 -0
- package/src/components/calendar.tsx +139 -0
- package/src/components/combobox.tsx +390 -0
- package/src/components/date-picker.tsx +414 -0
- package/src/components/multi-select.tsx +3 -1
- package/src/components/select.tsx +29 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Select as SelectPrimitive } from "radix-ui";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
4
5
|
import { cn } from "../lib/utils.js";
|
|
5
6
|
import { useFieldControl } from "./field.js";
|
|
6
7
|
import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react";
|
|
@@ -13,8 +14,29 @@ function SelectGroup({ className, ...props }) {
|
|
|
13
14
|
function SelectValue({ ...props }) {
|
|
14
15
|
return _jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Visual do gatilho de seleção: borda, foco, aberto, desabilitado, erro e
|
|
19
|
+
* tamanhos. É o mesmo do SelectTrigger, exportado para os gatilhos que não são
|
|
20
|
+
* o Select do Radix (MultiSelect, Combobox, DatePicker ou um Popover próprio)
|
|
21
|
+
* não precisarem copiar as classes — cópia que fica para trás quando o kit
|
|
22
|
+
* muda.
|
|
23
|
+
*
|
|
24
|
+
* Placeholder: marque o gatilho com `data-placeholder` enquanto estiver vazio,
|
|
25
|
+
* como o Radix faz.
|
|
26
|
+
*
|
|
27
|
+
* <button className={cn(selectTriggerVariants({ size }), "w-full")} …>
|
|
28
|
+
*/
|
|
29
|
+
const selectTriggerVariants = cva("flex items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent pr-2.5 pl-3 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring data-[state=open]:border-ring disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
30
|
+
variants: {
|
|
31
|
+
size: {
|
|
32
|
+
default: "h-9",
|
|
33
|
+
sm: "h-7.5 rounded-[min(var(--radius-md),10px)]",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
defaultVariants: { size: "default" },
|
|
37
|
+
});
|
|
16
38
|
function SelectTrigger({ className, size = "default", children, ...props }) {
|
|
17
|
-
return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn("
|
|
39
|
+
return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn(selectTriggerVariants({ size }), "w-fit py-2 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5", className), ...useFieldControl(props, { withRequired: false }), children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronDownIcon, { className: "pointer-events-none size-4 opacity-70" }) })] }));
|
|
18
40
|
}
|
|
19
41
|
function SelectContent({ className, children, position = "popper", align = "start", ...props }) {
|
|
20
42
|
return (_jsx(SelectPrimitive.Portal, { children: _jsxs(SelectPrimitive.Content, { "data-slot": "select-content", "data-align-trigger": position === "item-aligned", className: cn("relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-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", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className), position: position, align: align, ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.Viewport, { "data-position": position, className: cn("p-1 data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)", position === "popper" && ""), children: children }), _jsx(SelectScrollDownButton, {})] }) }));
|
|
@@ -34,5 +56,5 @@ function SelectScrollUpButton({ className, ...props }) {
|
|
|
34
56
|
function SelectScrollDownButton({ className, ...props }) {
|
|
35
57
|
return (_jsx(SelectPrimitive.ScrollDownButton, { "data-slot": "select-scroll-down-button", className: cn("z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: _jsx(ChevronDownIcon, {}) }));
|
|
36
58
|
}
|
|
37
|
-
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, };
|
|
59
|
+
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, selectTriggerVariants, };
|
|
38
60
|
//# sourceMappingURL=select.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/components/select.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAGZ,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/components/select.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strategicos/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Componentes React da Strategicos (shadcn + Radix + Tailwind v4).",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"clsx": "^2.1.1",
|
|
44
44
|
"lucide-react": "^1.12.0",
|
|
45
45
|
"radix-ui": "^1.4.3",
|
|
46
|
+
"react-day-picker": "^10.0.2",
|
|
46
47
|
"tailwind-merge": "^3.5.0",
|
|
47
48
|
"tw-animate-css": "^1.4.0"
|
|
48
49
|
},
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
// Derivado do Calendar do Tremor (Apache-2.0) e modificado pela Strategicos.
|
|
4
|
+
// Ver THIRD_PARTY_NOTICES.md.
|
|
5
|
+
|
|
6
|
+
import * as React from "react"
|
|
7
|
+
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react"
|
|
8
|
+
import { DayPicker, type DayButtonProps } from "react-day-picker"
|
|
9
|
+
import { ptBR } from "react-day-picker/locale"
|
|
10
|
+
|
|
11
|
+
import { cn } from "../lib/utils.js"
|
|
12
|
+
import { buttonVariants } from "./button.js"
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Calendário (react-day-picker), com o desenho do Calendar do Tremor nos tokens
|
|
16
|
+
* do kit. É a peça de dentro do DatePicker; use solto quando o calendário fica
|
|
17
|
+
* aberto na tela.
|
|
18
|
+
*
|
|
19
|
+
* <Calendar mode="single" selected={dia} onSelect={setDia} />
|
|
20
|
+
*
|
|
21
|
+
* Padrões: português do Brasil (semana começando no domingo) e dias de fora do
|
|
22
|
+
* mês visíveis. `captionLayout="dropdown"` troca o título por seletores de mês
|
|
23
|
+
* e ano — útil para datas distantes, como nascimento. Aceita todas as props do
|
|
24
|
+
* DayPicker.
|
|
25
|
+
*/
|
|
26
|
+
function Calendar({
|
|
27
|
+
className,
|
|
28
|
+
classNames,
|
|
29
|
+
captionLayout = "label",
|
|
30
|
+
showOutsideDays = true,
|
|
31
|
+
locale = ptBR,
|
|
32
|
+
components,
|
|
33
|
+
...props
|
|
34
|
+
}: React.ComponentProps<typeof DayPicker>) {
|
|
35
|
+
return (
|
|
36
|
+
<DayPicker
|
|
37
|
+
data-slot="calendar"
|
|
38
|
+
locale={locale}
|
|
39
|
+
showOutsideDays={showOutsideDays}
|
|
40
|
+
captionLayout={captionLayout}
|
|
41
|
+
className={cn("w-fit p-3", className)}
|
|
42
|
+
classNames={{
|
|
43
|
+
months: "relative flex flex-col gap-4 sm:flex-row",
|
|
44
|
+
month: "flex w-full flex-col gap-3",
|
|
45
|
+
nav: "absolute inset-x-0 top-0 flex items-center justify-between",
|
|
46
|
+
button_previous: cn(buttonVariants({ variant: "ghost", size: "icon-sm" }), "aria-disabled:pointer-events-none aria-disabled:opacity-40"),
|
|
47
|
+
button_next: cn(buttonVariants({ variant: "ghost", size: "icon-sm" }), "aria-disabled:pointer-events-none aria-disabled:opacity-40"),
|
|
48
|
+
month_caption: "flex h-7.5 items-center justify-center px-8",
|
|
49
|
+
// Os meses vêm em minúscula no pt-BR ("outubro 2026"): só a primeira
|
|
50
|
+
// letra sobe — `capitalize` faria "Outubro De 2026" em outros formatos.
|
|
51
|
+
caption_label: cn(
|
|
52
|
+
"text-sm font-semibold select-none first-letter:uppercase",
|
|
53
|
+
captionLayout !== "label" && "flex h-7.5 items-center gap-1 rounded-md pr-1 pl-2 font-medium [&>svg]:size-3.5 [&>svg]:text-muted-foreground"
|
|
54
|
+
),
|
|
55
|
+
dropdowns: "flex items-center gap-1.5 text-sm",
|
|
56
|
+
dropdown_root: "relative rounded-md border border-input transition-colors has-focus-visible:border-ring",
|
|
57
|
+
dropdown: "absolute inset-0 cursor-pointer opacity-0",
|
|
58
|
+
month_grid: "w-full border-collapse",
|
|
59
|
+
weekdays: "flex",
|
|
60
|
+
weekday: "w-9 pb-1 text-xs font-medium text-muted-foreground select-none",
|
|
61
|
+
week: "mt-0.5 flex w-full",
|
|
62
|
+
day: "relative size-9 p-0 text-center select-none",
|
|
63
|
+
// Faixa do intervalo: o fundo fica na célula, para os dias do meio
|
|
64
|
+
// emendarem; as pontas arredondam do lado de fora.
|
|
65
|
+
range_start: "rounded-l-md bg-accent",
|
|
66
|
+
range_middle: "bg-accent",
|
|
67
|
+
range_end: "rounded-r-md bg-accent",
|
|
68
|
+
today: "",
|
|
69
|
+
outside: "text-muted-foreground aria-selected:text-muted-foreground",
|
|
70
|
+
disabled: "text-muted-foreground opacity-50",
|
|
71
|
+
hidden: "invisible",
|
|
72
|
+
...classNames,
|
|
73
|
+
}}
|
|
74
|
+
components={{
|
|
75
|
+
Chevron: ({ className, orientation, ...rest }) => {
|
|
76
|
+
const Icon = orientation === "left" ? ChevronLeftIcon : orientation === "right" ? ChevronRightIcon : ChevronDownIcon
|
|
77
|
+
return <Icon className={cn("size-4", className)} {...rest} />
|
|
78
|
+
},
|
|
79
|
+
DayButton: CalendarDayButton,
|
|
80
|
+
...components,
|
|
81
|
+
}}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Dia do calendário. Os estados viram data-* para o estilo, e "hoje" ganha o
|
|
88
|
+
* traço embaixo do número, como no Tremor.
|
|
89
|
+
*
|
|
90
|
+
* O dia escolhido é `data-picked`, e não `data-selected-*`: o styles.css
|
|
91
|
+
* registra a variante `data-selected`, e o Tailwind lê `data-selected-x:` como
|
|
92
|
+
* essa variante com um valor — a classe é descartada sem aviso. */
|
|
93
|
+
function CalendarDayButton({ className, day, modifiers, children, ...props }: DayButtonProps) {
|
|
94
|
+
const ref = React.useRef<HTMLButtonElement>(null)
|
|
95
|
+
React.useEffect(() => {
|
|
96
|
+
if (modifiers.focused) ref.current?.focus()
|
|
97
|
+
}, [modifiers.focused])
|
|
98
|
+
|
|
99
|
+
const single = modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<button
|
|
103
|
+
ref={ref}
|
|
104
|
+
type="button"
|
|
105
|
+
data-picked={single || undefined}
|
|
106
|
+
data-range-start={modifiers.range_start || undefined}
|
|
107
|
+
data-range-end={modifiers.range_end || undefined}
|
|
108
|
+
data-range-middle={modifiers.range_middle || undefined}
|
|
109
|
+
data-today={modifiers.today || undefined}
|
|
110
|
+
className={cn(
|
|
111
|
+
"relative flex size-9 cursor-pointer items-center justify-center rounded-md text-sm tabular-nums outline-none transition-colors",
|
|
112
|
+
"hover:bg-accent hover:text-accent-foreground focus-visible:z-10 focus-visible:ring-3 focus-visible:ring-ring/50",
|
|
113
|
+
"disabled:pointer-events-none",
|
|
114
|
+
"data-today:font-semibold",
|
|
115
|
+
// Dourado só como preenchimento, com o texto escuro do primary-foreground.
|
|
116
|
+
"data-picked:bg-primary data-picked:text-primary-foreground data-picked:hover:bg-primary-hover",
|
|
117
|
+
"data-range-start:bg-primary data-range-start:text-primary-foreground data-range-start:hover:bg-primary-hover",
|
|
118
|
+
"data-range-end:bg-primary data-range-end:text-primary-foreground data-range-end:hover:bg-primary-hover",
|
|
119
|
+
"data-range-middle:rounded-none data-range-middle:hover:bg-transparent data-range-middle:hover:underline",
|
|
120
|
+
className
|
|
121
|
+
)}
|
|
122
|
+
{...props}
|
|
123
|
+
>
|
|
124
|
+
{children}
|
|
125
|
+
{modifiers.today && (
|
|
126
|
+
<span
|
|
127
|
+
aria-hidden
|
|
128
|
+
className={cn(
|
|
129
|
+
"absolute bottom-1.5 left-1/2 h-0.5 w-4 -translate-x-1/2 rounded-full",
|
|
130
|
+
// primary-strong: o dourado claro não chega a 3:1 sobre o branco.
|
|
131
|
+
single || modifiers.range_start || modifiers.range_end ? "bg-primary-foreground" : "bg-primary-strong"
|
|
132
|
+
)}
|
|
133
|
+
/>
|
|
134
|
+
)}
|
|
135
|
+
</button>
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export { Calendar, CalendarDayButton }
|