@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.
Files changed (77) hide show
  1. package/.turbo/turbo-build.log +386 -378
  2. package/.turbo/turbo-test.log +12 -11
  3. package/CHANGELOG.md +2 -2
  4. package/dist/components/ai-elements/conversation-virtual.cjs +115 -0
  5. package/dist/components/ai-elements/conversation-virtual.d.cts +30 -0
  6. package/dist/components/ai-elements/conversation-virtual.d.ts +30 -0
  7. package/dist/components/ai-elements/conversation-virtual.js +115 -0
  8. package/dist/components/model-selection/available-model-picker.cjs +21 -77
  9. package/dist/components/model-selection/available-model-picker.js +22 -78
  10. package/dist/components/model-selection/model-picker-body.cjs +106 -0
  11. package/dist/components/model-selection/model-picker-body.d.cts +41 -0
  12. package/dist/components/model-selection/model-picker-body.d.ts +41 -0
  13. package/dist/components/model-selection/model-picker-body.js +106 -0
  14. package/dist/components/model-selection/thinking-level-picker.cjs +7 -3
  15. package/dist/components/model-selection/thinking-level-picker.js +7 -3
  16. package/dist/components/model-selection/thinking-picker.cjs +1 -1
  17. package/dist/components/model-selection/thinking-picker.js +1 -1
  18. package/dist/components/ui/calendar.cjs +1 -1
  19. package/dist/components/ui/calendar.js +1 -1
  20. package/dist/components/ui/combobox.cjs +1 -1
  21. package/dist/components/ui/combobox.js +1 -1
  22. package/dist/components/ui/form.d.cts +1 -1
  23. package/dist/components/ui/form.d.ts +1 -1
  24. package/dist/components/ui/input-group.cjs +1 -1
  25. package/dist/components/ui/input-group.js +1 -1
  26. package/dist/components/ui/input-otp.cjs +1 -1
  27. package/dist/components/ui/input-otp.js +1 -1
  28. package/dist/components/ui/input.cjs +3 -3
  29. package/dist/components/ui/input.js +3 -3
  30. package/dist/components/ui/native-select.cjs +2 -2
  31. package/dist/components/ui/native-select.js +2 -2
  32. package/dist/components/ui/select.cjs +1 -1
  33. package/dist/components/ui/select.js +1 -1
  34. package/dist/components/ui/slider.cjs +6 -0
  35. package/dist/components/ui/slider.d.cts +1 -1
  36. package/dist/components/ui/slider.d.ts +1 -1
  37. package/dist/components/ui/slider.js +6 -0
  38. package/dist/components/ui/spinner.d.cts +2 -1
  39. package/dist/components/ui/spinner.d.ts +2 -1
  40. package/dist/components/ui/textarea.cjs +1 -1
  41. package/dist/components/ui/textarea.js +1 -1
  42. package/dist/index.d.cts +2 -1
  43. package/dist/index.d.ts +2 -1
  44. package/dist/styles/globals.css +32 -0
  45. package/dist/theme/apply-theme.cjs +65 -12
  46. package/dist/theme/apply-theme.js +55 -2
  47. package/dist/theme/index.d.cts +1 -1
  48. package/dist/theme/index.d.ts +1 -1
  49. package/dist/theme/types.cjs +15 -2
  50. package/dist/theme/types.d.cts +21 -1
  51. package/dist/theme/types.d.ts +21 -1
  52. package/dist/theme/types.js +14 -1
  53. package/package.json +21 -20
  54. package/scripts/smoke-dist.mjs +2 -2
  55. package/src/components/ai-elements/conversation-virtual.test.tsx +126 -0
  56. package/src/components/ai-elements/conversation-virtual.tsx +162 -0
  57. package/src/components/model-selection/available-model-picker.tsx +26 -98
  58. package/src/components/model-selection/model-picker-body.test.tsx +152 -0
  59. package/src/components/model-selection/model-picker-body.tsx +188 -0
  60. package/src/components/model-selection/thinking-level-picker.tsx +9 -3
  61. package/src/components/model-selection/thinking-picker.test.tsx +41 -0
  62. package/src/components/model-selection/thinking-picker.tsx +1 -1
  63. package/src/components/ui/calendar.test.tsx +43 -0
  64. package/src/components/ui/calendar.tsx +1 -1
  65. package/src/components/ui/combobox.tsx +1 -1
  66. package/src/components/ui/input-group.tsx +1 -1
  67. package/src/components/ui/input-otp.tsx +1 -1
  68. package/src/components/ui/input.tsx +3 -3
  69. package/src/components/ui/native-select.tsx +2 -2
  70. package/src/components/ui/select.tsx +1 -1
  71. package/src/components/ui/slider.tsx +6 -0
  72. package/src/components/ui/spinner.tsx +1 -1
  73. package/src/components/ui/textarea.tsx +1 -1
  74. package/src/styles/globals.css +32 -0
  75. package/src/theme/apply-theme.test.ts +126 -0
  76. package/src/theme/apply-theme.ts +66 -3
  77. 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-6 gap-1 rounded-lg border border-border/50 bg-muted/20 p-1", className), children: levels.map((level) => {
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: _common.THINKING_LABELS[level]
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-6 gap-1 rounded-lg border border-border/50 bg-muted/20 p-1", className), children: levels.map((level) => {
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: THINKING_LABELS[level]
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
- table: "w-full border-collapse",
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
- table: "w-full border-collapse",
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 focus-within:ring-ring/50 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 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] focus-within:ring-[3px] has-aria-invalid:ring-[3px] has-data-[slot=combobox-chip]:px-1.5",
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 focus-within:ring-ring/50 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 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] focus-within:ring-[3px] has-aria-invalid:ring-[3px] has-data-[slot=combobox-chip]:px-1.5",
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
@@ -11,7 +11,7 @@ declare const useFormField: () => {
11
11
  isDirty: boolean;
12
12
  isTouched: boolean;
13
13
  isValidating: boolean;
14
- error?: react_hook_form.FieldError;
14
+ error?: react_hook_form.FieldError | undefined;
15
15
  id: string;
16
16
  name: string;
17
17
  formItemId: string;
@@ -11,7 +11,7 @@ declare const useFormField: () => {
11
11
  isDirty: boolean;
12
12
  isTouched: boolean;
13
13
  isValidating: boolean;
14
- error?: react_hook_form.FieldError;
14
+ error?: react_hook_form.FieldError | undefined;
15
15
  id: string;
16
16
  name: string;
17
17
  formItemId: string;
@@ -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 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px]",
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 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px]",
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 data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 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 data-[active=true]:ring-[3px]",
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 data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 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 data-[active=true]:ring-[3px]",
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 md:text-base",
13
- "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
14
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
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 md:text-base",
13
- "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
14
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
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 focus-visible:ring-ring/50 focus-visible:ring-[3px]",
25
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
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 focus-visible:ring-ring/50 focus-visible:ring-[3px]",
25
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
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 focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 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 focus-visible:ring-[3px] 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",
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 focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 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 focus-visible:ring-[3px] 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",
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]