@financedistrict/apps-ui 0.1.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/LICENSE +19 -0
- package/README.md +119 -0
- package/dist/Radio-BYWz1n7p.d.cts +32 -0
- package/dist/Radio-BYWz1n7p.d.ts +32 -0
- package/dist/SelectTrigger-By0iPBI3.d.cts +78 -0
- package/dist/SelectTrigger-By0iPBI3.d.ts +78 -0
- package/dist/accordion.cjs +322 -0
- package/dist/accordion.d.cts +156 -0
- package/dist/accordion.d.ts +156 -0
- package/dist/accordion.js +2 -0
- package/dist/apps-ui.umd.js +1 -0
- package/dist/button.cjs +366 -0
- package/dist/button.d.cts +52 -0
- package/dist/button.d.ts +52 -0
- package/dist/button.js +3 -0
- package/dist/checkbox.cjs +74 -0
- package/dist/checkbox.d.cts +63 -0
- package/dist/checkbox.d.ts +63 -0
- package/dist/checkbox.js +2 -0
- package/dist/chunk-3RU7JMFE.js +27 -0
- package/dist/chunk-5TWRK4NW.js +783 -0
- package/dist/chunk-7EOSDFS3.js +9 -0
- package/dist/chunk-AIQ4UOGK.js +142 -0
- package/dist/chunk-B3MMGTPV.js +200 -0
- package/dist/chunk-DAHQYLUI.js +146 -0
- package/dist/chunk-DGBXADSS.js +1 -0
- package/dist/chunk-E6KPNTWW.js +295 -0
- package/dist/chunk-EOAB6G2D.js +149 -0
- package/dist/chunk-FAOVKDVM.js +32 -0
- package/dist/chunk-FV76Z4Z2.js +78 -0
- package/dist/chunk-GLTLBUZ7.js +285 -0
- package/dist/chunk-GTZFV43T.js +154 -0
- package/dist/chunk-HRGZNL4A.js +88 -0
- package/dist/chunk-IEVN3J2F.js +98 -0
- package/dist/chunk-IRS3T6LF.js +352 -0
- package/dist/chunk-IYYHCQXG.js +146 -0
- package/dist/chunk-JIXW3455.js +89 -0
- package/dist/chunk-N4VAP2GB.js +77 -0
- package/dist/chunk-SJ2ZRYVV.js +167 -0
- package/dist/chunk-SNU4YXOR.js +66 -0
- package/dist/chunk-TT6JQATV.js +99 -0
- package/dist/chunk-UPQ3ZPCO.js +66 -0
- package/dist/chunk-UVUSVFOH.js +264 -0
- package/dist/chunk-WJFPGGJB.js +255 -0
- package/dist/chunk-WXEBQA7A.js +371 -0
- package/dist/chunk-Y2O4YYZQ.js +184 -0
- package/dist/cut-corner.cjs +111 -0
- package/dist/cut-corner.d.cts +49 -0
- package/dist/cut-corner.d.ts +49 -0
- package/dist/cut-corner.js +1 -0
- package/dist/dialog.cjs +441 -0
- package/dist/dialog.d.cts +240 -0
- package/dist/dialog.d.ts +240 -0
- package/dist/dialog.js +3 -0
- package/dist/feature-card.cjs +182 -0
- package/dist/feature-card.d.cts +54 -0
- package/dist/feature-card.d.ts +54 -0
- package/dist/feature-card.js +2 -0
- package/dist/filter.cjs +873 -0
- package/dist/filter.d.cts +129 -0
- package/dist/filter.d.ts +129 -0
- package/dist/filter.js +6 -0
- package/dist/index.cjs +4583 -0
- package/dist/index.d.cts +29 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +27 -0
- package/dist/inline-select.cjs +856 -0
- package/dist/inline-select.d.cts +92 -0
- package/dist/inline-select.d.ts +92 -0
- package/dist/inline-select.js +6 -0
- package/dist/input.cjs +263 -0
- package/dist/input.d.cts +157 -0
- package/dist/input.d.ts +157 -0
- package/dist/input.js +4 -0
- package/dist/panel.cjs +185 -0
- package/dist/panel.d.cts +103 -0
- package/dist/panel.d.ts +103 -0
- package/dist/panel.js +2 -0
- package/dist/property-grid.cjs +110 -0
- package/dist/property-grid.d.cts +56 -0
- package/dist/property-grid.d.ts +56 -0
- package/dist/property-grid.js +2 -0
- package/dist/radio.cjs +74 -0
- package/dist/radio.d.cts +39 -0
- package/dist/radio.d.ts +39 -0
- package/dist/radio.js +2 -0
- package/dist/scrollbar.cjs +34 -0
- package/dist/scrollbar.d.cts +35 -0
- package/dist/scrollbar.d.ts +35 -0
- package/dist/scrollbar.js +1 -0
- package/dist/search-bar.cjs +408 -0
- package/dist/search-bar.d.cts +42 -0
- package/dist/search-bar.d.ts +42 -0
- package/dist/search-bar.js +4 -0
- package/dist/select.cjs +998 -0
- package/dist/select.d.cts +357 -0
- package/dist/select.d.ts +357 -0
- package/dist/select.js +5 -0
- package/dist/selectable-feature-card.cjs +159 -0
- package/dist/selectable-feature-card.d.cts +74 -0
- package/dist/selectable-feature-card.d.ts +74 -0
- package/dist/selectable-feature-card.js +3 -0
- package/dist/sidebar-item.cjs +175 -0
- package/dist/sidebar-item.d.cts +75 -0
- package/dist/sidebar-item.d.ts +75 -0
- package/dist/sidebar-item.js +2 -0
- package/dist/switch.cjs +86 -0
- package/dist/switch.d.cts +72 -0
- package/dist/switch.d.ts +72 -0
- package/dist/switch.js +2 -0
- package/dist/table-cell.cjs +196 -0
- package/dist/table-cell.d.cts +76 -0
- package/dist/table-cell.d.ts +76 -0
- package/dist/table-cell.js +2 -0
- package/dist/table-title.cjs +34 -0
- package/dist/table-title.d.cts +16 -0
- package/dist/table-title.d.ts +16 -0
- package/dist/table-title.js +2 -0
- package/dist/tabs.cjs +299 -0
- package/dist/tabs.d.cts +116 -0
- package/dist/tabs.d.ts +116 -0
- package/dist/tabs.js +2 -0
- package/dist/toast.cjs +87 -0
- package/dist/toast.d.cts +48 -0
- package/dist/toast.d.ts +48 -0
- package/dist/toast.js +2 -0
- package/dist/token-input.cjs +415 -0
- package/dist/token-input.d.cts +90 -0
- package/dist/token-input.d.ts +90 -0
- package/dist/token-input.js +3 -0
- package/dist/tooltip.cjs +384 -0
- package/dist/tooltip.d.cts +142 -0
- package/dist/tooltip.d.ts +142 -0
- package/dist/tooltip.js +2 -0
- package/package.json +200 -0
- package/src/fonts.css +33 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { cn } from './chunk-7EOSDFS3.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var tableCellVariants = cva(
|
|
7
|
+
[
|
|
8
|
+
// The cell is the group that drives hover/active styling of its descendants.
|
|
9
|
+
"group",
|
|
10
|
+
// Layout — 56px row, slots on a horizontal axis; overflow clipped for truncation.
|
|
11
|
+
"flex h-14 w-full items-center gap-3 overflow-hidden px-2 py-4",
|
|
12
|
+
// Brand-accent background on hover / keyboard-focus / active (self). Reset
|
|
13
|
+
// native control chrome so an asChild button/anchor styles cleanly.
|
|
14
|
+
"appearance-none bg-transparent outline-none transition-colors",
|
|
15
|
+
"hover:bg-card-brand-accent focus-visible:bg-card-brand-accent data-[state=active]:bg-card-brand-accent"
|
|
16
|
+
],
|
|
17
|
+
{
|
|
18
|
+
variants: {
|
|
19
|
+
last: {
|
|
20
|
+
// Row divider on all but the last row; recolors on hover / focus / active.
|
|
21
|
+
false: [
|
|
22
|
+
"border-b border-card-border",
|
|
23
|
+
"hover:border-card-brand-border-accent focus-visible:border-card-brand-border-accent data-[state=active]:border-card-brand-border-accent"
|
|
24
|
+
],
|
|
25
|
+
true: ""
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
defaultVariants: {
|
|
29
|
+
last: false
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
function setRef(ref, node) {
|
|
34
|
+
if (typeof ref === "function") ref(node);
|
|
35
|
+
else if (ref) ref.current = node;
|
|
36
|
+
}
|
|
37
|
+
function TableCell({
|
|
38
|
+
className,
|
|
39
|
+
last = false,
|
|
40
|
+
leading,
|
|
41
|
+
trailing,
|
|
42
|
+
active = false,
|
|
43
|
+
asChild = false,
|
|
44
|
+
children,
|
|
45
|
+
ref,
|
|
46
|
+
...props
|
|
47
|
+
}) {
|
|
48
|
+
const rootClassName = cn(tableCellVariants({ last }), className);
|
|
49
|
+
const dataState = active ? "active" : void 0;
|
|
50
|
+
const leadingSlot = leading != null ? /* @__PURE__ */ jsx(
|
|
51
|
+
"span",
|
|
52
|
+
{
|
|
53
|
+
"data-slot": "table-cell-leading",
|
|
54
|
+
className: "flex shrink-0 items-center",
|
|
55
|
+
children: leading
|
|
56
|
+
}
|
|
57
|
+
) : null;
|
|
58
|
+
const trailingSlot = trailing != null ? /* @__PURE__ */ jsx(
|
|
59
|
+
"span",
|
|
60
|
+
{
|
|
61
|
+
"data-slot": "table-cell-trailing",
|
|
62
|
+
className: "flex shrink-0 items-center",
|
|
63
|
+
children: trailing
|
|
64
|
+
}
|
|
65
|
+
) : null;
|
|
66
|
+
const middleSlot = (middle) => middle != null ? /* @__PURE__ */ jsx(
|
|
67
|
+
"span",
|
|
68
|
+
{
|
|
69
|
+
"data-slot": "table-cell-middle",
|
|
70
|
+
className: "flex min-w-0 flex-1 flex-col",
|
|
71
|
+
children: middle
|
|
72
|
+
}
|
|
73
|
+
) : null;
|
|
74
|
+
if (asChild) {
|
|
75
|
+
if (!React.isValidElement(children)) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
"TableCell: `asChild` requires a single React element child"
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
const child = children;
|
|
81
|
+
const childProps = child.props;
|
|
82
|
+
return React.cloneElement(
|
|
83
|
+
child,
|
|
84
|
+
{
|
|
85
|
+
...props,
|
|
86
|
+
...childProps,
|
|
87
|
+
"data-slot": "table-cell",
|
|
88
|
+
"data-state": dataState,
|
|
89
|
+
className: cn(
|
|
90
|
+
rootClassName,
|
|
91
|
+
childProps.className
|
|
92
|
+
),
|
|
93
|
+
ref: (node) => {
|
|
94
|
+
setRef(ref, node);
|
|
95
|
+
setRef(childProps.ref, node);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
leadingSlot,
|
|
99
|
+
middleSlot(childProps.children),
|
|
100
|
+
trailingSlot
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
return /* @__PURE__ */ jsxs(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
"data-slot": "table-cell",
|
|
107
|
+
"data-state": dataState,
|
|
108
|
+
className: rootClassName,
|
|
109
|
+
ref,
|
|
110
|
+
...props,
|
|
111
|
+
children: [
|
|
112
|
+
leadingSlot,
|
|
113
|
+
middleSlot(children),
|
|
114
|
+
trailingSlot
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
function CellText({ label, meta, className, ...props }) {
|
|
120
|
+
const hasMeta = Array.isArray(meta) && meta.length > 0;
|
|
121
|
+
return /* @__PURE__ */ jsxs(
|
|
122
|
+
"div",
|
|
123
|
+
{
|
|
124
|
+
"data-slot": "cell-text",
|
|
125
|
+
className: cn("flex min-w-0 flex-col gap-0.5", className),
|
|
126
|
+
...props,
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ jsx(
|
|
129
|
+
"span",
|
|
130
|
+
{
|
|
131
|
+
"data-slot": "cell-text-label",
|
|
132
|
+
className: cn(
|
|
133
|
+
"body-03 min-w-0 truncate",
|
|
134
|
+
"text-card-foreground",
|
|
135
|
+
"group-hover:text-card-brand-foreground group-focus-visible:text-card-brand-foreground group-data-[state=active]:text-card-brand-foreground"
|
|
136
|
+
),
|
|
137
|
+
children: label
|
|
138
|
+
}
|
|
139
|
+
),
|
|
140
|
+
hasMeta && /* @__PURE__ */ jsx(
|
|
141
|
+
"div",
|
|
142
|
+
{
|
|
143
|
+
"data-slot": "cell-text-meta",
|
|
144
|
+
className: cn(
|
|
145
|
+
"flex min-w-0 items-center gap-1",
|
|
146
|
+
"body-mono-04",
|
|
147
|
+
"text-card-foreground-muted",
|
|
148
|
+
"group-hover:text-card-brand-foreground-muted group-focus-visible:text-card-brand-foreground-muted group-data-[state=active]:text-card-brand-foreground-muted"
|
|
149
|
+
),
|
|
150
|
+
children: meta.map((segment, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
151
|
+
index > 0 && /* @__PURE__ */ jsx(
|
|
152
|
+
"span",
|
|
153
|
+
{
|
|
154
|
+
"aria-hidden": "true",
|
|
155
|
+
className: "size-0.5 shrink-0 rounded-full bg-current"
|
|
156
|
+
}
|
|
157
|
+
),
|
|
158
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: segment })
|
|
159
|
+
] }, index))
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export { CellText, TableCell, tableCellVariants };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { cn } from './chunk-7EOSDFS3.js';
|
|
2
|
+
import { CheckIcon } from '@phosphor-icons/react';
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var checkboxVariants = cva([
|
|
7
|
+
// Box — 20×20 (`size-5`), 2px radius (Figma `radius/xs`), 1px border.
|
|
8
|
+
// `peer` lets the sibling indicator react to :checked / :disabled.
|
|
9
|
+
"peer size-5 shrink-0 appearance-none rounded-xs border",
|
|
10
|
+
"cursor-pointer transition-colors",
|
|
11
|
+
// Default
|
|
12
|
+
"bg-background border-border",
|
|
13
|
+
// Hover (unselected) — focus keeps the DEFAULT border; only the ring signals
|
|
14
|
+
// focus (so focus doesn't visually read as hover).
|
|
15
|
+
"hover:border-border-accent",
|
|
16
|
+
// Focus ring — suppress the native ring, draw the shared `--focus` ring the
|
|
17
|
+
// same way ghost Button does: 2px stroke, 2px offset (`outline-solid`
|
|
18
|
+
// restores what `outline-none` zeroed).
|
|
19
|
+
"outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus",
|
|
20
|
+
// Selected
|
|
21
|
+
"checked:bg-brand-primary-background checked:border-brand-primary-border",
|
|
22
|
+
"checked:hover:bg-brand-primary-accent checked:hover:border-brand-primary-border",
|
|
23
|
+
"checked:focus-visible:bg-brand-primary-accent checked:focus-visible:border-brand-primary-border",
|
|
24
|
+
// Disabled — shared neutral-muted look whether selected or not (per Figma)
|
|
25
|
+
"disabled:pointer-events-none disabled:cursor-not-allowed disabled:border-border-muted",
|
|
26
|
+
"checked:disabled:bg-background checked:disabled:border-border-muted"
|
|
27
|
+
]);
|
|
28
|
+
function Checkbox({
|
|
29
|
+
className,
|
|
30
|
+
wrapperClassName,
|
|
31
|
+
onChange,
|
|
32
|
+
onCheckedChange,
|
|
33
|
+
...props
|
|
34
|
+
}) {
|
|
35
|
+
const handleChange = (event) => {
|
|
36
|
+
onChange?.(event);
|
|
37
|
+
onCheckedChange?.(event.currentTarget.checked);
|
|
38
|
+
};
|
|
39
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("relative inline-flex shrink-0", wrapperClassName), children: [
|
|
40
|
+
/* @__PURE__ */ jsx(
|
|
41
|
+
"input",
|
|
42
|
+
{
|
|
43
|
+
type: "checkbox",
|
|
44
|
+
"data-slot": "checkbox",
|
|
45
|
+
className: cn(checkboxVariants(), className),
|
|
46
|
+
...props,
|
|
47
|
+
onChange: handleChange
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
CheckIcon,
|
|
52
|
+
{
|
|
53
|
+
"aria-hidden": "true",
|
|
54
|
+
weight: "regular",
|
|
55
|
+
"data-slot": "checkbox-indicator",
|
|
56
|
+
className: cn(
|
|
57
|
+
"pointer-events-none invisible absolute inset-0 m-auto size-4",
|
|
58
|
+
"text-brand-primary-foreground",
|
|
59
|
+
"peer-checked:visible peer-disabled:text-foreground-muted"
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { Checkbox, checkboxVariants };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { cn } from './chunk-7EOSDFS3.js';
|
|
2
|
+
import { cva } from 'class-variance-authority';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var propertyGridCellVariants = cva(
|
|
6
|
+
[
|
|
7
|
+
// Layout — 40px row, single line, slots on a horizontal axis.
|
|
8
|
+
"flex h-10 min-w-0 items-center gap-1 py-3",
|
|
9
|
+
// Type — Archivo 14/20.
|
|
10
|
+
"body-03"
|
|
11
|
+
],
|
|
12
|
+
{
|
|
13
|
+
variants: {
|
|
14
|
+
variant: {
|
|
15
|
+
title: "justify-start text-card-foreground-muted",
|
|
16
|
+
content: "justify-end text-card-foreground"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: {
|
|
20
|
+
variant: "title"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
var propertyGridItemVariants = cva(["grid grid-cols-2"], {
|
|
25
|
+
variants: {
|
|
26
|
+
last: {
|
|
27
|
+
false: "border-b border-card-border",
|
|
28
|
+
true: ""
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
defaultVariants: {
|
|
32
|
+
last: false
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
function PropertyGridItem({
|
|
36
|
+
className,
|
|
37
|
+
last = false,
|
|
38
|
+
children,
|
|
39
|
+
ref,
|
|
40
|
+
...props
|
|
41
|
+
}) {
|
|
42
|
+
return /* @__PURE__ */ jsx(
|
|
43
|
+
"div",
|
|
44
|
+
{
|
|
45
|
+
"data-slot": "property-grid-item",
|
|
46
|
+
className: cn(propertyGridItemVariants({ last }), className),
|
|
47
|
+
ref,
|
|
48
|
+
...props,
|
|
49
|
+
children
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
function PropertyGridCell({
|
|
54
|
+
variant,
|
|
55
|
+
className,
|
|
56
|
+
leading,
|
|
57
|
+
trailing,
|
|
58
|
+
children,
|
|
59
|
+
ref,
|
|
60
|
+
...props
|
|
61
|
+
}) {
|
|
62
|
+
const slotClass = "flex shrink-0 items-center text-card-foreground-muted [&_svg]:size-4";
|
|
63
|
+
return /* @__PURE__ */ jsxs(
|
|
64
|
+
"div",
|
|
65
|
+
{
|
|
66
|
+
"data-slot": `property-grid-${variant}`,
|
|
67
|
+
className: cn(propertyGridCellVariants({ variant }), className),
|
|
68
|
+
ref,
|
|
69
|
+
...props,
|
|
70
|
+
children: [
|
|
71
|
+
leading != null && /* @__PURE__ */ jsx(
|
|
72
|
+
"span",
|
|
73
|
+
{
|
|
74
|
+
"data-slot": `property-grid-${variant}-leading`,
|
|
75
|
+
className: slotClass,
|
|
76
|
+
children: leading
|
|
77
|
+
}
|
|
78
|
+
),
|
|
79
|
+
children != null && /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children }),
|
|
80
|
+
trailing != null && /* @__PURE__ */ jsx(
|
|
81
|
+
"span",
|
|
82
|
+
{
|
|
83
|
+
"data-slot": `property-grid-${variant}-trailing`,
|
|
84
|
+
className: slotClass,
|
|
85
|
+
children: trailing
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
function PropertyGridTitle(props) {
|
|
93
|
+
return /* @__PURE__ */ jsx(PropertyGridCell, { variant: "title", ...props });
|
|
94
|
+
}
|
|
95
|
+
function PropertyGridContent(props) {
|
|
96
|
+
return /* @__PURE__ */ jsx(PropertyGridCell, { variant: "content", ...props });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { PropertyGridContent, PropertyGridItem, PropertyGridTitle, propertyGridCellVariants, propertyGridItemVariants };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { cn } from './chunk-7EOSDFS3.js';
|
|
2
|
+
import { CircleIcon } from '@phosphor-icons/react';
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var radioVariants = cva([
|
|
7
|
+
// Circle — 20×20 (`size-5`), fully round (Figma `radius/full`), 1px border.
|
|
8
|
+
// `peer` lets the sibling indicator react to :checked / :disabled.
|
|
9
|
+
"peer size-5 shrink-0 appearance-none rounded-full border",
|
|
10
|
+
"cursor-pointer transition-colors",
|
|
11
|
+
// Default
|
|
12
|
+
"bg-background border-border",
|
|
13
|
+
// Hover (unselected) — focus keeps the DEFAULT border; only the ring signals
|
|
14
|
+
// focus (so focus doesn't visually read as hover).
|
|
15
|
+
"hover:border-border-accent",
|
|
16
|
+
// Focus ring — suppress the native ring, draw the shared `--focus` ring the
|
|
17
|
+
// same way Checkbox and ghost Button do: 2px stroke, 2px offset
|
|
18
|
+
// (`outline-solid` restores what `outline-none` zeroed).
|
|
19
|
+
"outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus",
|
|
20
|
+
// Selected
|
|
21
|
+
"checked:bg-brand-primary-background checked:border-brand-primary-border",
|
|
22
|
+
"checked:hover:bg-brand-primary-accent checked:hover:border-brand-primary-border",
|
|
23
|
+
"checked:focus-visible:bg-brand-primary-accent checked:focus-visible:border-brand-primary-border",
|
|
24
|
+
// Disabled — shared neutral-muted look whether selected or not (per Figma)
|
|
25
|
+
"disabled:pointer-events-none disabled:cursor-not-allowed disabled:border-border-muted",
|
|
26
|
+
"checked:disabled:bg-background checked:disabled:border-border-muted"
|
|
27
|
+
]);
|
|
28
|
+
function Radio({
|
|
29
|
+
className,
|
|
30
|
+
wrapperClassName,
|
|
31
|
+
onChange,
|
|
32
|
+
onCheckedChange,
|
|
33
|
+
...props
|
|
34
|
+
}) {
|
|
35
|
+
const handleChange = (event) => {
|
|
36
|
+
onChange?.(event);
|
|
37
|
+
onCheckedChange?.(event.currentTarget.checked);
|
|
38
|
+
};
|
|
39
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("relative inline-flex shrink-0", wrapperClassName), children: [
|
|
40
|
+
/* @__PURE__ */ jsx(
|
|
41
|
+
"input",
|
|
42
|
+
{
|
|
43
|
+
type: "radio",
|
|
44
|
+
"data-slot": "radio",
|
|
45
|
+
className: cn(radioVariants(), className),
|
|
46
|
+
...props,
|
|
47
|
+
onChange: handleChange
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
CircleIcon,
|
|
52
|
+
{
|
|
53
|
+
"aria-hidden": "true",
|
|
54
|
+
weight: "fill",
|
|
55
|
+
"data-slot": "radio-indicator",
|
|
56
|
+
className: cn(
|
|
57
|
+
"pointer-events-none invisible absolute inset-0 m-auto size-3",
|
|
58
|
+
"text-brand-primary-foreground",
|
|
59
|
+
"peer-checked:visible peer-disabled:text-foreground-muted"
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { Radio, radioVariants };
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { cn } from './chunk-7EOSDFS3.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var tabsRootVariants = cva(["flex flex-col"]);
|
|
7
|
+
var tabsListVariants = cva(["inline-flex items-center"]);
|
|
8
|
+
var tabsTriggerVariants = cva(
|
|
9
|
+
[
|
|
10
|
+
"group inline-flex cursor-pointer items-center justify-center gap-1 px-2 py-2.5",
|
|
11
|
+
"body-03-medium border-b-2 transition-colors",
|
|
12
|
+
"outline-none focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus",
|
|
13
|
+
"[&_svg]:size-4 [&_svg]:shrink-0",
|
|
14
|
+
"disabled:cursor-not-allowed"
|
|
15
|
+
],
|
|
16
|
+
{
|
|
17
|
+
variants: {
|
|
18
|
+
selected: {
|
|
19
|
+
true: "border-card-brand-border-accent text-foreground-accent",
|
|
20
|
+
false: "border-transparent text-foreground"
|
|
21
|
+
},
|
|
22
|
+
disabled: {
|
|
23
|
+
true: "text-foreground-muted",
|
|
24
|
+
false: ""
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
compoundVariants: [
|
|
28
|
+
// Unselected + enabled: faint underline on hover, purple text+underline
|
|
29
|
+
// while pressed (Figma hover / active states).
|
|
30
|
+
{
|
|
31
|
+
selected: false,
|
|
32
|
+
disabled: false,
|
|
33
|
+
className: "hover:border-card-brand-border active:border-card-brand-border-accent active:text-foreground-accent"
|
|
34
|
+
},
|
|
35
|
+
// Selected + disabled: the underline drops from accent to the faint token
|
|
36
|
+
// (Figma disabled-selected). Wins over the accent border from
|
|
37
|
+
// `selected:true` because compound variants are appended last.
|
|
38
|
+
{
|
|
39
|
+
selected: true,
|
|
40
|
+
disabled: true,
|
|
41
|
+
className: "border-card-brand-border"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
defaultVariants: {
|
|
45
|
+
selected: false,
|
|
46
|
+
disabled: false
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
var tabsContentVariants = cva([
|
|
51
|
+
"outline-none focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus"
|
|
52
|
+
]);
|
|
53
|
+
var TabsContext = React.createContext(null);
|
|
54
|
+
function useTabsContext(part) {
|
|
55
|
+
const context = React.useContext(TabsContext);
|
|
56
|
+
if (context === null) {
|
|
57
|
+
throw new Error(`${part} must be used within <Tabs.Root>`);
|
|
58
|
+
}
|
|
59
|
+
return context;
|
|
60
|
+
}
|
|
61
|
+
function setRef(ref, node) {
|
|
62
|
+
if (typeof ref === "function") ref(node);
|
|
63
|
+
else if (ref) ref.current = node;
|
|
64
|
+
}
|
|
65
|
+
function TabsRoot({
|
|
66
|
+
value: valueProp,
|
|
67
|
+
defaultValue,
|
|
68
|
+
onValueChange,
|
|
69
|
+
className,
|
|
70
|
+
children,
|
|
71
|
+
ref,
|
|
72
|
+
...props
|
|
73
|
+
}) {
|
|
74
|
+
const isControlled = valueProp !== void 0;
|
|
75
|
+
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
|
|
76
|
+
const value = isControlled ? valueProp : uncontrolledValue;
|
|
77
|
+
const select = (next) => {
|
|
78
|
+
if (!isControlled) setUncontrolledValue(next);
|
|
79
|
+
onValueChange?.(next);
|
|
80
|
+
};
|
|
81
|
+
const baseId = React.useId();
|
|
82
|
+
const getTriggerId = (tabValue) => `${baseId}-tab-${tabValue}`;
|
|
83
|
+
const getPanelId = (tabValue) => `${baseId}-panel-${tabValue}`;
|
|
84
|
+
const [triggers, setTriggers] = React.useState([]);
|
|
85
|
+
const registerTrigger = React.useCallback((registration) => {
|
|
86
|
+
setTriggers((prev) => {
|
|
87
|
+
const existing = prev.findIndex((t) => t.value === registration.value);
|
|
88
|
+
if (existing === -1) return [...prev, registration];
|
|
89
|
+
const next = [...prev];
|
|
90
|
+
next[existing] = registration;
|
|
91
|
+
return next;
|
|
92
|
+
});
|
|
93
|
+
}, []);
|
|
94
|
+
const unregisterTrigger = React.useCallback((tabValue) => {
|
|
95
|
+
setTriggers((prev) => prev.filter((t) => t.value !== tabValue));
|
|
96
|
+
}, []);
|
|
97
|
+
const domOrdered = [...triggers].sort(
|
|
98
|
+
(a, b) => a.node.compareDocumentPosition(b.node) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
|
|
99
|
+
);
|
|
100
|
+
const firstEnabled = domOrdered.find((t) => !t.disabled)?.value;
|
|
101
|
+
const tabStopValue = value ?? firstEnabled;
|
|
102
|
+
const onTriggerKeyDown = (event) => {
|
|
103
|
+
if (!["ArrowRight", "ArrowLeft", "Home", "End"].includes(event.key)) return;
|
|
104
|
+
const enabled = domOrdered.filter((t) => !t.disabled);
|
|
105
|
+
if (enabled.length === 0) return;
|
|
106
|
+
const currentIndex = enabled.findIndex(
|
|
107
|
+
(t) => t.node === event.currentTarget
|
|
108
|
+
);
|
|
109
|
+
if (currentIndex === -1) return;
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
let nextIndex = currentIndex;
|
|
112
|
+
switch (event.key) {
|
|
113
|
+
case "ArrowRight":
|
|
114
|
+
nextIndex = (currentIndex + 1) % enabled.length;
|
|
115
|
+
break;
|
|
116
|
+
case "ArrowLeft":
|
|
117
|
+
nextIndex = (currentIndex - 1 + enabled.length) % enabled.length;
|
|
118
|
+
break;
|
|
119
|
+
case "Home":
|
|
120
|
+
nextIndex = 0;
|
|
121
|
+
break;
|
|
122
|
+
case "End":
|
|
123
|
+
nextIndex = enabled.length - 1;
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
const target = enabled[nextIndex];
|
|
127
|
+
if (!target) return;
|
|
128
|
+
target.node.focus();
|
|
129
|
+
select(target.value);
|
|
130
|
+
};
|
|
131
|
+
const contextValue = {
|
|
132
|
+
value,
|
|
133
|
+
select,
|
|
134
|
+
tabStopValue,
|
|
135
|
+
registerTrigger,
|
|
136
|
+
unregisterTrigger,
|
|
137
|
+
onTriggerKeyDown,
|
|
138
|
+
getTriggerId,
|
|
139
|
+
getPanelId
|
|
140
|
+
};
|
|
141
|
+
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
142
|
+
"div",
|
|
143
|
+
{
|
|
144
|
+
ref,
|
|
145
|
+
"data-slot": "tabs",
|
|
146
|
+
className: cn(tabsRootVariants(), className),
|
|
147
|
+
...props,
|
|
148
|
+
children
|
|
149
|
+
}
|
|
150
|
+
) });
|
|
151
|
+
}
|
|
152
|
+
function TabsList({ className, children, ref, ...props }) {
|
|
153
|
+
useTabsContext("Tabs.List");
|
|
154
|
+
return /* @__PURE__ */ jsx(
|
|
155
|
+
"div",
|
|
156
|
+
{
|
|
157
|
+
ref,
|
|
158
|
+
role: "tablist",
|
|
159
|
+
"data-slot": "tabs-list",
|
|
160
|
+
className: cn(tabsListVariants(), className),
|
|
161
|
+
...props,
|
|
162
|
+
children
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
function TabsTrigger({
|
|
167
|
+
value,
|
|
168
|
+
disabled = false,
|
|
169
|
+
className,
|
|
170
|
+
children,
|
|
171
|
+
onClick,
|
|
172
|
+
onKeyDown,
|
|
173
|
+
ref,
|
|
174
|
+
...props
|
|
175
|
+
}) {
|
|
176
|
+
const {
|
|
177
|
+
value: selectedValue,
|
|
178
|
+
select,
|
|
179
|
+
tabStopValue,
|
|
180
|
+
registerTrigger,
|
|
181
|
+
unregisterTrigger,
|
|
182
|
+
onTriggerKeyDown,
|
|
183
|
+
getTriggerId,
|
|
184
|
+
getPanelId
|
|
185
|
+
} = useTabsContext("Tabs.Trigger");
|
|
186
|
+
const selected = value === selectedValue;
|
|
187
|
+
const triggerId = getTriggerId(value);
|
|
188
|
+
const panelId = getPanelId(value);
|
|
189
|
+
const buttonRef = React.useRef(null);
|
|
190
|
+
const setButtonRef = (node) => {
|
|
191
|
+
buttonRef.current = node;
|
|
192
|
+
setRef(ref, node);
|
|
193
|
+
};
|
|
194
|
+
React.useEffect(() => {
|
|
195
|
+
const node = buttonRef.current;
|
|
196
|
+
if (!node) return;
|
|
197
|
+
registerTrigger({ value, disabled, node });
|
|
198
|
+
return () => unregisterTrigger(value);
|
|
199
|
+
}, [registerTrigger, unregisterTrigger, value, disabled]);
|
|
200
|
+
return /* @__PURE__ */ jsx(
|
|
201
|
+
"button",
|
|
202
|
+
{
|
|
203
|
+
...props,
|
|
204
|
+
ref: setButtonRef,
|
|
205
|
+
type: "button",
|
|
206
|
+
role: "tab",
|
|
207
|
+
id: triggerId,
|
|
208
|
+
"data-slot": "tabs-trigger",
|
|
209
|
+
"data-state": selected ? "active" : "inactive",
|
|
210
|
+
"data-disabled": disabled || void 0,
|
|
211
|
+
"aria-selected": selected,
|
|
212
|
+
"aria-controls": selected ? panelId : void 0,
|
|
213
|
+
tabIndex: value === tabStopValue ? 0 : -1,
|
|
214
|
+
disabled,
|
|
215
|
+
className: cn(tabsTriggerVariants({ selected, disabled }), className),
|
|
216
|
+
onClick: (event) => {
|
|
217
|
+
onClick?.(event);
|
|
218
|
+
if (!event.defaultPrevented) select(value);
|
|
219
|
+
},
|
|
220
|
+
onKeyDown: (event) => {
|
|
221
|
+
onKeyDown?.(event);
|
|
222
|
+
if (!event.defaultPrevented) onTriggerKeyDown(event);
|
|
223
|
+
},
|
|
224
|
+
children
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
function TabsContent({
|
|
229
|
+
value,
|
|
230
|
+
className,
|
|
231
|
+
children,
|
|
232
|
+
ref,
|
|
233
|
+
...props
|
|
234
|
+
}) {
|
|
235
|
+
const {
|
|
236
|
+
value: selectedValue,
|
|
237
|
+
getTriggerId,
|
|
238
|
+
getPanelId
|
|
239
|
+
} = useTabsContext("Tabs.Content");
|
|
240
|
+
if (value !== selectedValue) return null;
|
|
241
|
+
return /* @__PURE__ */ jsx(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
ref,
|
|
245
|
+
role: "tabpanel",
|
|
246
|
+
id: getPanelId(value),
|
|
247
|
+
"aria-labelledby": getTriggerId(value),
|
|
248
|
+
"data-slot": "tabs-content",
|
|
249
|
+
"data-state": "active",
|
|
250
|
+
tabIndex: 0,
|
|
251
|
+
className: cn(tabsContentVariants(), className),
|
|
252
|
+
...props,
|
|
253
|
+
children
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
var Tabs = {
|
|
258
|
+
Root: TabsRoot,
|
|
259
|
+
List: TabsList,
|
|
260
|
+
Trigger: TabsTrigger,
|
|
261
|
+
Content: TabsContent
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
export { Tabs, TabsContent, TabsList, TabsRoot, TabsTrigger, tabsContentVariants, tabsListVariants, tabsRootVariants, tabsTriggerVariants };
|