@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
package/src/theme/apply-theme.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_GLASS_EFFECT,
|
|
3
|
+
WINDOWS_GLASS_MATERIALS,
|
|
4
|
+
type ColorTokens,
|
|
5
|
+
type ThemeGlassEffect,
|
|
6
|
+
type ThemePreset,
|
|
4
7
|
} from './types';
|
|
5
8
|
|
|
6
9
|
// ── Token → CSS Variable Mapping ─────────────────────────────
|
|
@@ -86,6 +89,38 @@ function tint(color: string, percentage: number): string {
|
|
|
86
89
|
return `color-mix(in srgb, ${color} ${percentage}%, transparent)`;
|
|
87
90
|
}
|
|
88
91
|
|
|
92
|
+
function applyGlassEffect(
|
|
93
|
+
root: HTMLElement,
|
|
94
|
+
glass: ThemeGlassEffect | undefined,
|
|
95
|
+
colors: ColorTokens,
|
|
96
|
+
): void {
|
|
97
|
+
const enabled = glass?.enabled === true;
|
|
98
|
+
root.classList.toggle('theme-glass', enabled);
|
|
99
|
+
root.style.removeProperty('--window-glass-opaque-base');
|
|
100
|
+
root.style.removeProperty('--window-glass-sidebar');
|
|
101
|
+
root.style.removeProperty('--window-glass-opaque-surface');
|
|
102
|
+
root.style.removeProperty('--window-glass-opaque-elevated');
|
|
103
|
+
if (!enabled) return;
|
|
104
|
+
|
|
105
|
+
const opacity = Math.min(1, Math.max(0, glass.opacity));
|
|
106
|
+
const percentage = Math.round(opacity * 100);
|
|
107
|
+
root.style.setProperty('--bg-base', tint(colors.bgBase, percentage));
|
|
108
|
+
root.style.setProperty(
|
|
109
|
+
'--window-glass-sidebar',
|
|
110
|
+
tint(colors.bgSurface, (glass.sidebarOpacity ?? DEFAULT_GLASS_EFFECT.sidebarOpacity) * 100),
|
|
111
|
+
);
|
|
112
|
+
root.style.setProperty('--window-glass-opaque-base', colors.bgBase);
|
|
113
|
+
root.style.setProperty('--window-glass-opaque-surface', colors.bgSurface);
|
|
114
|
+
root.style.setProperty('--window-glass-opaque-elevated', colors.bgElevated);
|
|
115
|
+
// Thin local layers preserve the wallpaper while separating nested content.
|
|
116
|
+
root.style.setProperty('--bg-surface', tint(colors.bgSurface, (glass.surfaceOpacity ?? DEFAULT_GLASS_EFFECT.surfaceOpacity) * 100));
|
|
117
|
+
root.style.setProperty('--bg-elevated', tint(colors.textPrimary, (glass.selectionOpacity ?? DEFAULT_GLASS_EFFECT.selectionOpacity) * 100));
|
|
118
|
+
root.style.setProperty('--text-muted', colors.textSecondary);
|
|
119
|
+
const border = (glass.borderOpacity ?? DEFAULT_GLASS_EFFECT.borderOpacity) * 100;
|
|
120
|
+
root.style.setProperty('--border-subtle', tint(colors.textPrimary, border * 2 / 3));
|
|
121
|
+
root.style.setProperty('--border-default', tint(colors.textPrimary, border));
|
|
122
|
+
}
|
|
123
|
+
|
|
89
124
|
// ── Apply / Reset ────────────────────────────────────────────
|
|
90
125
|
|
|
91
126
|
/** Apply a theme preset for the given mode. */
|
|
@@ -130,6 +165,8 @@ export function applyThemePreset(
|
|
|
130
165
|
root.style.setProperty('--radius', preset.radius.md);
|
|
131
166
|
}
|
|
132
167
|
|
|
168
|
+
applyGlassEffect(root, preset.glass, colors);
|
|
169
|
+
|
|
133
170
|
root.classList.toggle('dark', mode === 'dark');
|
|
134
171
|
}
|
|
135
172
|
|
|
@@ -142,6 +179,10 @@ const ALL_MANAGED_VARS = [
|
|
|
142
179
|
'--font-size-base',
|
|
143
180
|
'--spacing',
|
|
144
181
|
'--radius',
|
|
182
|
+
'--window-glass-opaque-base',
|
|
183
|
+
'--window-glass-sidebar',
|
|
184
|
+
'--window-glass-opaque-surface',
|
|
185
|
+
'--window-glass-opaque-elevated',
|
|
145
186
|
];
|
|
146
187
|
|
|
147
188
|
/** Remove all inline theme overrides, reverting to CSS defaults. */
|
|
@@ -150,6 +191,7 @@ export function resetTheme(): void {
|
|
|
150
191
|
for (const cssVar of ALL_MANAGED_VARS) {
|
|
151
192
|
root.style.removeProperty(cssVar);
|
|
152
193
|
}
|
|
194
|
+
root.classList.remove('theme-glass');
|
|
153
195
|
}
|
|
154
196
|
|
|
155
197
|
// ── Validation ───────────────────────────────────────────────
|
|
@@ -221,6 +263,26 @@ function sanitiseRadius(raw: unknown): ThemePreset['radius'] | undefined {
|
|
|
221
263
|
return Object.keys(result).length > 0 ? result : undefined;
|
|
222
264
|
}
|
|
223
265
|
|
|
266
|
+
function sanitiseGlass(raw: unknown): ThemeGlassEffect | undefined {
|
|
267
|
+
if (!raw || typeof raw !== 'object') return undefined;
|
|
268
|
+
const value = raw as Record<string, unknown>;
|
|
269
|
+
if (typeof value.enabled !== 'boolean') return undefined;
|
|
270
|
+
|
|
271
|
+
const result = { ...DEFAULT_GLASS_EFFECT, enabled: value.enabled };
|
|
272
|
+
for (const key of ['opacity', 'sidebarOpacity', 'surfaceOpacity', 'selectionOpacity', 'borderOpacity'] as const) {
|
|
273
|
+
const amount = value[key];
|
|
274
|
+
if (typeof amount === 'number' && Number.isFinite(amount)) {
|
|
275
|
+
result[key] = Math.min(1, Math.max(0, amount));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (typeof value.blurRadius === 'number' && Number.isFinite(value.blurRadius)) {
|
|
279
|
+
result.blurRadius = Math.round(Math.min(64, Math.max(0, value.blurRadius)));
|
|
280
|
+
}
|
|
281
|
+
result.windowsMaterial = WINDOWS_GLASS_MATERIALS.find((material) => material === value.windowsMaterial)
|
|
282
|
+
?? DEFAULT_GLASS_EFFECT.windowsMaterial;
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
|
|
224
286
|
/** Validate and normalise an unknown value into a ThemePreset. */
|
|
225
287
|
export function validateThemePreset(data: unknown): ThemePreset | null {
|
|
226
288
|
if (!data || typeof data !== 'object') return null;
|
|
@@ -246,5 +308,6 @@ export function validateThemePreset(data: unknown): ThemePreset | null {
|
|
|
246
308
|
typography: sanitiseTypography(d.typography),
|
|
247
309
|
spacing: sanitiseSpacing(d.spacing),
|
|
248
310
|
radius: sanitiseRadius(d.radius),
|
|
311
|
+
glass: sanitiseGlass(d.glass),
|
|
249
312
|
};
|
|
250
313
|
}
|
package/src/theme/types.ts
CHANGED
|
@@ -105,6 +105,25 @@ export interface RadiusTokens {
|
|
|
105
105
|
lg?: string;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
export const WINDOWS_GLASS_MATERIALS = ['acrylic', 'mica', 'tabbed'] as const;
|
|
109
|
+
export type WindowsGlassMaterial = typeof WINDOWS_GLASS_MATERIALS[number];
|
|
110
|
+
|
|
111
|
+
export interface ThemeGlassEffect {
|
|
112
|
+
/** Show the desktop through Sero's surfaces. */
|
|
113
|
+
enabled: boolean;
|
|
114
|
+
/** Window tint opacity from 0 to 1. */
|
|
115
|
+
opacity: number;
|
|
116
|
+
/** Direct macOS desktop blur radius, from 0 to 64 pixels. */
|
|
117
|
+
blurRadius?: number;
|
|
118
|
+
/** Windows 11 system backdrop. */
|
|
119
|
+
windowsMaterial?: WindowsGlassMaterial;
|
|
120
|
+
/** Independent local layer opacities from 0 to 1. */
|
|
121
|
+
sidebarOpacity?: number;
|
|
122
|
+
surfaceOpacity?: number;
|
|
123
|
+
selectionOpacity?: number;
|
|
124
|
+
borderOpacity?: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
108
127
|
// ── Theme Preset ─────────────────────────────────────────────
|
|
109
128
|
|
|
110
129
|
export interface ThemePreset {
|
|
@@ -141,6 +160,9 @@ export interface ThemePreset {
|
|
|
141
160
|
|
|
142
161
|
/** Border radius overrides. */
|
|
143
162
|
radius?: RadiusTokens;
|
|
163
|
+
|
|
164
|
+
/** Optional translucent desktop window treatment. */
|
|
165
|
+
glass?: ThemeGlassEffect;
|
|
144
166
|
}
|
|
145
167
|
|
|
146
168
|
/** Lightweight metadata for listing presets without loading full data. */
|
|
@@ -218,6 +240,17 @@ export const DEFAULT_RADIUS: Required<RadiusTokens> = {
|
|
|
218
240
|
lg: '12px',
|
|
219
241
|
};
|
|
220
242
|
|
|
243
|
+
export const DEFAULT_GLASS_EFFECT: Required<ThemeGlassEffect> = {
|
|
244
|
+
enabled: false,
|
|
245
|
+
opacity: 0.78,
|
|
246
|
+
blurRadius: 24,
|
|
247
|
+
windowsMaterial: 'acrylic',
|
|
248
|
+
sidebarOpacity: 0.08,
|
|
249
|
+
surfaceOpacity: 0.18,
|
|
250
|
+
selectionOpacity: 0.08,
|
|
251
|
+
borderOpacity: 0.18,
|
|
252
|
+
};
|
|
253
|
+
|
|
221
254
|
/** Default colour tokens matching globals.css .dark values. */
|
|
222
255
|
export const DEFAULT_DARK_COLORS: ColorTokens = {
|
|
223
256
|
bgBase: '#0a0a0b',
|