@sero-ai/ui 0.5.0 → 0.6.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/.turbo/turbo-build.log +386 -378
- package/.turbo/turbo-test.log +12 -11
- package/CHANGELOG.md +2 -2
- package/dist/components/ai-elements/conversation-virtual.cjs +115 -0
- package/dist/components/ai-elements/conversation-virtual.d.cts +30 -0
- package/dist/components/ai-elements/conversation-virtual.d.ts +30 -0
- package/dist/components/ai-elements/conversation-virtual.js +115 -0
- package/dist/components/model-selection/available-model-picker.cjs +21 -77
- package/dist/components/model-selection/available-model-picker.js +22 -78
- package/dist/components/model-selection/model-picker-body.cjs +106 -0
- package/dist/components/model-selection/model-picker-body.d.cts +41 -0
- package/dist/components/model-selection/model-picker-body.d.ts +41 -0
- package/dist/components/model-selection/model-picker-body.js +106 -0
- package/dist/components/model-selection/thinking-level-picker.cjs +7 -3
- package/dist/components/model-selection/thinking-level-picker.js +7 -3
- package/dist/components/model-selection/thinking-picker.cjs +1 -1
- package/dist/components/model-selection/thinking-picker.js +1 -1
- package/dist/components/ui/calendar.cjs +1 -1
- package/dist/components/ui/calendar.js +1 -1
- package/dist/components/ui/combobox.cjs +1 -1
- package/dist/components/ui/combobox.js +1 -1
- package/dist/components/ui/form.d.cts +1 -1
- package/dist/components/ui/form.d.ts +1 -1
- package/dist/components/ui/input-group.cjs +1 -1
- package/dist/components/ui/input-group.js +1 -1
- package/dist/components/ui/input-otp.cjs +1 -1
- package/dist/components/ui/input-otp.js +1 -1
- package/dist/components/ui/input.cjs +3 -3
- package/dist/components/ui/input.js +3 -3
- package/dist/components/ui/native-select.cjs +2 -2
- package/dist/components/ui/native-select.js +2 -2
- package/dist/components/ui/select.cjs +1 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/slider.cjs +6 -0
- package/dist/components/ui/slider.d.cts +1 -1
- package/dist/components/ui/slider.d.ts +1 -1
- package/dist/components/ui/slider.js +6 -0
- package/dist/components/ui/spinner.d.cts +2 -1
- package/dist/components/ui/spinner.d.ts +2 -1
- package/dist/components/ui/textarea.cjs +1 -1
- package/dist/components/ui/textarea.js +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/styles/globals.css +32 -0
- package/dist/theme/apply-theme.cjs +65 -12
- package/dist/theme/apply-theme.js +55 -2
- package/dist/theme/index.d.cts +1 -1
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/types.cjs +15 -2
- package/dist/theme/types.d.cts +21 -1
- package/dist/theme/types.d.ts +21 -1
- package/dist/theme/types.js +14 -1
- package/package.json +21 -20
- package/scripts/smoke-dist.mjs +2 -2
- package/src/components/ai-elements/conversation-virtual.test.tsx +126 -0
- package/src/components/ai-elements/conversation-virtual.tsx +162 -0
- package/src/components/model-selection/available-model-picker.tsx +26 -98
- package/src/components/model-selection/model-picker-body.test.tsx +152 -0
- package/src/components/model-selection/model-picker-body.tsx +188 -0
- package/src/components/model-selection/thinking-level-picker.tsx +9 -3
- package/src/components/model-selection/thinking-picker.test.tsx +41 -0
- package/src/components/model-selection/thinking-picker.tsx +1 -1
- package/src/components/ui/calendar.test.tsx +43 -0
- package/src/components/ui/calendar.tsx +1 -1
- package/src/components/ui/combobox.tsx +1 -1
- package/src/components/ui/input-group.tsx +1 -1
- package/src/components/ui/input-otp.tsx +1 -1
- package/src/components/ui/input.tsx +3 -3
- package/src/components/ui/native-select.tsx +2 -2
- package/src/components/ui/select.tsx +1 -1
- package/src/components/ui/slider.tsx +6 -0
- package/src/components/ui/spinner.tsx +1 -1
- package/src/components/ui/textarea.tsx +1 -1
- package/src/styles/globals.css +32 -0
- package/src/theme/apply-theme.test.ts +126 -0
- package/src/theme/apply-theme.ts +66 -3
- package/src/theme/types.ts +33 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _jsxruntime = require('react/jsx-runtime');
|
|
2
|
+
var _react = require('react');
|
|
3
|
+
var _lucidereact = require('lucide-react');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _common = require('@sero-ai/common');
|
|
8
|
+
var _searchinput = require('../ui/search-input');
|
|
9
|
+
var _utils = require('../../lib/utils');
|
|
10
|
+
function ProviderLogo({
|
|
11
|
+
logo,
|
|
12
|
+
displayName,
|
|
13
|
+
className
|
|
14
|
+
}) {
|
|
15
|
+
const [failed, setFailed] = _react.useState.call(void 0, false);
|
|
16
|
+
_react.useEffect.call(void 0, () => setFailed(false), [logo]);
|
|
17
|
+
if (!logo || failed) return null;
|
|
18
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
19
|
+
"img",
|
|
20
|
+
{
|
|
21
|
+
src: logo,
|
|
22
|
+
alt: displayName,
|
|
23
|
+
onError: () => setFailed(true),
|
|
24
|
+
className: _utils.cn.call(void 0, "size-3.5 shrink-0 rounded-sm dark:invert", className)
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
function ModelPickerBody({
|
|
29
|
+
groups,
|
|
30
|
+
value,
|
|
31
|
+
onChange,
|
|
32
|
+
searchPlaceholder = "Search models...",
|
|
33
|
+
emptyLabel = "No matching models",
|
|
34
|
+
noModelsLabel = "No models available",
|
|
35
|
+
autoFocusSearch = true,
|
|
36
|
+
showProviderLogos = true,
|
|
37
|
+
searchEndAdornment,
|
|
38
|
+
className,
|
|
39
|
+
listClassName
|
|
40
|
+
}) {
|
|
41
|
+
const [query, setQuery] = _react.useState.call(void 0, "");
|
|
42
|
+
const inputRef = _react.useRef.call(void 0, null);
|
|
43
|
+
_react.useEffect.call(void 0, () => {
|
|
44
|
+
if (!autoFocusSearch) return;
|
|
45
|
+
const frame = requestAnimationFrame(() => _optionalChain([inputRef, 'access', _ => _.current, 'optionalAccess', _2 => _2.focus, 'call', _3 => _3()]));
|
|
46
|
+
return () => cancelAnimationFrame(frame);
|
|
47
|
+
}, [autoFocusSearch]);
|
|
48
|
+
const filteredGroups = _react.useMemo.call(void 0, () => _common.filterModelGroups.call(void 0, groups, query), [groups, query]);
|
|
49
|
+
const totalResults = _react.useMemo.call(void 0,
|
|
50
|
+
() => filteredGroups.reduce((count, group) => count + group.models.length, 0),
|
|
51
|
+
[filteredGroups]
|
|
52
|
+
);
|
|
53
|
+
const handleSelect = _react.useCallback.call(void 0,
|
|
54
|
+
(provider, modelId) => {
|
|
55
|
+
onChange(_common.modelKey.call(void 0, provider, modelId));
|
|
56
|
+
setQuery("");
|
|
57
|
+
},
|
|
58
|
+
[onChange]
|
|
59
|
+
);
|
|
60
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className, children: [
|
|
61
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
62
|
+
_searchinput.SearchInput,
|
|
63
|
+
{
|
|
64
|
+
ref: inputRef,
|
|
65
|
+
value: query,
|
|
66
|
+
onChange: (event) => setQuery(event.target.value),
|
|
67
|
+
placeholder: searchPlaceholder,
|
|
68
|
+
"data-slot": "model-filter",
|
|
69
|
+
containerClassName: "border-b border-border/40",
|
|
70
|
+
endAdornment: searchEndAdornment
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _utils.cn.call(void 0, "max-h-[280px] overflow-y-auto py-1", listClassName), children: groups.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: noModelsLabel }) : totalResults === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: emptyLabel }) : filteredGroups.map((group, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
|
|
74
|
+
index > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mx-3 border-t border-border/30" }) : null,
|
|
75
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 px-3 pb-1 pt-2", children: [
|
|
76
|
+
showProviderLogos ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ProviderLogo, { logo: group.logo, displayName: group.displayName }) : null,
|
|
77
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-sm font-semibold uppercase tracking-wider text-muted-foreground", children: group.displayName })
|
|
78
|
+
] }),
|
|
79
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-1", children: group.models.map((model) => {
|
|
80
|
+
const nextValue = _common.modelKey.call(void 0, model.provider, model.modelId);
|
|
81
|
+
const isSelected = nextValue === value;
|
|
82
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
83
|
+
"button",
|
|
84
|
+
{
|
|
85
|
+
type: "button",
|
|
86
|
+
onClick: () => handleSelect(model.provider, model.modelId),
|
|
87
|
+
className: _utils.cn.call(void 0,
|
|
88
|
+
"flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-left text-sm transition-colors",
|
|
89
|
+
isSelected ? "bg-secondary text-foreground" : "text-muted-foreground hover:bg-secondary/60 hover:text-foreground"
|
|
90
|
+
),
|
|
91
|
+
children: [
|
|
92
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex size-4 shrink-0 items-center justify-center", children: isSelected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "size-1.5 rounded-full bg-border" }) }),
|
|
93
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "min-w-0 flex-1 truncate font-medium", children: model.name }),
|
|
94
|
+
model.reasoning ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Sparkles, { className: "size-3 shrink-0 text-amber-500/60" }) : null
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
nextValue
|
|
98
|
+
);
|
|
99
|
+
}) })
|
|
100
|
+
] }, group.provider)) })
|
|
101
|
+
] });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
exports.ModelPickerBody = ModelPickerBody; exports.ProviderLogo = ProviderLogo;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { SharedModelInfo, SharedAvailableModelGroup } from '@sero-ai/common';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A provider logo.
|
|
7
|
+
*
|
|
8
|
+
* `logo` is a remote URL, so it is empty for some providers and it fails
|
|
9
|
+
* on a machine with no internet. Either way we show nothing rather than
|
|
10
|
+
* a broken image.
|
|
11
|
+
*/
|
|
12
|
+
declare function ProviderLogo({ logo, displayName, className, }: {
|
|
13
|
+
logo: string;
|
|
14
|
+
displayName: string;
|
|
15
|
+
className?: string;
|
|
16
|
+
}): react_jsx_runtime.JSX.Element | null;
|
|
17
|
+
interface ModelPickerBodyProps<TModel extends SharedModelInfo, TGroup extends SharedAvailableModelGroup<TModel>> {
|
|
18
|
+
groups: TGroup[];
|
|
19
|
+
/** The selected model as `provider/modelId`, or '' for none. */
|
|
20
|
+
value: string;
|
|
21
|
+
/** Called with the new `provider/modelId`. */
|
|
22
|
+
onChange: (value: string) => void;
|
|
23
|
+
searchPlaceholder?: string;
|
|
24
|
+
emptyLabel?: string;
|
|
25
|
+
noModelsLabel?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Focus the search field on mount. Turn this off on a phone: the
|
|
28
|
+
* on-screen keyboard would cover the list the user came to read.
|
|
29
|
+
*/
|
|
30
|
+
autoFocusSearch?: boolean;
|
|
31
|
+
/** Hide provider logos where the network may not reach them. */
|
|
32
|
+
showProviderLogos?: boolean;
|
|
33
|
+
/** Shown at the right of the search field, such as a settings button. */
|
|
34
|
+
searchEndAdornment?: ReactNode;
|
|
35
|
+
className?: string;
|
|
36
|
+
/** Applied to the scrolling list, so a caller sets its height. */
|
|
37
|
+
listClassName?: string;
|
|
38
|
+
}
|
|
39
|
+
declare function ModelPickerBody<TModel extends SharedModelInfo, TGroup extends SharedAvailableModelGroup<TModel>>({ groups, value, onChange, searchPlaceholder, emptyLabel, noModelsLabel, autoFocusSearch, showProviderLogos, searchEndAdornment, className, listClassName, }: ModelPickerBodyProps<TModel, TGroup>): react_jsx_runtime.JSX.Element;
|
|
40
|
+
|
|
41
|
+
export { ModelPickerBody, ProviderLogo };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { SharedModelInfo, SharedAvailableModelGroup } from '@sero-ai/common';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A provider logo.
|
|
7
|
+
*
|
|
8
|
+
* `logo` is a remote URL, so it is empty for some providers and it fails
|
|
9
|
+
* on a machine with no internet. Either way we show nothing rather than
|
|
10
|
+
* a broken image.
|
|
11
|
+
*/
|
|
12
|
+
declare function ProviderLogo({ logo, displayName, className, }: {
|
|
13
|
+
logo: string;
|
|
14
|
+
displayName: string;
|
|
15
|
+
className?: string;
|
|
16
|
+
}): react_jsx_runtime.JSX.Element | null;
|
|
17
|
+
interface ModelPickerBodyProps<TModel extends SharedModelInfo, TGroup extends SharedAvailableModelGroup<TModel>> {
|
|
18
|
+
groups: TGroup[];
|
|
19
|
+
/** The selected model as `provider/modelId`, or '' for none. */
|
|
20
|
+
value: string;
|
|
21
|
+
/** Called with the new `provider/modelId`. */
|
|
22
|
+
onChange: (value: string) => void;
|
|
23
|
+
searchPlaceholder?: string;
|
|
24
|
+
emptyLabel?: string;
|
|
25
|
+
noModelsLabel?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Focus the search field on mount. Turn this off on a phone: the
|
|
28
|
+
* on-screen keyboard would cover the list the user came to read.
|
|
29
|
+
*/
|
|
30
|
+
autoFocusSearch?: boolean;
|
|
31
|
+
/** Hide provider logos where the network may not reach them. */
|
|
32
|
+
showProviderLogos?: boolean;
|
|
33
|
+
/** Shown at the right of the search field, such as a settings button. */
|
|
34
|
+
searchEndAdornment?: ReactNode;
|
|
35
|
+
className?: string;
|
|
36
|
+
/** Applied to the scrolling list, so a caller sets its height. */
|
|
37
|
+
listClassName?: string;
|
|
38
|
+
}
|
|
39
|
+
declare function ModelPickerBody<TModel extends SharedModelInfo, TGroup extends SharedAvailableModelGroup<TModel>>({ groups, value, onChange, searchPlaceholder, emptyLabel, noModelsLabel, autoFocusSearch, showProviderLogos, searchEndAdornment, className, listClassName, }: ModelPickerBodyProps<TModel, TGroup>): react_jsx_runtime.JSX.Element;
|
|
40
|
+
|
|
41
|
+
export { ModelPickerBody, ProviderLogo };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { Check, Sparkles } from "lucide-react";
|
|
4
|
+
import {
|
|
5
|
+
filterModelGroups,
|
|
6
|
+
modelKey
|
|
7
|
+
} from "@sero-ai/common";
|
|
8
|
+
import { SearchInput } from "../ui/search-input";
|
|
9
|
+
import { cn } from "../../lib/utils";
|
|
10
|
+
function ProviderLogo({
|
|
11
|
+
logo,
|
|
12
|
+
displayName,
|
|
13
|
+
className
|
|
14
|
+
}) {
|
|
15
|
+
const [failed, setFailed] = useState(false);
|
|
16
|
+
useEffect(() => setFailed(false), [logo]);
|
|
17
|
+
if (!logo || failed) return null;
|
|
18
|
+
return /* @__PURE__ */ jsx(
|
|
19
|
+
"img",
|
|
20
|
+
{
|
|
21
|
+
src: logo,
|
|
22
|
+
alt: displayName,
|
|
23
|
+
onError: () => setFailed(true),
|
|
24
|
+
className: cn("size-3.5 shrink-0 rounded-sm dark:invert", className)
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
function ModelPickerBody({
|
|
29
|
+
groups,
|
|
30
|
+
value,
|
|
31
|
+
onChange,
|
|
32
|
+
searchPlaceholder = "Search models...",
|
|
33
|
+
emptyLabel = "No matching models",
|
|
34
|
+
noModelsLabel = "No models available",
|
|
35
|
+
autoFocusSearch = true,
|
|
36
|
+
showProviderLogos = true,
|
|
37
|
+
searchEndAdornment,
|
|
38
|
+
className,
|
|
39
|
+
listClassName
|
|
40
|
+
}) {
|
|
41
|
+
const [query, setQuery] = useState("");
|
|
42
|
+
const inputRef = useRef(null);
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (!autoFocusSearch) return;
|
|
45
|
+
const frame = requestAnimationFrame(() => inputRef.current?.focus());
|
|
46
|
+
return () => cancelAnimationFrame(frame);
|
|
47
|
+
}, [autoFocusSearch]);
|
|
48
|
+
const filteredGroups = useMemo(() => filterModelGroups(groups, query), [groups, query]);
|
|
49
|
+
const totalResults = useMemo(
|
|
50
|
+
() => filteredGroups.reduce((count, group) => count + group.models.length, 0),
|
|
51
|
+
[filteredGroups]
|
|
52
|
+
);
|
|
53
|
+
const handleSelect = useCallback(
|
|
54
|
+
(provider, modelId) => {
|
|
55
|
+
onChange(modelKey(provider, modelId));
|
|
56
|
+
setQuery("");
|
|
57
|
+
},
|
|
58
|
+
[onChange]
|
|
59
|
+
);
|
|
60
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
SearchInput,
|
|
63
|
+
{
|
|
64
|
+
ref: inputRef,
|
|
65
|
+
value: query,
|
|
66
|
+
onChange: (event) => setQuery(event.target.value),
|
|
67
|
+
placeholder: searchPlaceholder,
|
|
68
|
+
"data-slot": "model-filter",
|
|
69
|
+
containerClassName: "border-b border-border/40",
|
|
70
|
+
endAdornment: searchEndAdornment
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ jsx("div", { className: cn("max-h-[280px] overflow-y-auto py-1", listClassName), children: groups.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: noModelsLabel }) : totalResults === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: emptyLabel }) : filteredGroups.map((group, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
74
|
+
index > 0 ? /* @__PURE__ */ jsx("div", { className: "mx-3 border-t border-border/30" }) : null,
|
|
75
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 pb-1 pt-2", children: [
|
|
76
|
+
showProviderLogos ? /* @__PURE__ */ jsx(ProviderLogo, { logo: group.logo, displayName: group.displayName }) : null,
|
|
77
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold uppercase tracking-wider text-muted-foreground", children: group.displayName })
|
|
78
|
+
] }),
|
|
79
|
+
/* @__PURE__ */ jsx("div", { className: "px-1", children: group.models.map((model) => {
|
|
80
|
+
const nextValue = modelKey(model.provider, model.modelId);
|
|
81
|
+
const isSelected = nextValue === value;
|
|
82
|
+
return /* @__PURE__ */ jsxs(
|
|
83
|
+
"button",
|
|
84
|
+
{
|
|
85
|
+
type: "button",
|
|
86
|
+
onClick: () => handleSelect(model.provider, model.modelId),
|
|
87
|
+
className: cn(
|
|
88
|
+
"flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-left text-sm transition-colors",
|
|
89
|
+
isSelected ? "bg-secondary text-foreground" : "text-muted-foreground hover:bg-secondary/60 hover:text-foreground"
|
|
90
|
+
),
|
|
91
|
+
children: [
|
|
92
|
+
/* @__PURE__ */ jsx("div", { className: "flex size-4 shrink-0 items-center justify-center", children: isSelected ? /* @__PURE__ */ jsx(Check, { className: "size-3.5 text-emerald-500" }) : /* @__PURE__ */ jsx("div", { className: "size-1.5 rounded-full bg-border" }) }),
|
|
93
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate font-medium", children: model.name }),
|
|
94
|
+
model.reasoning ? /* @__PURE__ */ jsx(Sparkles, { className: "size-3 shrink-0 text-amber-500/60" }) : null
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
nextValue
|
|
98
|
+
);
|
|
99
|
+
}) })
|
|
100
|
+
] }, group.provider)) })
|
|
101
|
+
] });
|
|
102
|
+
}
|
|
103
|
+
export {
|
|
104
|
+
ModelPickerBody,
|
|
105
|
+
ProviderLogo
|
|
106
|
+
};
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
var _common = require('@sero-ai/common');
|
|
6
6
|
var _utils = require('../../lib/utils');
|
|
7
|
+
const COMPACT_LABELS = {
|
|
8
|
+
..._common.THINKING_LABELS,
|
|
9
|
+
xhigh: "X-High"
|
|
10
|
+
};
|
|
7
11
|
function ThinkingLevelPicker({
|
|
8
12
|
value,
|
|
9
13
|
onChange,
|
|
@@ -14,7 +18,7 @@ function ThinkingLevelPicker({
|
|
|
14
18
|
}) {
|
|
15
19
|
const allowed = new Set(_nullishCoalesce(availableLevels, () => ( _common.THINKING_LEVELS)));
|
|
16
20
|
const levels = showUnsupported || !availableLevels ? _common.THINKING_LEVELS : _common.THINKING_LEVELS.filter((level) => allowed.has(level));
|
|
17
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _utils.cn.call(void 0, "grid grid-cols-
|
|
21
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _utils.cn.call(void 0, "grid grid-cols-7 gap-1 rounded-lg border border-border/50 bg-muted/20 p-1", className), children: levels.map((level) => {
|
|
18
22
|
const isActive = value === level;
|
|
19
23
|
const isAvailable = allowed.has(level) || !availableLevels;
|
|
20
24
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
@@ -24,11 +28,11 @@ function ThinkingLevelPicker({
|
|
|
24
28
|
disabled: disabled || !isAvailable,
|
|
25
29
|
onClick: () => onChange(level),
|
|
26
30
|
className: _utils.cn.call(void 0,
|
|
27
|
-
"rounded-md px-2 py-1.5 text-sm font-medium transition-colors",
|
|
31
|
+
"whitespace-nowrap rounded-md px-2 py-1.5 text-sm font-medium transition-colors",
|
|
28
32
|
isActive ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:bg-background/70 hover:text-foreground",
|
|
29
33
|
(!isAvailable || disabled) && "cursor-not-allowed opacity-40 hover:bg-transparent hover:text-muted-foreground"
|
|
30
34
|
),
|
|
31
|
-
children:
|
|
35
|
+
children: COMPACT_LABELS[level]
|
|
32
36
|
},
|
|
33
37
|
level
|
|
34
38
|
);
|
|
@@ -4,6 +4,10 @@ import {
|
|
|
4
4
|
THINKING_LEVELS
|
|
5
5
|
} from "@sero-ai/common";
|
|
6
6
|
import { cn } from "../../lib/utils";
|
|
7
|
+
const COMPACT_LABELS = {
|
|
8
|
+
...THINKING_LABELS,
|
|
9
|
+
xhigh: "X-High"
|
|
10
|
+
};
|
|
7
11
|
function ThinkingLevelPicker({
|
|
8
12
|
value,
|
|
9
13
|
onChange,
|
|
@@ -14,7 +18,7 @@ function ThinkingLevelPicker({
|
|
|
14
18
|
}) {
|
|
15
19
|
const allowed = new Set(availableLevels ?? THINKING_LEVELS);
|
|
16
20
|
const levels = showUnsupported || !availableLevels ? THINKING_LEVELS : THINKING_LEVELS.filter((level) => allowed.has(level));
|
|
17
|
-
return /* @__PURE__ */ jsx("div", { className: cn("grid grid-cols-
|
|
21
|
+
return /* @__PURE__ */ jsx("div", { className: cn("grid grid-cols-7 gap-1 rounded-lg border border-border/50 bg-muted/20 p-1", className), children: levels.map((level) => {
|
|
18
22
|
const isActive = value === level;
|
|
19
23
|
const isAvailable = allowed.has(level) || !availableLevels;
|
|
20
24
|
return /* @__PURE__ */ jsx(
|
|
@@ -24,11 +28,11 @@ function ThinkingLevelPicker({
|
|
|
24
28
|
disabled: disabled || !isAvailable,
|
|
25
29
|
onClick: () => onChange(level),
|
|
26
30
|
className: cn(
|
|
27
|
-
"rounded-md px-2 py-1.5 text-sm font-medium transition-colors",
|
|
31
|
+
"whitespace-nowrap rounded-md px-2 py-1.5 text-sm font-medium transition-colors",
|
|
28
32
|
isActive ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:bg-background/70 hover:text-foreground",
|
|
29
33
|
(!isAvailable || disabled) && "cursor-not-allowed opacity-40 hover:bg-transparent hover:text-muted-foreground"
|
|
30
34
|
),
|
|
31
|
-
children:
|
|
35
|
+
children: COMPACT_LABELS[level]
|
|
32
36
|
},
|
|
33
37
|
level
|
|
34
38
|
);
|
|
@@ -14,7 +14,7 @@ function ThinkingPicker({
|
|
|
14
14
|
onSelect,
|
|
15
15
|
className
|
|
16
16
|
}) {
|
|
17
|
-
const levels = disabled ? _common.THINKING_LEVELS : _common.THINKING_LEVELS.filter((level) => level === "off" || available.includes(level));
|
|
17
|
+
const levels = disabled ? _common.THINKING_LEVELS.filter((level) => level === "off") : _common.THINKING_LEVELS.filter((level) => level === "off" || available.includes(level));
|
|
18
18
|
const activeIndex = Math.max(
|
|
19
19
|
0,
|
|
20
20
|
levels.indexOf(disabled ? "off" : current)
|
|
@@ -14,7 +14,7 @@ function ThinkingPicker({
|
|
|
14
14
|
onSelect,
|
|
15
15
|
className
|
|
16
16
|
}) {
|
|
17
|
-
const levels = disabled ? THINKING_LEVELS : THINKING_LEVELS.filter((level) => level === "off" || available.includes(level));
|
|
17
|
+
const levels = disabled ? THINKING_LEVELS.filter((level) => level === "off") : THINKING_LEVELS.filter((level) => level === "off" || available.includes(level));
|
|
18
18
|
const activeIndex = Math.max(
|
|
19
19
|
0,
|
|
20
20
|
levels.indexOf(disabled ? "off" : current)
|
|
@@ -79,7 +79,7 @@ function Calendar({
|
|
|
79
79
|
captionLayout === "label" ? "text-base" : "rounded-md pl-2 pr-1 flex items-center gap-1 text-base h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
|
|
80
80
|
defaultClassNames.caption_label
|
|
81
81
|
),
|
|
82
|
-
|
|
82
|
+
month_grid: _utils.cn.call(void 0, "w-full border-collapse", defaultClassNames.month_grid),
|
|
83
83
|
weekdays: _utils.cn.call(void 0, "flex", defaultClassNames.weekdays),
|
|
84
84
|
weekday: _utils.cn.call(void 0,
|
|
85
85
|
"text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none",
|
|
@@ -79,7 +79,7 @@ function Calendar({
|
|
|
79
79
|
captionLayout === "label" ? "text-base" : "rounded-md pl-2 pr-1 flex items-center gap-1 text-base h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
|
|
80
80
|
defaultClassNames.caption_label
|
|
81
81
|
),
|
|
82
|
-
|
|
82
|
+
month_grid: cn("w-full border-collapse", defaultClassNames.month_grid),
|
|
83
83
|
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
84
84
|
weekday: cn(
|
|
85
85
|
"text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none",
|
|
@@ -225,7 +225,7 @@ function ComboboxChips({
|
|
|
225
225
|
{
|
|
226
226
|
"data-slot": "combobox-chips",
|
|
227
227
|
className: _utils.cn.call(void 0,
|
|
228
|
-
"dark:bg-input/30 border-input focus-within:border-ring
|
|
228
|
+
"dark:bg-input/30 border-input focus-within:border-ring has-aria-invalid:border-destructive dark:has-aria-invalid:border-destructive/50 flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border bg-transparent bg-clip-padding px-2.5 py-1.5 text-base shadow-xs transition-[color,box-shadow] has-data-[slot=combobox-chip]:px-1.5",
|
|
229
229
|
className
|
|
230
230
|
),
|
|
231
231
|
...props
|
|
@@ -225,7 +225,7 @@ function ComboboxChips({
|
|
|
225
225
|
{
|
|
226
226
|
"data-slot": "combobox-chips",
|
|
227
227
|
className: cn(
|
|
228
|
-
"dark:bg-input/30 border-input focus-within:border-ring
|
|
228
|
+
"dark:bg-input/30 border-input focus-within:border-ring has-aria-invalid:border-destructive dark:has-aria-invalid:border-destructive/50 flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border bg-transparent bg-clip-padding px-2.5 py-1.5 text-base shadow-xs transition-[color,box-shadow] has-data-[slot=combobox-chip]:px-1.5",
|
|
229
229
|
className
|
|
230
230
|
),
|
|
231
231
|
...props
|
|
@@ -19,7 +19,7 @@ function InputGroup({ className, ...props }) {
|
|
|
19
19
|
"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
|
|
20
20
|
"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
|
|
21
21
|
// Focus state.
|
|
22
|
-
"has-[[data-slot=input-group-control]:focus-visible]:border-ring
|
|
22
|
+
"has-[[data-slot=input-group-control]:focus-visible]:border-ring",
|
|
23
23
|
// Error state.
|
|
24
24
|
"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
|
|
25
25
|
className
|
|
@@ -19,7 +19,7 @@ function InputGroup({ className, ...props }) {
|
|
|
19
19
|
"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
|
|
20
20
|
"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
|
|
21
21
|
// Focus state.
|
|
22
|
-
"has-[[data-slot=input-group-control]:focus-visible]:border-ring
|
|
22
|
+
"has-[[data-slot=input-group-control]:focus-visible]:border-ring",
|
|
23
23
|
// Error state.
|
|
24
24
|
"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
|
|
25
25
|
className
|
|
@@ -45,7 +45,7 @@ function InputOTPSlot({
|
|
|
45
45
|
"data-slot": "input-otp-slot",
|
|
46
46
|
"data-active": isActive,
|
|
47
47
|
className: _utils.cn.call(void 0,
|
|
48
|
-
"data-[active=true]:border-ring
|
|
48
|
+
"data-[active=true]:border-ring aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex size-9 items-center justify-center border-y border-r text-base shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10",
|
|
49
49
|
className
|
|
50
50
|
),
|
|
51
51
|
...props,
|
|
@@ -45,7 +45,7 @@ function InputOTPSlot({
|
|
|
45
45
|
"data-slot": "input-otp-slot",
|
|
46
46
|
"data-active": isActive,
|
|
47
47
|
className: cn(
|
|
48
|
-
"data-[active=true]:border-ring
|
|
48
|
+
"data-[active=true]:border-ring aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex size-9 items-center justify-center border-y border-r text-base shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10",
|
|
49
49
|
className
|
|
50
50
|
),
|
|
51
51
|
...props,
|
|
@@ -9,9 +9,9 @@ function Input({ className, type, placeholder, "aria-label": ariaLabel, ...props
|
|
|
9
9
|
type,
|
|
10
10
|
"data-slot": "input",
|
|
11
11
|
className: _utils.cn.call(void 0,
|
|
12
|
-
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-base file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50
|
|
13
|
-
"focus-visible:border-ring
|
|
14
|
-
"aria-invalid:
|
|
12
|
+
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-base file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
13
|
+
"focus-visible:border-ring",
|
|
14
|
+
"aria-invalid:border-destructive",
|
|
15
15
|
className
|
|
16
16
|
),
|
|
17
17
|
...props
|
|
@@ -9,9 +9,9 @@ function Input({ className, type, placeholder, "aria-label": ariaLabel, ...props
|
|
|
9
9
|
type,
|
|
10
10
|
"data-slot": "input",
|
|
11
11
|
className: cn(
|
|
12
|
-
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-base file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50
|
|
13
|
-
"focus-visible:border-ring
|
|
14
|
-
"aria-invalid:
|
|
12
|
+
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-base file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
13
|
+
"focus-visible:border-ring",
|
|
14
|
+
"aria-invalid:border-destructive",
|
|
15
15
|
className
|
|
16
16
|
),
|
|
17
17
|
...props
|
|
@@ -21,8 +21,8 @@ function NativeSelect({
|
|
|
21
21
|
"data-size": size,
|
|
22
22
|
className: _utils.cn.call(void 0,
|
|
23
23
|
"border-input placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 dark:hover:bg-input/50 h-9 w-full min-w-0 appearance-none rounded-md border bg-transparent px-3 py-2 pr-9 text-base shadow-xs transition-[color,box-shadow] outline-none disabled:pointer-events-none disabled:cursor-not-allowed data-[size=sm]:h-8 data-[size=sm]:py-1",
|
|
24
|
-
"focus-visible:border-ring
|
|
25
|
-
"aria-invalid:
|
|
24
|
+
"focus-visible:border-ring",
|
|
25
|
+
"aria-invalid:border-destructive",
|
|
26
26
|
className
|
|
27
27
|
),
|
|
28
28
|
...props
|
|
@@ -21,8 +21,8 @@ function NativeSelect({
|
|
|
21
21
|
"data-size": size,
|
|
22
22
|
className: cn(
|
|
23
23
|
"border-input placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 dark:hover:bg-input/50 h-9 w-full min-w-0 appearance-none rounded-md border bg-transparent px-3 py-2 pr-9 text-base shadow-xs transition-[color,box-shadow] outline-none disabled:pointer-events-none disabled:cursor-not-allowed data-[size=sm]:h-8 data-[size=sm]:py-1",
|
|
24
|
-
"focus-visible:border-ring
|
|
25
|
-
"aria-invalid:
|
|
24
|
+
"focus-visible:border-ring",
|
|
25
|
+
"aria-invalid:border-destructive",
|
|
26
26
|
className
|
|
27
27
|
),
|
|
28
28
|
...props
|
|
@@ -31,7 +31,7 @@ function SelectTrigger({
|
|
|
31
31
|
"data-slot": "select-trigger",
|
|
32
32
|
"data-size": size,
|
|
33
33
|
className: _utils.cn.call(void 0,
|
|
34
|
-
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring
|
|
34
|
+
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-base whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
35
35
|
className
|
|
36
36
|
),
|
|
37
37
|
...props,
|
|
@@ -31,7 +31,7 @@ function SelectTrigger({
|
|
|
31
31
|
"data-slot": "select-trigger",
|
|
32
32
|
"data-size": size,
|
|
33
33
|
className: cn(
|
|
34
|
-
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring
|
|
34
|
+
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-base whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
35
35
|
className
|
|
36
36
|
),
|
|
37
37
|
...props,
|
|
@@ -8,6 +8,9 @@ function Slider({
|
|
|
8
8
|
value,
|
|
9
9
|
min = 0,
|
|
10
10
|
max = 100,
|
|
11
|
+
id,
|
|
12
|
+
"aria-label": ariaLabel,
|
|
13
|
+
"aria-labelledby": ariaLabelledBy,
|
|
11
14
|
...props
|
|
12
15
|
}) {
|
|
13
16
|
const _values = React.useMemo(
|
|
@@ -55,6 +58,9 @@ function Slider({
|
|
|
55
58
|
_radixui.Slider.Thumb,
|
|
56
59
|
{
|
|
57
60
|
"data-slot": "slider-thumb",
|
|
61
|
+
id: id && index === 0 ? id : void 0,
|
|
62
|
+
"aria-label": ariaLabel,
|
|
63
|
+
"aria-labelledby": ariaLabelledBy,
|
|
58
64
|
className: "border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
|
|
59
65
|
},
|
|
60
66
|
thumbKeys[index]
|
|
@@ -2,6 +2,6 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { Slider as Slider$1 } from 'radix-ui';
|
|
4
4
|
|
|
5
|
-
declare function Slider({ className, defaultValue, value, min, max, ...props }: React.ComponentProps<typeof Slider$1.Root>): react_jsx_runtime.JSX.Element;
|
|
5
|
+
declare function Slider({ className, defaultValue, value, min, max, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: React.ComponentProps<typeof Slider$1.Root>): react_jsx_runtime.JSX.Element;
|
|
6
6
|
|
|
7
7
|
export { Slider };
|
|
@@ -2,6 +2,6 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { Slider as Slider$1 } from 'radix-ui';
|
|
4
4
|
|
|
5
|
-
declare function Slider({ className, defaultValue, value, min, max, ...props }: React.ComponentProps<typeof Slider$1.Root>): react_jsx_runtime.JSX.Element;
|
|
5
|
+
declare function Slider({ className, defaultValue, value, min, max, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: React.ComponentProps<typeof Slider$1.Root>): react_jsx_runtime.JSX.Element;
|
|
6
6
|
|
|
7
7
|
export { Slider };
|
|
@@ -8,6 +8,9 @@ function Slider({
|
|
|
8
8
|
value,
|
|
9
9
|
min = 0,
|
|
10
10
|
max = 100,
|
|
11
|
+
id,
|
|
12
|
+
"aria-label": ariaLabel,
|
|
13
|
+
"aria-labelledby": ariaLabelledBy,
|
|
11
14
|
...props
|
|
12
15
|
}) {
|
|
13
16
|
const _values = React.useMemo(
|
|
@@ -55,6 +58,9 @@ function Slider({
|
|
|
55
58
|
SliderPrimitive.Thumb,
|
|
56
59
|
{
|
|
57
60
|
"data-slot": "slider-thumb",
|
|
61
|
+
id: id && index === 0 ? id : void 0,
|
|
62
|
+
"aria-label": ariaLabel,
|
|
63
|
+
"aria-labelledby": ariaLabelledBy,
|
|
58
64
|
className: "border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
|
|
59
65
|
},
|
|
60
66
|
thumbKeys[index]
|