@vobs/ui 0.2.0 → 0.3.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/dist/app-shell-dom.d.ts +6 -0
- package/dist/app-shell-dom.js +373 -33
- package/dist/app-shell.d.ts +55 -19
- package/dist/app-shell.js +63 -18
- package/dist/base.css +1 -2
- package/dist/complex-inputs.js +7 -3
- package/dist/components.css +235 -47
- package/dist/data-display.d.ts +31 -0
- package/dist/data-display.js +72 -29
- package/dist/dialog.d.ts +26 -0
- package/dist/dialog.js +94 -0
- package/dist/forms.js +10 -6
- package/dist/index.d.ts +5 -1
- package/dist/index.js +7 -1
- package/dist/overlay.d.ts +4 -0
- package/dist/overlay.js +10 -5
- package/dist/page-state.d.ts +23 -0
- package/dist/page-state.js +96 -0
- package/dist/theme-data.d.ts +31 -0
- package/dist/theme-data.js +43 -0
- package/dist/theme.d.ts +19 -1
- package/dist/theme.js +72 -33
- package/dist/tokens.css +121 -0
- package/dist/tree.js +11 -5
- package/dist/virtual-list.js +28 -11
- package/package.json +17 -9
package/dist/theme-data.js
CHANGED
|
@@ -25,11 +25,15 @@ export const primitiveTokenValues = {
|
|
|
25
25
|
'--radius-10': '10px',
|
|
26
26
|
'--radius-full': '9999px',
|
|
27
27
|
'--spacer-0': '0px',
|
|
28
|
+
'--spacer-2': '2px',
|
|
28
29
|
'--spacer-4': '4px',
|
|
29
30
|
'--spacer-6': '6px',
|
|
30
31
|
'--spacer-8': '8px',
|
|
32
|
+
'--spacer-10': '10px',
|
|
31
33
|
'--spacer-12': '12px',
|
|
34
|
+
'--spacer-14': '14px',
|
|
32
35
|
'--spacer-16': '16px',
|
|
36
|
+
'--spacer-20': '20px',
|
|
33
37
|
'--spacer-24': '24px',
|
|
34
38
|
'--spacer-32': '32px',
|
|
35
39
|
'--spacer-40': '40px',
|
|
@@ -116,9 +120,11 @@ export const primitiveTokenValues = {
|
|
|
116
120
|
'--code-terminal-font-weight': '450',
|
|
117
121
|
'--code-terminal-line-height': '18px',
|
|
118
122
|
'--font-weight-default': '400',
|
|
123
|
+
'--font-weight-regular': 'var(--font-weight-default)',
|
|
119
124
|
'--font-weight-code': '450',
|
|
120
125
|
'--font-weight-medium': '500',
|
|
121
126
|
'--font-weight-strong': '600',
|
|
127
|
+
'--font-weight-semibold': 'var(--font-weight-strong)',
|
|
122
128
|
'--z-index-dropdown': '2000',
|
|
123
129
|
'--z-index-drawer': '2500',
|
|
124
130
|
'--z-index-modal': '3000',
|
|
@@ -165,6 +171,9 @@ const semanticAliases = {
|
|
|
165
171
|
'--color-warning': 'var(--status-warning-default)',
|
|
166
172
|
'--color-error': 'var(--status-error-default)',
|
|
167
173
|
'--color-error-soft': 'var(--status-error-surface-l1)',
|
|
174
|
+
'--color-foreground-muted': 'var(--text-secondary)',
|
|
175
|
+
'--accent-blue': 'var(--status-primary-default)',
|
|
176
|
+
'--code-string': 'var(--code-text)',
|
|
168
177
|
};
|
|
169
178
|
export const themeTokenValues = {
|
|
170
179
|
dark: {
|
|
@@ -254,22 +263,40 @@ export const themeTokenValues = {
|
|
|
254
263
|
'--bg-base-default': '#FFFFFF',
|
|
255
264
|
'--bg-base-secondary': '#F5F6F8',
|
|
256
265
|
'--bg-base-tertiary': '#EDF0F5',
|
|
266
|
+
'--bg-tooltip': '#0F1117',
|
|
267
|
+
'--bg-menu': '#FFFFFF',
|
|
268
|
+
'--bg-invert': '#0F1117',
|
|
269
|
+
'--bg-invert-hover': '#1F2937',
|
|
270
|
+
'--bg-invert-active': '#374151',
|
|
271
|
+
'--bg-invert-disabled': 'rgba(15, 17, 23, 0.12)',
|
|
257
272
|
'--bg-overlay-l1': 'rgba(0, 0, 0, 0.04)',
|
|
258
273
|
'--bg-overlay-l2': 'rgba(0, 0, 0, 0.06)',
|
|
259
274
|
'--bg-overlay-l3': 'rgba(0, 0, 0, 0.08)',
|
|
260
275
|
'--bg-overlay-l4': 'rgba(0, 0, 0, 0.12)',
|
|
261
276
|
'--text-default': '#0F1117',
|
|
277
|
+
'--text-default-hover': '#000000',
|
|
278
|
+
'--text-default-active': '#000000',
|
|
262
279
|
'--text-secondary': '#4B5563',
|
|
280
|
+
'--text-secondary-hover': '#1F2937',
|
|
281
|
+
'--text-secondary-active': '#1F2937',
|
|
263
282
|
'--text-tertiary': '#5B6370',
|
|
264
283
|
'--text-disabled': '#525A68',
|
|
265
284
|
'--text-onbrand': '#FFFFFF',
|
|
285
|
+
'--text-onaccent': '#FFFFFF',
|
|
266
286
|
'--icon-default': '#0F1117',
|
|
287
|
+
'--icon-default-hover': '#000000',
|
|
288
|
+
'--icon-default-active': '#000000',
|
|
267
289
|
'--icon-secondary': '#4B5563',
|
|
290
|
+
'--icon-secondary-hover': '#1F2937',
|
|
291
|
+
'--icon-secondary-active': '#1F2937',
|
|
268
292
|
'--icon-tertiary': '#5B6370',
|
|
269
293
|
'--icon-disabled': '#525A68',
|
|
294
|
+
'--icon-onbrand': '#FFFFFF',
|
|
295
|
+
'--icon-onaccent': '#FFFFFF',
|
|
270
296
|
'--border-neutral-l1': 'rgba(0, 0, 0, 0.12)',
|
|
271
297
|
'--border-neutral-l2': 'rgba(0, 0, 0, 0.18)',
|
|
272
298
|
'--border-neutral-l3': 'rgba(0, 0, 0, 0.25)',
|
|
299
|
+
'--border-contrast': '#0F1117',
|
|
273
300
|
'--status-success-default': '#16A34A',
|
|
274
301
|
'--status-warning-default': '#CA8A04',
|
|
275
302
|
'--status-error-default': '#DC2626',
|
|
@@ -319,6 +346,22 @@ export function deriveBrandTokens(color) {
|
|
|
319
346
|
: '#0C0C0D',
|
|
320
347
|
};
|
|
321
348
|
}
|
|
349
|
+
export function deriveBrandTextColor(color) {
|
|
350
|
+
const normalized = normalizeHexColor(color);
|
|
351
|
+
if (contrastRatio(normalized, '#FFFFFF') >= 4.5)
|
|
352
|
+
return normalized;
|
|
353
|
+
let low = 0;
|
|
354
|
+
let high = 1;
|
|
355
|
+
for (let index = 0; index < 24; index += 1) {
|
|
356
|
+
const amount = (low + high) / 2;
|
|
357
|
+
const candidate = mixHex(normalized, '#000000', amount);
|
|
358
|
+
if (contrastRatio(candidate, '#FFFFFF') >= 4.5)
|
|
359
|
+
high = amount;
|
|
360
|
+
else
|
|
361
|
+
low = amount;
|
|
362
|
+
}
|
|
363
|
+
return mixHex(normalized, '#000000', high);
|
|
364
|
+
}
|
|
322
365
|
export function normalizeHexColor(value) {
|
|
323
366
|
const input = value.trim();
|
|
324
367
|
const short = /^#?([0-9a-f]{3})$/iu.exec(input);
|
package/dist/theme.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @vobs/ui
|
|
4
4
|
*/
|
|
5
5
|
import { type BrandColor, type BrandInput, type ThemeName } from './theme-data.js';
|
|
6
|
-
export { brandPresets, contrastRatio, DEFAULT_BRAND_COLOR, DEFAULT_BRAND_ID, DEFAULT_THEME, deriveBrandTokens, normalizeHexColor, resolveBrandColor, type BrandColor, type BrandColorInput, type BrandInput, type BrandTokens, type ThemeName, } from './theme-data.js';
|
|
6
|
+
export { brandPresets, contrastRatio, DEFAULT_BRAND_COLOR, DEFAULT_BRAND_ID, DEFAULT_THEME, deriveBrandTokens, deriveBrandTextColor, normalizeHexColor, resolveBrandColor, type BrandColor, type BrandColorInput, type BrandInput, type BrandTokens, type ThemeName, } from './theme-data.js';
|
|
7
7
|
export interface ThemeStyleTarget {
|
|
8
8
|
setProperty(name: string, value: string): void;
|
|
9
9
|
removeProperty(name: string): string;
|
|
@@ -15,6 +15,7 @@ export interface ThemeTarget {
|
|
|
15
15
|
export interface ThemePersistence {
|
|
16
16
|
readTheme?(): unknown;
|
|
17
17
|
writeTheme?(theme: ThemeName): void;
|
|
18
|
+
writeSystemTheme?(): void;
|
|
18
19
|
readBrand?(): unknown;
|
|
19
20
|
writeBrand?(brand: BrandColor): void;
|
|
20
21
|
}
|
|
@@ -39,9 +40,24 @@ export interface ThemeState {
|
|
|
39
40
|
readonly theme: ThemeName;
|
|
40
41
|
readonly brand: BrandColor;
|
|
41
42
|
}
|
|
43
|
+
export type ThemePreference = ThemeName | 'system';
|
|
44
|
+
export declare const THEME_PREFERENCE_CHANGE_EVENT = "vobs:theme-preference-change";
|
|
45
|
+
export declare const THEME_STATE_CHANGE_EVENT = "vobs:theme-state-change";
|
|
46
|
+
export interface ThemePreferenceChangeDetail {
|
|
47
|
+
readonly shellId?: string;
|
|
48
|
+
readonly theme?: ThemePreference;
|
|
49
|
+
readonly brand?: BrandInput;
|
|
50
|
+
}
|
|
51
|
+
export interface ThemeStateChangeDetail {
|
|
52
|
+
readonly shellId: string;
|
|
53
|
+
readonly theme: ThemeName;
|
|
54
|
+
readonly preference: ThemePreference;
|
|
55
|
+
readonly brand: BrandColor;
|
|
56
|
+
}
|
|
42
57
|
export interface ThemeControllerOptions {
|
|
43
58
|
readonly target: ThemeTarget;
|
|
44
59
|
readonly initialTheme?: ThemeName;
|
|
60
|
+
readonly initialPreference?: ThemePreference;
|
|
45
61
|
readonly initialBrand?: BrandInput;
|
|
46
62
|
readonly persistence?: ThemePersistence;
|
|
47
63
|
readonly systemPreference?: SystemThemePreference;
|
|
@@ -49,9 +65,11 @@ export interface ThemeControllerOptions {
|
|
|
49
65
|
}
|
|
50
66
|
export interface ThemeController {
|
|
51
67
|
readonly theme: ThemeName;
|
|
68
|
+
readonly preference: ThemePreference;
|
|
52
69
|
readonly brand: BrandColor;
|
|
53
70
|
readonly state: ThemeState;
|
|
54
71
|
setTheme(theme: ThemeName): void;
|
|
72
|
+
setPreference(preference: ThemePreference): void;
|
|
55
73
|
toggleTheme(): ThemeName;
|
|
56
74
|
setBrand(brand: BrandInput): BrandColor;
|
|
57
75
|
subscribe(listener: (state: ThemeState) => void): () => void;
|
package/dist/theme.js
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* Copyright (c) 2026 vobsjs
|
|
3
3
|
* @vobs/ui
|
|
4
4
|
*/
|
|
5
|
-
import { brandPresets, contrastRatio, DEFAULT_BRAND_ID, DEFAULT_THEME, deriveBrandTokens, resolveBrandColor, themeTokenValues, } from './theme-data.js';
|
|
6
|
-
export { brandPresets, contrastRatio, DEFAULT_BRAND_COLOR, DEFAULT_BRAND_ID, DEFAULT_THEME, deriveBrandTokens, normalizeHexColor, resolveBrandColor, } from './theme-data.js';
|
|
5
|
+
import { brandPresets, contrastRatio, DEFAULT_BRAND_ID, DEFAULT_THEME, deriveBrandTokens, deriveBrandTextColor, resolveBrandColor, themeTokenValues, } from './theme-data.js';
|
|
6
|
+
export { brandPresets, contrastRatio, DEFAULT_BRAND_COLOR, DEFAULT_BRAND_ID, DEFAULT_THEME, deriveBrandTokens, deriveBrandTextColor, normalizeHexColor, resolveBrandColor, } from './theme-data.js';
|
|
7
|
+
export const THEME_PREFERENCE_CHANGE_EVENT = 'vobs:theme-preference-change';
|
|
8
|
+
export const THEME_STATE_CHANGE_EVENT = 'vobs:theme-state-change';
|
|
7
9
|
const brandVariableNames = [
|
|
8
10
|
'--bg-brand',
|
|
9
11
|
'--bg-brand-hover',
|
|
@@ -26,24 +28,21 @@ const brandVariableNames = [
|
|
|
26
28
|
];
|
|
27
29
|
export function createThemeController(options) {
|
|
28
30
|
const listeners = new Set();
|
|
29
|
-
const
|
|
30
|
-
let
|
|
31
|
-
|
|
31
|
+
const persistedPreference = readPersistedTheme(options.persistence);
|
|
32
|
+
let preference = persistedPreference ??
|
|
33
|
+
options.initialPreference ??
|
|
34
|
+
(options.initialTheme === undefined && options.systemPreference !== undefined
|
|
35
|
+
? 'system'
|
|
36
|
+
: (options.initialTheme ?? DEFAULT_THEME));
|
|
37
|
+
let followsSystem = preference === 'system';
|
|
38
|
+
let theme = resolveTheme(preference, options);
|
|
32
39
|
let brand = readPersistedBrand(options.persistence, options.onWarning) ??
|
|
33
40
|
readBrand(options.initialBrand ?? DEFAULT_BRAND_ID, options.onWarning);
|
|
34
41
|
let stopSystemPreference;
|
|
35
42
|
let destroyed = false;
|
|
36
43
|
applyTheme(options.target, theme);
|
|
37
|
-
applyBrand(options.target, brand);
|
|
38
|
-
|
|
39
|
-
stopSystemPreference = options.systemPreference?.subscribe?.((nextTheme) => {
|
|
40
|
-
if (destroyed || !followsSystem)
|
|
41
|
-
return;
|
|
42
|
-
theme = nextTheme;
|
|
43
|
-
applyTheme(options.target, theme);
|
|
44
|
-
notify();
|
|
45
|
-
});
|
|
46
|
-
}
|
|
44
|
+
applyBrand(options.target, brand, theme);
|
|
45
|
+
subscribeToSystemPreference();
|
|
47
46
|
function state() {
|
|
48
47
|
return { theme, brand };
|
|
49
48
|
}
|
|
@@ -53,19 +52,43 @@ export function createThemeController(options) {
|
|
|
53
52
|
listener(value);
|
|
54
53
|
}
|
|
55
54
|
function setTheme(nextTheme) {
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
setPreference(nextTheme);
|
|
56
|
+
}
|
|
57
|
+
function setPreference(nextPreference) {
|
|
58
|
+
assertThemePreference(nextPreference);
|
|
59
|
+
followsSystem = nextPreference === 'system';
|
|
58
60
|
stopSystemPreference?.();
|
|
59
61
|
stopSystemPreference = undefined;
|
|
60
|
-
|
|
62
|
+
preference = nextPreference;
|
|
63
|
+
theme = resolveTheme(preference, options);
|
|
61
64
|
applyTheme(options.target, theme);
|
|
62
|
-
options.
|
|
65
|
+
applyBrand(options.target, brand, theme);
|
|
66
|
+
if (preference === 'system')
|
|
67
|
+
options.persistence?.writeSystemTheme?.();
|
|
68
|
+
else
|
|
69
|
+
options.persistence?.writeTheme?.(theme);
|
|
70
|
+
subscribeToSystemPreference();
|
|
63
71
|
notify();
|
|
64
72
|
}
|
|
73
|
+
function subscribeToSystemPreference() {
|
|
74
|
+
if (!followsSystem || options.systemPreference?.subscribe === undefined)
|
|
75
|
+
return;
|
|
76
|
+
stopSystemPreference = options.systemPreference.subscribe((nextTheme) => {
|
|
77
|
+
if (destroyed || !followsSystem)
|
|
78
|
+
return;
|
|
79
|
+
theme = nextTheme;
|
|
80
|
+
applyTheme(options.target, theme);
|
|
81
|
+
applyBrand(options.target, brand, theme);
|
|
82
|
+
notify();
|
|
83
|
+
});
|
|
84
|
+
}
|
|
65
85
|
return {
|
|
66
86
|
get theme() {
|
|
67
87
|
return theme;
|
|
68
88
|
},
|
|
89
|
+
get preference() {
|
|
90
|
+
return preference;
|
|
91
|
+
},
|
|
69
92
|
get brand() {
|
|
70
93
|
return brand;
|
|
71
94
|
},
|
|
@@ -73,6 +96,7 @@ export function createThemeController(options) {
|
|
|
73
96
|
return state();
|
|
74
97
|
},
|
|
75
98
|
setTheme,
|
|
99
|
+
setPreference,
|
|
76
100
|
toggleTheme() {
|
|
77
101
|
const nextTheme = theme === 'dark' ? 'light' : 'dark';
|
|
78
102
|
setTheme(nextTheme);
|
|
@@ -80,7 +104,7 @@ export function createThemeController(options) {
|
|
|
80
104
|
},
|
|
81
105
|
setBrand(nextBrand) {
|
|
82
106
|
brand = readBrand(nextBrand, options.onWarning);
|
|
83
|
-
applyBrand(options.target, brand);
|
|
107
|
+
applyBrand(options.target, brand, theme);
|
|
84
108
|
options.persistence?.writeBrand?.(brand);
|
|
85
109
|
notify();
|
|
86
110
|
return brand;
|
|
@@ -110,6 +134,9 @@ export function createStorageThemePersistence(storage, keys = {}) {
|
|
|
110
134
|
writeTheme(theme) {
|
|
111
135
|
storage.setItem(themeKey, theme);
|
|
112
136
|
},
|
|
137
|
+
writeSystemTheme() {
|
|
138
|
+
storage.setItem(themeKey, 'system');
|
|
139
|
+
},
|
|
113
140
|
readBrand() {
|
|
114
141
|
const stored = storage.getItem(brandKey);
|
|
115
142
|
if (stored === null)
|
|
@@ -148,18 +175,23 @@ export function createThemeAttributes(state) {
|
|
|
148
175
|
const attributes = {
|
|
149
176
|
'data-theme': state.theme,
|
|
150
177
|
'data-brand': state.brand.id,
|
|
151
|
-
...(isPresetBrand(state.brand) ? {} : { style: serializeBrandStyle(state.brand) }),
|
|
178
|
+
...(isPresetBrand(state.brand) ? {} : { style: serializeBrandStyle(state.brand, state.theme) }),
|
|
152
179
|
};
|
|
153
180
|
return attributes;
|
|
154
181
|
}
|
|
155
182
|
export function createThemeBootstrapScript(state) {
|
|
156
183
|
const attributes = createThemeAttributes(state);
|
|
157
|
-
const variables = isPresetBrand(state.brand) ? {} : brandCssVariables(state.brand);
|
|
184
|
+
const variables = isPresetBrand(state.brand) ? {} : brandCssVariables(state.brand, state.theme);
|
|
158
185
|
return `(function(){var d=document.documentElement;d.setAttribute("data-theme",${JSON.stringify(attributes['data-theme'])});d.setAttribute("data-brand",${JSON.stringify(attributes['data-brand'])});var v=${JSON.stringify(variables)};for(var k in v){d.style.setProperty(k,v[k])}})()`;
|
|
159
186
|
}
|
|
160
187
|
function readPersistedTheme(persistence) {
|
|
161
188
|
const value = persistence?.readTheme?.();
|
|
162
|
-
return value === 'dark' || value === 'light' ? value : undefined;
|
|
189
|
+
return value === 'dark' || value === 'light' || value === 'system' ? value : undefined;
|
|
190
|
+
}
|
|
191
|
+
function resolveTheme(preference, options) {
|
|
192
|
+
return preference === 'system'
|
|
193
|
+
? (options.systemPreference?.read() ?? options.initialTheme ?? DEFAULT_THEME)
|
|
194
|
+
: preference;
|
|
163
195
|
}
|
|
164
196
|
function readPersistedBrand(persistence, onWarning) {
|
|
165
197
|
const value = persistence?.readBrand?.();
|
|
@@ -191,30 +223,32 @@ function readBrand(value, onWarning) {
|
|
|
191
223
|
function applyTheme(target, theme) {
|
|
192
224
|
target.setAttribute('data-theme', theme);
|
|
193
225
|
}
|
|
194
|
-
function applyBrand(target, brand) {
|
|
226
|
+
function applyBrand(target, brand, theme) {
|
|
195
227
|
target.setAttribute('data-brand', brand.id);
|
|
196
228
|
if (isPresetBrand(brand)) {
|
|
197
229
|
for (const name of brandVariableNames)
|
|
198
230
|
target.style.removeProperty(name);
|
|
199
231
|
return;
|
|
200
232
|
}
|
|
201
|
-
for (const [name, value] of Object.entries(brandCssVariables(brand))) {
|
|
233
|
+
for (const [name, value] of Object.entries(brandCssVariables(brand, theme))) {
|
|
202
234
|
target.style.setProperty(name, value);
|
|
203
235
|
}
|
|
204
236
|
}
|
|
205
|
-
function brandCssVariables(brand) {
|
|
237
|
+
function brandCssVariables(brand, theme = DEFAULT_THEME) {
|
|
206
238
|
const tokens = deriveBrandTokens(brand.color);
|
|
239
|
+
const readable = theme === 'light' ? deriveBrandTextColor(brand.color) : tokens.background;
|
|
240
|
+
const readableHover = theme === 'light' ? deriveBrandTextColor(tokens.hover) : tokens.hover;
|
|
207
241
|
return {
|
|
208
242
|
'--bg-brand': tokens.background,
|
|
209
243
|
'--bg-brand-hover': tokens.hover,
|
|
210
244
|
'--bg-brand-disabled': tokens.disabled,
|
|
211
245
|
'--bg-brand-popup': tokens.soft,
|
|
212
246
|
'--bg-brand-overlay': tokens.soft,
|
|
213
|
-
'--text-brand':
|
|
214
|
-
'--text-brand-hover':
|
|
215
|
-
'--icon-brand':
|
|
216
|
-
'--icon-brand-hover':
|
|
217
|
-
'--border-brand':
|
|
247
|
+
'--text-brand': readable,
|
|
248
|
+
'--text-brand-hover': readableHover,
|
|
249
|
+
'--icon-brand': readable,
|
|
250
|
+
'--icon-brand-hover': readableHover,
|
|
251
|
+
'--border-brand': readable,
|
|
218
252
|
'--text-onbrand': tokens.onBrand,
|
|
219
253
|
'--icon-onbrand': tokens.onBrand,
|
|
220
254
|
'--color-primary': tokens.background,
|
|
@@ -225,8 +259,8 @@ function brandCssVariables(brand) {
|
|
|
225
259
|
'--color-on-primary': tokens.onBrand,
|
|
226
260
|
};
|
|
227
261
|
}
|
|
228
|
-
function serializeBrandStyle(brand) {
|
|
229
|
-
return Object.entries(brandCssVariables(brand))
|
|
262
|
+
function serializeBrandStyle(brand, theme) {
|
|
263
|
+
return Object.entries(brandCssVariables(brand, theme))
|
|
230
264
|
.map(([name, value]) => `${name}:${value}`)
|
|
231
265
|
.join(';');
|
|
232
266
|
}
|
|
@@ -245,6 +279,11 @@ function assertTheme(theme) {
|
|
|
245
279
|
if (theme !== 'dark' && theme !== 'light')
|
|
246
280
|
throw new TypeError(`Invalid theme: ${theme}`);
|
|
247
281
|
}
|
|
282
|
+
function assertThemePreference(preference) {
|
|
283
|
+
if (preference !== 'dark' && preference !== 'light' && preference !== 'system') {
|
|
284
|
+
throw new TypeError(`Invalid theme preference: ${preference}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
248
287
|
/**
|
|
249
288
|
* Reads a design-token value (CSS variable) for the active theme, for third-party adapters (contract ui-adapters.md §3.1).
|
|
250
289
|
* Data source: tokens.css variables on html[data-theme] (getComputedStyle reads the latest effective value).
|
package/dist/tokens.css
CHANGED
|
@@ -8,11 +8,15 @@
|
|
|
8
8
|
--radius-10: 10px;
|
|
9
9
|
--radius-full: 9999px;
|
|
10
10
|
--spacer-0: 0px;
|
|
11
|
+
--spacer-2: 2px;
|
|
11
12
|
--spacer-4: 4px;
|
|
12
13
|
--spacer-6: 6px;
|
|
13
14
|
--spacer-8: 8px;
|
|
15
|
+
--spacer-10: 10px;
|
|
14
16
|
--spacer-12: 12px;
|
|
17
|
+
--spacer-14: 14px;
|
|
15
18
|
--spacer-16: 16px;
|
|
19
|
+
--spacer-20: 20px;
|
|
16
20
|
--spacer-24: 24px;
|
|
17
21
|
--spacer-32: 32px;
|
|
18
22
|
--spacer-40: 40px;
|
|
@@ -99,9 +103,11 @@
|
|
|
99
103
|
--code-terminal-font-weight: 450;
|
|
100
104
|
--code-terminal-line-height: 18px;
|
|
101
105
|
--font-weight-default: 400;
|
|
106
|
+
--font-weight-regular: var(--font-weight-default);
|
|
102
107
|
--font-weight-code: 450;
|
|
103
108
|
--font-weight-medium: 500;
|
|
104
109
|
--font-weight-strong: 600;
|
|
110
|
+
--font-weight-semibold: var(--font-weight-strong);
|
|
105
111
|
--z-index-dropdown: 2000;
|
|
106
112
|
--z-index-drawer: 2500;
|
|
107
113
|
--z-index-modal: 3000;
|
|
@@ -231,6 +237,9 @@
|
|
|
231
237
|
--color-warning: var(--status-warning-default);
|
|
232
238
|
--color-error: var(--status-error-default);
|
|
233
239
|
--color-error-soft: var(--status-error-surface-l1);
|
|
240
|
+
--color-foreground-muted: var(--text-secondary);
|
|
241
|
+
--accent-blue: var(--status-primary-default);
|
|
242
|
+
--code-string: var(--code-text);
|
|
234
243
|
}
|
|
235
244
|
|
|
236
245
|
[data-theme="light"] {
|
|
@@ -238,22 +247,40 @@
|
|
|
238
247
|
--bg-base-default: #FFFFFF;
|
|
239
248
|
--bg-base-secondary: #F5F6F8;
|
|
240
249
|
--bg-base-tertiary: #EDF0F5;
|
|
250
|
+
--bg-tooltip: #0F1117;
|
|
251
|
+
--bg-menu: #FFFFFF;
|
|
252
|
+
--bg-invert: #0F1117;
|
|
253
|
+
--bg-invert-hover: #1F2937;
|
|
254
|
+
--bg-invert-active: #374151;
|
|
255
|
+
--bg-invert-disabled: rgba(15, 17, 23, 0.12);
|
|
241
256
|
--bg-overlay-l1: rgba(0, 0, 0, 0.04);
|
|
242
257
|
--bg-overlay-l2: rgba(0, 0, 0, 0.06);
|
|
243
258
|
--bg-overlay-l3: rgba(0, 0, 0, 0.08);
|
|
244
259
|
--bg-overlay-l4: rgba(0, 0, 0, 0.12);
|
|
245
260
|
--text-default: #0F1117;
|
|
261
|
+
--text-default-hover: #000000;
|
|
262
|
+
--text-default-active: #000000;
|
|
246
263
|
--text-secondary: #4B5563;
|
|
264
|
+
--text-secondary-hover: #1F2937;
|
|
265
|
+
--text-secondary-active: #1F2937;
|
|
247
266
|
--text-tertiary: #5B6370;
|
|
248
267
|
--text-disabled: #525A68;
|
|
249
268
|
--text-onbrand: #FFFFFF;
|
|
269
|
+
--text-onaccent: #FFFFFF;
|
|
250
270
|
--icon-default: #0F1117;
|
|
271
|
+
--icon-default-hover: #000000;
|
|
272
|
+
--icon-default-active: #000000;
|
|
251
273
|
--icon-secondary: #4B5563;
|
|
274
|
+
--icon-secondary-hover: #1F2937;
|
|
275
|
+
--icon-secondary-active: #1F2937;
|
|
252
276
|
--icon-tertiary: #5B6370;
|
|
253
277
|
--icon-disabled: #525A68;
|
|
278
|
+
--icon-onbrand: #FFFFFF;
|
|
279
|
+
--icon-onaccent: #FFFFFF;
|
|
254
280
|
--border-neutral-l1: rgba(0, 0, 0, 0.12);
|
|
255
281
|
--border-neutral-l2: rgba(0, 0, 0, 0.18);
|
|
256
282
|
--border-neutral-l3: rgba(0, 0, 0, 0.25);
|
|
283
|
+
--border-contrast: #0F1117;
|
|
257
284
|
--status-success-default: #16A34A;
|
|
258
285
|
--status-warning-default: #CA8A04;
|
|
259
286
|
--status-error-default: #DC2626;
|
|
@@ -294,6 +321,9 @@
|
|
|
294
321
|
--color-warning: var(--status-warning-default);
|
|
295
322
|
--color-error: var(--status-error-default);
|
|
296
323
|
--color-error-soft: var(--status-error-surface-l1);
|
|
324
|
+
--color-foreground-muted: var(--text-secondary);
|
|
325
|
+
--accent-blue: var(--status-primary-default);
|
|
326
|
+
--code-string: var(--code-text);
|
|
297
327
|
}
|
|
298
328
|
|
|
299
329
|
:root,
|
|
@@ -312,6 +342,16 @@
|
|
|
312
342
|
--icon-onbrand: #0C0C0D;
|
|
313
343
|
}
|
|
314
344
|
|
|
345
|
+
[data-theme="light"],
|
|
346
|
+
[data-theme="light"][data-brand="green"],
|
|
347
|
+
[data-theme="light"] [data-brand="green"] {
|
|
348
|
+
--text-brand: #1C874F;
|
|
349
|
+
--text-brand-hover: #09884A;
|
|
350
|
+
--icon-brand: #1C874F;
|
|
351
|
+
--icon-brand-hover: #09884A;
|
|
352
|
+
--border-brand: #1C874F;
|
|
353
|
+
}
|
|
354
|
+
|
|
315
355
|
[data-brand="blue"] {
|
|
316
356
|
--bg-brand: #80C1FF;
|
|
317
357
|
--bg-brand-hover: #6EA6DB;
|
|
@@ -327,6 +367,15 @@
|
|
|
327
367
|
--icon-onbrand: #0C0C0D;
|
|
328
368
|
}
|
|
329
369
|
|
|
370
|
+
[data-theme="light"][data-brand="blue"],
|
|
371
|
+
[data-theme="light"] [data-brand="blue"] {
|
|
372
|
+
--text-brand: #517AA2;
|
|
373
|
+
--text-brand-hover: #517AA2;
|
|
374
|
+
--icon-brand: #517AA2;
|
|
375
|
+
--icon-brand-hover: #517AA2;
|
|
376
|
+
--border-brand: #517AA2;
|
|
377
|
+
}
|
|
378
|
+
|
|
330
379
|
[data-brand="purple"] {
|
|
331
380
|
--bg-brand: #8E80FF;
|
|
332
381
|
--bg-brand-hover: #9E92FF;
|
|
@@ -342,6 +391,15 @@
|
|
|
342
391
|
--icon-onbrand: #0C0C0D;
|
|
343
392
|
}
|
|
344
393
|
|
|
394
|
+
[data-theme="light"][data-brand="purple"],
|
|
395
|
+
[data-theme="light"] [data-brand="purple"] {
|
|
396
|
+
--text-brand: #7468D0;
|
|
397
|
+
--text-brand-hover: #756CBE;
|
|
398
|
+
--icon-brand: #7468D0;
|
|
399
|
+
--icon-brand-hover: #756CBE;
|
|
400
|
+
--border-brand: #7468D0;
|
|
401
|
+
}
|
|
402
|
+
|
|
345
403
|
[data-brand="yellow"] {
|
|
346
404
|
--bg-brand: #FFD080;
|
|
347
405
|
--bg-brand-hover: #DBB36E;
|
|
@@ -357,6 +415,15 @@
|
|
|
357
415
|
--icon-onbrand: #0C0C0D;
|
|
358
416
|
}
|
|
359
417
|
|
|
418
|
+
[data-theme="light"][data-brand="yellow"],
|
|
419
|
+
[data-theme="light"] [data-brand="yellow"] {
|
|
420
|
+
--text-brand: #8C7347;
|
|
421
|
+
--text-brand-hover: #8C7347;
|
|
422
|
+
--icon-brand: #8C7347;
|
|
423
|
+
--icon-brand-hover: #8C7347;
|
|
424
|
+
--border-brand: #8C7347;
|
|
425
|
+
}
|
|
426
|
+
|
|
360
427
|
[data-brand="red"] {
|
|
361
428
|
--bg-brand: #FF8080;
|
|
362
429
|
--bg-brand-hover: #DB6E6E;
|
|
@@ -372,6 +439,15 @@
|
|
|
372
439
|
--icon-onbrand: #0C0C0D;
|
|
373
440
|
}
|
|
374
441
|
|
|
442
|
+
[data-theme="light"][data-brand="red"],
|
|
443
|
+
[data-theme="light"] [data-brand="red"] {
|
|
444
|
+
--text-brand: #B65B5B;
|
|
445
|
+
--text-brand-hover: #B65B5B;
|
|
446
|
+
--icon-brand: #B65B5B;
|
|
447
|
+
--icon-brand-hover: #B65B5B;
|
|
448
|
+
--border-brand: #B65B5B;
|
|
449
|
+
}
|
|
450
|
+
|
|
375
451
|
[data-brand="teal"] {
|
|
376
452
|
--bg-brand: #2DD288;
|
|
377
453
|
--bg-brand-hover: #27B575;
|
|
@@ -387,6 +463,15 @@
|
|
|
387
463
|
--icon-onbrand: #0C0C0D;
|
|
388
464
|
}
|
|
389
465
|
|
|
466
|
+
[data-theme="light"][data-brand="teal"],
|
|
467
|
+
[data-theme="light"] [data-brand="teal"] {
|
|
468
|
+
--text-brand: #1D8758;
|
|
469
|
+
--text-brand-hover: #1D8758;
|
|
470
|
+
--icon-brand: #1D8758;
|
|
471
|
+
--icon-brand-hover: #1D8758;
|
|
472
|
+
--border-brand: #1D8758;
|
|
473
|
+
}
|
|
474
|
+
|
|
390
475
|
[data-brand="cyan"] {
|
|
391
476
|
--bg-brand: #04CBE5;
|
|
392
477
|
--bg-brand-hover: #27D2E9;
|
|
@@ -402,6 +487,15 @@
|
|
|
402
487
|
--icon-onbrand: #0C0C0D;
|
|
403
488
|
}
|
|
404
489
|
|
|
490
|
+
[data-theme="light"][data-brand="cyan"],
|
|
491
|
+
[data-theme="light"] [data-brand="cyan"] {
|
|
492
|
+
--text-brand: #038293;
|
|
493
|
+
--text-brand-hover: #188291;
|
|
494
|
+
--icon-brand: #038293;
|
|
495
|
+
--icon-brand-hover: #188291;
|
|
496
|
+
--border-brand: #038293;
|
|
497
|
+
}
|
|
498
|
+
|
|
405
499
|
[data-brand="violet"] {
|
|
406
500
|
--bg-brand: #BFA5FF;
|
|
407
501
|
--bg-brand-hover: #A48EDB;
|
|
@@ -417,6 +511,15 @@
|
|
|
417
511
|
--icon-onbrand: #0C0C0D;
|
|
418
512
|
}
|
|
419
513
|
|
|
514
|
+
[data-theme="light"][data-brand="violet"],
|
|
515
|
+
[data-theme="light"] [data-brand="violet"] {
|
|
516
|
+
--text-brand: #7F6DA9;
|
|
517
|
+
--text-brand-hover: #7E6DA9;
|
|
518
|
+
--icon-brand: #7F6DA9;
|
|
519
|
+
--icon-brand-hover: #7E6DA9;
|
|
520
|
+
--border-brand: #7F6DA9;
|
|
521
|
+
}
|
|
522
|
+
|
|
420
523
|
[data-brand="slate"] {
|
|
421
524
|
--bg-brand: #AFB9CF;
|
|
422
525
|
--bg-brand-hover: #979FB2;
|
|
@@ -432,6 +535,15 @@
|
|
|
432
535
|
--icon-onbrand: #0C0C0D;
|
|
433
536
|
}
|
|
434
537
|
|
|
538
|
+
[data-theme="light"][data-brand="slate"],
|
|
539
|
+
[data-theme="light"] [data-brand="slate"] {
|
|
540
|
+
--text-brand: #707785;
|
|
541
|
+
--text-brand-hover: #717685;
|
|
542
|
+
--icon-brand: #707785;
|
|
543
|
+
--icon-brand-hover: #717685;
|
|
544
|
+
--border-brand: #707785;
|
|
545
|
+
}
|
|
546
|
+
|
|
435
547
|
[data-brand="neutral"] {
|
|
436
548
|
--bg-brand: #BABABA;
|
|
437
549
|
--bg-brand-hover: #A0A0A0;
|
|
@@ -446,4 +558,13 @@
|
|
|
446
558
|
--text-onbrand: #0C0C0D;
|
|
447
559
|
--icon-onbrand: #0C0C0D;
|
|
448
560
|
}
|
|
561
|
+
|
|
562
|
+
[data-theme="light"][data-brand="neutral"],
|
|
563
|
+
[data-theme="light"] [data-brand="neutral"] {
|
|
564
|
+
--text-brand: #767676;
|
|
565
|
+
--text-brand-hover: #767676;
|
|
566
|
+
--icon-brand: #767676;
|
|
567
|
+
--icon-brand-hover: #767676;
|
|
568
|
+
--border-brand: #767676;
|
|
569
|
+
}
|
|
449
570
|
}
|
package/dist/tree.js
CHANGED
|
@@ -102,13 +102,17 @@ export function createTreeLazyLoadStateContract(options) {
|
|
|
102
102
|
const loadedIds = normalizeTreeIds(options.loadedIds, knownIds);
|
|
103
103
|
const errorIds = normalizeTreeIds(options.errorIds, knownIds);
|
|
104
104
|
const retryableIds = normalizeTreeIds(options.retryableIds, knownIds);
|
|
105
|
+
const loadingSet = new Set(loadingIds);
|
|
106
|
+
const loadedSet = new Set(loadedIds);
|
|
107
|
+
const errorSet = new Set(errorIds);
|
|
108
|
+
const retryableSet = new Set(retryableIds);
|
|
105
109
|
const nodeContracts = options.nodes.map((node) => treeLazyLoadNodeContract(node, {
|
|
106
110
|
disabled,
|
|
107
111
|
error: options.errors?.[node.id],
|
|
108
|
-
loading:
|
|
109
|
-
loaded:
|
|
110
|
-
errored:
|
|
111
|
-
retryable:
|
|
112
|
+
loading: loadingSet.has(node.id),
|
|
113
|
+
loaded: loadedSet.has(node.id),
|
|
114
|
+
errored: errorSet.has(node.id),
|
|
115
|
+
retryable: retryableSet.has(node.id),
|
|
112
116
|
}));
|
|
113
117
|
const nodes = options.nodes.map((node, index) => treeNodeWithLazyContract(node, nodeContracts[index]));
|
|
114
118
|
const loadableCount = nodeContracts.filter((node) => node.lazy).length;
|
|
@@ -405,9 +409,11 @@ function normalizeTreeIds(ids, knownIds) {
|
|
|
405
409
|
if (ids === undefined)
|
|
406
410
|
return [];
|
|
407
411
|
const result = [];
|
|
412
|
+
const seen = new Set();
|
|
408
413
|
for (const id of ids) {
|
|
409
|
-
if (!knownIds.has(id) ||
|
|
414
|
+
if (!knownIds.has(id) || seen.has(id))
|
|
410
415
|
continue;
|
|
416
|
+
seen.add(id);
|
|
411
417
|
result.push(id);
|
|
412
418
|
}
|
|
413
419
|
return result;
|