@vobs/theme 1.0.0 → 1.2.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/index.cjs +765 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +756 -0
- package/dist/index.js.map +1 -0
- package/package.json +21 -6
- package/src/index.ts +4 -4
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,765 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
|
|
6
|
+
// packages/reactivity/src/debug.ts
|
|
7
|
+
var activeDebugHooks = null;
|
|
8
|
+
var signalNames = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
function hasDebugHooks() {
|
|
10
|
+
return activeDebugHooks !== null;
|
|
11
|
+
}
|
|
12
|
+
__name(hasDebugHooks, "hasDebugHooks");
|
|
13
|
+
function setSignalDebugName(signal, name) {
|
|
14
|
+
signalNames.set(signal, name);
|
|
15
|
+
invokeDebug("signalNamed", signal, name);
|
|
16
|
+
}
|
|
17
|
+
__name(setSignalDebugName, "setSignalDebugName");
|
|
18
|
+
function invokeDebug(name, ...args) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
__name(invokeDebug, "invokeDebug");
|
|
22
|
+
|
|
23
|
+
// packages/reactivity/src/owner.ts
|
|
24
|
+
var currentOwner = null;
|
|
25
|
+
function getCurrentOwner() {
|
|
26
|
+
return currentOwner;
|
|
27
|
+
}
|
|
28
|
+
__name(getCurrentOwner, "getCurrentOwner");
|
|
29
|
+
function onDispose(cleanup) {
|
|
30
|
+
throw new Error("Vobs: onDispose \u5FC5\u987B\u5728 Owner \u4F5C\u7528\u57DF\u5185\u8C03\u7528");
|
|
31
|
+
}
|
|
32
|
+
__name(onDispose, "onDispose");
|
|
33
|
+
|
|
34
|
+
// packages/reactivity/src/signal.ts
|
|
35
|
+
var currentSubscriber = null;
|
|
36
|
+
function getCurrentSubscriber() {
|
|
37
|
+
return currentSubscriber;
|
|
38
|
+
}
|
|
39
|
+
__name(getCurrentSubscriber, "getCurrentSubscriber");
|
|
40
|
+
function setCurrentSubscriber(subscriber) {
|
|
41
|
+
currentSubscriber = subscriber;
|
|
42
|
+
}
|
|
43
|
+
__name(setCurrentSubscriber, "setCurrentSubscriber");
|
|
44
|
+
function trackDependency(dependency) {
|
|
45
|
+
if (!currentSubscriber || currentSubscriber.disposed) return;
|
|
46
|
+
!currentSubscriber.dependencies.has(dependency);
|
|
47
|
+
currentSubscriber.dependencies.add(dependency);
|
|
48
|
+
}
|
|
49
|
+
__name(trackDependency, "trackDependency");
|
|
50
|
+
function state(initialValue, debugName) {
|
|
51
|
+
let value = initialValue;
|
|
52
|
+
let disposed = false;
|
|
53
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
54
|
+
const signalInstance = {
|
|
55
|
+
get value() {
|
|
56
|
+
const subscriber = getCurrentSubscriber();
|
|
57
|
+
if (subscriber && !subscriber.disposed) {
|
|
58
|
+
subscribers.add(subscriber);
|
|
59
|
+
trackDependency(signalInstance);
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
},
|
|
63
|
+
set value(nextValue) {
|
|
64
|
+
if (disposed || Object.is(value, nextValue)) return;
|
|
65
|
+
value = nextValue;
|
|
66
|
+
for (const subscriber of [...subscribers]) subscriber.notify();
|
|
67
|
+
},
|
|
68
|
+
unsubscribe(subscriber) {
|
|
69
|
+
subscribers.delete(subscriber);
|
|
70
|
+
},
|
|
71
|
+
// 与 `.value =` 赋值同一条路径:判等短路、debug hook、notify 全部一致。
|
|
72
|
+
// 以闭包实现,可安全地作为回调直接传递(无 this 绑定问题)。
|
|
73
|
+
set(next) {
|
|
74
|
+
signalInstance.value = next;
|
|
75
|
+
},
|
|
76
|
+
dispose() {
|
|
77
|
+
if (disposed) return;
|
|
78
|
+
disposed = true;
|
|
79
|
+
subscribers.clear();
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
if (debugName?.trim()) setSignalDebugName(signalInstance, debugName.trim());
|
|
83
|
+
return signalInstance;
|
|
84
|
+
}
|
|
85
|
+
__name(state, "state");
|
|
86
|
+
|
|
87
|
+
// packages/reactivity/src/scheduler.ts
|
|
88
|
+
var _Scheduler = class _Scheduler {
|
|
89
|
+
constructor() {
|
|
90
|
+
this.dirtyEffects = /* @__PURE__ */ new Set();
|
|
91
|
+
this.lowPriorityEffects = /* @__PURE__ */ new Set();
|
|
92
|
+
// flush 不可重入(flushing 标志保证),缓冲数组可在轮次间安全复用,避免每轮分配。
|
|
93
|
+
this.normalBuffer = [];
|
|
94
|
+
this.lowBuffer = [];
|
|
95
|
+
this.flushing = false;
|
|
96
|
+
this.scheduled = false;
|
|
97
|
+
this.batchDepth = 0;
|
|
98
|
+
}
|
|
99
|
+
schedule(effect2) {
|
|
100
|
+
if (effect2.disposed) return;
|
|
101
|
+
this.dirtyEffects.add(effect2);
|
|
102
|
+
this.lowPriorityEffects.delete(effect2);
|
|
103
|
+
this.ensureScheduled();
|
|
104
|
+
}
|
|
105
|
+
/** Queue an effect behind normal updates while preserving deterministic order. */
|
|
106
|
+
scheduleLow(effect2) {
|
|
107
|
+
if (effect2.disposed) return;
|
|
108
|
+
if (!this.dirtyEffects.has(effect2)) this.lowPriorityEffects.add(effect2);
|
|
109
|
+
this.ensureScheduled();
|
|
110
|
+
}
|
|
111
|
+
ensureScheduled() {
|
|
112
|
+
if (this.batchDepth === 0 && !this.flushing && !this.scheduled) {
|
|
113
|
+
this.scheduled = true;
|
|
114
|
+
queueMicrotask(() => {
|
|
115
|
+
this.scheduled = false;
|
|
116
|
+
this.flush();
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
remove(effect2) {
|
|
121
|
+
this.dirtyEffects.delete(effect2);
|
|
122
|
+
this.lowPriorityEffects.delete(effect2);
|
|
123
|
+
}
|
|
124
|
+
batch(fn) {
|
|
125
|
+
this.batchDepth++;
|
|
126
|
+
try {
|
|
127
|
+
return fn();
|
|
128
|
+
} finally {
|
|
129
|
+
this.batchDepth--;
|
|
130
|
+
if (this.batchDepth === 0) this.flush();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
flush() {
|
|
134
|
+
if (this.flushing || this.batchDepth > 0) return;
|
|
135
|
+
this.flushing = true;
|
|
136
|
+
let rounds = 0;
|
|
137
|
+
let firstError;
|
|
138
|
+
let hasError = false;
|
|
139
|
+
try {
|
|
140
|
+
while (this.dirtyEffects.size > 0 || this.lowPriorityEffects.size > 0) {
|
|
141
|
+
if (++rounds > 100) {
|
|
142
|
+
this.dirtyEffects.clear();
|
|
143
|
+
this.lowPriorityEffects.clear();
|
|
144
|
+
throw new Error("Vobs: \u54CD\u5E94\u5F0F\u66F4\u65B0\u8D85\u8FC7 100 \u8F6E\uFF0C\u53EF\u80FD\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56");
|
|
145
|
+
}
|
|
146
|
+
this.collectRunnable(this.dirtyEffects, this.normalBuffer);
|
|
147
|
+
this.collectRunnable(this.lowPriorityEffects, this.lowBuffer);
|
|
148
|
+
sortEffects(this.normalBuffer);
|
|
149
|
+
sortEffects(this.lowBuffer);
|
|
150
|
+
for (const effect2 of this.normalBuffer) {
|
|
151
|
+
try {
|
|
152
|
+
effect2.run();
|
|
153
|
+
} catch (error) {
|
|
154
|
+
if (!hasError) {
|
|
155
|
+
firstError = error;
|
|
156
|
+
hasError = true;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
for (const effect2 of this.lowBuffer) {
|
|
161
|
+
try {
|
|
162
|
+
effect2.run();
|
|
163
|
+
} catch (error) {
|
|
164
|
+
if (!hasError) {
|
|
165
|
+
firstError = error;
|
|
166
|
+
hasError = true;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
this.normalBuffer.length = 0;
|
|
171
|
+
this.lowBuffer.length = 0;
|
|
172
|
+
}
|
|
173
|
+
} finally {
|
|
174
|
+
this.normalBuffer.length = 0;
|
|
175
|
+
this.lowBuffer.length = 0;
|
|
176
|
+
this.flushing = false;
|
|
177
|
+
}
|
|
178
|
+
if (hasError) throw firstError;
|
|
179
|
+
}
|
|
180
|
+
/** 收集未 disposed 的 effect 并清空源集合;run() 期间新调度的 effect 留给下一轮。 */
|
|
181
|
+
collectRunnable(source, target) {
|
|
182
|
+
for (const effect2 of source) {
|
|
183
|
+
if (!effect2.disposed) target.push(effect2);
|
|
184
|
+
}
|
|
185
|
+
source.clear();
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
__name(_Scheduler, "Scheduler");
|
|
189
|
+
var Scheduler = _Scheduler;
|
|
190
|
+
function sortEffects(effects) {
|
|
191
|
+
if (effects.length > 1) {
|
|
192
|
+
effects.sort((a, b) => b.depth - a.depth || a.order - b.order);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
__name(sortEffects, "sortEffects");
|
|
196
|
+
var scheduler = new Scheduler();
|
|
197
|
+
|
|
198
|
+
// packages/reactivity/src/effect.ts
|
|
199
|
+
var nextEffectOrder = 1;
|
|
200
|
+
function cleanupDependencies(subscriber) {
|
|
201
|
+
for (const dependency of subscriber.dependencies) {
|
|
202
|
+
dependency.unsubscribe(subscriber);
|
|
203
|
+
}
|
|
204
|
+
subscriber.dependencies.clear();
|
|
205
|
+
}
|
|
206
|
+
__name(cleanupDependencies, "cleanupDependencies");
|
|
207
|
+
function effect(callback) {
|
|
208
|
+
const owner = getCurrentOwner();
|
|
209
|
+
let cleanup;
|
|
210
|
+
let dirty = true;
|
|
211
|
+
let disposed = false;
|
|
212
|
+
const eff = {
|
|
213
|
+
order: nextEffectOrder++,
|
|
214
|
+
depth: owner?.depth ?? 0,
|
|
215
|
+
dependencies: /* @__PURE__ */ new Set(),
|
|
216
|
+
get disposed() {
|
|
217
|
+
return disposed;
|
|
218
|
+
},
|
|
219
|
+
notify() {
|
|
220
|
+
if (disposed || dirty) return;
|
|
221
|
+
dirty = true;
|
|
222
|
+
scheduler.schedule(eff);
|
|
223
|
+
},
|
|
224
|
+
run() {
|
|
225
|
+
if (disposed || !dirty) return;
|
|
226
|
+
dirty = false;
|
|
227
|
+
const previousCleanup = cleanup;
|
|
228
|
+
cleanup = void 0;
|
|
229
|
+
let cleanupError;
|
|
230
|
+
if (previousCleanup) {
|
|
231
|
+
try {
|
|
232
|
+
previousCleanup();
|
|
233
|
+
} catch (error) {
|
|
234
|
+
cleanupError = error;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
cleanupDependencies(eff);
|
|
238
|
+
const previous = getCurrentSubscriber();
|
|
239
|
+
setCurrentSubscriber(eff);
|
|
240
|
+
let thrown;
|
|
241
|
+
let handled = false;
|
|
242
|
+
try {
|
|
243
|
+
const result = owner ? owner.run(callback) : callback();
|
|
244
|
+
cleanup = typeof result === "function" ? result : void 0;
|
|
245
|
+
} catch (error) {
|
|
246
|
+
thrown = error;
|
|
247
|
+
handled = false;
|
|
248
|
+
if (!handled) throw error;
|
|
249
|
+
} finally {
|
|
250
|
+
setCurrentSubscriber(previous);
|
|
251
|
+
}
|
|
252
|
+
if (cleanupError && !thrown) throw cleanupError;
|
|
253
|
+
},
|
|
254
|
+
scheduleLow() {
|
|
255
|
+
if (disposed || dirty) return;
|
|
256
|
+
dirty = true;
|
|
257
|
+
scheduler.scheduleLow(eff);
|
|
258
|
+
},
|
|
259
|
+
dispose() {
|
|
260
|
+
if (disposed) return;
|
|
261
|
+
disposed = true;
|
|
262
|
+
dirty = false;
|
|
263
|
+
scheduler.remove(eff);
|
|
264
|
+
const previousCleanup = cleanup;
|
|
265
|
+
cleanup = void 0;
|
|
266
|
+
let cleanupError;
|
|
267
|
+
if (previousCleanup) {
|
|
268
|
+
try {
|
|
269
|
+
previousCleanup();
|
|
270
|
+
} catch (error) {
|
|
271
|
+
cleanupError = error;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
cleanupDependencies(eff);
|
|
275
|
+
if (cleanupError) throw cleanupError;
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
eff.run();
|
|
279
|
+
return eff;
|
|
280
|
+
}
|
|
281
|
+
__name(effect, "effect");
|
|
282
|
+
var renderEffect = effect;
|
|
283
|
+
|
|
284
|
+
// packages/reactivity/src/memo.ts
|
|
285
|
+
function memo(compute) {
|
|
286
|
+
let cached;
|
|
287
|
+
let dirty = true;
|
|
288
|
+
let disposed = false;
|
|
289
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
290
|
+
const memoSubscriber = {
|
|
291
|
+
dependencies: /* @__PURE__ */ new Set(),
|
|
292
|
+
get disposed() {
|
|
293
|
+
return disposed;
|
|
294
|
+
},
|
|
295
|
+
notify() {
|
|
296
|
+
if (disposed || dirty) return;
|
|
297
|
+
dirty = true;
|
|
298
|
+
for (const subscriber of [...subscribers]) subscriber.notify();
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
const memoSignal = {
|
|
302
|
+
get value() {
|
|
303
|
+
const subscriber = getCurrentSubscriber();
|
|
304
|
+
if (subscriber && !subscriber.disposed) {
|
|
305
|
+
subscribers.add(subscriber);
|
|
306
|
+
trackDependency(memoSignal);
|
|
307
|
+
}
|
|
308
|
+
if (dirty) {
|
|
309
|
+
cleanupDependencies(memoSubscriber);
|
|
310
|
+
const previous = getCurrentSubscriber();
|
|
311
|
+
setCurrentSubscriber(memoSubscriber);
|
|
312
|
+
try {
|
|
313
|
+
cached = compute();
|
|
314
|
+
dirty = false;
|
|
315
|
+
} finally {
|
|
316
|
+
setCurrentSubscriber(previous);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return cached;
|
|
320
|
+
},
|
|
321
|
+
set value(_) {
|
|
322
|
+
throw new Error("memo: \u6D3E\u751F\u503C\u4E0D\u80FD\u76F4\u63A5\u8D4B\u503C");
|
|
323
|
+
},
|
|
324
|
+
unsubscribe(subscriber) {
|
|
325
|
+
subscribers.delete(subscriber);
|
|
326
|
+
},
|
|
327
|
+
dispose() {
|
|
328
|
+
if (disposed) return;
|
|
329
|
+
disposed = true;
|
|
330
|
+
subscribers.clear();
|
|
331
|
+
cleanupDependencies(memoSubscriber);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
return memoSignal;
|
|
335
|
+
}
|
|
336
|
+
__name(memo, "memo");
|
|
337
|
+
|
|
338
|
+
// packages/runtime/src/debug.ts
|
|
339
|
+
var activeRuntimeDebugHooks = null;
|
|
340
|
+
function getRuntimeDebugHooks() {
|
|
341
|
+
return activeRuntimeDebugHooks;
|
|
342
|
+
}
|
|
343
|
+
__name(getRuntimeDebugHooks, "getRuntimeDebugHooks");
|
|
344
|
+
function invokeRuntimeDebug(name, ...args) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
__name(invokeRuntimeDebug, "invokeRuntimeDebug");
|
|
348
|
+
function describeDebugNode(node) {
|
|
349
|
+
if (!node || typeof node !== "object") return "node";
|
|
350
|
+
const value = node;
|
|
351
|
+
const name = typeof value.tagName === "string" ? value.tagName.toLowerCase() : typeof value.nodeName === "string" ? value.nodeName.toLowerCase() : "node";
|
|
352
|
+
const id = typeof value.id === "string" && value.id ? `#${value.id}` : "";
|
|
353
|
+
const className = typeof value.className === "string" && value.className ? `.${value.className.trim().split(/\s+/).filter(Boolean).join(".")}` : "";
|
|
354
|
+
return `${name}${id}${className}`;
|
|
355
|
+
}
|
|
356
|
+
__name(describeDebugNode, "describeDebugNode");
|
|
357
|
+
|
|
358
|
+
// packages/runtime/src/hmr.ts
|
|
359
|
+
var globalTarget = globalThis;
|
|
360
|
+
var hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: /* @__PURE__ */ new Map() };
|
|
361
|
+
globalTarget.__VOBS_HMR__ = hmrGlobal;
|
|
362
|
+
function markHmrInstanceMounted(node, parent) {
|
|
363
|
+
const instance = hmrInstances.get(node);
|
|
364
|
+
if (instance) instance.parent = parent;
|
|
365
|
+
}
|
|
366
|
+
__name(markHmrInstanceMounted, "markHmrInstanceMounted");
|
|
367
|
+
var hmrInstances = /* @__PURE__ */ new WeakMap();
|
|
368
|
+
function getRenderer() {
|
|
369
|
+
{
|
|
370
|
+
throw new Error("\u6E32\u67D3\u5668\u672A\u521D\u59CB\u5316");
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
__name(getRenderer, "getRenderer");
|
|
374
|
+
function createElement(tag) {
|
|
375
|
+
return getRenderer().createElement(tag);
|
|
376
|
+
}
|
|
377
|
+
__name(createElement, "createElement");
|
|
378
|
+
function insertBefore(parent, child, anchor) {
|
|
379
|
+
if (isVobsFragment(child)) {
|
|
380
|
+
child.mount(parent, isVobsFragment(anchor) ? anchor.start : anchor);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
getRenderer().insertBefore(parent, child, isVobsFragment(anchor) ? anchor.start : anchor);
|
|
384
|
+
markHmrInstanceMounted(child, parent);
|
|
385
|
+
}
|
|
386
|
+
__name(insertBefore, "insertBefore");
|
|
387
|
+
|
|
388
|
+
// packages/runtime/src/fragment.ts
|
|
389
|
+
function isVobsFragment(value) {
|
|
390
|
+
return Boolean(value) && typeof value === "object" && value.kind === "vobs-fragment";
|
|
391
|
+
}
|
|
392
|
+
__name(isVobsFragment, "isVobsFragment");
|
|
393
|
+
|
|
394
|
+
// packages/vobs/src/context.ts
|
|
395
|
+
var ownerProviders = /* @__PURE__ */ new WeakMap();
|
|
396
|
+
function provide(key, value, options = {}) {
|
|
397
|
+
throw new Error("Vobs: provide \u5FC5\u987B\u5728\u7EC4\u4EF6\u6216 Owner \u4F5C\u7528\u57DF\u5185\u8C03\u7528");
|
|
398
|
+
}
|
|
399
|
+
__name(provide, "provide");
|
|
400
|
+
function inject(key, fallback) {
|
|
401
|
+
const owner = getCurrentOwner();
|
|
402
|
+
const value = owner ? injectFromOwner(owner, key) : void 0;
|
|
403
|
+
return value === void 0 ? fallback : value;
|
|
404
|
+
}
|
|
405
|
+
__name(inject, "inject");
|
|
406
|
+
function provideToOwner(owner, key, value, options = {}) {
|
|
407
|
+
let providers = ownerProviders.get(owner);
|
|
408
|
+
if (!providers) {
|
|
409
|
+
providers = /* @__PURE__ */ new Map();
|
|
410
|
+
ownerProviders.set(owner, providers);
|
|
411
|
+
owner.onDispose(() => ownerProviders.delete(owner));
|
|
412
|
+
}
|
|
413
|
+
if (providers.has(key) && !options.override) {
|
|
414
|
+
throw new Error(`Vobs: \u6CE8\u5165\u9879 ${String(key)} \u5DF2\u5B58\u5728\uFF1B\u5982\u9700\u8986\u76D6\u8BF7\u4F20\u5165 override: true`);
|
|
415
|
+
}
|
|
416
|
+
providers.set(key, value);
|
|
417
|
+
}
|
|
418
|
+
__name(provideToOwner, "provideToOwner");
|
|
419
|
+
function injectFromOwner(owner, key) {
|
|
420
|
+
let current = owner;
|
|
421
|
+
while (current) {
|
|
422
|
+
const providers = ownerProviders.get(current);
|
|
423
|
+
if (providers?.has(key)) return providers.get(key);
|
|
424
|
+
current = current.parent;
|
|
425
|
+
}
|
|
426
|
+
return void 0;
|
|
427
|
+
}
|
|
428
|
+
__name(injectFromOwner, "injectFromOwner");
|
|
429
|
+
|
|
430
|
+
// packages/vobs/src/app.ts
|
|
431
|
+
function createInjectionKey(description) {
|
|
432
|
+
return Symbol(description);
|
|
433
|
+
}
|
|
434
|
+
__name(createInjectionKey, "createInjectionKey");
|
|
435
|
+
|
|
436
|
+
// packages/theme/src/index.ts
|
|
437
|
+
var THEME_KEY = createInjectionKey("vobs.theme");
|
|
438
|
+
var defaultLightTheme = {
|
|
439
|
+
colorScheme: "light",
|
|
440
|
+
brand: {
|
|
441
|
+
primary: "#2563eb",
|
|
442
|
+
secondary: "#0f766e",
|
|
443
|
+
accent: "#d97706"
|
|
444
|
+
},
|
|
445
|
+
semantic: {
|
|
446
|
+
success: "#15803d",
|
|
447
|
+
warning: "#b45309",
|
|
448
|
+
danger: "#b91c1c",
|
|
449
|
+
info: "#0369a1"
|
|
450
|
+
},
|
|
451
|
+
neutral: {
|
|
452
|
+
background: "#ffffff",
|
|
453
|
+
surface: "#f8fafc",
|
|
454
|
+
foreground: "#172033",
|
|
455
|
+
muted: "#64748b",
|
|
456
|
+
border: "#cbd5e1"
|
|
457
|
+
},
|
|
458
|
+
spacing: {
|
|
459
|
+
sm: "4px",
|
|
460
|
+
md: "8px",
|
|
461
|
+
lg: "16px"
|
|
462
|
+
},
|
|
463
|
+
radius: {
|
|
464
|
+
sm: "2px",
|
|
465
|
+
md: "4px",
|
|
466
|
+
lg: "6px"
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
var defaultDarkTheme = {
|
|
470
|
+
colorScheme: "dark",
|
|
471
|
+
brand: {
|
|
472
|
+
primary: "#60a5fa",
|
|
473
|
+
secondary: "#2dd4bf",
|
|
474
|
+
accent: "#fbbf24"
|
|
475
|
+
},
|
|
476
|
+
semantic: {
|
|
477
|
+
success: "#4ade80",
|
|
478
|
+
warning: "#fbbf24",
|
|
479
|
+
danger: "#f87171",
|
|
480
|
+
info: "#38bdf8"
|
|
481
|
+
},
|
|
482
|
+
neutral: {
|
|
483
|
+
background: "#111827",
|
|
484
|
+
surface: "#1f2937",
|
|
485
|
+
foreground: "#f8fafc",
|
|
486
|
+
muted: "#94a3b8",
|
|
487
|
+
border: "#334155"
|
|
488
|
+
},
|
|
489
|
+
spacing: {
|
|
490
|
+
sm: "4px",
|
|
491
|
+
md: "8px",
|
|
492
|
+
lg: "16px"
|
|
493
|
+
},
|
|
494
|
+
radius: {
|
|
495
|
+
sm: "2px",
|
|
496
|
+
md: "4px",
|
|
497
|
+
lg: "6px"
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
var appliedVariables = /* @__PURE__ */ new WeakMap();
|
|
501
|
+
function createTheme(options = {}) {
|
|
502
|
+
const mode = state(options.defaultMode ?? "light");
|
|
503
|
+
const systemMode = state(readSystemMode());
|
|
504
|
+
const themes = state({
|
|
505
|
+
light: mergeThemes(defaultLightTheme, options.defaultTheme ?? {}, options.themes?.light ?? {}),
|
|
506
|
+
dark: mergeThemes(defaultDarkTheme, options.defaultTheme ?? {}, options.themes?.dark ?? {})
|
|
507
|
+
});
|
|
508
|
+
const overrides = state({});
|
|
509
|
+
const resolvedMode = memo(() => mode.value === "system" ? systemMode.value : mode.value);
|
|
510
|
+
const theme = memo(() => mergeThemes(themes.value[resolvedMode.value], overrides.value));
|
|
511
|
+
const brand = memo(() => {
|
|
512
|
+
const value = theme.value.brand;
|
|
513
|
+
return isThemeTokens(value) ? value : {};
|
|
514
|
+
});
|
|
515
|
+
let disposed = false;
|
|
516
|
+
let stopSystemListener;
|
|
517
|
+
if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
|
|
518
|
+
const media = window.matchMedia("(prefers-color-scheme: dark)");
|
|
519
|
+
const listener = /* @__PURE__ */ __name((event) => {
|
|
520
|
+
systemMode.value = event.matches ? "dark" : "light";
|
|
521
|
+
}, "listener");
|
|
522
|
+
if (media.addEventListener) {
|
|
523
|
+
media.addEventListener("change", listener);
|
|
524
|
+
stopSystemListener = /* @__PURE__ */ __name(() => media.removeEventListener("change", listener), "stopSystemListener");
|
|
525
|
+
} else {
|
|
526
|
+
media.addListener(listener);
|
|
527
|
+
stopSystemListener = /* @__PURE__ */ __name(() => media.removeListener(listener), "stopSystemListener");
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
const context = {
|
|
531
|
+
theme,
|
|
532
|
+
brand,
|
|
533
|
+
mode,
|
|
534
|
+
resolvedMode,
|
|
535
|
+
dehydrate() {
|
|
536
|
+
ensureActive();
|
|
537
|
+
return { version: 1, mode: mode.value, overrides: overrides.value };
|
|
538
|
+
},
|
|
539
|
+
hydrate(snapshot) {
|
|
540
|
+
ensureActive();
|
|
541
|
+
const restored = parseDehydratedState(snapshot);
|
|
542
|
+
mode.value = restored.mode;
|
|
543
|
+
overrides.value = restored.overrides;
|
|
544
|
+
},
|
|
545
|
+
setTheme(nextTheme) {
|
|
546
|
+
ensureActive();
|
|
547
|
+
overrides.value = nextTheme;
|
|
548
|
+
},
|
|
549
|
+
setMode(nextMode) {
|
|
550
|
+
ensureActive();
|
|
551
|
+
mode.value = validateMode(nextMode);
|
|
552
|
+
},
|
|
553
|
+
setBrand(nextBrand) {
|
|
554
|
+
ensureActive();
|
|
555
|
+
overrides.value = mergeThemes(overrides.value, {
|
|
556
|
+
brand: {
|
|
557
|
+
...brand.value,
|
|
558
|
+
...nextBrand
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
},
|
|
562
|
+
registerTheme(nextMode, nextTheme) {
|
|
563
|
+
ensureActive();
|
|
564
|
+
const previous = themes.value[nextMode];
|
|
565
|
+
themes.value = {
|
|
566
|
+
...themes.value,
|
|
567
|
+
[nextMode]: mergeThemes(previous, nextTheme)
|
|
568
|
+
};
|
|
569
|
+
return () => {
|
|
570
|
+
if (disposed) return;
|
|
571
|
+
themes.value = { ...themes.value, [nextMode]: previous };
|
|
572
|
+
};
|
|
573
|
+
},
|
|
574
|
+
dispose() {
|
|
575
|
+
if (disposed) return;
|
|
576
|
+
disposed = true;
|
|
577
|
+
stopSystemListener?.();
|
|
578
|
+
stopSystemListener = void 0;
|
|
579
|
+
theme.dispose();
|
|
580
|
+
brand.dispose();
|
|
581
|
+
resolvedMode.dispose();
|
|
582
|
+
mode.dispose();
|
|
583
|
+
systemMode.dispose();
|
|
584
|
+
themes.dispose();
|
|
585
|
+
overrides.dispose();
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
return context;
|
|
589
|
+
function ensureActive() {
|
|
590
|
+
if (disposed) throw new Error("Vobs Theme: \u5DF2\u9500\u6BC1\u7684\u4E0A\u4E0B\u6587\u4E0D\u80FD\u7EE7\u7EED\u4F7F\u7528");
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
__name(createTheme, "createTheme");
|
|
594
|
+
function themePlugin(options = {}) {
|
|
595
|
+
return {
|
|
596
|
+
name: "@vobs/theme",
|
|
597
|
+
version: "0.1.0",
|
|
598
|
+
install(context) {
|
|
599
|
+
const ownedTheme = options.theme ? void 0 : createTheme(options);
|
|
600
|
+
const theme = options.theme ?? ownedTheme;
|
|
601
|
+
context.provide(THEME_KEY, theme);
|
|
602
|
+
return () => ownedTheme?.dispose();
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
__name(themePlugin, "themePlugin");
|
|
607
|
+
function useTheme() {
|
|
608
|
+
const theme = inject(THEME_KEY);
|
|
609
|
+
if (!theme) throw new Error("Vobs Theme: \u627E\u4E0D\u5230\u4E0A\u4E0B\u6587\uFF0C\u8BF7\u5B89\u88C5 themePlugin");
|
|
610
|
+
return theme;
|
|
611
|
+
}
|
|
612
|
+
__name(useTheme, "useTheme");
|
|
613
|
+
function ThemeBoundary(props = {}) {
|
|
614
|
+
const parent = useTheme();
|
|
615
|
+
const local = createScopedTheme(parent, mergeThemes(
|
|
616
|
+
props.theme ?? {},
|
|
617
|
+
props.tokens ?? {},
|
|
618
|
+
props.brand ? { brand: props.brand } : {}
|
|
619
|
+
));
|
|
620
|
+
provide();
|
|
621
|
+
const root = createElement("div");
|
|
622
|
+
renderEffect(() => {
|
|
623
|
+
applyThemeVariables(root, local.theme.value);
|
|
624
|
+
root.dataset.vobsMode = local.resolvedMode.value;
|
|
625
|
+
});
|
|
626
|
+
const child = typeof props.children === "function" ? props.children() : props.children;
|
|
627
|
+
if (child) insertBefore(root, child, null);
|
|
628
|
+
return root;
|
|
629
|
+
}
|
|
630
|
+
__name(ThemeBoundary, "ThemeBoundary");
|
|
631
|
+
function flattenTheme(theme) {
|
|
632
|
+
const variables = {};
|
|
633
|
+
flattenInto(theme, "", variables);
|
|
634
|
+
return variables;
|
|
635
|
+
}
|
|
636
|
+
__name(flattenTheme, "flattenTheme");
|
|
637
|
+
function createScopedTheme(parent, initialOverrides) {
|
|
638
|
+
const overrides = state(initialOverrides);
|
|
639
|
+
const theme = memo(() => mergeThemes(parent.theme.value, overrides.value));
|
|
640
|
+
const brand = memo(() => {
|
|
641
|
+
const value = theme.value.brand;
|
|
642
|
+
return isThemeTokens(value) ? value : {};
|
|
643
|
+
});
|
|
644
|
+
let disposed = false;
|
|
645
|
+
const context = {
|
|
646
|
+
theme,
|
|
647
|
+
brand,
|
|
648
|
+
mode: parent.mode,
|
|
649
|
+
resolvedMode: parent.resolvedMode,
|
|
650
|
+
dehydrate: parent.dehydrate,
|
|
651
|
+
hydrate: parent.hydrate,
|
|
652
|
+
setTheme(nextTheme) {
|
|
653
|
+
ensureActive();
|
|
654
|
+
overrides.value = nextTheme;
|
|
655
|
+
},
|
|
656
|
+
setMode(nextMode) {
|
|
657
|
+
ensureActive();
|
|
658
|
+
parent.setMode(nextMode);
|
|
659
|
+
},
|
|
660
|
+
setBrand(nextBrand) {
|
|
661
|
+
ensureActive();
|
|
662
|
+
overrides.value = mergeThemes(overrides.value, {
|
|
663
|
+
brand: { ...brand.value, ...nextBrand }
|
|
664
|
+
});
|
|
665
|
+
},
|
|
666
|
+
registerTheme(nextMode, nextTheme) {
|
|
667
|
+
ensureActive();
|
|
668
|
+
return parent.registerTheme(nextMode, nextTheme);
|
|
669
|
+
},
|
|
670
|
+
dispose() {
|
|
671
|
+
if (disposed) return;
|
|
672
|
+
disposed = true;
|
|
673
|
+
theme.dispose();
|
|
674
|
+
brand.dispose();
|
|
675
|
+
overrides.dispose();
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
return context;
|
|
679
|
+
function ensureActive() {
|
|
680
|
+
if (disposed) throw new Error("Vobs Theme: \u5DF2\u9500\u6BC1\u7684\u5C40\u90E8\u4E0A\u4E0B\u6587\u4E0D\u80FD\u7EE7\u7EED\u4F7F\u7528");
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
__name(createScopedTheme, "createScopedTheme");
|
|
684
|
+
function parseDehydratedState(snapshot) {
|
|
685
|
+
let value = snapshot;
|
|
686
|
+
if (typeof snapshot === "string") {
|
|
687
|
+
try {
|
|
688
|
+
value = JSON.parse(snapshot);
|
|
689
|
+
} catch {
|
|
690
|
+
throw new Error("Vobs Theme: \u521D\u59CB\u72B6\u6001\u4E0D\u662F\u6709\u6548 JSON");
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
if (!value || typeof value !== "object") throw new Error("Vobs Theme: \u521D\u59CB\u72B6\u6001\u683C\u5F0F\u65E0\u6548");
|
|
694
|
+
const candidate = value;
|
|
695
|
+
if (candidate.version !== 1 || !candidate.overrides || typeof candidate.overrides !== "object") {
|
|
696
|
+
throw new Error("Vobs Theme: \u521D\u59CB\u72B6\u6001\u7248\u672C\u6216\u5B57\u6BB5\u65E0\u6548");
|
|
697
|
+
}
|
|
698
|
+
return {
|
|
699
|
+
version: 1,
|
|
700
|
+
mode: validateMode(candidate.mode),
|
|
701
|
+
overrides: candidate.overrides
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
__name(parseDehydratedState, "parseDehydratedState");
|
|
705
|
+
function applyThemeVariables(root, theme) {
|
|
706
|
+
const next = flattenTheme(theme);
|
|
707
|
+
const previous = appliedVariables.get(root) ?? /* @__PURE__ */ new Set();
|
|
708
|
+
for (const [key, value] of Object.entries(next)) {
|
|
709
|
+
root.style.setProperty(key, value);
|
|
710
|
+
previous.delete(key);
|
|
711
|
+
}
|
|
712
|
+
for (const key of previous) root.style.removeProperty(key);
|
|
713
|
+
appliedVariables.set(root, new Set(Object.keys(next)));
|
|
714
|
+
}
|
|
715
|
+
__name(applyThemeVariables, "applyThemeVariables");
|
|
716
|
+
function flattenInto(value, path, output) {
|
|
717
|
+
if (value === void 0) return;
|
|
718
|
+
if (isThemeTokens(value)) {
|
|
719
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
720
|
+
const nextPath = key.startsWith("--") ? key : path ? `${path}-${key}` : key;
|
|
721
|
+
flattenInto(nested, nextPath, output);
|
|
722
|
+
}
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
const variable = path.startsWith("--") ? path : `--vobs-${path}`;
|
|
726
|
+
output[variable] = String(value);
|
|
727
|
+
}
|
|
728
|
+
__name(flattenInto, "flattenInto");
|
|
729
|
+
function mergeThemes(...themes) {
|
|
730
|
+
const result = {};
|
|
731
|
+
for (const theme of themes) {
|
|
732
|
+
for (const [key, value] of Object.entries(theme)) {
|
|
733
|
+
const previous = result[key];
|
|
734
|
+
result[key] = isThemeTokens(previous) && isThemeTokens(value) ? mergeThemes(previous, value) : value;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return result;
|
|
738
|
+
}
|
|
739
|
+
__name(mergeThemes, "mergeThemes");
|
|
740
|
+
function isThemeTokens(value) {
|
|
741
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
742
|
+
}
|
|
743
|
+
__name(isThemeTokens, "isThemeTokens");
|
|
744
|
+
function validateMode(mode) {
|
|
745
|
+
if (mode !== "light" && mode !== "dark" && mode !== "system") {
|
|
746
|
+
throw new Error("Vobs Theme: mode \u5FC5\u987B\u662F light\u3001dark \u6216 system");
|
|
747
|
+
}
|
|
748
|
+
return mode;
|
|
749
|
+
}
|
|
750
|
+
__name(validateMode, "validateMode");
|
|
751
|
+
function readSystemMode() {
|
|
752
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
753
|
+
}
|
|
754
|
+
__name(readSystemMode, "readSystemMode");
|
|
755
|
+
|
|
756
|
+
exports.THEME_KEY = THEME_KEY;
|
|
757
|
+
exports.ThemeBoundary = ThemeBoundary;
|
|
758
|
+
exports.createTheme = createTheme;
|
|
759
|
+
exports.defaultDarkTheme = defaultDarkTheme;
|
|
760
|
+
exports.defaultLightTheme = defaultLightTheme;
|
|
761
|
+
exports.flattenTheme = flattenTheme;
|
|
762
|
+
exports.themePlugin = themePlugin;
|
|
763
|
+
exports.useTheme = useTheme;
|
|
764
|
+
//# sourceMappingURL=index.cjs.map
|
|
765
|
+
//# sourceMappingURL=index.cjs.map
|