atlas-react-kit 0.12.0 → 1.0.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/COMPONENTS.md +201 -100
- package/DESIGN_RULES.md +44 -1
- package/README.md +10 -9
- package/dist/accordion.d.ts +1 -0
- package/dist/alert.d.ts +1 -1
- package/dist/avatar.d.ts +1 -0
- package/dist/badge.d.ts +4 -5
- package/dist/breadcrumb.d.ts +2 -3
- package/dist/button.d.ts +4 -5
- package/dist/calendar.d.ts +2 -0
- package/dist/card.d.ts +3 -0
- package/dist/chart.d.ts +152 -0
- package/dist/chart.js +177 -0
- package/dist/color-legend.d.ts +8 -0
- package/dist/combobox.d.ts +13 -4
- package/dist/combobox.js +1 -8
- package/dist/date-picker.d.ts +16 -6
- package/dist/date-picker.js +13 -20
- package/dist/date-time-picker.d.ts +5 -2
- package/dist/date-time-picker.js +6 -5
- package/dist/dialog.d.ts +1 -0
- package/dist/dialog.js +4 -2
- package/dist/dropdown-menu.d.ts +9 -8
- package/dist/empty-panel.d.ts +8 -2
- package/dist/empty-panel.js +2 -2
- package/dist/error-boundary.d.ts +7 -2
- package/dist/field.d.ts +4 -1
- package/dist/field.js +1 -1
- package/dist/form/checkbox-field.d.ts +45 -0
- package/dist/form/checkbox-field.js +39 -0
- package/dist/form/combobox-field.d.ts +13 -0
- package/dist/form/combobox-field.js +14 -0
- package/dist/form/control-field.d.ts +30 -0
- package/dist/form/control-field.js +22 -0
- package/dist/form/date-picker-field.d.ts +7 -21
- package/dist/form/date-picker-field.js +4 -4
- package/dist/form/date-time-picker-field.d.ts +7 -22
- package/dist/form/date-time-picker-field.js +3 -3
- package/dist/form/feedback-field.d.ts +2 -0
- package/dist/form/field-error.d.ts +49 -0
- package/dist/form/field-shell.d.ts +47 -8
- package/dist/form/field-shell.js +24 -7
- package/dist/form/markdown-field.d.ts +4 -16
- package/dist/form/markdown-field.js +2 -2
- package/dist/form/select-field.d.ts +7 -7
- package/dist/form/select-field.js +2 -2
- package/dist/form/text-field.d.ts +29 -12
- package/dist/form/text-field.js +10 -6
- package/dist/form/toggle-group-field.d.ts +30 -0
- package/dist/form/toggle-group-field.js +19 -0
- package/dist/info-tip.d.ts +10 -1
- package/dist/internal/as-child.d.ts +8 -0
- package/dist/internal/as-child.js +1 -0
- package/dist/internal/date-like.d.ts +23 -0
- package/dist/internal/form-control.d.ts +3 -2
- package/dist/internal/form-control.js +3 -2
- package/dist/internal/kanban-layout.d.ts +55 -0
- package/dist/internal/kanban-layout.js +80 -0
- package/dist/internal/kanban-plugins.d.ts +17 -0
- package/dist/internal/kanban-plugins.js +17 -0
- package/dist/internal/use-media-query.d.ts +4 -2
- package/dist/internal/use-media-query.js +11 -15
- package/dist/kanban.d.ts +84 -0
- package/dist/kanban.js +197 -0
- package/dist/markdown.d.ts +2 -0
- package/dist/meter.d.ts +7 -0
- package/dist/nav-link.d.ts +23 -0
- package/dist/nav-link.js +31 -0
- package/dist/next/nav-link.d.ts +11 -0
- package/dist/next/nav-link.js +14 -0
- package/dist/next/period-stepper.d.ts +11 -0
- package/dist/next/period-stepper.js +16 -0
- package/dist/page-header.d.ts +19 -0
- package/dist/page-header.js +11 -0
- package/dist/pagination.d.ts +2 -0
- package/dist/period-stepper.d.ts +32 -0
- package/dist/period-stepper.js +27 -0
- package/dist/picker-shell.d.ts +43 -6
- package/dist/picker-shell.js +2 -2
- package/dist/progress.d.ts +1 -0
- package/dist/search-picker.d.ts +12 -0
- package/dist/select.d.ts +1 -0
- package/dist/skip-link.d.ts +7 -0
- package/dist/skip-link.js +10 -0
- package/dist/slider.d.ts +11 -0
- package/dist/sortable-table-head.d.ts +2 -0
- package/dist/stat-tile.d.ts +5 -0
- package/dist/table-body-skeleton.d.ts +2 -0
- package/dist/table.d.ts +1 -0
- package/dist/tabs.d.ts +9 -5
- package/dist/tabs.js +1 -1
- package/dist/toast.d.ts +7 -1
- package/dist/toggle-group.d.ts +9 -2
- package/dist/toggle-group.js +2 -1
- package/dist/toggle.d.ts +1 -1
- package/package.json +85 -11
- package/skills/atlas-react-kit/SKILL.md +2 -0
- package/theme.css +11 -0
package/DESIGN_RULES.md
CHANGED
|
@@ -32,6 +32,36 @@ its own soft tint in both themes. Status tones have no paired foreground token;
|
|
|
32
32
|
avoid placing text on solid status fills. Application-specific identity colors
|
|
33
33
|
belong to the application.
|
|
34
34
|
|
|
35
|
+
### Public tokens and slots
|
|
36
|
+
|
|
37
|
+
These are public API from 1.0, so apps may use them and a rename or removal
|
|
38
|
+
is a breaking change:
|
|
39
|
+
|
|
40
|
+
- Color tokens and their `--color-*` utilities: `background`, `foreground`,
|
|
41
|
+
`card`, `popover`, `primary`, `secondary`, `muted`, `accent`, `selected`
|
|
42
|
+
(each with its `-foreground` pair where one exists), `destructive`,
|
|
43
|
+
`success`, `warning`, `border`, `input`, `ring`, `chart-1` to `chart-5`,
|
|
44
|
+
and the `sidebar` set.
|
|
45
|
+
- `--radius` and the `--radius-*` scale, and `--font-heading`.
|
|
46
|
+
- Every `data-slot` listed under "Styling parts" in
|
|
47
|
+
[COMPONENTS.md](./COMPONENTS.md#styling-parts).
|
|
48
|
+
|
|
49
|
+
Everything else in `theme.css` is internal and may change in a minor
|
|
50
|
+
release: the scroll-shadow variables (`--scroll-fade`, `--scroll-fill`,
|
|
51
|
+
`--table-scroll-fade`, `--tabs-scroll-fade`) and any `data-slot` not listed
|
|
52
|
+
in COMPONENTS.md.
|
|
53
|
+
|
|
54
|
+
### Prop names
|
|
55
|
+
|
|
56
|
+
- A controlled value is `value` with `onValueChange`; open state is `open`
|
|
57
|
+
with `onOpenChange`; a checked state is `checked` with `onCheckedChange`.
|
|
58
|
+
- Sizes run `sm`, `default`, `lg`; `Button` adds `xs` and `icon-*` sizes.
|
|
59
|
+
- `variant="default"` is the plain look; other variants name what they mean
|
|
60
|
+
(`outline`, `ghost`, `destructive`).
|
|
61
|
+
|
|
62
|
+
Deprecated aliases (`onChange` on the date pickers, `EmptyPanel`
|
|
63
|
+
`size="md"`) keep working until 2.0.
|
|
64
|
+
|
|
35
65
|
## Accessibility
|
|
36
66
|
|
|
37
67
|
The target is WCAG 2.2 AA. CI runs axe-core's WCAG 2.2 A and AA rules against
|
|
@@ -138,9 +168,22 @@ or its `data-slot`.
|
|
|
138
168
|
`text-base md:text-sm`, `border-input`, and `shadow-xs`. Do not restyle those
|
|
139
169
|
triggers as outline buttons in application code.
|
|
140
170
|
|
|
171
|
+
`form/*` fields stack label, hint, control, and error with `gap-1.5`, and the
|
|
172
|
+
error sits below the control. It takes no space until it shows, so a row of
|
|
173
|
+
fields keeps its controls on one top edge only with `items-start`
|
|
174
|
+
(`grid grid-cols-2 items-start gap-3`); the default `stretch` is fine for a
|
|
175
|
+
single column. Wrap a control the kit does not ship (a combobox, a segmented
|
|
176
|
+
picker) in `FormControlField` instead of `Field` and `FieldLabel`, whose
|
|
177
|
+
`gap-3` spacing does not match. A field shows its error once
|
|
178
|
+
`meta.isTouched` is true or `submitted` is set, never on a field the person
|
|
179
|
+
has not reached yet.
|
|
180
|
+
|
|
141
181
|
Use `Tabs` with actual `TabsContent` panels. For URL view switches, use a labelled
|
|
142
182
|
`TabsNav` with links and `aria-current="page"` on the active link. The optional
|
|
143
|
-
Next adapter provides `TabsNavLink` with this behavior.
|
|
183
|
+
Next adapter provides `TabsNavLink` with this behavior. App-shell destinations
|
|
184
|
+
(Calendar, Tasks, Settings) use `NavLink` from `nav-link`: a pill with `active`
|
|
185
|
+
from the app, not tabs. Pass `asChild` for a router link, or use the optional
|
|
186
|
+
Next adapter `next/nav-link`. `TabsNav` and `TabsList`
|
|
144
187
|
scroll overflowing labels inside themselves (`overflow-x-auto overflow-y-hidden`,
|
|
145
188
|
with padding for the active border and focus ring counted in the scroller
|
|
146
189
|
height, and an edge fade like `Table`). Do not wrap them in another
|
package/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Atlas React Kit
|
|
2
2
|
|
|
3
3
|
Shared React components and a Tailwind theme with square corners, semantic
|
|
4
|
-
colors, and distinct selected states.
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
colors, and distinct selected states. From 1.0 the API is stable: breaking
|
|
5
|
+
changes to stable components only ship in a major release (see
|
|
6
|
+
[CONTRIBUTING.md](./CONTRIBUTING.md#versions-and-releases)).
|
|
7
7
|
React 19, Tailwind 4, and Node >=20.19 are required. Next 16 is needed only
|
|
8
|
-
when using `next/tabs-nav-link`.
|
|
8
|
+
when using `next/nav-link`, `next/period-stepper`, or `next/tabs-nav-link`.
|
|
9
9
|
|
|
10
10
|
```sh
|
|
11
|
-
npm install --save-exact atlas-react-kit@0.
|
|
11
|
+
npm install --save-exact atlas-react-kit@1.0.0
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
Import components by subpath:
|
|
@@ -42,8 +42,9 @@ this example assumes it is one directory below the project root.
|
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
The theme includes animations and shared light/dark tokens. Wrap the tree with
|
|
45
|
-
`ThemeProvider` from `atlas-react-kit/theme-provider
|
|
46
|
-
|
|
45
|
+
`ThemeProvider` from `atlas-react-kit/theme-provider` (install
|
|
46
|
+
`next-themes@^0.4.6` first), or set the `dark` class on an ancestor to activate
|
|
47
|
+
dark colors. Supply your own font configuration;
|
|
47
48
|
`font-heading` uses the configured sans font. Application-specific tokens stay
|
|
48
49
|
with the application.
|
|
49
50
|
|
|
@@ -101,7 +102,7 @@ The public site is Storybook in `site/`. `npm run build --prefix site`
|
|
|
101
102
|
typechecks the stories, builds Storybook into `site/dist`, then checks the
|
|
102
103
|
static output. Vercel serves that directory; `/playground` and `/storybook`
|
|
103
104
|
redirect to `/`. The site and Storybook dependencies are not part of the npm
|
|
104
|
-
package. Optional feature libraries (markdown, dates, toasts, theme, Next) are
|
|
105
|
+
package. Optional feature libraries (markdown, dates, toasts, theme, Next, dnd-kit) are
|
|
105
106
|
peer dependencies and are required only when those entry points are imported.
|
|
106
107
|
The package does not bundle React.
|
|
107
108
|
|
|
@@ -128,7 +129,7 @@ artifact with the package owner's npm login:
|
|
|
128
129
|
```sh
|
|
129
130
|
mkdir -p release-artifacts
|
|
130
131
|
npm pack --pack-destination release-artifacts
|
|
131
|
-
npm publish ./release-artifacts/atlas-react-kit-0.
|
|
132
|
+
npm publish ./release-artifacts/atlas-react-kit-1.0.0.tgz --access public
|
|
132
133
|
```
|
|
133
134
|
|
|
134
135
|
Pin an exact package version in consuming applications. Roll back an upgrade by
|
package/dist/accordion.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ declare function Accordion({ ...props }: React.ComponentProps<typeof AccordionPr
|
|
|
5
5
|
declare function AccordionItem({ className, ...props }: React.ComponentProps<typeof AccordionPrimitive.Item>): React.JSX.Element;
|
|
6
6
|
/** `headerClassName` styles the heading wrapper (`data-slot="accordion-header"`). */
|
|
7
7
|
declare function AccordionTrigger({ className, headerClassName, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Trigger> & {
|
|
8
|
+
/** Classes for the heading wrapper around the trigger. */
|
|
8
9
|
headerClassName?: string;
|
|
9
10
|
}): React.JSX.Element;
|
|
10
11
|
/**
|
package/dist/alert.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { type VariantProps } from "class-variance-authority";
|
|
|
6
6
|
* (the destructive tint is too faint for text in light mode).
|
|
7
7
|
*/
|
|
8
8
|
declare const alertVariants: (props?: ({
|
|
9
|
-
variant?: "default" | "
|
|
9
|
+
variant?: "default" | "destructive" | "success" | "warning" | null | undefined;
|
|
10
10
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
11
11
|
/**
|
|
12
12
|
* Inline message about the page or a section (save failed, trial ending).
|
package/dist/avatar.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Avatar as AvatarPrimitive } from "radix-ui";
|
|
|
6
6
|
* replaces it.
|
|
7
7
|
*/
|
|
8
8
|
declare function Avatar({ className, size, ...props }: React.ComponentProps<typeof AvatarPrimitive.Root> & {
|
|
9
|
+
/** `sm` 24px, `default` 32px, `lg` 40px. Default `default`. */
|
|
9
10
|
size?: "sm" | "default" | "lg";
|
|
10
11
|
}): React.JSX.Element;
|
|
11
12
|
declare function AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>): React.JSX.Element;
|
package/dist/badge.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
import type { AsChildProps } from "./internal/as-child.js";
|
|
3
4
|
declare const badgeVariants: (props?: ({
|
|
4
|
-
variant?: "default" | "
|
|
5
|
-
tone?: "
|
|
5
|
+
variant?: "default" | "destructive" | "ghost" | "link" | "outline" | "secondary" | "soft" | null | undefined;
|
|
6
|
+
tone?: "destructive" | "neutral" | "success" | "warning" | null | undefined;
|
|
6
7
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
-
declare function Badge({ className, variant, tone, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> &
|
|
8
|
-
asChild?: boolean;
|
|
9
|
-
}): React.JSX.Element;
|
|
8
|
+
declare function Badge({ className, variant, tone, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & AsChildProps): React.JSX.Element;
|
|
10
9
|
export { Badge, badgeVariants };
|
package/dist/breadcrumb.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import type { AsChildProps } from "./internal/as-child.js";
|
|
2
3
|
/**
|
|
3
4
|
* Where the current page sits in a hierarchy. The last item is
|
|
4
5
|
* `BreadcrumbPage` (plain text with `aria-current="page"`), not a link.
|
|
@@ -7,9 +8,7 @@ declare function Breadcrumb({ ...props }: React.ComponentProps<"nav">): React.JS
|
|
|
7
8
|
declare function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">): React.JSX.Element;
|
|
8
9
|
declare function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
|
|
9
10
|
/** Pass `asChild` to render a router link (e.g. Next `Link`) with these styles. */
|
|
10
|
-
declare function BreadcrumbLink({ asChild, className, ...props }: React.ComponentProps<"a"> &
|
|
11
|
-
asChild?: boolean;
|
|
12
|
-
}): React.JSX.Element;
|
|
11
|
+
declare function BreadcrumbLink({ asChild, className, ...props }: React.ComponentProps<"a"> & AsChildProps): React.JSX.Element;
|
|
13
12
|
declare function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
14
13
|
declare function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<"li">): React.JSX.Element;
|
|
15
14
|
declare function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
package/dist/button.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
import type { AsChildProps } from "./internal/as-child.js";
|
|
3
4
|
/**
|
|
4
5
|
* Outline and ghost hover/focus: selected-foreground border, selected wash, and
|
|
5
6
|
* `selected-foreground` text (primary in light mode, a lighter purple that
|
|
@@ -8,10 +9,8 @@ import { type VariantProps } from "class-variance-authority";
|
|
|
8
9
|
*/
|
|
9
10
|
declare const quietButtonInteraction: string;
|
|
10
11
|
declare const buttonVariants: (props?: ({
|
|
11
|
-
variant?: "default" | "
|
|
12
|
-
size?: "default" | "
|
|
12
|
+
variant?: "default" | "destructive" | "ghost" | "link" | "outline" | "secondary" | null | undefined;
|
|
13
|
+
size?: "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xs" | "lg" | "sm" | "xs" | null | undefined;
|
|
13
14
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
14
|
-
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> &
|
|
15
|
-
asChild?: boolean;
|
|
16
|
-
}): React.JSX.Element;
|
|
15
|
+
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & AsChildProps): React.JSX.Element;
|
|
17
16
|
export { Button, buttonVariants, quietButtonInteraction };
|
package/dist/calendar.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import * as React from "react";
|
|
|
2
2
|
import { DayPicker, type DayButton, type Locale } from "react-day-picker";
|
|
3
3
|
import { Button } from "./button.js";
|
|
4
4
|
declare function Calendar({ className, classNames, showOutsideDays, captionLayout, buttonVariant, locale, formatters, labels, components, ...props }: React.ComponentProps<typeof DayPicker> & {
|
|
5
|
+
/** Button variant for the previous / next month buttons. Default `ghost`. */
|
|
5
6
|
buttonVariant?: React.ComponentProps<typeof Button>["variant"];
|
|
6
7
|
}): React.JSX.Element;
|
|
7
8
|
declare function CalendarDayButton({ className, day, modifiers, locale, ...props }: React.ComponentProps<typeof DayButton> & {
|
|
9
|
+
/** Locale for the day's `data-day` date string. */
|
|
8
10
|
locale?: Partial<Locale>;
|
|
9
11
|
}): React.JSX.Element;
|
|
10
12
|
export { Calendar, CalendarDayButton };
|
package/dist/card.d.ts
CHANGED
|
@@ -8,11 +8,14 @@ import * as React from "react";
|
|
|
8
8
|
* scroll instead of widening the card. `overflow-hidden` still clips media.
|
|
9
9
|
*/
|
|
10
10
|
declare function Card({ className, size, flush, role, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: React.ComponentProps<"div"> & {
|
|
11
|
+
/** `sm` tightens padding and gaps. Default `default`. */
|
|
11
12
|
size?: "default" | "sm";
|
|
13
|
+
/** Remove the padding so lists and tables run edge to edge. Default `false`. */
|
|
12
14
|
flush?: boolean;
|
|
13
15
|
}): React.JSX.Element;
|
|
14
16
|
declare function CardHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
15
17
|
declare function CardTitle({ as: Component, className, ...props }: React.ComponentProps<"div"> & {
|
|
18
|
+
/** Element to render, e.g. a heading level for the outline. Default `div`. */
|
|
16
19
|
as?: "div" | "h1" | "h2" | "h3" | "h4";
|
|
17
20
|
}): React.JSX.Element;
|
|
18
21
|
declare function CardDescription({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
package/dist/chart.d.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Building blocks for small SVG charts: a plot frame in viewBox units, axis
|
|
4
|
+
* math, a gridline axis, a tooltip, a legend, and pointer/arrow-key
|
|
5
|
+
* scrubbing. The chart itself (bars, lines, what they mean) stays in the
|
|
6
|
+
* app; these pieces keep every chart's axis, readout, and keyboard use alike.
|
|
7
|
+
*/
|
|
8
|
+
/** Space around the plot, in viewBox units, for axis labels. */
|
|
9
|
+
export type ChartPadding = {
|
|
10
|
+
/** Above the plot. Default 10. */
|
|
11
|
+
top: number;
|
|
12
|
+
/** Right of the plot. Default 12. */
|
|
13
|
+
right: number;
|
|
14
|
+
/** Below the baseline, for x labels. Default 20. */
|
|
15
|
+
bottom: number;
|
|
16
|
+
/** Left of the plot, for y labels. Default 40. */
|
|
17
|
+
left: number;
|
|
18
|
+
};
|
|
19
|
+
/** A chart's viewBox and the plot box inside it, in viewBox units. */
|
|
20
|
+
export type ChartFrame = {
|
|
21
|
+
/** The whole chart's width. */
|
|
22
|
+
width: number;
|
|
23
|
+
/** The whole chart's height. */
|
|
24
|
+
height: number;
|
|
25
|
+
/** The `viewBox` attribute for the chart's `<svg>`. */
|
|
26
|
+
viewBox: string;
|
|
27
|
+
/** The plot's left edge on x. */
|
|
28
|
+
left: number;
|
|
29
|
+
/** The plot's right edge on x. */
|
|
30
|
+
right: number;
|
|
31
|
+
/** The plot's top edge on y. */
|
|
32
|
+
top: number;
|
|
33
|
+
/** The plot's bottom edge on y: the baseline, where 0 sits. */
|
|
34
|
+
bottom: number;
|
|
35
|
+
/** `right - left`. */
|
|
36
|
+
plotWidth: number;
|
|
37
|
+
/** `bottom - top`. */
|
|
38
|
+
plotHeight: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Frame for a chart `height` units tall. Charts that share a `width` and
|
|
42
|
+
* padding line up when stacked. The SVG scales to its box, so these are
|
|
43
|
+
* viewBox units, not pixels.
|
|
44
|
+
*/
|
|
45
|
+
export declare function chartFrame(height: number, { width, padding, }?: {
|
|
46
|
+
/** The chart's width in viewBox units. Default 640. */
|
|
47
|
+
width?: number;
|
|
48
|
+
/** Overrides for any side of the default padding. */
|
|
49
|
+
padding?: Partial<ChartPadding>;
|
|
50
|
+
}): ChartFrame;
|
|
51
|
+
/**
|
|
52
|
+
* Round `max` up to a clean axis ceiling (1, 2, 2.5, 4, or 5 × 10^n). The 4
|
|
53
|
+
* step keeps a value just past 25 off a half-empty 50 axis.
|
|
54
|
+
*/
|
|
55
|
+
export declare function niceCeil(max: number): number;
|
|
56
|
+
/** `count` even steps from 0 to `niceCeil(max)`, both ends included. */
|
|
57
|
+
export declare function niceTicks(max: number, count?: number): number[];
|
|
58
|
+
/** Linear scale from [0, domainMax] onto [0, rangeMax]; a zero domain maps to 0. */
|
|
59
|
+
export declare function scaleLinear(domainMax: number, rangeMax: number): (value: number) => number;
|
|
60
|
+
/** SVG path through the points (`M x y L x y …`); empty for no points. */
|
|
61
|
+
export declare function linePath(points: ReadonlyArray<{
|
|
62
|
+
x: number;
|
|
63
|
+
y: number;
|
|
64
|
+
}>): string;
|
|
65
|
+
/**
|
|
66
|
+
* A bar with a rounded data end and a square baseline. (x, y) is the top
|
|
67
|
+
* left; the bar grows down to y + h. Pass `r = 0` for a square bar.
|
|
68
|
+
*/
|
|
69
|
+
export declare function roundedTopBarPath(x: number, y: number, w: number, h: number, r?: number): string;
|
|
70
|
+
/** Short axis label: 1500 → "1.5k", 2000000 → "2M". */
|
|
71
|
+
export declare function compactNumber(n: number): string;
|
|
72
|
+
type IndexRange = {
|
|
73
|
+
/** The first data index the plot can pick. */
|
|
74
|
+
min: number;
|
|
75
|
+
/** The last data index the plot can pick; may stop short of the axis end. */
|
|
76
|
+
max: number;
|
|
77
|
+
};
|
|
78
|
+
/** The index range plus how many intervals the plot's width spans. */
|
|
79
|
+
type PlotSteps = IndexRange & {
|
|
80
|
+
/** Intervals across the plot width (data points minus one on a full axis). */
|
|
81
|
+
steps: number;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Data index at viewBox x `viewX`. The plot spans `steps` intervals from
|
|
85
|
+
* `min`; the result is clamped to [min, max], so `max` can stop short of the
|
|
86
|
+
* axis (days not reached yet).
|
|
87
|
+
*/
|
|
88
|
+
export declare function indexAtPlotX(viewX: number, frame: ChartFrame, { steps, min, max }: PlotSteps): number;
|
|
89
|
+
/** Arrow-key move by `delta`, clamped; with nothing picked it starts at `min`. */
|
|
90
|
+
export declare function stepIndex(current: number | null, delta: 1 | -1, { min, max }: IndexRange): number;
|
|
91
|
+
/**
|
|
92
|
+
* Crosshair state: the pointer or the arrow keys pick a data index in
|
|
93
|
+
* [min, max], and Escape or leaving the plot clears it. Put `svgRef` and the
|
|
94
|
+
* handlers on the chart's `<svg>`, which needs `tabIndex={0}`.
|
|
95
|
+
*/
|
|
96
|
+
export declare function useChartScrub({ frame, steps, min, max, }: PlotSteps & {
|
|
97
|
+
/** The chart's frame, for mapping pointer x onto the plot. */
|
|
98
|
+
frame: ChartFrame;
|
|
99
|
+
}): {
|
|
100
|
+
svgRef: React.RefObject<SVGSVGElement | null>;
|
|
101
|
+
index: number | null;
|
|
102
|
+
clear: () => void;
|
|
103
|
+
onPointerMove: (event: React.PointerEvent<SVGSVGElement>) => void;
|
|
104
|
+
onKeyDown: (event: React.KeyboardEvent) => void;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Horizontal gridlines from 0 to `niceCeil(yMax)` with labels in the left
|
|
108
|
+
* padding. Render inside the chart's `<svg>`.
|
|
109
|
+
*/
|
|
110
|
+
export declare function ChartYAxisGrid({ frame, yMax, tickCount, format, }: {
|
|
111
|
+
/** The chart's frame; lines span the plot, labels sit in the left padding. */
|
|
112
|
+
frame: ChartFrame;
|
|
113
|
+
/** The largest data value; the axis tops out at `niceCeil(yMax)`. */
|
|
114
|
+
yMax: number;
|
|
115
|
+
/** How many even steps from 0 to the top. Default 4. */
|
|
116
|
+
tickCount?: number;
|
|
117
|
+
/** Label text for a tick value. Default `compactNumber`. */
|
|
118
|
+
format?: (value: number) => string;
|
|
119
|
+
}): React.JSX.Element;
|
|
120
|
+
/**
|
|
121
|
+
* Readout for the hovered or focused point, placed in percent of the chart
|
|
122
|
+
* box (its wrapper must be `relative`). It sits right of the point and
|
|
123
|
+
* flips left past 55% so it does not clip at the edge.
|
|
124
|
+
*/
|
|
125
|
+
export declare function ChartTooltip({ xPct, yPct, className, style, children, ...props }: {
|
|
126
|
+
/** The point's x, in percent of the chart box's width. */
|
|
127
|
+
xPct: number;
|
|
128
|
+
/** The point's y, in percent of the chart box's height; capped at 60. */
|
|
129
|
+
yPct: number;
|
|
130
|
+
} & React.ComponentProps<"div">): React.JSX.Element;
|
|
131
|
+
/** A series' line key, shared by tooltip rows and legend keys. */
|
|
132
|
+
type SeriesKeyProps = {
|
|
133
|
+
/** The series name. */
|
|
134
|
+
label: React.ReactNode;
|
|
135
|
+
/** The series stroke, e.g. `stroke-primary`. */
|
|
136
|
+
swatchClassName: string;
|
|
137
|
+
/** Draws the swatch dashed, for a dashed series line. */
|
|
138
|
+
dashed?: boolean;
|
|
139
|
+
};
|
|
140
|
+
/** Tooltip row: the value leads, the label follows, keyed by the series stroke. */
|
|
141
|
+
export declare function ChartTooltipRow({ label, value, swatchClassName, dashed, }: SeriesKeyProps & {
|
|
142
|
+
/** The series' value at the point, shown first in bold. */
|
|
143
|
+
value: React.ReactNode;
|
|
144
|
+
}): React.JSX.Element;
|
|
145
|
+
/** Row of legend keys under a chart. */
|
|
146
|
+
export declare function ChartLegend({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
147
|
+
/** One legend entry: a solid or dashed line swatch and its label. */
|
|
148
|
+
export declare function ChartLegendKey({ label, swatchClassName, dashed, className, }: SeriesKeyProps & {
|
|
149
|
+
/** Classes for the key's wrapper. */
|
|
150
|
+
className?: string;
|
|
151
|
+
}): React.JSX.Element;
|
|
152
|
+
export {};
|
package/dist/chart.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { clamp } from "./internal/math.js";
|
|
5
|
+
import { overlaySurface } from "./internal/overlay-styles.js";
|
|
6
|
+
import { cn } from "./utils.js";
|
|
7
|
+
/** Room for compact y labels on the left and x labels underneath. */
|
|
8
|
+
const defaultPadding = {
|
|
9
|
+
top: 10,
|
|
10
|
+
right: 12,
|
|
11
|
+
bottom: 20,
|
|
12
|
+
left: 40,
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Frame for a chart `height` units tall. Charts that share a `width` and
|
|
16
|
+
* padding line up when stacked. The SVG scales to its box, so these are
|
|
17
|
+
* viewBox units, not pixels.
|
|
18
|
+
*/
|
|
19
|
+
export function chartFrame(height, { width = 640, padding, } = {}) {
|
|
20
|
+
const pad = { ...defaultPadding, ...padding };
|
|
21
|
+
const plotWidth = width - pad.left - pad.right;
|
|
22
|
+
const plotHeight = height - pad.top - pad.bottom;
|
|
23
|
+
return {
|
|
24
|
+
width,
|
|
25
|
+
height,
|
|
26
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
27
|
+
left: pad.left,
|
|
28
|
+
right: pad.left + plotWidth,
|
|
29
|
+
top: pad.top,
|
|
30
|
+
bottom: pad.top + plotHeight,
|
|
31
|
+
plotWidth,
|
|
32
|
+
plotHeight,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Round `max` up to a clean axis ceiling (1, 2, 2.5, 4, or 5 × 10^n). The 4
|
|
37
|
+
* step keeps a value just past 25 off a half-empty 50 axis.
|
|
38
|
+
*/
|
|
39
|
+
export function niceCeil(max) {
|
|
40
|
+
if (max <= 0)
|
|
41
|
+
return 1;
|
|
42
|
+
const pow = 10 ** Math.floor(Math.log10(max));
|
|
43
|
+
for (const step of [1, 2, 2.5, 4, 5]) {
|
|
44
|
+
if (max <= step * pow)
|
|
45
|
+
return step * pow;
|
|
46
|
+
}
|
|
47
|
+
return 10 * pow;
|
|
48
|
+
}
|
|
49
|
+
/** `count` even steps from 0 to `niceCeil(max)`, both ends included. */
|
|
50
|
+
export function niceTicks(max, count = 4) {
|
|
51
|
+
const top = niceCeil(max);
|
|
52
|
+
return Array.from({ length: count + 1 }, (_, i) => (top / count) * i);
|
|
53
|
+
}
|
|
54
|
+
/** Linear scale from [0, domainMax] onto [0, rangeMax]; a zero domain maps to 0. */
|
|
55
|
+
export function scaleLinear(domainMax, rangeMax) {
|
|
56
|
+
return (value) => domainMax === 0 ? 0 : (value / domainMax) * rangeMax;
|
|
57
|
+
}
|
|
58
|
+
function round2(n) {
|
|
59
|
+
return Math.round(n * 100) / 100;
|
|
60
|
+
}
|
|
61
|
+
/** SVG path through the points (`M x y L x y …`); empty for no points. */
|
|
62
|
+
export function linePath(points) {
|
|
63
|
+
return points
|
|
64
|
+
.map((p, i) => `${i === 0 ? "M" : "L"} ${round2(p.x)} ${round2(p.y)}`)
|
|
65
|
+
.join(" ");
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A bar with a rounded data end and a square baseline. (x, y) is the top
|
|
69
|
+
* left; the bar grows down to y + h. Pass `r = 0` for a square bar.
|
|
70
|
+
*/
|
|
71
|
+
export function roundedTopBarPath(x, y, w, h, r = 4) {
|
|
72
|
+
const rad = Math.min(r, w / 2, h);
|
|
73
|
+
return [
|
|
74
|
+
`M ${round2(x)} ${round2(y + h)}`,
|
|
75
|
+
`L ${round2(x)} ${round2(y + rad)}`,
|
|
76
|
+
`Q ${round2(x)} ${round2(y)} ${round2(x + rad)} ${round2(y)}`,
|
|
77
|
+
`L ${round2(x + w - rad)} ${round2(y)}`,
|
|
78
|
+
`Q ${round2(x + w)} ${round2(y)} ${round2(x + w)} ${round2(y + rad)}`,
|
|
79
|
+
`L ${round2(x + w)} ${round2(y + h)}`,
|
|
80
|
+
"Z",
|
|
81
|
+
].join(" ");
|
|
82
|
+
}
|
|
83
|
+
function trimZero(n) {
|
|
84
|
+
const fixed = n.toFixed(1);
|
|
85
|
+
return fixed.endsWith(".0") ? fixed.slice(0, -2) : fixed;
|
|
86
|
+
}
|
|
87
|
+
/** Short axis label: 1500 → "1.5k", 2000000 → "2M". */
|
|
88
|
+
export function compactNumber(n) {
|
|
89
|
+
const abs = Math.abs(n);
|
|
90
|
+
if (abs >= 1_000_000)
|
|
91
|
+
return `${trimZero(n / 1_000_000)}M`;
|
|
92
|
+
if (abs >= 1_000)
|
|
93
|
+
return `${trimZero(n / 1_000)}k`;
|
|
94
|
+
return String(Math.round(n));
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Data index at viewBox x `viewX`. The plot spans `steps` intervals from
|
|
98
|
+
* `min`; the result is clamped to [min, max], so `max` can stop short of the
|
|
99
|
+
* axis (days not reached yet).
|
|
100
|
+
*/
|
|
101
|
+
export function indexAtPlotX(viewX, frame, { steps, min, max }) {
|
|
102
|
+
const index = Math.round(((viewX - frame.left) / frame.plotWidth) * steps) + min;
|
|
103
|
+
return clamp(index, min, max);
|
|
104
|
+
}
|
|
105
|
+
/** Arrow-key move by `delta`, clamped; with nothing picked it starts at `min`. */
|
|
106
|
+
export function stepIndex(current, delta, { min, max }) {
|
|
107
|
+
if (current === null)
|
|
108
|
+
return min;
|
|
109
|
+
return clamp(current + delta, min, max);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Crosshair state: the pointer or the arrow keys pick a data index in
|
|
113
|
+
* [min, max], and Escape or leaving the plot clears it. Put `svgRef` and the
|
|
114
|
+
* handlers on the chart's `<svg>`, which needs `tabIndex={0}`.
|
|
115
|
+
*/
|
|
116
|
+
export function useChartScrub({ frame, steps, min, max, }) {
|
|
117
|
+
const svgRef = React.useRef(null);
|
|
118
|
+
const [index, setIndex] = React.useState(null);
|
|
119
|
+
const clear = React.useCallback(() => setIndex(null), []);
|
|
120
|
+
const onPointerMove = React.useCallback((event) => {
|
|
121
|
+
const rect = svgRef.current?.getBoundingClientRect();
|
|
122
|
+
if (!rect)
|
|
123
|
+
return;
|
|
124
|
+
const viewX = ((event.clientX - rect.left) / rect.width) * frame.width;
|
|
125
|
+
setIndex(indexAtPlotX(viewX, frame, { steps, min, max }));
|
|
126
|
+
}, [frame, steps, min, max]);
|
|
127
|
+
const onKeyDown = React.useCallback((event) => {
|
|
128
|
+
if (event.key === "ArrowRight" || event.key === "ArrowLeft") {
|
|
129
|
+
const delta = event.key === "ArrowRight" ? 1 : -1;
|
|
130
|
+
setIndex((current) => stepIndex(current, delta, { min, max }));
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
}
|
|
133
|
+
else if (event.key === "Escape") {
|
|
134
|
+
setIndex(null);
|
|
135
|
+
}
|
|
136
|
+
}, [min, max]);
|
|
137
|
+
return { svgRef, index, clear, onPointerMove, onKeyDown };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Horizontal gridlines from 0 to `niceCeil(yMax)` with labels in the left
|
|
141
|
+
* padding. Render inside the chart's `<svg>`.
|
|
142
|
+
*/
|
|
143
|
+
export function ChartYAxisGrid({ frame, yMax, tickCount = 4, format = compactNumber, }) {
|
|
144
|
+
const ticks = niceTicks(yMax, tickCount);
|
|
145
|
+
const top = ticks[ticks.length - 1] ?? 1;
|
|
146
|
+
const y = (value) => frame.bottom - (value / top) * frame.plotHeight;
|
|
147
|
+
return (_jsx("g", { "data-slot": "chart-y-axis", children: ticks.map((tick) => (_jsxs("g", { children: [_jsx("line", { x1: frame.left, y1: y(tick), x2: frame.right, y2: y(tick), strokeWidth: 1, className: "stroke-border" }), _jsx("text", { x: frame.left - 6, y: y(tick) + 3, textAnchor: "end", className: "fill-muted-foreground text-[10px] tabular-nums", children: format(tick) })] }, tick))) }));
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Readout for the hovered or focused point, placed in percent of the chart
|
|
151
|
+
* box (its wrapper must be `relative`). It sits right of the point and
|
|
152
|
+
* flips left past 55% so it does not clip at the edge.
|
|
153
|
+
*/
|
|
154
|
+
export function ChartTooltip({ xPct, yPct, className, style, children, ...props }) {
|
|
155
|
+
const flip = xPct > 55;
|
|
156
|
+
return (_jsx("div", { role: "status", "data-slot": "chart-tooltip", className: cn(overlaySurface, "pointer-events-none absolute z-10 min-w-32 px-2.5 py-2 text-xs", className), style: {
|
|
157
|
+
left: `${xPct}%`,
|
|
158
|
+
top: `${Math.min(yPct, 60)}%`,
|
|
159
|
+
transform: flip ? "translateX(calc(-100% - 12px))" : "translateX(12px)",
|
|
160
|
+
...style,
|
|
161
|
+
}, ...props, children: children }));
|
|
162
|
+
}
|
|
163
|
+
function SeriesSwatch({ width, strokeWidth, dashed, className, }) {
|
|
164
|
+
return (_jsx("svg", { width: width, height: "4", "aria-hidden": true, className: "shrink-0", children: _jsx("line", { x1: "0", y1: "2", x2: width, y2: "2", strokeWidth: strokeWidth, strokeDasharray: dashed ? "3 2" : undefined, className: className }) }));
|
|
165
|
+
}
|
|
166
|
+
/** Tooltip row: the value leads, the label follows, keyed by the series stroke. */
|
|
167
|
+
export function ChartTooltipRow({ label, value, swatchClassName, dashed, }) {
|
|
168
|
+
return (_jsxs("div", { "data-slot": "chart-tooltip-row", className: "flex items-center gap-2 py-0.5", children: [_jsx(SeriesSwatch, { width: 14, strokeWidth: 2.5, dashed: dashed, className: swatchClassName }), _jsx("span", { className: "font-semibold tabular-nums", children: value }), _jsx("span", { className: "text-muted-foreground", children: label })] }));
|
|
169
|
+
}
|
|
170
|
+
/** Row of legend keys under a chart. */
|
|
171
|
+
export function ChartLegend({ className, ...props }) {
|
|
172
|
+
return (_jsx("div", { "data-slot": "chart-legend", className: cn("flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground", className), ...props }));
|
|
173
|
+
}
|
|
174
|
+
/** One legend entry: a solid or dashed line swatch and its label. */
|
|
175
|
+
export function ChartLegendKey({ label, swatchClassName, dashed, className, }) {
|
|
176
|
+
return (_jsxs("span", { "data-slot": "chart-legend-key", className: cn("inline-flex items-center gap-1.5", className), children: [_jsx(SeriesSwatch, { width: 16, strokeWidth: 2, dashed: dashed, className: swatchClassName }), label] }));
|
|
177
|
+
}
|
package/dist/color-legend.d.ts
CHANGED
|
@@ -2,15 +2,23 @@ import type * as React from "react";
|
|
|
2
2
|
export type ColorLegendItem = {
|
|
3
3
|
/** CSS color from the app (map bins, status scales). The kit does not own it. */
|
|
4
4
|
color: string;
|
|
5
|
+
/** Value range for the swatch, such as `0–10`, shown before the label. */
|
|
5
6
|
range?: string;
|
|
7
|
+
/** What the color means. */
|
|
6
8
|
label: string;
|
|
7
9
|
};
|
|
8
10
|
export type ColorLegendProps = Omit<React.ComponentProps<"figure">, "children" | "title"> & {
|
|
11
|
+
/** Heading above the list, drawn as the figure's caption. */
|
|
9
12
|
title?: string;
|
|
13
|
+
/** One row per color, in display order. */
|
|
10
14
|
items: ColorLegendItem[];
|
|
15
|
+
/** A small muted note under the list, such as the data source. */
|
|
11
16
|
caption?: React.ReactNode;
|
|
17
|
+
/** Extra content after the caption. */
|
|
12
18
|
children?: React.ReactNode;
|
|
19
|
+
/** Names the legend when there is no `title`. */
|
|
13
20
|
"aria-label"?: string;
|
|
21
|
+
/** Classes for the figure, e.g. overlay position and card fill. */
|
|
14
22
|
className?: string;
|
|
15
23
|
};
|
|
16
24
|
/**
|
package/dist/combobox.d.ts
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import type { SearchPickerProps } from "./search-picker.js";
|
|
2
3
|
export type ComboboxOption = {
|
|
4
|
+
/** What `onValueChange` reports and `value` matches; unique in the list. */
|
|
3
5
|
value: string;
|
|
6
|
+
/** The visible text, on the trigger when selected and in the list. */
|
|
4
7
|
label: string;
|
|
5
8
|
};
|
|
6
9
|
type ComboboxProps = {
|
|
10
|
+
/** Every choice, in display order. */
|
|
7
11
|
options: ComboboxOption[];
|
|
12
|
+
/** The selected option's value; the trigger shows its label. */
|
|
8
13
|
value?: string;
|
|
14
|
+
/** Called with the chosen (or created) value; the popover then closes. */
|
|
9
15
|
onValueChange: (value: string) => void;
|
|
16
|
+
/** Trigger text when nothing is selected. Default `"Select"`. */
|
|
10
17
|
placeholder?: string;
|
|
18
|
+
/** Placeholder and accessible name for the search input. Default `"Search"`. */
|
|
11
19
|
searchPlaceholder?: string;
|
|
12
|
-
|
|
20
|
+
/** Disables the trigger, so the list cannot open. */
|
|
13
21
|
disabled?: boolean;
|
|
22
|
+
/** Goes on the trigger, so a `<Label htmlFor>` names it. Generated when omitted. */
|
|
14
23
|
id?: string;
|
|
15
24
|
/** Classes for the trigger, e.g. its width; the list matches it. */
|
|
16
25
|
className?: string;
|
|
17
|
-
/** Classes for the listbox, e.g. its height. Defaults to `max-h-60`. */
|
|
18
|
-
listClassName?: string;
|
|
19
26
|
/**
|
|
20
27
|
* Classes for the popover panel, e.g. a width other than the trigger's.
|
|
21
28
|
* Defaults to the trigger width.
|
|
22
29
|
*/
|
|
23
30
|
contentClassName?: string;
|
|
31
|
+
/** Marks the trigger invalid, drawing the error border. */
|
|
24
32
|
"aria-invalid"?: boolean;
|
|
25
33
|
/** Name the trigger when there is no `<Label htmlFor={id}>`. */
|
|
26
34
|
"aria-label"?: string;
|
|
35
|
+
/** Id of the element that names the trigger and the list. */
|
|
27
36
|
"aria-labelledby"?: string;
|
|
28
37
|
/**
|
|
29
38
|
* Offer creating the current query when it is not already an option.
|
|
@@ -41,7 +50,7 @@ type ComboboxProps = {
|
|
|
41
50
|
* `Create "{value}"`.
|
|
42
51
|
*/
|
|
43
52
|
createLabel?: (value: string) => string;
|
|
44
|
-
} & Omit<React.ComponentProps<"button">, "value" | "defaultValue" | "children" | "type" | "role" | "aria-expanded" | "aria-controls" | "onKeyDown">;
|
|
53
|
+
} & Pick<SearchPickerProps<ComboboxOption>, "emptyText" | "listClassName"> & Omit<React.ComponentProps<"button">, "value" | "defaultValue" | "children" | "type" | "role" | "aria-expanded" | "aria-controls" | "onKeyDown">;
|
|
45
54
|
/**
|
|
46
55
|
* Searchable single-select built from Button, Popover, and Input.
|
|
47
56
|
* The trigger uses the same form-control chrome as Input and SelectTrigger.
|