@labpics/colors 0.1.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.
@@ -0,0 +1,482 @@
1
+ /* @ts-self-types="./labcolors.d.ts" */
2
+
3
+ /**
4
+ * A configured contrast engine. Construct with [`LabColors::new`], then call
5
+ * [`resolve_theme`](LabColors::resolve_theme) many times; identical calls are
6
+ * served from the contract cache.
7
+ */
8
+ export class LabColors {
9
+ __destroy_into_raw() {
10
+ const ptr = this.__wbg_ptr;
11
+ this.__wbg_ptr = 0;
12
+ LabColorsFinalization.unregister(this);
13
+ return ptr;
14
+ }
15
+ free() {
16
+ const ptr = this.__destroy_into_raw();
17
+ wasm.__wbg_labcolors_free(ptr, 0);
18
+ }
19
+ /**
20
+ * Calculate a relative confidence score for the [`muddiness`](Self::muddiness)
21
+ * call on an sRGB hex colour: `0` means the call is unreliable (near the
22
+ * decision boundary or the grey frontier), higher means more confident.
23
+ * The practical ceiling is an internal calibration detail, not a public
24
+ * contract — do not hardcode an upper bound against this value.
25
+ * @param {string} hex
26
+ * @returns {number}
27
+ */
28
+ confidence(hex) {
29
+ try {
30
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
31
+ const ptr0 = passStringToWasm0(hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
32
+ const len0 = WASM_VECTOR_LEN;
33
+ wasm.labcolors_confidence(retptr, this.__wbg_ptr, ptr0, len0);
34
+ var r0 = getDataViewMemory0().getFloat64(retptr + 8 * 0, true);
35
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
36
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
37
+ if (r3) {
38
+ throw takeObject(r2);
39
+ }
40
+ return r0;
41
+ } finally {
42
+ wasm.__wbindgen_add_to_stack_pointer(16);
43
+ }
44
+ }
45
+ /**
46
+ * Загрузить конфиг дизайн-системы (JSON по типу `ThemeConfig` из `.d.ts`).
47
+ *
48
+ * Полный preflight движка: невалидный конфиг отклоняется структурной
49
+ * ошибкой `invalid_config: …` и НЕ меняет состояние. После успешной
50
+ * загрузки `resolveTheme` эмитит роли конфига (включая полупрозрачные
51
+ * `rgba`-роли лестницы). Возвращает отпечаток конфига — 16 hex-символов;
52
+ * разные конфиги дают разные отпечатки (и разные кэш-пространства).
53
+ * @param {string} json
54
+ * @returns {string}
55
+ */
56
+ loadConfig(json) {
57
+ let deferred3_0;
58
+ let deferred3_1;
59
+ try {
60
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
61
+ const ptr0 = passStringToWasm0(json, wasm.__wbindgen_export, wasm.__wbindgen_export2);
62
+ const len0 = WASM_VECTOR_LEN;
63
+ wasm.labcolors_loadConfig(retptr, this.__wbg_ptr, ptr0, len0);
64
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
65
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
66
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
67
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
68
+ var ptr2 = r0;
69
+ var len2 = r1;
70
+ if (r3) {
71
+ ptr2 = 0; len2 = 0;
72
+ throw takeObject(r2);
73
+ }
74
+ deferred3_0 = ptr2;
75
+ deferred3_1 = len2;
76
+ return getStringFromWasm0(ptr2, len2);
77
+ } finally {
78
+ wasm.__wbindgen_add_to_stack_pointer(16);
79
+ wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
80
+ }
81
+ }
82
+ /**
83
+ * Calculate the muddiness score (0 to 1) of an sRGB hex colour.
84
+ * @param {string} hex
85
+ * @returns {number}
86
+ */
87
+ muddiness(hex) {
88
+ try {
89
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
90
+ const ptr0 = passStringToWasm0(hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
91
+ const len0 = WASM_VECTOR_LEN;
92
+ wasm.labcolors_muddiness(retptr, this.__wbg_ptr, ptr0, len0);
93
+ var r0 = getDataViewMemory0().getFloat64(retptr + 8 * 0, true);
94
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
95
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
96
+ if (r3) {
97
+ throw takeObject(r2);
98
+ }
99
+ return r0;
100
+ } finally {
101
+ wasm.__wbindgen_add_to_stack_pointer(16);
102
+ }
103
+ }
104
+ /**
105
+ * Create a zero-config engine on the default role table and the default
106
+ * per-theme viewing conditions.
107
+ *
108
+ * `v1` takes no config; the brand/anchor seam is left for a future
109
+ * version. Adding an optional config object later is additive — it does
110
+ * not change this signature.
111
+ */
112
+ constructor() {
113
+ const ret = wasm.labcolors_new();
114
+ this.__wbg_ptr = ret;
115
+ LabColorsFinalization.register(this, this.__wbg_ptr, this);
116
+ return this;
117
+ }
118
+ /**
119
+ * Recheck the contrasts `fgHexes` achieve against `bgHex` under `theme` —
120
+ * the cheap per-frame primitive a reactive runtime uses to decide whether
121
+ * already-resolved colours still pass against a changed background (re-solve
122
+ * only when they stably do not). No full solve: one perceptual-model forward
123
+ * for the background plus one per foreground.
124
+ *
125
+ * Returns a `Float64Array` of `[lc, wcagRatio]` pairs, interleaved and in the
126
+ * order of `fgHexes`: index `2*i` is foreground `i`'s signed `Lc`, `2*i+1`
127
+ * its WCAG ratio. Rejects (structured `{code, message}`) on an invalid hex or
128
+ * an unknown theme.
129
+ * @param {string} bg_hex
130
+ * @param {string[]} fg_hexes
131
+ * @param {string} theme
132
+ * @returns {Float64Array}
133
+ */
134
+ recheckContrast(bg_hex, fg_hexes, theme) {
135
+ try {
136
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
137
+ const ptr0 = passStringToWasm0(bg_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
138
+ const len0 = WASM_VECTOR_LEN;
139
+ const ptr1 = passArrayJsValueToWasm0(fg_hexes, wasm.__wbindgen_export);
140
+ const len1 = WASM_VECTOR_LEN;
141
+ const ptr2 = passStringToWasm0(theme, wasm.__wbindgen_export, wasm.__wbindgen_export2);
142
+ const len2 = WASM_VECTOR_LEN;
143
+ wasm.labcolors_recheckContrast(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2);
144
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
145
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
146
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
147
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
148
+ if (r3) {
149
+ throw takeObject(r2);
150
+ }
151
+ var v4 = getArrayF64FromWasm0(r0, r1).slice();
152
+ wasm.__wbindgen_export4(r0, r1 * 8, 8);
153
+ return v4;
154
+ } finally {
155
+ wasm.__wbindgen_add_to_stack_pointer(16);
156
+ }
157
+ }
158
+ /**
159
+ * Resolve every role for `bgHex` under `theme` (`"light" | "dark" |
160
+ * "light-ic" | "dark-ic"`).
161
+ *
162
+ * Returns a [`ResolvedTheme`] object. Per-role unreachability is part of a
163
+ * successful result (each role carries its own `kind`); only whole-call
164
+ * failures (invalid hex, unknown theme) reject — as a
165
+ * structured `{ code, message }` error, never an unwound panic.
166
+ * @param {string} bg_hex
167
+ * @param {string} theme
168
+ * @returns {ResolvedTheme}
169
+ */
170
+ resolveTheme(bg_hex, theme) {
171
+ try {
172
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
173
+ const ptr0 = passStringToWasm0(bg_hex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
174
+ const len0 = WASM_VECTOR_LEN;
175
+ const ptr1 = passStringToWasm0(theme, wasm.__wbindgen_export, wasm.__wbindgen_export2);
176
+ const len1 = WASM_VECTOR_LEN;
177
+ wasm.labcolors_resolveTheme(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
178
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
179
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
180
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
181
+ if (r2) {
182
+ throw takeObject(r1);
183
+ }
184
+ return takeObject(r0);
185
+ } finally {
186
+ wasm.__wbindgen_add_to_stack_pointer(16);
187
+ }
188
+ }
189
+ }
190
+ if (Symbol.dispose) LabColors.prototype[Symbol.dispose] = LabColors.prototype.free;
191
+ function __wbg_get_imports() {
192
+ const import0 = {
193
+ __proto__: null,
194
+ __wbg_Error_9dc85fe1bc224456: function(arg0, arg1) {
195
+ const ret = Error(getStringFromWasm0(arg0, arg1));
196
+ return addHeapObject(ret);
197
+ },
198
+ __wbg___wbindgen_string_get_fa2687d531ed17a5: function(arg0, arg1) {
199
+ const obj = getObject(arg1);
200
+ const ret = typeof(obj) === 'string' ? obj : undefined;
201
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
202
+ var len1 = WASM_VECTOR_LEN;
203
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
204
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
205
+ },
206
+ __wbg___wbindgen_throw_bbadd78c1bac3a77: function(arg0, arg1) {
207
+ throw new Error(getStringFromWasm0(arg0, arg1));
208
+ },
209
+ __wbg_new_20b778a4c5c691c3: function() {
210
+ const ret = new Object();
211
+ return addHeapObject(ret);
212
+ },
213
+ __wbg_set_a6ba3ac0e634b822: function() { return handleError(function (arg0, arg1, arg2) {
214
+ const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2));
215
+ return ret;
216
+ }, arguments); },
217
+ __wbindgen_cast_0000000000000001: function(arg0) {
218
+ // Cast intrinsic for `F64 -> Externref`.
219
+ const ret = arg0;
220
+ return addHeapObject(ret);
221
+ },
222
+ __wbindgen_cast_0000000000000002: function(arg0, arg1) {
223
+ // Cast intrinsic for `Ref(String) -> Externref`.
224
+ const ret = getStringFromWasm0(arg0, arg1);
225
+ return addHeapObject(ret);
226
+ },
227
+ __wbindgen_object_drop_ref: function(arg0) {
228
+ takeObject(arg0);
229
+ },
230
+ };
231
+ return {
232
+ __proto__: null,
233
+ "./labcolors_bg.js": import0,
234
+ };
235
+ }
236
+
237
+ const LabColorsFinalization = (typeof FinalizationRegistry === 'undefined')
238
+ ? { register: () => {}, unregister: () => {} }
239
+ : new FinalizationRegistry(ptr => wasm.__wbg_labcolors_free(ptr, 1));
240
+
241
+ function addHeapObject(obj) {
242
+ if (heap_next === heap.length) heap.push(heap.length + 1);
243
+ const idx = heap_next;
244
+ heap_next = heap[idx];
245
+
246
+ heap[idx] = obj;
247
+ return idx;
248
+ }
249
+
250
+ function dropObject(idx) {
251
+ if (idx < 1028) return;
252
+ heap[idx] = heap_next;
253
+ heap_next = idx;
254
+ }
255
+
256
+ function getArrayF64FromWasm0(ptr, len) {
257
+ ptr = ptr >>> 0;
258
+ return getFloat64ArrayMemory0().subarray(ptr / 8, ptr / 8 + len);
259
+ }
260
+
261
+ let cachedDataViewMemory0 = null;
262
+ function getDataViewMemory0() {
263
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
264
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
265
+ }
266
+ return cachedDataViewMemory0;
267
+ }
268
+
269
+ let cachedFloat64ArrayMemory0 = null;
270
+ function getFloat64ArrayMemory0() {
271
+ if (cachedFloat64ArrayMemory0 === null || cachedFloat64ArrayMemory0.byteLength === 0) {
272
+ cachedFloat64ArrayMemory0 = new Float64Array(wasm.memory.buffer);
273
+ }
274
+ return cachedFloat64ArrayMemory0;
275
+ }
276
+
277
+ function getStringFromWasm0(ptr, len) {
278
+ return decodeText(ptr >>> 0, len);
279
+ }
280
+
281
+ let cachedUint8ArrayMemory0 = null;
282
+ function getUint8ArrayMemory0() {
283
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
284
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
285
+ }
286
+ return cachedUint8ArrayMemory0;
287
+ }
288
+
289
+ function getObject(idx) { return heap[idx]; }
290
+
291
+ function handleError(f, args) {
292
+ try {
293
+ return f.apply(this, args);
294
+ } catch (e) {
295
+ wasm.__wbindgen_export3(addHeapObject(e));
296
+ }
297
+ }
298
+
299
+ let heap = new Array(1024).fill(undefined);
300
+ heap.push(undefined, null, true, false);
301
+
302
+ let heap_next = heap.length;
303
+
304
+ function isLikeNone(x) {
305
+ return x === undefined || x === null;
306
+ }
307
+
308
+ function passArrayJsValueToWasm0(array, malloc) {
309
+ const ptr = malloc(array.length * 4, 4) >>> 0;
310
+ const mem = getDataViewMemory0();
311
+ for (let i = 0; i < array.length; i++) {
312
+ mem.setUint32(ptr + 4 * i, addHeapObject(array[i]), true);
313
+ }
314
+ WASM_VECTOR_LEN = array.length;
315
+ return ptr;
316
+ }
317
+
318
+ function passStringToWasm0(arg, malloc, realloc) {
319
+ if (realloc === undefined) {
320
+ const buf = cachedTextEncoder.encode(arg);
321
+ const ptr = malloc(buf.length, 1) >>> 0;
322
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
323
+ WASM_VECTOR_LEN = buf.length;
324
+ return ptr;
325
+ }
326
+
327
+ let len = arg.length;
328
+ let ptr = malloc(len, 1) >>> 0;
329
+
330
+ const mem = getUint8ArrayMemory0();
331
+
332
+ let offset = 0;
333
+
334
+ for (; offset < len; offset++) {
335
+ const code = arg.charCodeAt(offset);
336
+ if (code > 0x7F) break;
337
+ mem[ptr + offset] = code;
338
+ }
339
+ if (offset !== len) {
340
+ if (offset !== 0) {
341
+ arg = arg.slice(offset);
342
+ }
343
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
344
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
345
+ const ret = cachedTextEncoder.encodeInto(arg, view);
346
+
347
+ offset += ret.written;
348
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
349
+ }
350
+
351
+ WASM_VECTOR_LEN = offset;
352
+ return ptr;
353
+ }
354
+
355
+ function takeObject(idx) {
356
+ const ret = getObject(idx);
357
+ dropObject(idx);
358
+ return ret;
359
+ }
360
+
361
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
362
+ cachedTextDecoder.decode();
363
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
364
+ let numBytesDecoded = 0;
365
+ function decodeText(ptr, len) {
366
+ numBytesDecoded += len;
367
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
368
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
369
+ cachedTextDecoder.decode();
370
+ numBytesDecoded = len;
371
+ }
372
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
373
+ }
374
+
375
+ const cachedTextEncoder = new TextEncoder();
376
+
377
+ if (!('encodeInto' in cachedTextEncoder)) {
378
+ cachedTextEncoder.encodeInto = function (arg, view) {
379
+ const buf = cachedTextEncoder.encode(arg);
380
+ view.set(buf);
381
+ return {
382
+ read: arg.length,
383
+ written: buf.length
384
+ };
385
+ };
386
+ }
387
+
388
+ let WASM_VECTOR_LEN = 0;
389
+
390
+ let wasmModule, wasmInstance, wasm;
391
+ function __wbg_finalize_init(instance, module) {
392
+ wasmInstance = instance;
393
+ wasm = instance.exports;
394
+ wasmModule = module;
395
+ cachedDataViewMemory0 = null;
396
+ cachedFloat64ArrayMemory0 = null;
397
+ cachedUint8ArrayMemory0 = null;
398
+ return wasm;
399
+ }
400
+
401
+ async function __wbg_load(module, imports) {
402
+ if (typeof Response === 'function' && module instanceof Response) {
403
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
404
+ try {
405
+ return await WebAssembly.instantiateStreaming(module, imports);
406
+ } catch (e) {
407
+ const validResponse = module.ok && expectedResponseType(module.type);
408
+
409
+ if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
410
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
411
+
412
+ } else { throw e; }
413
+ }
414
+ }
415
+
416
+ const bytes = await module.arrayBuffer();
417
+ return await WebAssembly.instantiate(bytes, imports);
418
+ } else {
419
+ const instance = await WebAssembly.instantiate(module, imports);
420
+
421
+ if (instance instanceof WebAssembly.Instance) {
422
+ return { instance, module };
423
+ } else {
424
+ return instance;
425
+ }
426
+ }
427
+
428
+ function expectedResponseType(type) {
429
+ switch (type) {
430
+ case 'basic': case 'cors': case 'default': return true;
431
+ }
432
+ return false;
433
+ }
434
+ }
435
+
436
+ function initSync(module) {
437
+ if (wasm !== undefined) return wasm;
438
+
439
+
440
+ if (module !== undefined) {
441
+ if (Object.getPrototypeOf(module) === Object.prototype) {
442
+ ({module} = module)
443
+ } else {
444
+ console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
445
+ }
446
+ }
447
+
448
+ const imports = __wbg_get_imports();
449
+ if (!(module instanceof WebAssembly.Module)) {
450
+ module = new WebAssembly.Module(module);
451
+ }
452
+ const instance = new WebAssembly.Instance(module, imports);
453
+ return __wbg_finalize_init(instance, module);
454
+ }
455
+
456
+ async function __wbg_init(module_or_path) {
457
+ if (wasm !== undefined) return wasm;
458
+
459
+
460
+ if (module_or_path !== undefined) {
461
+ if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
462
+ ({module_or_path} = module_or_path)
463
+ } else {
464
+ console.warn('using deprecated parameters for the initialization function; pass a single object instead')
465
+ }
466
+ }
467
+
468
+ if (module_or_path === undefined) {
469
+ module_or_path = new URL('labcolors_bg.wasm', import.meta.url);
470
+ }
471
+ const imports = __wbg_get_imports();
472
+
473
+ if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
474
+ module_or_path = fetch(module_or_path);
475
+ }
476
+
477
+ const { instance, module } = await __wbg_load(await module_or_path, imports);
478
+
479
+ return __wbg_finalize_init(instance, module);
480
+ }
481
+
482
+ export { initSync, __wbg_init as default };
Binary file
@@ -0,0 +1,15 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export const __wbg_labcolors_free: (a: number, b: number) => void;
5
+ export const labcolors_confidence: (a: number, b: number, c: number, d: number) => void;
6
+ export const labcolors_loadConfig: (a: number, b: number, c: number, d: number) => void;
7
+ export const labcolors_muddiness: (a: number, b: number, c: number, d: number) => void;
8
+ export const labcolors_new: () => number;
9
+ export const labcolors_recheckContrast: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
10
+ export const labcolors_resolveTheme: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
11
+ export const __wbindgen_export: (a: number, b: number) => number;
12
+ export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
13
+ export const __wbindgen_export3: (a: number) => void;
14
+ export const __wbindgen_add_to_stack_pointer: (a: number) => number;
15
+ export const __wbindgen_export4: (a: number, b: number, c: number) => void;
@@ -0,0 +1,57 @@
1
+ // Public types for the reactive theme runtime.
2
+
3
+ import type { LabColors, ResolvedTheme, ThemeName } from "./pkg/labcolors.js";
4
+
5
+ export interface WatchThemeOptions {
6
+ /** An initialised `LabColors` engine (after `await init()`). */
7
+ colors: Pick<LabColors, "resolveTheme">;
8
+ /** Theme name. */
9
+ theme: ThemeName;
10
+ /**
11
+ * Explicit effective background, overriding the ancestor-composite. Use a hex
12
+ * string or a `() => hex` you sample yourself for image/gradient/blur surfaces
13
+ * that have no single readable `background-color`.
14
+ */
15
+ background?: string | (() => string);
16
+ /** Element to write the `--lab-*` variables onto. Defaults to the watched element. */
17
+ target?: HTMLElement;
18
+ /** Base colour when the ancestor chain is fully translucent. Default `"#FFFFFF"`. */
19
+ fallback?: string;
20
+ /** Auto-refresh on DOM attribute mutations. Default `true`. */
21
+ observe?: boolean;
22
+ /** Mutation-observer root. Defaults to the document element. */
23
+ root?: Node;
24
+ /** Window-like host (for `MutationObserver`). Defaults to `globalThis`. */
25
+ win?: Window;
26
+ /** Injection seam for the computed style of an element (testing). */
27
+ getStyle?: (element: unknown) => { getPropertyValue(property: string): string };
28
+ /** Injection seam for an element's parent (testing). */
29
+ parentOf?: (element: unknown) => unknown;
30
+ }
31
+
32
+ export interface WatchController {
33
+ /**
34
+ * Re-resolve and re-apply if the effective background (or theme) changed;
35
+ * `force` re-applies unconditionally. Returns the now-applied result, or the
36
+ * cached one when nothing changed.
37
+ */
38
+ refresh(force?: boolean): ResolvedTheme | null;
39
+ /** Switch theme and re-apply. */
40
+ setTheme(theme: ThemeName): void;
41
+ /** The effective background hex last resolved. */
42
+ background(): string;
43
+ /** Disconnect observers and stop watching. */
44
+ stop(): void;
45
+ }
46
+
47
+ /**
48
+ * Keep an element's `--lab-*` variables in sync with its (effective) background.
49
+ *
50
+ * Discrete background/theme changes are caught by a `MutationObserver`;
51
+ * continuous (animated) backgrounds are driven by calling `refresh()` from a
52
+ * `requestAnimationFrame` loop (cheap — re-resolves only on real change).
53
+ */
54
+ export declare function watchTheme(
55
+ element: HTMLElement,
56
+ options: WatchThemeOptions,
57
+ ): WatchController;