@vvedantb/ui 0.17.1 → 0.18.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 +251 -3
- package/package.json +13 -5
- package/shell/src/SidebarResize.tsx +1 -4
- package/src/ai-elements/__snapshots__/queue.test.tsx.snap +11 -0
- package/src/ai-elements/activity-question-utils.ts +26 -0
- package/src/ai-elements/activity-question.tsx +159 -0
- package/src/ai-elements/activity-shared.tsx +459 -0
- package/src/ai-elements/activity-step-detail.tsx +115 -0
- package/src/ai-elements/activity-step-label.ts +981 -0
- package/src/ai-elements/activity-tasks-utils.ts +199 -0
- package/src/ai-elements/activity-tasks.tsx +770 -0
- package/src/ai-elements/artifact.tsx +162 -52
- package/src/ai-elements/attachments.tsx +62 -32
- package/src/ai-elements/code-block.tsx +76 -22
- package/src/ai-elements/context.tsx +370 -0
- package/src/ai-elements/conversation.tsx +186 -62
- package/src/ai-elements/file-chip.tsx +53 -0
- package/src/ai-elements/message.tsx +161 -50
- package/src/ai-elements/model-picker-content.tsx +505 -0
- package/src/ai-elements/model-picker-types.ts +56 -0
- package/src/ai-elements/model-picker.tsx +301 -0
- package/src/ai-elements/model-selector.tsx +102 -21
- package/src/ai-elements/plan.tsx +130 -0
- package/src/ai-elements/prompt-input-settings.tsx +144 -0
- package/src/ai-elements/prompt-input-speech.tsx +189 -0
- package/src/ai-elements/prompt-input-traits.tsx +281 -0
- package/src/ai-elements/prompt-input.tsx +320 -134
- package/src/ai-elements/provider-icon.tsx +133 -0
- package/src/ai-elements/queue.tsx +293 -9
- package/src/ai-elements/shimmer.tsx +72 -1
- package/src/ai-elements/simple-model-ladder.tsx +108 -0
- package/src/ai-elements/test-results.tsx +510 -0
- package/src/ai-elements/trace.tsx +243 -0
- package/src/ai-elements/use-streaming-disclosure.ts +50 -0
- package/src/ai-elements/web-preview.tsx +349 -0
- package/src/composer/input-area/ComposerSlashMenu.tsx +1 -1
- package/src/index.ts +66 -12
- package/src/kibo/avatar-stack.tsx +40 -0
- package/src/kibo/contribution-graph.tsx +539 -0
- package/src/kibo/cursor.tsx +72 -0
- package/src/kibo/gantt-features.tsx +439 -0
- package/src/kibo/gantt-header.tsx +181 -0
- package/src/kibo/gantt-provider.tsx +657 -0
- package/src/kibo/gantt-sidebar.tsx +157 -0
- package/src/kibo/gantt-timeline.tsx +154 -0
- package/src/kibo/index.ts +151 -0
- package/src/kibo/kanban.tsx +338 -0
- package/src/kibo/kanbanDropTarget.ts +25 -0
- package/src/kibo/list.tsx +162 -0
- package/src/kibo/theme-switcher.tsx +109 -0
- package/src/kibo/video-player.tsx +237 -0
- package/src/markdown/Markdown.tsx +112 -0
- package/src/markdown/MarkdownBlockquote.tsx +45 -0
- package/src/markdown/MarkdownCodeBlock.tsx +197 -0
- package/src/markdown/MarkdownInlineCode.tsx +40 -0
- package/src/markdown/MarkdownLink.tsx +92 -0
- package/src/markdown/codeFence.ts +57 -0
- package/src/markdown/codeHighlight.ts +138 -0
- package/src/markdown/incrementalBlocks.ts +182 -0
- package/src/markdown/index.ts +3 -0
- package/src/markdown/markdownClipboard.ts +178 -0
- package/src/markdown/mermaid.ts +155 -0
- package/src/markdown/rehypeGithubAlerts.ts +80 -0
- package/src/motion/presets.ts +24 -0
- package/src/ui/__snapshots__/alt-wrappers.test.tsx.snap +19 -0
- package/src/ui/__snapshots__/sonner-dom.test.tsx.snap +5 -0
- package/src/ui/_menu-parts.tsx +29 -0
- package/src/ui/accordion.alt.tsx +46 -53
- package/src/ui/accordion.tsx +59 -10
- package/src/ui/avatar.tsx +56 -0
- package/src/ui/badge.tsx +45 -21
- package/src/ui/border-beam.tsx +97 -0
- package/src/ui/button-group.tsx +50 -21
- package/src/ui/button.tsx +67 -45
- package/src/ui/calendar.tsx +48 -5
- package/src/ui/card.tsx +77 -8
- package/src/ui/carousel.tsx +60 -0
- package/src/ui/centered-spinner.tsx +30 -0
- package/src/ui/checkbox.tsx +34 -16
- package/src/ui/clear-input.alt.tsx +33 -75
- package/src/ui/clear-input.tsx +140 -15
- package/src/ui/collapsible.tsx +40 -2
- package/src/ui/command.tsx +143 -70
- package/src/ui/context-menu.tsx +159 -93
- package/src/ui/crossfade-icon.tsx +123 -0
- package/src/ui/dialog.tsx +154 -70
- package/src/ui/dropdown-menu.tsx +177 -117
- package/src/ui/hover-card.tsx +59 -17
- package/src/ui/input-group.alt.tsx +83 -83
- package/src/ui/input-group.tsx +129 -58
- package/src/ui/input.tsx +13 -4
- package/src/ui/label.tsx +11 -8
- package/src/ui/list-row.tsx +232 -0
- package/src/ui/loading-state.tsx +215 -0
- package/src/ui/popover.tsx +56 -23
- package/src/ui/progress.tsx +28 -16
- package/src/ui/refresh-spin-icon.tsx +41 -0
- package/src/ui/search-input.tsx +66 -15
- package/src/ui/select.tsx +171 -100
- package/src/ui/separator.tsx +23 -14
- package/src/ui/slider.tsx +21 -7
- package/src/ui/sonner.tsx +68 -30
- package/src/ui/spinner.tsx +229 -11
- package/src/ui/status-dot.tsx +84 -0
- package/src/ui/surface.tsx +49 -0
- package/src/ui/switch.tsx +29 -15
- package/src/ui/table.tsx +38 -16
- package/src/ui/tabs.tsx +123 -35
- package/src/ui/tabsSliding.ts +33 -1
- package/src/ui/textarea.tsx +13 -4
- package/src/ui/tooltip.tsx +50 -14
- package/src/ui/ui-config.tsx +149 -0
- package/src/utils/cat-color.ts +123 -0
- package/src/utils/dayjs.ts +6 -0
- package/src/utils/gesture.ts +59 -0
- package/src/utils/runtimeVisibility.ts +167 -0
- package/src/utils/sharedClock.ts +96 -0
- package/src/utils/surface-radius.ts +16 -0
- package/src/utils/useDragSensors.ts +58 -0
- package/tokens/examples/tokens-moved/Fixture.tsx +283 -0
- package/tokens/examples/tokens-moved/README.md +20 -0
- package/tokens/examples/tokens-moved/index.html +12 -0
- package/tokens/examples/tokens-moved/main.tsx +6 -0
- package/tokens/examples/tokens-moved/package.json +14 -0
- package/tokens/examples/tokens-moved/styles.css +12 -0
- package/tokens/examples/tokens-moved/tsconfig.json +14 -0
- package/tokens/examples/tokens-moved/vite.config.ts +11 -0
- package/tokens/src/css/border-beam.css +116 -0
- package/tokens/src/css/markdown.css +318 -0
package/src/ui/search-input.tsx
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { IconSearch } from "@tabler/icons-react";
|
|
5
|
-
import { cn } from "../utils/cn";
|
|
6
5
|
import { ClearInput, type ClearInputProps } from "./clear-input";
|
|
7
6
|
import { Kbd } from "./kbd";
|
|
7
|
+
import { useCn, useUiConfig } from "./ui-config";
|
|
8
8
|
|
|
9
9
|
const sizeClasses = {
|
|
10
10
|
sm: { input: "h-8 pl-8 text-sm", icon: "left-2" },
|
|
@@ -19,6 +19,26 @@ const variantClasses = {
|
|
|
19
19
|
},
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
type EnterKeyHint = React.InputHTMLAttributes<HTMLInputElement>["enterKeyHint"];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* `UiConfig.SearchInput`. `classes.input` and `classes.icon` replace the
|
|
26
|
+
* size classes of the input and the whole icon class; `classes.wrapper` is a
|
|
27
|
+
* base for the wrapper. Variant classes still apply after them. The other keys
|
|
28
|
+
* are prop defaults; `false` leaves the attribute off.
|
|
29
|
+
*/
|
|
30
|
+
export interface SearchInputConfig {
|
|
31
|
+
classes?: { wrapper?: string; input?: string; icon?: string };
|
|
32
|
+
/** Search icon size in px. Default `16`. */
|
|
33
|
+
iconSize?: number;
|
|
34
|
+
label?: string | false;
|
|
35
|
+
placeholder?: string;
|
|
36
|
+
clearLabel?: string;
|
|
37
|
+
enterKeyHint?: EnterKeyHint | false;
|
|
38
|
+
/** Element that receives `className`: `"input"` (default) or `"wrapper"`. */
|
|
39
|
+
classNameTarget?: "input" | "wrapper";
|
|
40
|
+
}
|
|
41
|
+
|
|
22
42
|
export interface SearchInputProps extends Omit<ClearInputProps, "leading" | "size"> {
|
|
23
43
|
/** `aria-label`, and the placeholder when `placeholder` is not set. Default `"Search"`. */
|
|
24
44
|
label?: string;
|
|
@@ -28,46 +48,77 @@ export interface SearchInputProps extends Omit<ClearInputProps, "leading" | "siz
|
|
|
28
48
|
size?: keyof typeof sizeClasses;
|
|
29
49
|
/** `toolbar`: transparent until hover or focus, fixed width from `sm`. Default `"default"`. */
|
|
30
50
|
variant?: keyof typeof variantClasses;
|
|
51
|
+
/** Called after `onChange` whenever the value becomes empty (typed away or cleared). */
|
|
52
|
+
onClear?: () => void;
|
|
53
|
+
/** Classes for the input, merged after `className` when that also targets the input. */
|
|
54
|
+
inputClassName?: string;
|
|
31
55
|
}
|
|
32
56
|
|
|
33
57
|
const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(
|
|
34
58
|
(
|
|
35
59
|
{
|
|
36
|
-
label
|
|
60
|
+
label,
|
|
37
61
|
placeholder,
|
|
38
|
-
clearLabel
|
|
62
|
+
clearLabel,
|
|
39
63
|
shortcut,
|
|
40
64
|
size = "sm",
|
|
41
65
|
variant = "default",
|
|
42
66
|
className,
|
|
43
67
|
wrapperClassName,
|
|
68
|
+
inputClassName,
|
|
69
|
+
onClear,
|
|
70
|
+
onChange,
|
|
44
71
|
...props
|
|
45
72
|
},
|
|
46
73
|
ref,
|
|
47
74
|
) => {
|
|
75
|
+
const config = useUiConfig("SearchInput");
|
|
76
|
+
const cn = useCn();
|
|
77
|
+
const name = label ?? config?.label ?? "Search";
|
|
78
|
+
const hint = config?.enterKeyHint ?? "search";
|
|
79
|
+
const onWrapper = config?.classNameTarget === "wrapper";
|
|
48
80
|
const showShortcut = Boolean(shortcut) && props.value.length === 0;
|
|
49
81
|
return (
|
|
50
82
|
<ClearInput
|
|
51
83
|
ref={ref}
|
|
52
|
-
aria-label={
|
|
53
|
-
placeholder={placeholder ??
|
|
54
|
-
clearLabel={clearLabel}
|
|
55
|
-
enterKeyHint=
|
|
56
|
-
|
|
84
|
+
aria-label={name === false ? undefined : name}
|
|
85
|
+
placeholder={placeholder ?? config?.placeholder ?? (name === false ? undefined : name)}
|
|
86
|
+
clearLabel={clearLabel ?? config?.clearLabel ?? "Clear search"}
|
|
87
|
+
enterKeyHint={hint === false ? undefined : hint}
|
|
88
|
+
onChange={
|
|
89
|
+
onClear
|
|
90
|
+
? (next) => {
|
|
91
|
+
onChange(next);
|
|
92
|
+
if (next.length === 0) {
|
|
93
|
+
onClear();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
: onChange
|
|
97
|
+
}
|
|
98
|
+
wrapperClassName={cn(
|
|
99
|
+
config?.classes?.wrapper,
|
|
100
|
+
variantClasses[variant].wrapper,
|
|
101
|
+
wrapperClassName,
|
|
102
|
+
onWrapper && className,
|
|
103
|
+
)}
|
|
57
104
|
className={cn(
|
|
58
|
-
sizeClasses[size].input,
|
|
105
|
+
config?.classes?.input ?? sizeClasses[size].input,
|
|
59
106
|
variantClasses[variant].input,
|
|
60
107
|
showShortcut && "pr-12",
|
|
61
|
-
className,
|
|
108
|
+
!onWrapper && className,
|
|
109
|
+
inputClassName,
|
|
62
110
|
)}
|
|
63
111
|
leading={
|
|
64
112
|
<>
|
|
65
113
|
<IconSearch
|
|
66
|
-
size={16}
|
|
67
|
-
className={
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
114
|
+
size={config?.iconSize ?? 16}
|
|
115
|
+
className={
|
|
116
|
+
config?.classes?.icon ??
|
|
117
|
+
cn(
|
|
118
|
+
"pointer-events-none absolute top-1/2 -translate-y-1/2 shrink-0 text-muted-foreground",
|
|
119
|
+
sizeClasses[size].icon,
|
|
120
|
+
)
|
|
121
|
+
}
|
|
71
122
|
/>
|
|
72
123
|
{showShortcut ? (
|
|
73
124
|
<Kbd className="absolute right-2 top-1/2 -translate-y-1/2">{shortcut}</Kbd>
|
package/src/ui/select.tsx
CHANGED
|
@@ -7,6 +7,37 @@ import {
|
|
|
7
7
|
floatingSurfaceAnimateClass,
|
|
8
8
|
floatingSurfaceClass,
|
|
9
9
|
} from "./_menu-classes";
|
|
10
|
+
import { useCn, useUiConfig } from "./ui-config";
|
|
11
|
+
|
|
12
|
+
/** App defaults for `Select*` (see `UiConfigProvider`). */
|
|
13
|
+
export interface SelectConfig {
|
|
14
|
+
/** Replaces the built-in classes of a part. */
|
|
15
|
+
classes?: {
|
|
16
|
+
trigger?: string;
|
|
17
|
+
/** Both scroll buttons. */
|
|
18
|
+
scrollButton?: string;
|
|
19
|
+
content?: string;
|
|
20
|
+
/** Viewport classes for every `position`. */
|
|
21
|
+
viewport?: string;
|
|
22
|
+
/** Extra viewport classes for `position="popper"`. */
|
|
23
|
+
popperViewport?: string;
|
|
24
|
+
label?: string;
|
|
25
|
+
item?: string;
|
|
26
|
+
separator?: string;
|
|
27
|
+
};
|
|
28
|
+
/** Replace the built-in icons. */
|
|
29
|
+
icons?: {
|
|
30
|
+
trigger?: React.ReactNode;
|
|
31
|
+
scrollUp?: React.ReactNode;
|
|
32
|
+
scrollDown?: React.ReactNode;
|
|
33
|
+
/** `SelectItem` indicator. */
|
|
34
|
+
check?: React.ReactNode;
|
|
35
|
+
};
|
|
36
|
+
/** Adds `data-slot="select-trigger"` to the trigger, for parent selectors such as `ButtonGroup`'s. */
|
|
37
|
+
triggerSlot?: boolean;
|
|
38
|
+
/** Default for `SelectContent` `collisionPadding`. */
|
|
39
|
+
collisionPadding?: number | Partial<Record<"top" | "right" | "bottom" | "left", number>>;
|
|
40
|
+
}
|
|
10
41
|
|
|
11
42
|
const Select = SelectPrimitive.Root;
|
|
12
43
|
const SelectGroup = SelectPrimitive.Group;
|
|
@@ -15,140 +46,180 @@ const SelectValue = SelectPrimitive.Value;
|
|
|
15
46
|
const SelectTrigger = React.forwardRef<
|
|
16
47
|
React.ComponentRef<typeof SelectPrimitive.Trigger>,
|
|
17
48
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
|
18
|
-
>(({ className, children, ...props }, ref) =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
49
|
+
>(({ className, children, ...props }, ref) => {
|
|
50
|
+
const config = useUiConfig("Select");
|
|
51
|
+
const merge = useCn();
|
|
52
|
+
return (
|
|
53
|
+
<SelectPrimitive.Trigger
|
|
54
|
+
ref={ref}
|
|
55
|
+
data-slot={config?.triggerSlot ? "select-trigger" : undefined}
|
|
56
|
+
className={merge(
|
|
57
|
+
config?.classes?.trigger ?? [
|
|
58
|
+
"flex h-10 w-full max-sm:min-w-0 items-center justify-between whitespace-nowrap rounded-field border border-border bg-field-background px-3.5 py-2 text-base sm:text-sm ring-offset-background placeholder:text-field-placeholder transition-[border-color,box-shadow,background-color] duration-200 ease-smooth disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
59
|
+
fieldFocusClass,
|
|
60
|
+
],
|
|
61
|
+
className,
|
|
62
|
+
)}
|
|
63
|
+
{...props}
|
|
64
|
+
>
|
|
65
|
+
{children}
|
|
66
|
+
<SelectPrimitive.Icon asChild>
|
|
67
|
+
{config?.icons?.trigger ?? <IconChevronDown className="h-4 w-4 text-muted-foreground/85" />}
|
|
68
|
+
</SelectPrimitive.Icon>
|
|
69
|
+
</SelectPrimitive.Trigger>
|
|
70
|
+
);
|
|
71
|
+
});
|
|
34
72
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
35
73
|
|
|
36
74
|
const SelectScrollUpButton = React.forwardRef<
|
|
37
75
|
React.ComponentRef<typeof SelectPrimitive.ScrollUpButton>,
|
|
38
76
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
|
39
|
-
>(({ className, ...props }, ref) =>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
77
|
+
>(({ className, ...props }, ref) => {
|
|
78
|
+
const config = useUiConfig("Select");
|
|
79
|
+
const merge = useCn();
|
|
80
|
+
return (
|
|
81
|
+
<SelectPrimitive.ScrollUpButton
|
|
82
|
+
ref={ref}
|
|
83
|
+
className={merge(
|
|
84
|
+
config?.classes?.scrollButton ??
|
|
85
|
+
"flex cursor-default items-center justify-center py-1 text-muted-foreground",
|
|
86
|
+
className,
|
|
87
|
+
)}
|
|
88
|
+
{...props}
|
|
89
|
+
>
|
|
90
|
+
{config?.icons?.scrollUp ?? <IconChevronUp className="h-4 w-4" />}
|
|
91
|
+
</SelectPrimitive.ScrollUpButton>
|
|
92
|
+
);
|
|
93
|
+
});
|
|
51
94
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
52
95
|
|
|
53
96
|
const SelectScrollDownButton = React.forwardRef<
|
|
54
97
|
React.ComponentRef<typeof SelectPrimitive.ScrollDownButton>,
|
|
55
98
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
|
56
|
-
>(({ className, ...props }, ref) =>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
99
|
+
>(({ className, ...props }, ref) => {
|
|
100
|
+
const config = useUiConfig("Select");
|
|
101
|
+
const merge = useCn();
|
|
102
|
+
return (
|
|
103
|
+
<SelectPrimitive.ScrollDownButton
|
|
104
|
+
ref={ref}
|
|
105
|
+
className={merge(
|
|
106
|
+
config?.classes?.scrollButton ??
|
|
107
|
+
"flex cursor-default items-center justify-center py-1 text-muted-foreground",
|
|
108
|
+
className,
|
|
109
|
+
)}
|
|
110
|
+
{...props}
|
|
111
|
+
>
|
|
112
|
+
{config?.icons?.scrollDown ?? <IconChevronDown className="h-4 w-4" />}
|
|
113
|
+
</SelectPrimitive.ScrollDownButton>
|
|
114
|
+
);
|
|
115
|
+
});
|
|
68
116
|
SelectScrollDownButton.displayName =
|
|
69
117
|
SelectPrimitive.ScrollDownButton.displayName;
|
|
70
118
|
|
|
71
119
|
const SelectContent = React.forwardRef<
|
|
72
120
|
React.ComponentRef<typeof SelectPrimitive.Content>,
|
|
73
121
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
74
|
-
>(({ className, children, position = "popper", ...props }, ref) =>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
<SelectScrollUpButton />
|
|
90
|
-
<SelectPrimitive.Viewport
|
|
91
|
-
className={cn(
|
|
92
|
-
"p-1.5",
|
|
122
|
+
>(({ className, children, position = "popper", collisionPadding, ...props }, ref) => {
|
|
123
|
+
const config = useUiConfig("Select");
|
|
124
|
+
const merge = useCn();
|
|
125
|
+
const classes = config?.classes;
|
|
126
|
+
return (
|
|
127
|
+
<SelectPrimitive.Portal>
|
|
128
|
+
<SelectPrimitive.Content
|
|
129
|
+
ref={ref}
|
|
130
|
+
collisionPadding={collisionPadding ?? config?.collisionPadding}
|
|
131
|
+
className={merge(
|
|
132
|
+
classes?.content ?? [
|
|
133
|
+
"relative z-50 max-h-96 min-w-32 overflow-hidden outline-none",
|
|
134
|
+
floatingSurfaceClass,
|
|
135
|
+
floatingSurfaceAnimateClass,
|
|
136
|
+
],
|
|
93
137
|
position === "popper" &&
|
|
94
|
-
"
|
|
138
|
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
139
|
+
className,
|
|
95
140
|
)}
|
|
141
|
+
position={position}
|
|
142
|
+
{...props}
|
|
96
143
|
>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
144
|
+
<SelectScrollUpButton />
|
|
145
|
+
<SelectPrimitive.Viewport
|
|
146
|
+
className={cn(
|
|
147
|
+
classes?.viewport ?? "p-1.5",
|
|
148
|
+
position === "popper" &&
|
|
149
|
+
(classes?.popperViewport ??
|
|
150
|
+
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),
|
|
151
|
+
)}
|
|
152
|
+
>
|
|
153
|
+
{children}
|
|
154
|
+
</SelectPrimitive.Viewport>
|
|
155
|
+
<SelectScrollDownButton />
|
|
156
|
+
</SelectPrimitive.Content>
|
|
157
|
+
</SelectPrimitive.Portal>
|
|
158
|
+
);
|
|
159
|
+
});
|
|
103
160
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
104
161
|
|
|
105
162
|
const SelectLabel = React.forwardRef<
|
|
106
163
|
React.ComponentRef<typeof SelectPrimitive.Label>,
|
|
107
164
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
|
108
|
-
>(({ className, ...props }, ref) =>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
165
|
+
>(({ className, ...props }, ref) => {
|
|
166
|
+
const label = useUiConfig("Select")?.classes?.label;
|
|
167
|
+
const merge = useCn();
|
|
168
|
+
return (
|
|
169
|
+
<SelectPrimitive.Label
|
|
170
|
+
ref={ref}
|
|
171
|
+
className={merge(
|
|
172
|
+
label ??
|
|
173
|
+
"px-2.5 py-1.5 text-xs font-semibold uppercase tracking-widest text-muted-foreground",
|
|
174
|
+
className,
|
|
175
|
+
)}
|
|
176
|
+
{...props}
|
|
177
|
+
/>
|
|
178
|
+
);
|
|
179
|
+
});
|
|
118
180
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
119
181
|
|
|
120
182
|
const SelectItem = React.forwardRef<
|
|
121
183
|
React.ComponentRef<typeof SelectPrimitive.Item>,
|
|
122
184
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
|
123
|
-
>(({ className, children, ...props }, ref) =>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
185
|
+
>(({ className, children, ...props }, ref) => {
|
|
186
|
+
const config = useUiConfig("Select");
|
|
187
|
+
const merge = useCn();
|
|
188
|
+
return (
|
|
189
|
+
<SelectPrimitive.Item
|
|
190
|
+
ref={ref}
|
|
191
|
+
className={merge(
|
|
192
|
+
config?.classes?.item ??
|
|
193
|
+
"relative flex w-full cursor-pointer select-none items-center rounded-menu-item py-2 max-sm:min-h-10 pl-2.5 pr-8 text-sm outline-none transition-[background-color,color] focus:bg-default focus:text-foreground data-[highlighted]:bg-default data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50",
|
|
194
|
+
className,
|
|
195
|
+
)}
|
|
196
|
+
{...props}
|
|
197
|
+
>
|
|
198
|
+
<span className="absolute right-2.5 flex h-3.5 w-3.5 items-center justify-center">
|
|
199
|
+
<SelectPrimitive.ItemIndicator>
|
|
200
|
+
{config?.icons?.check ?? <IconCheck className="h-4 w-4" />}
|
|
201
|
+
</SelectPrimitive.ItemIndicator>
|
|
202
|
+
</span>
|
|
203
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
204
|
+
</SelectPrimitive.Item>
|
|
205
|
+
);
|
|
206
|
+
});
|
|
140
207
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
141
208
|
|
|
142
209
|
const SelectSeparator = React.forwardRef<
|
|
143
210
|
React.ComponentRef<typeof SelectPrimitive.Separator>,
|
|
144
211
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
|
145
|
-
>(({ className, ...props }, ref) =>
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
)
|
|
212
|
+
>(({ className, ...props }, ref) => {
|
|
213
|
+
const separator = useUiConfig("Select")?.classes?.separator;
|
|
214
|
+
const merge = useCn();
|
|
215
|
+
return (
|
|
216
|
+
<SelectPrimitive.Separator
|
|
217
|
+
ref={ref}
|
|
218
|
+
className={merge(separator ?? "-mx-1.5 my-1 h-px bg-separator", className)}
|
|
219
|
+
{...props}
|
|
220
|
+
/>
|
|
221
|
+
);
|
|
222
|
+
});
|
|
152
223
|
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
153
224
|
|
|
154
225
|
export {
|
package/src/ui/separator.tsx
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
3
|
-
import {
|
|
3
|
+
import { useCn, useUiConfig } from "./ui-config";
|
|
4
|
+
|
|
5
|
+
export interface SeparatorConfig {
|
|
6
|
+
/** Replaces the built-in classes of a part. `root` excludes the orientation size classes. */
|
|
7
|
+
classes?: { root?: string };
|
|
8
|
+
}
|
|
4
9
|
|
|
5
10
|
const Separator = React.forwardRef<
|
|
6
11
|
React.ComponentRef<typeof SeparatorPrimitive.Root>,
|
|
@@ -9,19 +14,23 @@ const Separator = React.forwardRef<
|
|
|
9
14
|
(
|
|
10
15
|
{ className, orientation = "horizontal", decorative = true, ...props },
|
|
11
16
|
ref,
|
|
12
|
-
) =>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
orientation
|
|
20
|
-
className
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
) => {
|
|
18
|
+
const root = useUiConfig("Separator")?.classes?.root;
|
|
19
|
+
const merge = useCn();
|
|
20
|
+
return (
|
|
21
|
+
<SeparatorPrimitive.Root
|
|
22
|
+
ref={ref}
|
|
23
|
+
decorative={decorative}
|
|
24
|
+
orientation={orientation}
|
|
25
|
+
className={merge(
|
|
26
|
+
root ?? "shrink-0 bg-separator",
|
|
27
|
+
orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
|
|
28
|
+
className,
|
|
29
|
+
)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
},
|
|
25
34
|
);
|
|
26
35
|
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
|
27
36
|
|
package/src/ui/slider.tsx
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
3
|
-
import {
|
|
3
|
+
import { useCn, useUiConfig } from "./ui-config";
|
|
4
|
+
|
|
5
|
+
/** `UiConfig.Slider`: `classes` replace the built-in part classes; the `*ClassName` props still merge after. */
|
|
6
|
+
export interface SliderConfig {
|
|
7
|
+
classes?: { root?: string; track?: string; range?: string; thumb?: string };
|
|
8
|
+
}
|
|
4
9
|
|
|
5
10
|
type SliderProps = React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> & {
|
|
6
11
|
/** Accessible name per thumb, by index. Wins over `aria-label` on the first thumb. */
|
|
7
12
|
thumbLabels?: string[];
|
|
8
|
-
/** Classes for the track, merged after the defaults so they win (`bg-default dark:bg-muted/40`). */
|
|
13
|
+
/** Classes for the track, merged after the defaults so they win (`bg-default dark:bg-muted/40`). check-tokens-allow: muted */
|
|
9
14
|
trackClassName?: string;
|
|
10
15
|
/** Classes for the filled range, merged after the defaults so they win (`bg-primary`). */
|
|
11
16
|
rangeClassName?: string;
|
|
12
|
-
/** Classes for every thumb, merged after the defaults so they win (`bg-background dark:bg-foreground dark:border-muted`). */
|
|
17
|
+
/** Classes for every thumb, merged after the defaults so they win (`bg-background dark:bg-foreground dark:border-muted`). check-tokens-allow: muted */
|
|
13
18
|
thumbClassName?: string;
|
|
14
19
|
};
|
|
15
20
|
|
|
16
21
|
// `id`, `aria-label`, `aria-labelledby` and `aria-valuetext` go to the first
|
|
17
22
|
// Thumb, not Root: the thumb is the focusable role="slider" element, so
|
|
18
23
|
// `<Label htmlFor={id}>` and the accessible name land on it. The ref stays on Root.
|
|
24
|
+
// `children` render inside the track, after the range (for example tick marks).
|
|
19
25
|
const Slider = React.forwardRef<React.ComponentRef<typeof SliderPrimitive.Root>, SliderProps>(
|
|
20
26
|
(
|
|
21
27
|
{
|
|
@@ -28,15 +34,19 @@ const Slider = React.forwardRef<React.ComponentRef<typeof SliderPrimitive.Root>,
|
|
|
28
34
|
trackClassName,
|
|
29
35
|
rangeClassName,
|
|
30
36
|
thumbClassName,
|
|
37
|
+
children,
|
|
31
38
|
...props
|
|
32
39
|
},
|
|
33
40
|
ref,
|
|
34
41
|
) => {
|
|
42
|
+
const classes = useUiConfig("Slider")?.classes;
|
|
43
|
+
const cn = useCn();
|
|
35
44
|
const count = (props.value ?? props.defaultValue ?? [props.min ?? 0]).length;
|
|
36
45
|
return (
|
|
37
46
|
<SliderPrimitive.Root
|
|
38
47
|
className={cn(
|
|
39
|
-
|
|
48
|
+
classes?.root ??
|
|
49
|
+
"relative flex w-full touch-none select-none items-center data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
|
|
40
50
|
className,
|
|
41
51
|
)}
|
|
42
52
|
{...props}
|
|
@@ -44,16 +54,19 @@ const Slider = React.forwardRef<React.ComponentRef<typeof SliderPrimitive.Root>,
|
|
|
44
54
|
>
|
|
45
55
|
<SliderPrimitive.Track
|
|
46
56
|
className={cn(
|
|
47
|
-
|
|
57
|
+
classes?.track ??
|
|
58
|
+
"relative grow overflow-hidden rounded-full bg-default dark:bg-muted/40 data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5", // check-tokens-allow: muted
|
|
48
59
|
trackClassName,
|
|
49
60
|
)}
|
|
50
61
|
>
|
|
51
62
|
<SliderPrimitive.Range
|
|
52
63
|
className={cn(
|
|
53
|
-
|
|
64
|
+
classes?.range ??
|
|
65
|
+
"absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full",
|
|
54
66
|
rangeClassName,
|
|
55
67
|
)}
|
|
56
68
|
/>
|
|
69
|
+
{children}
|
|
57
70
|
</SliderPrimitive.Track>
|
|
58
71
|
{Array.from({ length: count }, (_, i) => (
|
|
59
72
|
<SliderPrimitive.Thumb
|
|
@@ -63,7 +76,8 @@ const Slider = React.forwardRef<React.ComponentRef<typeof SliderPrimitive.Root>,
|
|
|
63
76
|
aria-labelledby={i === 0 ? ariaLabelledBy : undefined}
|
|
64
77
|
aria-valuetext={i === 0 ? ariaValueText : undefined}
|
|
65
78
|
className={cn(
|
|
66
|
-
|
|
79
|
+
classes?.thumb ??
|
|
80
|
+
"block size-4 shrink-0 rounded-full border border-border bg-background shadow-sm transition-[box-shadow] duration-200 ease-smooth focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring data-[disabled]:cursor-not-allowed dark:border-muted dark:bg-foreground", // check-tokens-allow: muted
|
|
67
81
|
thumbClassName,
|
|
68
82
|
)}
|
|
69
83
|
/>
|