what-core 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/chunk-D5YDPQ57.min.js +1 -0
  2. package/dist/chunk-O3SKPRTY.min.js +0 -1
  3. package/dist/chunk-W33M3HL5.min.js +1 -0
  4. package/dist/index.min.js +6 -7
  5. package/dist/jsx-dev-runtime.min.js +0 -1
  6. package/dist/jsx-runtime.min.js +0 -1
  7. package/dist/render.min.js +1 -2
  8. package/dist/testing.min.js +1 -2
  9. package/package.json +2 -2
  10. package/render.d.ts +18 -0
  11. package/src/agent-context.js +3 -2
  12. package/src/dom.js +16 -0
  13. package/src/guardrails.js +17 -46
  14. package/src/reactive.js +42 -4
  15. package/src/render.js +159 -55
  16. package/dist/a11y.js +0 -440
  17. package/dist/animation.js +0 -548
  18. package/dist/chunk-AW3BAPIK.js +0 -1685
  19. package/dist/chunk-AW3BAPIK.js.map +0 -7
  20. package/dist/chunk-AZP2EOGX.js +0 -188
  21. package/dist/chunk-AZP2EOGX.js.map +0 -7
  22. package/dist/chunk-F2HUXI22.js +0 -1675
  23. package/dist/chunk-F2HUXI22.js.map +0 -7
  24. package/dist/chunk-KBM6CWG4.min.js +0 -2
  25. package/dist/chunk-KBM6CWG4.min.js.map +0 -7
  26. package/dist/chunk-KL7TNUIU.min.js +0 -2
  27. package/dist/chunk-KL7TNUIU.min.js.map +0 -7
  28. package/dist/chunk-L6XOF7P4.min.js +0 -2
  29. package/dist/chunk-L6XOF7P4.min.js.map +0 -7
  30. package/dist/chunk-M7UEET5O.js +0 -1323
  31. package/dist/chunk-M7UEET5O.js.map +0 -7
  32. package/dist/chunk-O3SKPRTY.min.js.map +0 -7
  33. package/dist/chunk-RN6QIBWL.min.js +0 -2
  34. package/dist/chunk-RN6QIBWL.min.js.map +0 -7
  35. package/dist/chunk-VMTTYB4L.min.js +0 -2
  36. package/dist/chunk-VMTTYB4L.min.js.map +0 -7
  37. package/dist/chunk-VP4WLF5A.js +0 -1323
  38. package/dist/chunk-VP4WLF5A.js.map +0 -7
  39. package/dist/chunk-YA3W4XKH.js +0 -1323
  40. package/dist/chunk-YA3W4XKH.js.map +0 -7
  41. package/dist/compiler.js +0 -1799
  42. package/dist/compiler.js.map +0 -7
  43. package/dist/compiler.min.js +0 -2
  44. package/dist/compiler.min.js.map +0 -7
  45. package/dist/components.js +0 -229
  46. package/dist/data.js +0 -638
  47. package/dist/devtools.js +0 -10
  48. package/dist/devtools.js.map +0 -7
  49. package/dist/devtools.min.js +0 -2
  50. package/dist/devtools.min.js.map +0 -7
  51. package/dist/dom.js +0 -439
  52. package/dist/form.js +0 -509
  53. package/dist/h.js +0 -152
  54. package/dist/head.js +0 -51
  55. package/dist/helpers.js +0 -140
  56. package/dist/hooks.js +0 -210
  57. package/dist/index.js +0 -3578
  58. package/dist/index.js.map +0 -7
  59. package/dist/index.min.js.map +0 -7
  60. package/dist/jsx-dev-runtime.js +0 -23
  61. package/dist/jsx-dev-runtime.js.map +0 -7
  62. package/dist/jsx-dev-runtime.min.js.map +0 -7
  63. package/dist/jsx-runtime.js +0 -21
  64. package/dist/jsx-runtime.js.map +0 -7
  65. package/dist/jsx-runtime.min.js.map +0 -7
  66. package/dist/reactive.js +0 -432
  67. package/dist/render.js +0 -41
  68. package/dist/render.js.map +0 -7
  69. package/dist/render.min.js.map +0 -7
  70. package/dist/scheduler.js +0 -246
  71. package/dist/skeleton.js +0 -363
  72. package/dist/store.js +0 -83
  73. package/dist/testing.js +0 -439
  74. package/dist/testing.js.map +0 -7
  75. package/dist/testing.min.js.map +0 -7
  76. package/dist/what.js +0 -117
package/dist/index.js DELETED
@@ -1,3578 +0,0 @@
1
- import {
2
- _$createComponent,
3
- _$templateImpl,
4
- _setTextInsertHook,
5
- classList,
6
- delegateEvents,
7
- hydrate,
8
- insert,
9
- isHydrating,
10
- mapArray,
11
- on,
12
- setProp,
13
- spread,
14
- svgTemplate,
15
- template
16
- } from "./chunk-M7UEET5O.js";
17
- import {
18
- ErrorBoundary,
19
- For,
20
- Island,
21
- Match,
22
- Portal,
23
- Show,
24
- Suspense,
25
- Switch,
26
- __DEV__,
27
- __drainPreinstallBuffer,
28
- __setDevToolsHooks,
29
- batch,
30
- cls,
31
- computed,
32
- createRoot,
33
- debounce,
34
- each,
35
- effect,
36
- flushSync,
37
- getCurrentComponent,
38
- getOwner,
39
- lazy,
40
- memo,
41
- memo2,
42
- mount,
43
- onCleanup,
44
- runWithOwner,
45
- signal,
46
- style,
47
- throttle,
48
- transition,
49
- untrack,
50
- useClickOutside,
51
- useLocalStorage,
52
- useMediaQuery
53
- } from "./chunk-AW3BAPIK.js";
54
- import {
55
- Fragment,
56
- h,
57
- html
58
- } from "./chunk-AZP2EOGX.js";
59
-
60
- // packages/core/src/server-context.js
61
- var _current = null;
62
- function getServerContext() {
63
- return _current;
64
- }
65
- function setServerContext(ctx) {
66
- const prev = _current;
67
- _current = ctx;
68
- return prev;
69
- }
70
- function runWithServerContext(ctx, fn) {
71
- const prev = _current;
72
- _current = ctx;
73
- try {
74
- return fn();
75
- } finally {
76
- _current = prev;
77
- }
78
- }
79
-
80
- // packages/core/src/hydration-data.js
81
- var _cache;
82
- function __readHydrationData() {
83
- if (_cache !== void 0) return _cache;
84
- if (typeof document === "undefined") return _cache = null;
85
- const el = document.getElementById("__what_data");
86
- if (!el) return _cache = null;
87
- try {
88
- _cache = JSON.parse(el.textContent);
89
- } catch {
90
- _cache = null;
91
- }
92
- return _cache;
93
- }
94
- function __resetHydrationData() {
95
- _cache = void 0;
96
- }
97
- function getLoaderData() {
98
- const data = __readHydrationData();
99
- return data ? data.loaderData : void 0;
100
- }
101
- function getResource(key) {
102
- const data = __readHydrationData();
103
- return data && data.resources ? data.resources[key] : void 0;
104
- }
105
-
106
- // packages/core/src/hooks.js
107
- function useLoaderData() {
108
- if (typeof document === "undefined") {
109
- const ctx = getServerContext();
110
- return ctx ? ctx.loaderData : void 0;
111
- }
112
- return getLoaderData();
113
- }
114
- function getCtx(hookName) {
115
- const ctx = getCurrentComponent();
116
- if (!ctx) {
117
- throw new Error(
118
- `[what] ${hookName || "Hook"}() can only be called inside a component function. Did you call it outside of a component or in an async callback? If you need reactive state outside a component, use signal() directly.`
119
- );
120
- }
121
- return ctx;
122
- }
123
- function getHook(ctx) {
124
- const index = ctx.hookIndex++;
125
- return { index, exists: index < ctx.hooks.length };
126
- }
127
- function useState(initial) {
128
- const ctx = getCtx("useState");
129
- const { index, exists } = getHook(ctx);
130
- if (!exists) {
131
- const s2 = signal(typeof initial === "function" ? initial() : initial);
132
- ctx.hooks[index] = s2;
133
- }
134
- const s = ctx.hooks[index];
135
- return [s, s.set];
136
- }
137
- function useSignal(initial) {
138
- const ctx = getCtx("useSignal");
139
- const { index, exists } = getHook(ctx);
140
- if (!exists) {
141
- ctx.hooks[index] = signal(typeof initial === "function" ? initial() : initial);
142
- }
143
- return ctx.hooks[index];
144
- }
145
- function useComputed(fn) {
146
- const ctx = getCtx("useComputed");
147
- const { index, exists } = getHook(ctx);
148
- if (!exists) {
149
- ctx.hooks[index] = computed(fn);
150
- }
151
- return ctx.hooks[index];
152
- }
153
- function useEffect(fn, deps) {
154
- const ctx = getCtx("useEffect");
155
- const { index, exists } = getHook(ctx);
156
- if (!exists) {
157
- ctx.hooks[index] = { cleanup: null, dispose: null };
158
- }
159
- if (__DEV__ && Array.isArray(deps) && deps.length > 0) {
160
- for (let i = 0; i < deps.length; i++) {
161
- const dep = deps[i];
162
- if (dep != null && typeof dep !== "function") {
163
- console.warn(
164
- `[what] useEffect dep at index ${i} is not a function. Did you mean to pass a signal? Use count instead of count()`
165
- );
166
- }
167
- }
168
- }
169
- const hook = ctx.hooks[index];
170
- if (hook.dispose) return;
171
- if (deps === void 0) {
172
- queueMicrotask(() => {
173
- if (ctx.disposed) return;
174
- hook.dispose = effect(() => {
175
- if (hook.cleanup) {
176
- try {
177
- hook.cleanup();
178
- } catch (e) {
179
- }
180
- hook.cleanup = null;
181
- }
182
- const result = fn();
183
- if (typeof result === "function") hook.cleanup = result;
184
- });
185
- ctx.effects = ctx.effects || [];
186
- ctx.effects.push(hook.dispose);
187
- });
188
- } else if (deps.length === 0) {
189
- queueMicrotask(() => {
190
- if (ctx.disposed) return;
191
- const result = fn();
192
- if (typeof result === "function") hook.cleanup = result;
193
- });
194
- hook.dispose = true;
195
- } else {
196
- queueMicrotask(() => {
197
- if (ctx.disposed) return;
198
- hook.dispose = effect(() => {
199
- for (let i = 0; i < deps.length; i++) {
200
- const dep = deps[i];
201
- if (typeof dep === "function" && dep._signal) {
202
- dep();
203
- }
204
- }
205
- if (hook.cleanup) {
206
- try {
207
- hook.cleanup();
208
- } catch (e) {
209
- }
210
- hook.cleanup = null;
211
- }
212
- const result = untrack(() => fn());
213
- if (typeof result === "function") hook.cleanup = result;
214
- });
215
- ctx.effects = ctx.effects || [];
216
- ctx.effects.push(hook.dispose);
217
- });
218
- }
219
- }
220
- function useMemo(fn, deps) {
221
- const ctx = getCtx("useMemo");
222
- const { index, exists } = getHook(ctx);
223
- if (!exists) {
224
- ctx.hooks[index] = { computed: computed(fn) };
225
- }
226
- return ctx.hooks[index].computed;
227
- }
228
- function useCallback(fn, deps) {
229
- const ctx = getCtx("useCallback");
230
- const { index, exists } = getHook(ctx);
231
- if (!exists) {
232
- ctx.hooks[index] = { callback: fn };
233
- }
234
- return ctx.hooks[index].callback;
235
- }
236
- function useRef(initial) {
237
- const ctx = getCtx("useRef");
238
- const { index, exists } = getHook(ctx);
239
- if (!exists) {
240
- ctx.hooks[index] = { current: initial };
241
- }
242
- return ctx.hooks[index];
243
- }
244
- function useContext(context) {
245
- let ctx = getCurrentComponent();
246
- if (__DEV__ && !ctx) {
247
- console.warn(
248
- `[what] useContext(${context?.displayName || "Context"}) called outside of component render. useContext must be called during component rendering, not inside effects or event handlers. Store the context value in a variable during render and use that variable in your callback.`
249
- );
250
- }
251
- while (ctx) {
252
- if (ctx._contextValues && ctx._contextValues.has(context)) {
253
- const val = ctx._contextValues.get(context);
254
- return val && val._signal ? val() : val;
255
- }
256
- ctx = ctx._parentCtx;
257
- }
258
- return context._defaultValue;
259
- }
260
- function createContext(defaultValue) {
261
- const context = {
262
- _defaultValue: defaultValue,
263
- Provider: ({ value, children }) => {
264
- const ctx = getCtx("Context.Provider");
265
- if (!ctx._contextValues) ctx._contextValues = /* @__PURE__ */ new Map();
266
- if (!ctx._contextSignals) ctx._contextSignals = /* @__PURE__ */ new Map();
267
- if (!ctx._contextSignals.has(context)) {
268
- const s = signal(value);
269
- ctx._contextSignals.set(context, s);
270
- ctx._contextValues.set(context, s);
271
- } else {
272
- ctx._contextSignals.get(context).set(value);
273
- }
274
- return children;
275
- },
276
- // React-compatible Consumer: <Context.Consumer>{value => ...}</Context.Consumer>
277
- Consumer: ({ children }) => {
278
- const value = useContext(context);
279
- return typeof children === "function" ? children(value) : children;
280
- }
281
- };
282
- return context;
283
- }
284
- function useReducer(reducer, initialState, init) {
285
- const ctx = getCtx("useReducer");
286
- const { index, exists } = getHook(ctx);
287
- if (!exists) {
288
- const initial = init ? init(initialState) : initialState;
289
- const s = signal(initial);
290
- const dispatch = (action) => {
291
- s.set((prev) => reducer(prev, action));
292
- };
293
- ctx.hooks[index] = { signal: s, dispatch };
294
- }
295
- const hook = ctx.hooks[index];
296
- return [hook.signal, hook.dispatch];
297
- }
298
- function onMount(fn) {
299
- const ctx = getCtx("onMount");
300
- if (!ctx.mounted) {
301
- ctx._mountCallbacks = ctx._mountCallbacks || [];
302
- ctx._mountCallbacks.push(fn);
303
- }
304
- }
305
- function onCleanup2(fn) {
306
- const ctx = getCtx("onCleanup");
307
- ctx._cleanupCallbacks = ctx._cleanupCallbacks || [];
308
- ctx._cleanupCallbacks.push(fn);
309
- }
310
- function createResource(fetcher, options = {}) {
311
- if (typeof document === "undefined") {
312
- const ctx2 = getServerContext();
313
- if (ctx2) {
314
- const key = options.key != null ? options.key : `__r${ctx2.resourceCounter++}`;
315
- const cached = ctx2.resources.get(key);
316
- if (cached && cached.status === "ready") {
317
- const accessor = () => cached.value;
318
- return [accessor, { loading: () => false, error: () => null, refetch: () => {
319
- }, mutate: () => {
320
- } }];
321
- }
322
- if (cached && cached.status === "error") {
323
- const accessor = () => void 0;
324
- return [accessor, { loading: () => false, error: () => cached.error, refetch: () => {
325
- }, mutate: () => {
326
- } }];
327
- }
328
- if (!cached) {
329
- const promise = Promise.resolve().then(() => fetcher(options.source ?? true, {})).then((v) => {
330
- ctx2.resources.set(key, { status: "ready", value: v });
331
- }).catch((e) => {
332
- ctx2.resources.set(key, { status: "error", error: e });
333
- });
334
- ctx2.resources.set(key, { status: "pending", promise });
335
- throw promise;
336
- }
337
- throw cached.promise;
338
- }
339
- if (options.initialValue != null) {
340
- const accessor = () => options.initialValue;
341
- return [accessor, { loading: () => false, error: () => null, refetch: () => {
342
- }, mutate: () => {
343
- } }];
344
- }
345
- throw Promise.resolve().then(() => fetcher(options.source ?? true, {}));
346
- }
347
- let seeded = options.initialValue;
348
- if (seeded == null && options.key != null) {
349
- const fromPayload = getResource(options.key);
350
- if (fromPayload !== void 0) seeded = fromPayload;
351
- }
352
- const data = signal(seeded ?? null);
353
- const loading = signal(seeded == null);
354
- const error = signal(null);
355
- let controller = null;
356
- const refetch = async (source) => {
357
- if (controller) controller.abort();
358
- controller = new AbortController();
359
- const { signal: abortSignal } = controller;
360
- loading.set(true);
361
- error.set(null);
362
- try {
363
- const result = await fetcher(source, { signal: abortSignal });
364
- if (!abortSignal.aborted) {
365
- batch(() => {
366
- data.set(result);
367
- loading.set(false);
368
- });
369
- }
370
- } catch (e) {
371
- if (!abortSignal.aborted) {
372
- batch(() => {
373
- error.set(e);
374
- loading.set(false);
375
- });
376
- }
377
- }
378
- };
379
- const mutate2 = (value) => {
380
- data.set(typeof value === "function" ? value(data()) : value);
381
- };
382
- const ctx = getCurrentComponent?.();
383
- if (ctx) {
384
- ctx._cleanupCallbacks = ctx._cleanupCallbacks || [];
385
- ctx._cleanupCallbacks.push(() => {
386
- if (controller) controller.abort();
387
- });
388
- }
389
- if (seeded == null) {
390
- refetch(options.source);
391
- }
392
- return [data, { loading, error, refetch, mutate: mutate2 }];
393
- }
394
-
395
- // packages/core/src/store.js
396
- function derived(fn) {
397
- fn._storeComputed = true;
398
- return fn;
399
- }
400
- var _storeComputedWarned = false;
401
- function storeComputed(fn) {
402
- if (!_storeComputedWarned) {
403
- _storeComputedWarned = true;
404
- console.warn("[what] storeComputed() is deprecated. Use derived() instead.");
405
- }
406
- return derived(fn);
407
- }
408
- function createStore(definition) {
409
- const signals = {};
410
- const computeds = {};
411
- const actions = {};
412
- const state = {};
413
- for (const [key, value] of Object.entries(definition)) {
414
- if (typeof value === "function" && value._storeComputed) {
415
- if (__DEV__ && value.length === 0) {
416
- console.warn(
417
- `[what] derived() for "${key}" should accept the state parameter, e.g. derived(state => ...).`
418
- );
419
- }
420
- computeds[key] = value;
421
- } else if (typeof value === "function") {
422
- actions[key] = value;
423
- } else {
424
- signals[key] = signal(value);
425
- }
426
- }
427
- for (const [key, fn] of Object.entries(computeds)) {
428
- const proxy = new Proxy({}, {
429
- get(_, prop) {
430
- if (signals[prop]) return signals[prop]();
431
- if (computeds[prop]) return computeds[prop]();
432
- return void 0;
433
- }
434
- });
435
- computeds[key] = computed(() => fn(proxy));
436
- }
437
- for (const [key, fn] of Object.entries(actions)) {
438
- actions[key] = (...args) => {
439
- let result;
440
- batch(() => {
441
- const proxy = new Proxy({}, {
442
- get(_, prop) {
443
- if (signals[prop]) return signals[prop].peek();
444
- if (computeds[prop]) return computeds[prop].peek();
445
- if (actions[prop]) return actions[prop];
446
- return void 0;
447
- },
448
- set(_, prop, val) {
449
- if (signals[prop]) signals[prop].set(val);
450
- return true;
451
- }
452
- });
453
- result = fn.apply(proxy, args);
454
- });
455
- return result;
456
- };
457
- }
458
- return function useStore() {
459
- const result = {};
460
- for (const [key, s] of Object.entries(signals)) {
461
- Object.defineProperty(result, key, { get: () => s(), enumerable: true });
462
- }
463
- for (const [key, c] of Object.entries(computeds)) {
464
- Object.defineProperty(result, key, { get: () => c(), enumerable: true });
465
- }
466
- for (const [key, fn] of Object.entries(actions)) {
467
- result[key] = fn;
468
- }
469
- return result;
470
- };
471
- }
472
- var _atomWarned = false;
473
- function atom(initial) {
474
- if (!_atomWarned) {
475
- _atomWarned = true;
476
- console.warn("[what] atom() is deprecated. Use signal() directly instead.");
477
- }
478
- return signal(initial);
479
- }
480
-
481
- // packages/core/src/head.js
482
- var headState = {
483
- title: null,
484
- metas: /* @__PURE__ */ new Map(),
485
- links: /* @__PURE__ */ new Map()
486
- };
487
- function Head({ title, meta, link, children }) {
488
- if (typeof document === "undefined") {
489
- const ctx = getServerContext();
490
- if (ctx && ctx.head) writeToSink(ctx.head, { title, meta, link });
491
- return children ?? null;
492
- }
493
- if (title) {
494
- document.title = title;
495
- headState.title = title;
496
- }
497
- if (meta) {
498
- for (const attrs of Array.isArray(meta) ? meta : [meta]) {
499
- const key = attrs.name || attrs.property || attrs.httpEquiv || JSON.stringify(attrs);
500
- setHeadTag("meta", key, attrs);
501
- }
502
- }
503
- if (link) {
504
- for (const attrs of Array.isArray(link) ? link : [link]) {
505
- const key = attrs.rel + (attrs.href || "");
506
- setHeadTag("link", key, attrs);
507
- }
508
- }
509
- return children || null;
510
- }
511
- function metaKey(attrs) {
512
- return attrs.name || attrs.property || attrs.httpEquiv || JSON.stringify(attrs);
513
- }
514
- function writeToSink(sink, { title, meta, link }) {
515
- if (title != null) sink.title = title;
516
- if (meta) {
517
- for (const attrs of Array.isArray(meta) ? meta : [meta]) {
518
- sink.metas.set(metaKey(attrs), attrs);
519
- }
520
- }
521
- if (link) {
522
- for (const attrs of Array.isArray(link) ? link : [link]) {
523
- sink.links.set(attrs.rel + (attrs.href || ""), attrs);
524
- }
525
- }
526
- }
527
- function beginHeadCollection() {
528
- return { title: null, metas: /* @__PURE__ */ new Map(), links: /* @__PURE__ */ new Map() };
529
- }
530
- function endHeadCollection(sink) {
531
- if (!sink) return "";
532
- let out = "";
533
- if (sink.title != null) out += `<title>${escapeHtml(String(sink.title))}</title>`;
534
- for (const attrs of sink.metas.values()) out += renderHeadTag("meta", attrs);
535
- for (const attrs of sink.links.values()) out += renderHeadTag("link", attrs);
536
- return out;
537
- }
538
- function renderHeadTag(tag, attrs) {
539
- let s = `<${tag}`;
540
- for (const [k, v] of Object.entries(attrs)) {
541
- if (v == null || v === false) continue;
542
- const name = k === "httpEquiv" ? "http-equiv" : k;
543
- s += ` ${name}="${escapeHtml(String(v))}"`;
544
- }
545
- return s + ">";
546
- }
547
- function escapeHtml(str) {
548
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
549
- }
550
- function setHeadTag(tag, key, attrs) {
551
- const existing = document.head.querySelector(`[data-what-head="${key}"]`);
552
- if (existing) {
553
- updateElement(existing, attrs);
554
- return;
555
- }
556
- const el = document.createElement(tag);
557
- el.setAttribute("data-what-head", key);
558
- for (const [k, v] of Object.entries(attrs)) {
559
- el.setAttribute(k, v);
560
- }
561
- document.head.appendChild(el);
562
- }
563
- function updateElement(el, attrs) {
564
- for (const [k, v] of Object.entries(attrs)) {
565
- if (el.getAttribute(k) !== v) {
566
- el.setAttribute(k, v);
567
- }
568
- }
569
- }
570
- function clearHead() {
571
- const tags = document.head.querySelectorAll("[data-what-head]");
572
- for (const tag of tags) tag.remove();
573
- headState.metas.clear();
574
- headState.links.clear();
575
- }
576
-
577
- // packages/core/src/scheduler.js
578
- var readQueue = [];
579
- var writeQueue = [];
580
- var scheduled = false;
581
- function scheduleRead(fn) {
582
- readQueue.push(fn);
583
- schedule();
584
- return () => {
585
- const idx = readQueue.indexOf(fn);
586
- if (idx !== -1) readQueue.splice(idx, 1);
587
- };
588
- }
589
- function scheduleWrite(fn) {
590
- writeQueue.push(fn);
591
- schedule();
592
- return () => {
593
- const idx = writeQueue.indexOf(fn);
594
- if (idx !== -1) writeQueue.splice(idx, 1);
595
- };
596
- }
597
- function flushScheduler() {
598
- while (readQueue.length > 0) {
599
- const fn = readQueue.shift();
600
- try {
601
- fn();
602
- } catch (e) {
603
- console.error("[what] Scheduler read error:", e);
604
- }
605
- }
606
- while (writeQueue.length > 0) {
607
- const fn = writeQueue.shift();
608
- try {
609
- fn();
610
- } catch (e) {
611
- console.error("[what] Scheduler write error:", e);
612
- }
613
- }
614
- scheduled = false;
615
- }
616
- function schedule() {
617
- if (scheduled) return;
618
- scheduled = true;
619
- requestAnimationFrame(flushScheduler);
620
- }
621
- function measure(fn) {
622
- return new Promise((resolve) => {
623
- scheduleRead(() => {
624
- resolve(fn());
625
- });
626
- });
627
- }
628
- function mutate(fn) {
629
- return new Promise((resolve) => {
630
- scheduleWrite(() => {
631
- fn();
632
- resolve();
633
- });
634
- });
635
- }
636
- function useScheduledEffect(readFn, writeFn) {
637
- const effectKey = /* @__PURE__ */ Symbol("scheduledEffect");
638
- return effect(() => {
639
- raf(effectKey, () => {
640
- scheduleRead(() => {
641
- const data = readFn();
642
- if (writeFn) {
643
- scheduleWrite(() => writeFn(data));
644
- }
645
- });
646
- });
647
- });
648
- }
649
- function nextFrame() {
650
- let cancel;
651
- const promise = new Promise((resolve, reject) => {
652
- const id = requestAnimationFrame(resolve);
653
- cancel = () => {
654
- cancelAnimationFrame(id);
655
- reject(new Error("Cancelled"));
656
- };
657
- });
658
- promise.cancel = cancel;
659
- return promise;
660
- }
661
- var debouncedCallbacks = /* @__PURE__ */ new Map();
662
- function raf(key, fn) {
663
- if (debouncedCallbacks.has(key)) {
664
- debouncedCallbacks.set(key, fn);
665
- } else {
666
- debouncedCallbacks.set(key, fn);
667
- requestAnimationFrame(() => {
668
- const callback = debouncedCallbacks.get(key);
669
- debouncedCallbacks.delete(key);
670
- if (callback) callback();
671
- });
672
- }
673
- }
674
- var resizeObservers = /* @__PURE__ */ new WeakMap();
675
- var sharedResizeObserver = null;
676
- function onResize(element, callback) {
677
- if (typeof ResizeObserver === "undefined") {
678
- callback(element.getBoundingClientRect());
679
- return () => {
680
- };
681
- }
682
- if (!sharedResizeObserver) {
683
- sharedResizeObserver = new ResizeObserver((entries) => {
684
- scheduleRead(() => {
685
- for (const entry of entries) {
686
- const cb = resizeObservers.get(entry.target);
687
- if (cb) {
688
- cb(entry.contentRect);
689
- }
690
- }
691
- });
692
- });
693
- }
694
- resizeObservers.set(element, callback);
695
- sharedResizeObserver.observe(element);
696
- return () => {
697
- resizeObservers.delete(element);
698
- sharedResizeObserver.unobserve(element);
699
- };
700
- }
701
- function onIntersect(element, callback, options = {}) {
702
- if (typeof IntersectionObserver === "undefined") {
703
- callback({ isIntersecting: true, intersectionRatio: 1 });
704
- return () => {
705
- };
706
- }
707
- const observer = new IntersectionObserver((entries) => {
708
- scheduleRead(() => {
709
- for (const entry of entries) {
710
- callback(entry);
711
- }
712
- });
713
- }, options);
714
- observer.observe(element);
715
- return () => observer.disconnect();
716
- }
717
- function smoothScrollTo(element, options = {}) {
718
- const { duration = 300, easing = (t) => t * (2 - t) } = options;
719
- return new Promise((resolve) => {
720
- let startY;
721
- let targetY;
722
- let startTime;
723
- scheduleRead(() => {
724
- startY = window.scrollY;
725
- const rect = element.getBoundingClientRect();
726
- targetY = startY + rect.top;
727
- startTime = performance.now();
728
- tick();
729
- });
730
- function tick() {
731
- scheduleRead(() => {
732
- const elapsed = performance.now() - startTime;
733
- const progress = Math.min(elapsed / duration, 1);
734
- const easedProgress = easing(progress);
735
- const currentY = startY + (targetY - startY) * easedProgress;
736
- scheduleWrite(() => {
737
- window.scrollTo(0, currentY);
738
- if (progress < 1) {
739
- requestAnimationFrame(tick);
740
- } else {
741
- resolve();
742
- }
743
- });
744
- });
745
- }
746
- });
747
- }
748
-
749
- // packages/core/src/animation.js
750
- function scopedEffect(fn) {
751
- const ctx = getCurrentComponent?.();
752
- const dispose = effect(fn);
753
- if (ctx) ctx.effects.push(dispose);
754
- return dispose;
755
- }
756
- function spring(initialValue, options = {}) {
757
- const {
758
- stiffness = 100,
759
- damping = 10,
760
- mass = 1,
761
- precision = 0.01
762
- } = options;
763
- const current = signal(initialValue);
764
- const target = signal(initialValue);
765
- const velocity = signal(0);
766
- const isAnimating = signal(false);
767
- let rafId = null;
768
- let lastTime = null;
769
- function tick(time) {
770
- if (lastTime === null) {
771
- lastTime = time;
772
- rafId = requestAnimationFrame(tick);
773
- return;
774
- }
775
- const dt = Math.min((time - lastTime) / 1e3, 0.064);
776
- lastTime = time;
777
- const currentVal = current.peek();
778
- const targetVal = target.peek();
779
- const vel = velocity.peek();
780
- const displacement = currentVal - targetVal;
781
- const springForce = -stiffness * displacement;
782
- const dampingForce = -damping * vel;
783
- const acceleration = (springForce + dampingForce) / mass;
784
- const newVelocity = vel + acceleration * dt;
785
- const newValue = currentVal + newVelocity * dt;
786
- batch(() => {
787
- velocity.set(newVelocity);
788
- current.set(newValue);
789
- });
790
- if (Math.abs(newVelocity) < precision && Math.abs(displacement) < precision) {
791
- batch(() => {
792
- current.set(targetVal);
793
- velocity.set(0);
794
- isAnimating.set(false);
795
- });
796
- rafId = null;
797
- lastTime = null;
798
- return;
799
- }
800
- rafId = requestAnimationFrame(tick);
801
- }
802
- function set(newTarget) {
803
- target.set(newTarget);
804
- if (rafId === null) {
805
- isAnimating.set(true);
806
- lastTime = null;
807
- rafId = requestAnimationFrame(tick);
808
- }
809
- }
810
- function stop() {
811
- if (rafId) {
812
- cancelAnimationFrame(rafId);
813
- rafId = null;
814
- }
815
- isAnimating.set(false);
816
- lastTime = null;
817
- }
818
- function snap(value) {
819
- stop();
820
- batch(() => {
821
- current.set(value);
822
- target.set(value);
823
- velocity.set(0);
824
- });
825
- }
826
- const ctx = getCurrentComponent?.();
827
- if (ctx) {
828
- ctx._cleanupCallbacks = ctx._cleanupCallbacks || [];
829
- ctx._cleanupCallbacks.push(stop);
830
- }
831
- return {
832
- current: () => current(),
833
- target: () => target(),
834
- velocity: () => velocity(),
835
- isAnimating: () => isAnimating(),
836
- set,
837
- stop,
838
- snap,
839
- subscribe: current.subscribe
840
- };
841
- }
842
- function tween(from, to, options = {}) {
843
- const {
844
- duration = 300,
845
- easing = (t) => t * (2 - t),
846
- // easeOutQuad
847
- onUpdate,
848
- onComplete
849
- } = options;
850
- const progress = signal(0);
851
- const value = signal(from);
852
- const isAnimating = signal(true);
853
- let startTime = null;
854
- let rafId = null;
855
- function tick(time) {
856
- if (startTime === null) startTime = time;
857
- const elapsed = time - startTime;
858
- const t = Math.min(elapsed / duration, 1);
859
- const easedT = easing(t);
860
- const currentValue = from + (to - from) * easedT;
861
- batch(() => {
862
- progress.set(t);
863
- value.set(currentValue);
864
- });
865
- if (onUpdate) onUpdate(currentValue, t);
866
- if (t < 1) {
867
- rafId = requestAnimationFrame(tick);
868
- } else {
869
- isAnimating.set(false);
870
- if (onComplete) onComplete();
871
- }
872
- }
873
- rafId = requestAnimationFrame(tick);
874
- return {
875
- progress: () => progress(),
876
- value: () => value(),
877
- isAnimating: () => isAnimating(),
878
- cancel: () => {
879
- if (rafId) cancelAnimationFrame(rafId);
880
- isAnimating.set(false);
881
- },
882
- subscribe: value.subscribe
883
- };
884
- }
885
- var easings = {
886
- linear: (t) => t,
887
- easeInQuad: (t) => t * t,
888
- easeOutQuad: (t) => t * (2 - t),
889
- easeInOutQuad: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
890
- easeInCubic: (t) => t * t * t,
891
- easeOutCubic: (t) => --t * t * t + 1,
892
- easeInOutCubic: (t) => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
893
- easeInElastic: (t) => t === 0 ? 0 : t === 1 ? 1 : -Math.pow(2, 10 * t - 10) * Math.sin((t * 10 - 10.75) * (2 * Math.PI / 3)),
894
- easeOutElastic: (t) => t === 0 ? 0 : t === 1 ? 1 : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * (2 * Math.PI / 3)) + 1,
895
- easeOutBounce: (t) => {
896
- const n1 = 7.5625;
897
- const d1 = 2.75;
898
- if (t < 1 / d1) return n1 * t * t;
899
- if (t < 2 / d1) return n1 * (t -= 1.5 / d1) * t + 0.75;
900
- if (t < 2.5 / d1) return n1 * (t -= 2.25 / d1) * t + 0.9375;
901
- return n1 * (t -= 2.625 / d1) * t + 0.984375;
902
- }
903
- };
904
- function useTransition(options = {}) {
905
- const { duration = 300, easing = easings.easeOutQuad } = options;
906
- const isTransitioning = signal(false);
907
- const progress = signal(0);
908
- async function start(callback) {
909
- isTransitioning.set(true);
910
- progress.set(0);
911
- return new Promise((resolve) => {
912
- const startTime = performance.now();
913
- function tick(time) {
914
- const elapsed = time - startTime;
915
- const t = Math.min(elapsed / duration, 1);
916
- progress.set(easing(t));
917
- if (t < 1) {
918
- requestAnimationFrame(tick);
919
- } else {
920
- isTransitioning.set(false);
921
- if (callback) callback();
922
- resolve();
923
- }
924
- }
925
- requestAnimationFrame(tick);
926
- });
927
- }
928
- return {
929
- isTransitioning: () => isTransitioning(),
930
- progress: () => progress(),
931
- start
932
- };
933
- }
934
- function useGesture(element, handlers = {}) {
935
- const {
936
- onDrag,
937
- onDragStart,
938
- onDragEnd,
939
- onPinch,
940
- onSwipe,
941
- onTap,
942
- onLongPress,
943
- preventDefault = false
944
- // Set to true to allow e.preventDefault() in touch handlers
945
- } = handlers;
946
- const state = {
947
- isDragging: signal(false),
948
- startX: 0,
949
- startY: 0,
950
- currentX: signal(0),
951
- currentY: signal(0),
952
- deltaX: signal(0),
953
- deltaY: signal(0),
954
- velocity: signal({ x: 0, y: 0 })
955
- };
956
- let lastTime = 0;
957
- let lastX = 0;
958
- let lastY = 0;
959
- let longPressTimer = null;
960
- function handleStart(e) {
961
- const touch = e.touches ? e.touches[0] : e;
962
- state.startX = touch.clientX;
963
- state.startY = touch.clientY;
964
- lastX = touch.clientX;
965
- lastY = touch.clientY;
966
- lastTime = performance.now();
967
- state.isDragging.set(true);
968
- if (onDragStart) onDragStart({ x: state.startX, y: state.startY });
969
- if (onLongPress) {
970
- longPressTimer = setTimeout(() => {
971
- if (state.isDragging.peek()) {
972
- onLongPress({ x: lastX, y: lastY });
973
- }
974
- }, 500);
975
- }
976
- }
977
- function handleMove(e) {
978
- if (!state.isDragging.peek()) return;
979
- const touch = e.touches ? e.touches[0] : e;
980
- const x = touch.clientX;
981
- const y = touch.clientY;
982
- const now = performance.now();
983
- const dt = now - lastTime;
984
- batch(() => {
985
- state.currentX.set(x);
986
- state.currentY.set(y);
987
- state.deltaX.set(x - state.startX);
988
- state.deltaY.set(y - state.startY);
989
- if (dt > 0) {
990
- state.velocity.set({
991
- x: (x - lastX) / dt * 1e3,
992
- y: (y - lastY) / dt * 1e3
993
- });
994
- }
995
- });
996
- lastX = x;
997
- lastY = y;
998
- lastTime = now;
999
- if (longPressTimer) {
1000
- const distance = Math.sqrt(state.deltaX.peek() ** 2 + state.deltaY.peek() ** 2);
1001
- if (distance > 10) {
1002
- clearTimeout(longPressTimer);
1003
- longPressTimer = null;
1004
- }
1005
- }
1006
- if (onDrag) {
1007
- onDrag({
1008
- x,
1009
- y,
1010
- deltaX: state.deltaX.peek(),
1011
- deltaY: state.deltaY.peek(),
1012
- velocity: state.velocity.peek()
1013
- });
1014
- }
1015
- }
1016
- function handleEnd(e) {
1017
- if (!state.isDragging.peek()) return;
1018
- if (longPressTimer) {
1019
- clearTimeout(longPressTimer);
1020
- longPressTimer = null;
1021
- }
1022
- const deltaX = state.deltaX.peek();
1023
- const deltaY = state.deltaY.peek();
1024
- const velocity = state.velocity.peek();
1025
- const distance = Math.sqrt(deltaX ** 2 + deltaY ** 2);
1026
- if (distance < 10 && onTap) {
1027
- onTap({ x: state.startX, y: state.startY });
1028
- }
1029
- if (onSwipe && (Math.abs(velocity.x) > 500 || Math.abs(velocity.y) > 500)) {
1030
- const direction = Math.abs(velocity.x) > Math.abs(velocity.y) ? velocity.x > 0 ? "right" : "left" : velocity.y > 0 ? "down" : "up";
1031
- onSwipe({ direction, velocity });
1032
- }
1033
- if (onDragEnd) {
1034
- onDragEnd({
1035
- deltaX,
1036
- deltaY,
1037
- velocity
1038
- });
1039
- }
1040
- state.isDragging.set(false);
1041
- }
1042
- let initialPinchDistance = null;
1043
- function handlePinchMove(e) {
1044
- if (!onPinch || e.touches.length !== 2) return;
1045
- const touch1 = e.touches[0];
1046
- const touch2 = e.touches[1];
1047
- const distance = Math.sqrt(
1048
- (touch2.clientX - touch1.clientX) ** 2 + (touch2.clientY - touch1.clientY) ** 2
1049
- );
1050
- if (initialPinchDistance === null) {
1051
- initialPinchDistance = distance;
1052
- }
1053
- const scale = distance / initialPinchDistance;
1054
- const centerX = (touch1.clientX + touch2.clientX) / 2;
1055
- const centerY = (touch1.clientY + touch2.clientY) / 2;
1056
- onPinch({ scale, centerX, centerY });
1057
- }
1058
- function handlePinchEnd() {
1059
- initialPinchDistance = null;
1060
- }
1061
- if (typeof element === "function") {
1062
- scopedEffect(() => {
1063
- const el = untrack(element);
1064
- if (!el) return;
1065
- return attachListeners(el);
1066
- });
1067
- } else if (element?.current !== void 0) {
1068
- scopedEffect(() => {
1069
- const el = element.current;
1070
- if (!el) return;
1071
- return attachListeners(el);
1072
- });
1073
- } else if (element) {
1074
- attachListeners(element);
1075
- }
1076
- function attachListeners(el) {
1077
- el.addEventListener("mousedown", handleStart);
1078
- el.addEventListener("touchstart", handleStart, { passive: !preventDefault });
1079
- window.addEventListener("mousemove", handleMove);
1080
- window.addEventListener("touchmove", handlePinchMove);
1081
- window.addEventListener("touchmove", handleMove);
1082
- window.addEventListener("mouseup", handleEnd);
1083
- window.addEventListener("touchend", handleEnd);
1084
- window.addEventListener("touchend", handlePinchEnd);
1085
- return () => {
1086
- el.removeEventListener("mousedown", handleStart);
1087
- el.removeEventListener("touchstart", handleStart);
1088
- window.removeEventListener("mousemove", handleMove);
1089
- window.removeEventListener("touchmove", handlePinchMove);
1090
- window.removeEventListener("touchmove", handleMove);
1091
- window.removeEventListener("mouseup", handleEnd);
1092
- window.removeEventListener("touchend", handleEnd);
1093
- window.removeEventListener("touchend", handlePinchEnd);
1094
- };
1095
- }
1096
- return state;
1097
- }
1098
- function useAnimatedValue(initialValue) {
1099
- const value = signal(initialValue);
1100
- const animations = [];
1101
- return {
1102
- value: () => value(),
1103
- setValue: (v) => value.set(v),
1104
- // Spring to target
1105
- spring(toValue, config = {}) {
1106
- const s = spring(value.peek(), config);
1107
- s.set(toValue);
1108
- const dispose = effect(() => {
1109
- value.set(s.current());
1110
- });
1111
- return {
1112
- stop: () => {
1113
- s.stop();
1114
- dispose();
1115
- }
1116
- };
1117
- },
1118
- // Tween to target
1119
- timing(toValue, config = {}) {
1120
- const t = tween(value.peek(), toValue, {
1121
- ...config,
1122
- onUpdate: (v) => value.set(v)
1123
- });
1124
- return {
1125
- stop: () => t.cancel()
1126
- };
1127
- },
1128
- // Interpolate value
1129
- interpolate(inputRange, outputRange) {
1130
- return () => {
1131
- const v = value();
1132
- for (let i = 0; i < inputRange.length - 1; i++) {
1133
- if (v >= inputRange[i] && v <= inputRange[i + 1]) {
1134
- const t = (v - inputRange[i]) / (inputRange[i + 1] - inputRange[i]);
1135
- return outputRange[i] + (outputRange[i + 1] - outputRange[i]) * t;
1136
- }
1137
- }
1138
- if (v <= inputRange[0]) return outputRange[0];
1139
- return outputRange[outputRange.length - 1];
1140
- };
1141
- },
1142
- subscribe: value.subscribe
1143
- };
1144
- }
1145
- function createTransitionClasses(name) {
1146
- return {
1147
- enter: `${name}-enter`,
1148
- enterActive: `${name}-enter-active`,
1149
- enterDone: `${name}-enter-done`,
1150
- exit: `${name}-exit`,
1151
- exitActive: `${name}-exit-active`,
1152
- exitDone: `${name}-exit-done`
1153
- };
1154
- }
1155
- async function cssTransition(element, name, type = "enter", duration = 300) {
1156
- const classes = createTransitionClasses(name);
1157
- return new Promise((resolve) => {
1158
- scheduleWrite(() => {
1159
- element.classList.add(classes[type]);
1160
- scheduleRead(() => {
1161
- element.offsetHeight;
1162
- scheduleWrite(() => {
1163
- element.classList.add(classes[`${type}Active`]);
1164
- setTimeout(() => {
1165
- scheduleWrite(() => {
1166
- element.classList.remove(classes[type], classes[`${type}Active`]);
1167
- element.classList.add(classes[`${type}Done`]);
1168
- resolve();
1169
- });
1170
- }, duration);
1171
- });
1172
- });
1173
- });
1174
- });
1175
- }
1176
-
1177
- // packages/core/src/a11y.js
1178
- var focusedElement = signal(null);
1179
- if (typeof document !== "undefined") {
1180
- document.addEventListener("focusin", (e) => {
1181
- focusedElement.set(e.target);
1182
- });
1183
- }
1184
- function useFocus() {
1185
- return {
1186
- current: () => focusedElement(),
1187
- focus: (element) => element?.focus(),
1188
- blur: () => document.activeElement?.blur()
1189
- };
1190
- }
1191
- function useFocusRestore() {
1192
- const previousFocusRef = { current: null };
1193
- function capture(target) {
1194
- if (typeof document === "undefined") return;
1195
- previousFocusRef.current = target || document.activeElement || null;
1196
- }
1197
- function restore(fallbackTarget) {
1198
- const target = previousFocusRef.current || fallbackTarget;
1199
- if (target && typeof target.focus === "function") {
1200
- target.focus();
1201
- }
1202
- }
1203
- return {
1204
- capture,
1205
- restore,
1206
- previous: () => previousFocusRef.current
1207
- };
1208
- }
1209
- function useFocusTrap(containerRef) {
1210
- let previousFocus = null;
1211
- function activate() {
1212
- if (typeof document === "undefined") return;
1213
- previousFocus = document.activeElement;
1214
- const container = containerRef.current || containerRef;
1215
- if (!container || typeof container.querySelectorAll !== "function") return;
1216
- const focusables = getFocusableElements(container);
1217
- if (focusables.length === 0) return;
1218
- focusables[0].focus();
1219
- function handleKeydown(e) {
1220
- if (e.key !== "Tab") return;
1221
- const focusables2 = getFocusableElements(container);
1222
- const first = focusables2[0];
1223
- const last = focusables2[focusables2.length - 1];
1224
- if (e.shiftKey) {
1225
- if (document.activeElement === first) {
1226
- e.preventDefault();
1227
- last.focus();
1228
- }
1229
- } else {
1230
- if (document.activeElement === last) {
1231
- e.preventDefault();
1232
- first.focus();
1233
- }
1234
- }
1235
- }
1236
- container.addEventListener("keydown", handleKeydown);
1237
- return () => {
1238
- container.removeEventListener("keydown", handleKeydown);
1239
- };
1240
- }
1241
- function deactivate() {
1242
- if (previousFocus && typeof previousFocus.focus === "function") {
1243
- previousFocus.focus();
1244
- }
1245
- }
1246
- return { activate, deactivate };
1247
- }
1248
- function getFocusableElements(container) {
1249
- const selector = [
1250
- "button:not([disabled])",
1251
- "a[href]",
1252
- "input:not([disabled])",
1253
- "select:not([disabled])",
1254
- "textarea:not([disabled])",
1255
- '[tabindex]:not([tabindex="-1"])'
1256
- ].join(",");
1257
- return Array.from(container.querySelectorAll(selector)).filter((el) => {
1258
- return el.offsetParent !== null;
1259
- });
1260
- }
1261
- function FocusTrap({ children, active = true }) {
1262
- const containerRef = { current: null };
1263
- const refVersion = signal(0);
1264
- const trap = useFocusTrap(containerRef);
1265
- let trapCleanup = null;
1266
- const setRef = (el) => {
1267
- containerRef.current = el;
1268
- refVersion.set((v) => v + 1);
1269
- };
1270
- const dispose = effect(() => {
1271
- refVersion();
1272
- if (trapCleanup) {
1273
- trapCleanup();
1274
- trapCleanup = null;
1275
- trap.deactivate();
1276
- }
1277
- if (active && containerRef.current) {
1278
- trapCleanup = trap.activate();
1279
- return () => {
1280
- trapCleanup?.();
1281
- trapCleanup = null;
1282
- trap.deactivate();
1283
- };
1284
- }
1285
- });
1286
- const ctx = getCurrentComponent?.();
1287
- if (ctx) {
1288
- ctx._cleanupCallbacks = ctx._cleanupCallbacks || [];
1289
- ctx._cleanupCallbacks.push(() => {
1290
- dispose();
1291
- trapCleanup?.();
1292
- trapCleanup = null;
1293
- trap.deactivate();
1294
- });
1295
- }
1296
- return h("div", { ref: setRef }, children);
1297
- }
1298
- var announcer = null;
1299
- var announcerId = 0;
1300
- function getAnnouncer() {
1301
- if (typeof document === "undefined") return null;
1302
- if (!announcer) {
1303
- announcer = document.createElement("div");
1304
- announcer.id = "what-announcer";
1305
- announcer.setAttribute("aria-live", "polite");
1306
- announcer.setAttribute("aria-atomic", "true");
1307
- announcer.style.cssText = `
1308
- position: absolute;
1309
- width: 1px;
1310
- height: 1px;
1311
- padding: 0;
1312
- margin: -1px;
1313
- overflow: hidden;
1314
- clip: rect(0, 0, 0, 0);
1315
- white-space: nowrap;
1316
- border: 0;
1317
- `;
1318
- document.body.appendChild(announcer);
1319
- }
1320
- return announcer;
1321
- }
1322
- function announce(message, options = {}) {
1323
- const { priority = "polite", timeout = 1e3 } = options;
1324
- const announcer2 = getAnnouncer();
1325
- if (!announcer2) return;
1326
- announcer2.setAttribute("aria-live", priority);
1327
- const id = ++announcerId;
1328
- announcer2.textContent = "";
1329
- requestAnimationFrame(() => {
1330
- if (announcerId === id) {
1331
- announcer2.textContent = message;
1332
- }
1333
- });
1334
- setTimeout(() => {
1335
- if (announcerId === id) {
1336
- announcer2.textContent = "";
1337
- }
1338
- }, timeout);
1339
- }
1340
- function announceAssertive(message) {
1341
- return announce(message, { priority: "assertive" });
1342
- }
1343
- function SkipLink({ href = "#main", children = "Skip to content" }) {
1344
- return h("a", {
1345
- href,
1346
- class: "what-skip-link",
1347
- onClick: (e) => {
1348
- e.preventDefault();
1349
- const target = document.querySelector(href);
1350
- if (target) {
1351
- target.focus();
1352
- target.scrollIntoView();
1353
- }
1354
- },
1355
- style: {
1356
- position: "absolute",
1357
- top: "-40px",
1358
- left: "0",
1359
- padding: "8px",
1360
- background: "#000",
1361
- color: "#fff",
1362
- textDecoration: "none",
1363
- zIndex: "10000"
1364
- },
1365
- onFocus: (e) => {
1366
- e.target.style.top = "0";
1367
- },
1368
- onBlur: (e) => {
1369
- e.target.style.top = "-40px";
1370
- }
1371
- }, children);
1372
- }
1373
- function useAriaExpanded(initialExpanded = false) {
1374
- const expanded = signal(initialExpanded);
1375
- return {
1376
- expanded: () => expanded(),
1377
- toggle: () => expanded.set(!expanded.peek()),
1378
- open: () => expanded.set(true),
1379
- close: () => expanded.set(false),
1380
- buttonProps: () => ({
1381
- "aria-expanded": expanded(),
1382
- onClick: () => expanded.set(!expanded.peek())
1383
- }),
1384
- panelProps: () => ({
1385
- hidden: !expanded()
1386
- })
1387
- };
1388
- }
1389
- function useAriaSelected(initialSelected = null) {
1390
- const selected = signal(initialSelected);
1391
- return {
1392
- selected: () => selected(),
1393
- select: (value) => selected.set(value),
1394
- isSelected: (value) => selected() === value,
1395
- itemProps: (value) => ({
1396
- "aria-selected": selected() === value,
1397
- onClick: () => selected.set(value)
1398
- })
1399
- };
1400
- }
1401
- function useAriaChecked(initialChecked = false) {
1402
- const checked = signal(initialChecked);
1403
- return {
1404
- checked: () => checked(),
1405
- toggle: () => checked.set(!checked.peek()),
1406
- set: (value) => checked.set(value),
1407
- checkboxProps: () => ({
1408
- role: "checkbox",
1409
- "aria-checked": checked(),
1410
- tabIndex: 0,
1411
- onClick: () => checked.set(!checked.peek()),
1412
- onKeyDown: (e) => {
1413
- if (e.key === " " || e.key === "Enter") {
1414
- e.preventDefault();
1415
- checked.set(!checked.peek());
1416
- }
1417
- }
1418
- })
1419
- };
1420
- }
1421
- function useRovingTabIndex(itemCountOrSignal) {
1422
- const getCount = typeof itemCountOrSignal === "function" ? itemCountOrSignal : () => itemCountOrSignal;
1423
- const focusIndex = signal(0);
1424
- function handleKeyDown(e) {
1425
- const count = getCount();
1426
- if (count <= 0) return;
1427
- switch (e.key) {
1428
- case "ArrowDown":
1429
- case "ArrowRight":
1430
- e.preventDefault();
1431
- focusIndex.set((focusIndex.peek() + 1) % count);
1432
- break;
1433
- case "ArrowUp":
1434
- case "ArrowLeft":
1435
- e.preventDefault();
1436
- focusIndex.set((focusIndex.peek() - 1 + count) % count);
1437
- break;
1438
- case "Home":
1439
- e.preventDefault();
1440
- focusIndex.set(0);
1441
- break;
1442
- case "End":
1443
- e.preventDefault();
1444
- focusIndex.set(count - 1);
1445
- break;
1446
- }
1447
- }
1448
- return {
1449
- focusIndex: () => focusIndex(),
1450
- setFocusIndex: (i) => focusIndex.set(i),
1451
- getItemProps: (index) => ({
1452
- tabIndex: focusIndex() === index ? 0 : -1,
1453
- onKeyDown: handleKeyDown,
1454
- onFocus: () => focusIndex.set(index)
1455
- }),
1456
- containerProps: () => ({
1457
- role: "listbox"
1458
- })
1459
- };
1460
- }
1461
- function VisuallyHidden({ children, as = "span" }) {
1462
- return h(as, {
1463
- style: {
1464
- position: "absolute",
1465
- width: "1px",
1466
- height: "1px",
1467
- padding: "0",
1468
- margin: "-1px",
1469
- overflow: "hidden",
1470
- clip: "rect(0, 0, 0, 0)",
1471
- whiteSpace: "nowrap",
1472
- border: "0"
1473
- }
1474
- }, children);
1475
- }
1476
- function LiveRegion({ children, priority = "polite", atomic = true }) {
1477
- return h("div", {
1478
- "aria-live": priority,
1479
- "aria-atomic": atomic
1480
- }, children);
1481
- }
1482
- var idCounter = 0;
1483
- function useId(prefix = "what") {
1484
- const id = `${prefix}-${++idCounter}`;
1485
- return () => id;
1486
- }
1487
- function useIds(count, prefix = "what") {
1488
- const ids = [];
1489
- for (let i = 0; i < count; i++) {
1490
- ids.push(`${prefix}-${++idCounter}`);
1491
- }
1492
- return ids;
1493
- }
1494
- function useDescribedBy(description) {
1495
- const id = useId("desc");
1496
- return {
1497
- descriptionId: id,
1498
- descriptionProps: () => ({
1499
- id: id(),
1500
- style: { display: "none" }
1501
- }),
1502
- describedByProps: () => ({
1503
- "aria-describedby": id()
1504
- }),
1505
- Description: () => h("div", {
1506
- id: id(),
1507
- style: { display: "none" }
1508
- }, description)
1509
- };
1510
- }
1511
- function useLabelledBy(label) {
1512
- const id = useId("label");
1513
- return {
1514
- labelId: id,
1515
- labelProps: () => ({
1516
- id: id()
1517
- }),
1518
- labelledByProps: () => ({
1519
- "aria-labelledby": id()
1520
- })
1521
- };
1522
- }
1523
- var Keys = {
1524
- Enter: "Enter",
1525
- Space: " ",
1526
- Escape: "Escape",
1527
- ArrowUp: "ArrowUp",
1528
- ArrowDown: "ArrowDown",
1529
- ArrowLeft: "ArrowLeft",
1530
- ArrowRight: "ArrowRight",
1531
- Home: "Home",
1532
- End: "End",
1533
- Tab: "Tab"
1534
- };
1535
- function onKey(key, handler) {
1536
- return (e) => {
1537
- if (e.key === key) {
1538
- handler(e);
1539
- }
1540
- };
1541
- }
1542
- function onKeys(keys, handler) {
1543
- return (e) => {
1544
- if (keys.includes(e.key)) {
1545
- handler(e);
1546
- }
1547
- };
1548
- }
1549
-
1550
- // packages/core/src/skeleton.js
1551
- var skeletonStyles = `
1552
- .what-skeleton {
1553
- background: linear-gradient(
1554
- 90deg,
1555
- var(--skeleton-base, #e0e0e0) 0%,
1556
- var(--skeleton-highlight, #f0f0f0) 50%,
1557
- var(--skeleton-base, #e0e0e0) 100%
1558
- );
1559
- background-size: 200% 100%;
1560
- animation: what-skeleton-shimmer 1.5s infinite ease-in-out;
1561
- border-radius: var(--skeleton-radius, 4px);
1562
- }
1563
-
1564
- @keyframes what-skeleton-shimmer {
1565
- 0% { background-position: 200% 0; }
1566
- 100% { background-position: -200% 0; }
1567
- }
1568
-
1569
- .what-skeleton-pulse {
1570
- animation: what-skeleton-pulse 1.5s infinite ease-in-out;
1571
- }
1572
-
1573
- @keyframes what-skeleton-pulse {
1574
- 0%, 100% { opacity: 1; }
1575
- 50% { opacity: 0.5; }
1576
- }
1577
-
1578
- .what-skeleton-wave {
1579
- position: relative;
1580
- overflow: hidden;
1581
- }
1582
-
1583
- .what-skeleton-wave::after {
1584
- content: '';
1585
- position: absolute;
1586
- top: 0;
1587
- right: 0;
1588
- bottom: 0;
1589
- left: 0;
1590
- background: linear-gradient(
1591
- 90deg,
1592
- transparent 0%,
1593
- rgba(255, 255, 255, 0.4) 50%,
1594
- transparent 100%
1595
- );
1596
- animation: what-skeleton-wave 1.5s infinite;
1597
- }
1598
-
1599
- @keyframes what-skeleton-wave {
1600
- 0% { transform: translateX(-100%); }
1601
- 100% { transform: translateX(100%); }
1602
- }
1603
- `;
1604
- var stylesInjected = false;
1605
- function injectStyles() {
1606
- if (stylesInjected || typeof document === "undefined") return;
1607
- stylesInjected = true;
1608
- const style2 = document.createElement("style");
1609
- style2.textContent = skeletonStyles;
1610
- document.head.appendChild(style2);
1611
- }
1612
- function Skeleton({
1613
- width,
1614
- height,
1615
- variant = "shimmer",
1616
- // 'shimmer' | 'pulse' | 'wave'
1617
- circle = false,
1618
- class: className,
1619
- style: customStyle,
1620
- count = 1
1621
- }) {
1622
- injectStyles();
1623
- const baseClass = `what-skeleton ${variant === "pulse" ? "what-skeleton-pulse" : ""} ${variant === "wave" ? "what-skeleton-wave" : ""}`;
1624
- const finalClass = className ? `${baseClass} ${className}` : baseClass;
1625
- const style2 = {
1626
- width: typeof width === "number" ? `${width}px` : width,
1627
- height: typeof height === "number" ? `${height}px` : height,
1628
- borderRadius: circle ? "50%" : void 0,
1629
- ...customStyle
1630
- };
1631
- if (count === 1) {
1632
- return h("div", { class: finalClass, style: style2, "aria-hidden": "true" });
1633
- }
1634
- return Array.from(
1635
- { length: count },
1636
- (_, i) => h("div", {
1637
- key: i,
1638
- class: finalClass,
1639
- style: { ...style2, marginBottom: i < count - 1 ? "8px" : void 0 },
1640
- "aria-hidden": "true"
1641
- })
1642
- );
1643
- }
1644
- function SkeletonText({
1645
- lines = 3,
1646
- lastLineWidth = "60%",
1647
- lineHeight = 16,
1648
- gap = 8,
1649
- variant = "shimmer"
1650
- }) {
1651
- injectStyles();
1652
- return h(
1653
- "div",
1654
- { class: "what-skeleton-text", "aria-hidden": "true" },
1655
- Array.from(
1656
- { length: lines },
1657
- (_, i) => h("div", {
1658
- key: i,
1659
- class: `what-skeleton ${variant === "pulse" ? "what-skeleton-pulse" : ""}`,
1660
- style: {
1661
- height: `${lineHeight}px`,
1662
- width: i === lines - 1 ? lastLineWidth : "100%",
1663
- marginBottom: i < lines - 1 ? `${gap}px` : void 0
1664
- }
1665
- })
1666
- )
1667
- );
1668
- }
1669
- function SkeletonAvatar({
1670
- size = 40,
1671
- variant = "shimmer"
1672
- }) {
1673
- return Skeleton({
1674
- width: size,
1675
- height: size,
1676
- circle: true,
1677
- variant
1678
- });
1679
- }
1680
- function SkeletonCard({
1681
- imageHeight = 200,
1682
- lines = 3,
1683
- variant = "shimmer"
1684
- }) {
1685
- injectStyles();
1686
- return h(
1687
- "div",
1688
- { class: "what-skeleton-card", "aria-hidden": "true" },
1689
- // Image placeholder
1690
- h("div", {
1691
- class: `what-skeleton ${variant === "pulse" ? "what-skeleton-pulse" : ""}`,
1692
- style: { height: `${imageHeight}px`, width: "100%", marginBottom: "16px" }
1693
- }),
1694
- // Title
1695
- h("div", {
1696
- class: `what-skeleton ${variant === "pulse" ? "what-skeleton-pulse" : ""}`,
1697
- style: { height: "24px", width: "70%", marginBottom: "12px" }
1698
- }),
1699
- // Text lines
1700
- SkeletonText({ lines, variant })
1701
- );
1702
- }
1703
- function SkeletonTable({
1704
- rows = 5,
1705
- columns = 4,
1706
- variant = "shimmer"
1707
- }) {
1708
- injectStyles();
1709
- return h(
1710
- "div",
1711
- { class: "what-skeleton-table", "aria-hidden": "true" },
1712
- // Header
1713
- h(
1714
- "div",
1715
- { style: { display: "flex", gap: "16px", marginBottom: "16px" } },
1716
- Array.from(
1717
- { length: columns },
1718
- (_, i) => h("div", {
1719
- key: i,
1720
- class: `what-skeleton ${variant === "pulse" ? "what-skeleton-pulse" : ""}`,
1721
- style: { height: "20px", flex: 1 }
1722
- })
1723
- )
1724
- ),
1725
- // Rows
1726
- Array.from(
1727
- { length: rows },
1728
- (_, rowIndex) => h(
1729
- "div",
1730
- {
1731
- key: rowIndex,
1732
- style: {
1733
- display: "flex",
1734
- gap: "16px",
1735
- marginBottom: rowIndex < rows - 1 ? "12px" : void 0
1736
- }
1737
- },
1738
- Array.from(
1739
- { length: columns },
1740
- (_2, colIndex) => h("div", {
1741
- key: colIndex,
1742
- class: `what-skeleton ${variant === "pulse" ? "what-skeleton-pulse" : ""}`,
1743
- style: { height: "16px", flex: 1 }
1744
- })
1745
- )
1746
- )
1747
- )
1748
- );
1749
- }
1750
- function IslandSkeleton({
1751
- type = "default",
1752
- // 'default' | 'card' | 'text' | 'custom'
1753
- height,
1754
- children
1755
- }) {
1756
- injectStyles();
1757
- if (type === "card") {
1758
- return SkeletonCard({});
1759
- }
1760
- if (type === "text") {
1761
- return SkeletonText({});
1762
- }
1763
- if (children) {
1764
- return children;
1765
- }
1766
- return h("div", {
1767
- class: "what-skeleton what-island-skeleton",
1768
- style: {
1769
- height: typeof height === "number" ? `${height}px` : height || "100px",
1770
- width: "100%"
1771
- },
1772
- "aria-hidden": "true"
1773
- });
1774
- }
1775
- function useSkeleton(asyncFn, deps = []) {
1776
- const isLoading = signal(true);
1777
- const data = signal(null);
1778
- const error = signal(null);
1779
- effect(() => {
1780
- isLoading.set(true);
1781
- error.set(null);
1782
- Promise.resolve(asyncFn()).then((result) => {
1783
- data.set(result);
1784
- isLoading.set(false);
1785
- }).catch((err) => {
1786
- error.set(err);
1787
- isLoading.set(false);
1788
- });
1789
- });
1790
- return {
1791
- isLoading: () => isLoading(),
1792
- data: () => data(),
1793
- error: () => error(),
1794
- Skeleton: (props) => isLoading() ? Skeleton(props) : null
1795
- };
1796
- }
1797
- function Placeholder({
1798
- width = "100%",
1799
- height = 100,
1800
- label = "Loading...",
1801
- showLabel = false,
1802
- variant = "shimmer"
1803
- }) {
1804
- injectStyles();
1805
- return h(
1806
- "div",
1807
- {
1808
- class: `what-skeleton ${variant === "pulse" ? "what-skeleton-pulse" : ""}`,
1809
- style: {
1810
- width: typeof width === "number" ? `${width}px` : width,
1811
- height: typeof height === "number" ? `${height}px` : height,
1812
- display: "flex",
1813
- alignItems: "center",
1814
- justifyContent: "center"
1815
- },
1816
- "aria-label": label,
1817
- role: "status"
1818
- },
1819
- showLabel && h("span", {
1820
- style: {
1821
- color: "var(--skeleton-text, #999)",
1822
- fontSize: "14px"
1823
- }
1824
- }, label)
1825
- );
1826
- }
1827
- function LoadingDots({ size = 8, color = "#666" }) {
1828
- injectStyles();
1829
- const dotStyle = {
1830
- width: `${size}px`,
1831
- height: `${size}px`,
1832
- borderRadius: "50%",
1833
- backgroundColor: color,
1834
- animation: "what-skeleton-pulse 1s infinite ease-in-out"
1835
- };
1836
- return h(
1837
- "div",
1838
- {
1839
- class: "what-loading-dots",
1840
- style: { display: "flex", gap: `${size / 2}px` },
1841
- "aria-label": "Loading",
1842
- role: "status"
1843
- },
1844
- h("div", { style: { ...dotStyle, animationDelay: "0s" } }),
1845
- h("div", { style: { ...dotStyle, animationDelay: "0.2s" } }),
1846
- h("div", { style: { ...dotStyle, animationDelay: "0.4s" } })
1847
- );
1848
- }
1849
- function Spinner({ size = 24, color = "#666", strokeWidth = 2 }) {
1850
- return h(
1851
- "svg",
1852
- {
1853
- width: size,
1854
- height: size,
1855
- viewBox: "0 0 24 24",
1856
- style: { animation: "spin 1s linear infinite" },
1857
- "aria-label": "Loading",
1858
- role: "status"
1859
- },
1860
- h("style", null, "@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }"),
1861
- h("circle", {
1862
- cx: 12,
1863
- cy: 12,
1864
- r: 10,
1865
- stroke: color,
1866
- strokeWidth,
1867
- fill: "none",
1868
- strokeDasharray: "31.4 31.4",
1869
- strokeLinecap: "round"
1870
- })
1871
- );
1872
- }
1873
-
1874
- // packages/core/src/data.js
1875
- var cacheSignals = /* @__PURE__ */ new Map();
1876
- var errorSignals = /* @__PURE__ */ new Map();
1877
- var validatingSignals = /* @__PURE__ */ new Map();
1878
- var cacheTimestamps = /* @__PURE__ */ new Map();
1879
- var MAX_CACHE_SIZE = 200;
1880
- function getCacheSignal(key) {
1881
- cacheTimestamps.set(key, Date.now());
1882
- if (!cacheSignals.has(key)) {
1883
- cacheSignals.set(key, signal(null));
1884
- if (cacheSignals.size > MAX_CACHE_SIZE) {
1885
- evictOldest();
1886
- }
1887
- }
1888
- return cacheSignals.get(key);
1889
- }
1890
- function getErrorSignal(key) {
1891
- if (!errorSignals.has(key)) errorSignals.set(key, signal(null));
1892
- return errorSignals.get(key);
1893
- }
1894
- function getValidatingSignal(key) {
1895
- if (!validatingSignals.has(key)) validatingSignals.set(key, signal(false));
1896
- return validatingSignals.get(key);
1897
- }
1898
- function evictOldest() {
1899
- const entries = [...cacheTimestamps.entries()].sort((a, b) => a[1] - b[1]);
1900
- const toRemove = Math.floor(MAX_CACHE_SIZE * 0.2);
1901
- for (let i = 0; i < toRemove && i < entries.length; i++) {
1902
- const key = entries[i][0];
1903
- if (revalidationSubscribers.has(key) && revalidationSubscribers.get(key).size > 0) continue;
1904
- cacheSignals.delete(key);
1905
- errorSignals.delete(key);
1906
- validatingSignals.delete(key);
1907
- cacheTimestamps.delete(key);
1908
- lastFetchTimestamps.delete(key);
1909
- }
1910
- }
1911
- var revalidationSubscribers = /* @__PURE__ */ new Map();
1912
- function subscribeToKey(key, revalidateFn) {
1913
- if (!revalidationSubscribers.has(key)) revalidationSubscribers.set(key, /* @__PURE__ */ new Set());
1914
- revalidationSubscribers.get(key).add(revalidateFn);
1915
- return () => {
1916
- const subs = revalidationSubscribers.get(key);
1917
- if (subs) {
1918
- subs.delete(revalidateFn);
1919
- if (subs.size === 0) revalidationSubscribers.delete(key);
1920
- }
1921
- };
1922
- }
1923
- var inFlightRequests = /* @__PURE__ */ new Map();
1924
- var lastFetchTimestamps = /* @__PURE__ */ new Map();
1925
- function scopedEffect2(fn) {
1926
- const ctx = getCurrentComponent?.();
1927
- const dispose = effect(fn);
1928
- if (ctx) ctx.effects.push(dispose);
1929
- return dispose;
1930
- }
1931
- function useFetch(url, options = {}) {
1932
- const {
1933
- method = "GET",
1934
- body,
1935
- headers = {},
1936
- transform = (data2) => data2,
1937
- initialData = null
1938
- } = options;
1939
- const data = signal(initialData);
1940
- const error = signal(null);
1941
- const isLoading = signal(true);
1942
- let abortController = null;
1943
- async function fetchData() {
1944
- if (abortController) abortController.abort();
1945
- abortController = new AbortController();
1946
- const { signal: abortSignal } = abortController;
1947
- isLoading.set(true);
1948
- error.set(null);
1949
- try {
1950
- const response = await fetch(url, {
1951
- method,
1952
- headers: {
1953
- "Content-Type": "application/json",
1954
- ...headers
1955
- },
1956
- body: body ? JSON.stringify(body) : void 0,
1957
- signal: abortSignal
1958
- });
1959
- if (!response.ok) {
1960
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1961
- }
1962
- const json = await response.json();
1963
- if (!abortSignal.aborted) {
1964
- data.set(transform(json));
1965
- }
1966
- } catch (e) {
1967
- if (!abortSignal.aborted) {
1968
- error.set(e);
1969
- }
1970
- } finally {
1971
- if (!abortSignal.aborted) {
1972
- isLoading.set(false);
1973
- }
1974
- }
1975
- }
1976
- scopedEffect2(() => {
1977
- fetchData();
1978
- return () => {
1979
- if (abortController) abortController.abort();
1980
- };
1981
- });
1982
- return {
1983
- data: () => data(),
1984
- error: () => error(),
1985
- isLoading: () => isLoading(),
1986
- refetch: fetchData,
1987
- mutate: (newData) => data.set(newData)
1988
- };
1989
- }
1990
- function useSWR(key, fetcher, options = {}) {
1991
- const {
1992
- revalidateOnFocus = true,
1993
- revalidateOnReconnect = true,
1994
- refreshInterval = 0,
1995
- dedupingInterval = 2e3,
1996
- fallbackData,
1997
- onSuccess,
1998
- onError,
1999
- suspense = false
2000
- } = options;
2001
- if (key == null || key === false) {
2002
- const data2 = signal(fallbackData || null);
2003
- const error2 = signal(null);
2004
- return {
2005
- data: () => data2(),
2006
- error: () => error2(),
2007
- isLoading: () => false,
2008
- isValidating: () => false,
2009
- mutate: (newData) => data2.set(typeof newData === "function" ? newData(data2()) : newData),
2010
- revalidate: () => Promise.resolve()
2011
- };
2012
- }
2013
- const cacheS = getCacheSignal(key);
2014
- const error = getErrorSignal(key);
2015
- const isValidating = getValidatingSignal(key);
2016
- const data = computed(() => cacheS() ?? fallbackData ?? null);
2017
- const isLoading = computed(() => cacheS() == null && isValidating());
2018
- let abortController = null;
2019
- async function revalidate() {
2020
- const now = Date.now();
2021
- if (inFlightRequests.has(key)) {
2022
- const existing = inFlightRequests.get(key);
2023
- if (now - existing.timestamp < dedupingInterval) {
2024
- existing.refCount++;
2025
- return existing.promise;
2026
- }
2027
- }
2028
- const lastFetch = lastFetchTimestamps.get(key);
2029
- if (lastFetch && now - lastFetch < dedupingInterval && cacheS.peek() != null) {
2030
- return cacheS.peek();
2031
- }
2032
- if (abortController) {
2033
- const existing = inFlightRequests.get(key);
2034
- if (!existing || existing.refCount <= 1) {
2035
- abortController.abort();
2036
- }
2037
- }
2038
- abortController = new AbortController();
2039
- const { signal: abortSignal } = abortController;
2040
- isValidating.set(true);
2041
- const promise = fetcher(key, { signal: abortSignal });
2042
- inFlightRequests.set(key, { promise, timestamp: now, refCount: 1 });
2043
- try {
2044
- const result = await promise;
2045
- if (abortSignal.aborted) return;
2046
- batch(() => {
2047
- cacheS.set(result);
2048
- error.set(null);
2049
- });
2050
- cacheTimestamps.set(key, Date.now());
2051
- lastFetchTimestamps.set(key, Date.now());
2052
- if (onSuccess) onSuccess(result, key);
2053
- return result;
2054
- } catch (e) {
2055
- if (abortSignal.aborted) return;
2056
- error.set(e);
2057
- if (onError) onError(e, key);
2058
- throw e;
2059
- } finally {
2060
- if (!abortSignal.aborted) isValidating.set(false);
2061
- const flight = inFlightRequests.get(key);
2062
- if (flight) {
2063
- flight.refCount--;
2064
- if (flight.refCount <= 0) inFlightRequests.delete(key);
2065
- }
2066
- }
2067
- }
2068
- const unsubscribe = subscribeToKey(key, () => revalidate().catch(() => {
2069
- }));
2070
- scopedEffect2(() => {
2071
- revalidate().catch(() => {
2072
- });
2073
- return () => {
2074
- if (abortController) abortController.abort();
2075
- unsubscribe();
2076
- };
2077
- });
2078
- if (revalidateOnFocus && typeof window !== "undefined") {
2079
- scopedEffect2(() => {
2080
- const handler = () => {
2081
- if (document.visibilityState === "visible") {
2082
- revalidate().catch(() => {
2083
- });
2084
- }
2085
- };
2086
- document.addEventListener("visibilitychange", handler);
2087
- return () => document.removeEventListener("visibilitychange", handler);
2088
- });
2089
- }
2090
- if (revalidateOnReconnect && typeof window !== "undefined") {
2091
- scopedEffect2(() => {
2092
- const handler = () => revalidate().catch(() => {
2093
- });
2094
- window.addEventListener("online", handler);
2095
- return () => window.removeEventListener("online", handler);
2096
- });
2097
- }
2098
- if (refreshInterval > 0) {
2099
- scopedEffect2(() => {
2100
- const interval = setInterval(() => {
2101
- revalidate().catch(() => {
2102
- });
2103
- }, refreshInterval);
2104
- return () => clearInterval(interval);
2105
- });
2106
- }
2107
- return {
2108
- data: () => data(),
2109
- error: () => error(),
2110
- isLoading: () => isLoading(),
2111
- isValidating: () => isValidating(),
2112
- mutate: (newData, shouldRevalidate = true) => {
2113
- const resolved = typeof newData === "function" ? newData(cacheS.peek()) : newData;
2114
- cacheS.set(resolved);
2115
- cacheTimestamps.set(key, Date.now());
2116
- if (shouldRevalidate) {
2117
- revalidate().catch(() => {
2118
- });
2119
- }
2120
- },
2121
- revalidate
2122
- };
2123
- }
2124
- function useQuery(options) {
2125
- const {
2126
- queryKey,
2127
- queryFn,
2128
- enabled = true,
2129
- staleTime = 0,
2130
- cacheTime = 5 * 60 * 1e3,
2131
- refetchOnWindowFocus = true,
2132
- refetchInterval = false,
2133
- retry = 3,
2134
- retryDelay = (attempt) => Math.min(1e3 * 2 ** attempt, 3e4),
2135
- onSuccess,
2136
- onError,
2137
- onSettled,
2138
- select,
2139
- placeholderData
2140
- } = options;
2141
- const key = Array.isArray(queryKey) ? queryKey.join(":") : queryKey;
2142
- const cacheS = getCacheSignal(key);
2143
- const data = computed(() => {
2144
- const d = cacheS();
2145
- return select && d !== null ? select(d) : d;
2146
- });
2147
- const error = getErrorSignal(key);
2148
- const status = signal(cacheS.peek() != null ? "success" : "loading");
2149
- const fetchStatus = signal("idle");
2150
- let lastFetchTime = 0;
2151
- let abortController = null;
2152
- async function fetchQuery() {
2153
- if (!enabled) return;
2154
- const now = Date.now();
2155
- if (cacheS.peek() != null && now - lastFetchTime < staleTime) {
2156
- return cacheS.peek();
2157
- }
2158
- if (abortController) abortController.abort();
2159
- abortController = new AbortController();
2160
- const { signal: abortSignal } = abortController;
2161
- fetchStatus.set("fetching");
2162
- if (cacheS.peek() == null) {
2163
- status.set("loading");
2164
- }
2165
- let attempts = 0;
2166
- async function attemptFetch() {
2167
- try {
2168
- const result = await queryFn({ queryKey: Array.isArray(queryKey) ? queryKey : [queryKey], signal: abortSignal });
2169
- if (abortSignal.aborted) return;
2170
- batch(() => {
2171
- cacheS.set(result);
2172
- error.set(null);
2173
- status.set("success");
2174
- fetchStatus.set("idle");
2175
- });
2176
- lastFetchTime = Date.now();
2177
- cacheTimestamps.set(key, Date.now());
2178
- if (onSuccess) onSuccess(result);
2179
- if (onSettled) onSettled(result, null);
2180
- setTimeout(() => {
2181
- if (Date.now() - lastFetchTime >= cacheTime) {
2182
- const subs = revalidationSubscribers.get(key);
2183
- if (!subs || subs.size === 0) {
2184
- cacheSignals.delete(key);
2185
- errorSignals.delete(key);
2186
- validatingSignals.delete(key);
2187
- cacheTimestamps.delete(key);
2188
- lastFetchTimestamps.delete(key);
2189
- }
2190
- }
2191
- }, cacheTime);
2192
- return result;
2193
- } catch (e) {
2194
- if (abortSignal.aborted) return;
2195
- attempts++;
2196
- if (attempts < retry) {
2197
- await new Promise((resolve, reject) => {
2198
- const id = setTimeout(resolve, retryDelay(attempts));
2199
- abortSignal.addEventListener("abort", () => {
2200
- clearTimeout(id);
2201
- reject(new DOMException("Aborted", "AbortError"));
2202
- }, { once: true });
2203
- }).catch((e2) => {
2204
- if (e2.name === "AbortError") return;
2205
- throw e2;
2206
- });
2207
- if (abortSignal.aborted) return;
2208
- return attemptFetch();
2209
- }
2210
- batch(() => {
2211
- error.set(e);
2212
- status.set("error");
2213
- fetchStatus.set("idle");
2214
- });
2215
- if (onError) onError(e);
2216
- if (onSettled) onSettled(null, e);
2217
- throw e;
2218
- }
2219
- }
2220
- return attemptFetch();
2221
- }
2222
- const unsubscribe = subscribeToKey(key, () => fetchQuery().catch(() => {
2223
- }));
2224
- scopedEffect2(() => {
2225
- if (enabled) {
2226
- fetchQuery().catch(() => {
2227
- });
2228
- }
2229
- return () => {
2230
- if (abortController) abortController.abort();
2231
- unsubscribe();
2232
- };
2233
- });
2234
- if (refetchOnWindowFocus && typeof window !== "undefined") {
2235
- scopedEffect2(() => {
2236
- const handler = () => {
2237
- if (document.visibilityState === "visible") {
2238
- fetchQuery().catch(() => {
2239
- });
2240
- }
2241
- };
2242
- document.addEventListener("visibilitychange", handler);
2243
- return () => document.removeEventListener("visibilitychange", handler);
2244
- });
2245
- }
2246
- if (refetchInterval) {
2247
- scopedEffect2(() => {
2248
- const interval = setInterval(() => {
2249
- fetchQuery().catch(() => {
2250
- });
2251
- }, refetchInterval);
2252
- return () => clearInterval(interval);
2253
- });
2254
- }
2255
- return {
2256
- data: () => data() ?? placeholderData,
2257
- error: () => error(),
2258
- status: () => status(),
2259
- fetchStatus: () => fetchStatus(),
2260
- isLoading: () => status() === "loading",
2261
- isError: () => status() === "error",
2262
- isSuccess: () => status() === "success",
2263
- isFetching: () => fetchStatus() === "fetching",
2264
- refetch: fetchQuery
2265
- };
2266
- }
2267
- function useInfiniteQuery(options) {
2268
- const {
2269
- queryKey,
2270
- queryFn,
2271
- getNextPageParam,
2272
- getPreviousPageParam,
2273
- initialPageParam,
2274
- ...rest
2275
- } = options;
2276
- const pages = signal([]);
2277
- const pageParams = signal([initialPageParam]);
2278
- const hasNextPage = signal(true);
2279
- const hasPreviousPage = signal(false);
2280
- const isFetchingNextPage = signal(false);
2281
- const isFetchingPreviousPage = signal(false);
2282
- const key = Array.isArray(queryKey) ? queryKey.join(":") : queryKey;
2283
- let abortController = null;
2284
- let isRefetching = false;
2285
- async function fetchPage(pageParam, direction = "next") {
2286
- if (abortController) abortController.abort();
2287
- abortController = new AbortController();
2288
- const { signal: abortSignal } = abortController;
2289
- const loading = direction === "next" ? isFetchingNextPage : isFetchingPreviousPage;
2290
- loading.set(true);
2291
- try {
2292
- const result = await queryFn({
2293
- queryKey: Array.isArray(queryKey) ? queryKey : [queryKey],
2294
- pageParam,
2295
- signal: abortSignal
2296
- });
2297
- if (abortSignal.aborted) return;
2298
- batch(() => {
2299
- if (isRefetching) {
2300
- pages.set([result]);
2301
- pageParams.set([pageParam]);
2302
- isRefetching = false;
2303
- } else if (direction === "next") {
2304
- pages.set([...pages.peek(), result]);
2305
- pageParams.set([...pageParams.peek(), pageParam]);
2306
- } else {
2307
- pages.set([result, ...pages.peek()]);
2308
- pageParams.set([pageParam, ...pageParams.peek()]);
2309
- }
2310
- const nextParam = getNextPageParam?.(result, pages.peek());
2311
- hasNextPage.set(nextParam !== void 0);
2312
- if (getPreviousPageParam) {
2313
- const prevParam = getPreviousPageParam(result, pages.peek());
2314
- hasPreviousPage.set(prevParam !== void 0);
2315
- }
2316
- });
2317
- return result;
2318
- } finally {
2319
- if (!abortSignal.aborted) loading.set(false);
2320
- }
2321
- }
2322
- scopedEffect2(() => {
2323
- fetchPage(initialPageParam).catch(() => {
2324
- });
2325
- return () => {
2326
- if (abortController) abortController.abort();
2327
- };
2328
- });
2329
- return {
2330
- data: () => ({ pages: pages(), pageParams: pageParams() }),
2331
- hasNextPage: () => hasNextPage(),
2332
- hasPreviousPage: () => hasPreviousPage(),
2333
- isFetchingNextPage: () => isFetchingNextPage(),
2334
- isFetchingPreviousPage: () => isFetchingPreviousPage(),
2335
- fetchNextPage: async () => {
2336
- const lastPage = pages.peek()[pages.peek().length - 1];
2337
- const nextParam = getNextPageParam?.(lastPage, pages.peek());
2338
- if (nextParam !== void 0) {
2339
- return fetchPage(nextParam, "next");
2340
- }
2341
- },
2342
- fetchPreviousPage: async () => {
2343
- const firstPage = pages.peek()[0];
2344
- const prevParam = getPreviousPageParam?.(firstPage, pages.peek());
2345
- if (prevParam !== void 0) {
2346
- return fetchPage(prevParam, "previous");
2347
- }
2348
- },
2349
- refetch: async () => {
2350
- isRefetching = true;
2351
- return fetchPage(initialPageParam);
2352
- }
2353
- };
2354
- }
2355
- function invalidateQueries(keyOrPredicate, options = {}) {
2356
- const { hard = false } = options;
2357
- const keysToInvalidate = [];
2358
- if (typeof keyOrPredicate === "function") {
2359
- for (const [key] of cacheSignals) {
2360
- if (keyOrPredicate(key)) keysToInvalidate.push(key);
2361
- }
2362
- } else {
2363
- keysToInvalidate.push(keyOrPredicate);
2364
- }
2365
- for (const key of keysToInvalidate) {
2366
- if (hard && cacheSignals.has(key)) cacheSignals.get(key).set(null);
2367
- const subs = revalidationSubscribers.get(key);
2368
- if (subs) {
2369
- for (const revalidate of subs) revalidate();
2370
- }
2371
- }
2372
- }
2373
- function prefetchQuery(key, fetcher) {
2374
- const cacheS = getCacheSignal(key);
2375
- return fetcher(key).then((result) => {
2376
- cacheS.set(result);
2377
- cacheTimestamps.set(key, Date.now());
2378
- return result;
2379
- });
2380
- }
2381
- function setQueryData(key, updater) {
2382
- const cacheS = getCacheSignal(key);
2383
- const current = cacheS.peek();
2384
- cacheS.set(typeof updater === "function" ? updater(current) : updater);
2385
- cacheTimestamps.set(key, Date.now());
2386
- }
2387
- function getQueryData(key) {
2388
- return cacheSignals.has(key) ? cacheSignals.get(key).peek() : void 0;
2389
- }
2390
- function clearCache() {
2391
- cacheSignals.clear();
2392
- errorSignals.clear();
2393
- validatingSignals.clear();
2394
- cacheTimestamps.clear();
2395
- lastFetchTimestamps.clear();
2396
- inFlightRequests.clear();
2397
- }
2398
- function __getCacheSnapshot() {
2399
- const entries = [];
2400
- for (const [key, sig] of cacheSignals) {
2401
- entries.push({
2402
- key,
2403
- data: sig.peek(),
2404
- error: errorSignals.has(key) ? errorSignals.get(key).peek() : null,
2405
- isValidating: validatingSignals.has(key) ? validatingSignals.get(key).peek() : false
2406
- });
2407
- }
2408
- return entries;
2409
- }
2410
-
2411
- // packages/core/src/form.js
2412
- function useForm(options = {}) {
2413
- const ctx = getCurrentComponent?.();
2414
- if (ctx) {
2415
- const index = ctx.hookIndex++;
2416
- if (!ctx.hooks[index]) {
2417
- ctx.hooks[index] = createFormController(options);
2418
- }
2419
- return ctx.hooks[index];
2420
- }
2421
- return createFormController(options);
2422
- }
2423
- function createFormController(options = {}) {
2424
- const {
2425
- defaultValues = {},
2426
- mode = "onSubmit",
2427
- // 'onSubmit' | 'onChange' | 'onBlur'
2428
- reValidateMode = "onChange",
2429
- resolver
2430
- } = options;
2431
- const fieldSignals = {};
2432
- const errorSignals2 = {};
2433
- const touchedSignals = {};
2434
- const errorsState = signal({});
2435
- function getFieldSignal(name) {
2436
- if (!fieldSignals[name]) {
2437
- fieldSignals[name] = signal(defaultValues[name] ?? "");
2438
- }
2439
- return fieldSignals[name];
2440
- }
2441
- function getErrorSignal2(name) {
2442
- if (!errorSignals2[name]) {
2443
- errorSignals2[name] = signal(null);
2444
- }
2445
- return errorSignals2[name];
2446
- }
2447
- function getTouchedSignal(name) {
2448
- if (!touchedSignals[name]) {
2449
- touchedSignals[name] = signal(false);
2450
- }
2451
- return touchedSignals[name];
2452
- }
2453
- const isDirty = signal(false);
2454
- const isSubmitting = signal(false);
2455
- const isSubmitted = signal(false);
2456
- const isValidating = signal(false);
2457
- const submitCount = signal(0);
2458
- function getAllValues(tracked = false) {
2459
- const result = { ...defaultValues };
2460
- for (const [name, sig] of Object.entries(fieldSignals)) {
2461
- result[name] = tracked ? sig() : sig.peek();
2462
- }
2463
- return result;
2464
- }
2465
- function getAllErrors(tracked = false) {
2466
- return tracked ? errorsState() : errorsState.peek();
2467
- }
2468
- function setFieldError(name, error) {
2469
- const nextError = error ?? null;
2470
- getErrorSignal2(name).set(nextError);
2471
- errorsState.set((prev) => {
2472
- const prevError = prev[name];
2473
- if (prevError === nextError) return prev;
2474
- if (nextError == null) {
2475
- if (!Object.prototype.hasOwnProperty.call(prev, name)) return prev;
2476
- const next = { ...prev };
2477
- delete next[name];
2478
- return next;
2479
- }
2480
- return { ...prev, [name]: nextError };
2481
- });
2482
- }
2483
- function replaceAllErrors(nextErrors = {}) {
2484
- const normalized = nextErrors || {};
2485
- batch(() => {
2486
- for (const [name, sig] of Object.entries(errorSignals2)) {
2487
- if (!Object.prototype.hasOwnProperty.call(normalized, name)) {
2488
- sig.set(null);
2489
- }
2490
- }
2491
- for (const [name, err] of Object.entries(normalized)) {
2492
- getErrorSignal2(name).set(err ?? null);
2493
- }
2494
- errorsState.set({ ...normalized });
2495
- });
2496
- }
2497
- const isValid = computed(() => Object.keys(getAllErrors(true)).length === 0);
2498
- const dirtyFields = computed(() => {
2499
- const dirty = {};
2500
- for (const [name, sig] of Object.entries(fieldSignals)) {
2501
- if (sig() !== (defaultValues[name] ?? "")) {
2502
- dirty[name] = true;
2503
- }
2504
- }
2505
- return dirty;
2506
- });
2507
- async function validate(fieldName) {
2508
- if (!resolver) return true;
2509
- isValidating.set(true);
2510
- try {
2511
- const result = await resolver(getAllValues(false));
2512
- const nextErrors = result?.errors || {};
2513
- if (fieldName) {
2514
- const nextError = nextErrors[fieldName] ?? null;
2515
- setFieldError(fieldName, nextError);
2516
- return !nextError;
2517
- } else {
2518
- replaceAllErrors(nextErrors);
2519
- return Object.keys(nextErrors).length === 0;
2520
- }
2521
- } finally {
2522
- isValidating.set(false);
2523
- }
2524
- }
2525
- function register(name, options2 = {}) {
2526
- const fieldSig = getFieldSignal(name);
2527
- const isCheckbox = options2.type === "checkbox" || options2.type === "radio";
2528
- const handler = (e) => {
2529
- const value = e.target.type === "checkbox" || e.target.type === "radio" ? e.target.checked : e.target.value;
2530
- setValue(name, value);
2531
- if (mode === "onChange" || isSubmitted.peek() && reValidateMode === "onChange") {
2532
- validate(name);
2533
- }
2534
- };
2535
- const result = {
2536
- name,
2537
- onBlur: () => {
2538
- getTouchedSignal(name).set(true);
2539
- if (mode === "onBlur" || isSubmitted.peek() && reValidateMode === "onBlur") {
2540
- validate(name);
2541
- }
2542
- },
2543
- onFocus: () => {
2544
- },
2545
- ref: options2.ref
2546
- };
2547
- if (isCheckbox) {
2548
- Object.defineProperty(result, "checked", {
2549
- get() {
2550
- return !!fieldSig();
2551
- },
2552
- enumerable: true
2553
- });
2554
- result.onchange = handler;
2555
- } else {
2556
- Object.defineProperty(result, "value", {
2557
- get() {
2558
- return fieldSig();
2559
- },
2560
- enumerable: true
2561
- });
2562
- result.oninput = handler;
2563
- }
2564
- return result;
2565
- }
2566
- function setValue(name, value, options2 = {}) {
2567
- const { shouldValidate = false, shouldDirty = true } = options2;
2568
- getFieldSignal(name).set(value);
2569
- if (shouldDirty) isDirty.set(true);
2570
- if (shouldValidate) {
2571
- validate(name);
2572
- }
2573
- }
2574
- function getValue(name) {
2575
- return getFieldSignal(name)();
2576
- }
2577
- function setError(name, error) {
2578
- setFieldError(name, error);
2579
- }
2580
- function clearError(name) {
2581
- setFieldError(name, null);
2582
- }
2583
- function clearErrors() {
2584
- replaceAllErrors({});
2585
- }
2586
- function reset(newValues = defaultValues) {
2587
- batch(() => {
2588
- for (const [name, sig] of Object.entries(fieldSignals)) {
2589
- sig.set(newValues[name] ?? "");
2590
- }
2591
- for (const sig of Object.values(errorSignals2)) {
2592
- sig.set(null);
2593
- }
2594
- errorsState.set({});
2595
- for (const sig of Object.values(touchedSignals)) {
2596
- sig.set(false);
2597
- }
2598
- isDirty.set(false);
2599
- isSubmitted.set(false);
2600
- });
2601
- }
2602
- function handleSubmit(onValid, onInvalid) {
2603
- return async (e) => {
2604
- if (e) e.preventDefault();
2605
- isSubmitting.set(true);
2606
- isSubmitted.set(true);
2607
- submitCount.set(submitCount.peek() + 1);
2608
- const isFormValid = await validate();
2609
- if (isFormValid) {
2610
- await onValid(getAllValues());
2611
- } else if (onInvalid) {
2612
- onInvalid(getAllErrors(false));
2613
- }
2614
- isSubmitting.set(false);
2615
- };
2616
- }
2617
- function watch(name) {
2618
- if (name) {
2619
- return computed(() => getFieldSignal(name)());
2620
- }
2621
- return computed(() => getAllValues(true));
2622
- }
2623
- return {
2624
- register,
2625
- handleSubmit,
2626
- setValue,
2627
- getValue,
2628
- setError,
2629
- clearError,
2630
- clearErrors,
2631
- reset,
2632
- watch,
2633
- validate,
2634
- // Form state
2635
- formState: {
2636
- get values() {
2637
- return getAllValues(true);
2638
- },
2639
- get errors() {
2640
- return getAllErrors(true);
2641
- },
2642
- error: (name) => getErrorSignal2(name)(),
2643
- get touched() {
2644
- const result = {};
2645
- for (const [name, sig] of Object.entries(touchedSignals)) {
2646
- if (sig()) result[name] = true;
2647
- }
2648
- return result;
2649
- },
2650
- isDirty: () => isDirty(),
2651
- isValid,
2652
- isValidating: () => isValidating(),
2653
- isSubmitting: () => isSubmitting(),
2654
- isSubmitted: () => isSubmitted(),
2655
- submitCount: () => submitCount(),
2656
- dirtyFields
2657
- }
2658
- };
2659
- }
2660
- function zodResolver(schema) {
2661
- return async (values) => {
2662
- try {
2663
- const result = await schema.parseAsync(values);
2664
- return { values: result, errors: {} };
2665
- } catch (e) {
2666
- const errors = {};
2667
- for (const issue of e.errors || []) {
2668
- const path = issue.path.join(".");
2669
- if (!errors[path]) {
2670
- errors[path] = { type: issue.code, message: issue.message };
2671
- }
2672
- }
2673
- return { values: {}, errors };
2674
- }
2675
- };
2676
- }
2677
- function yupResolver(schema) {
2678
- return async (values) => {
2679
- try {
2680
- const result = await schema.validate(values, { abortEarly: false });
2681
- return { values: result, errors: {} };
2682
- } catch (e) {
2683
- const errors = {};
2684
- for (const err of e.inner || []) {
2685
- if (!errors[err.path]) {
2686
- errors[err.path] = { type: err.type, message: err.message };
2687
- }
2688
- }
2689
- return { values: {}, errors };
2690
- }
2691
- };
2692
- }
2693
- function simpleResolver(rules2) {
2694
- return async (values) => {
2695
- const errors = {};
2696
- for (const [field, fieldRules] of Object.entries(rules2)) {
2697
- const value = values[field];
2698
- for (const rule of fieldRules) {
2699
- const error = rule(value, values);
2700
- if (error) {
2701
- errors[field] = { type: "validation", message: error };
2702
- break;
2703
- }
2704
- }
2705
- }
2706
- return { values, errors };
2707
- };
2708
- }
2709
- var rules = {
2710
- required: (message = "This field is required") => (value) => {
2711
- if (value === void 0 || value === null || value === "") {
2712
- return message;
2713
- }
2714
- },
2715
- minLength: (min, message) => (value) => {
2716
- if (typeof value === "string" && value.length < min) {
2717
- return message || `Must be at least ${min} characters`;
2718
- }
2719
- },
2720
- maxLength: (max, message) => (value) => {
2721
- if (typeof value === "string" && value.length > max) {
2722
- return message || `Must be at most ${max} characters`;
2723
- }
2724
- },
2725
- min: (min, message) => (value) => {
2726
- if (typeof value === "number" && value < min) {
2727
- return message || `Must be at least ${min}`;
2728
- }
2729
- },
2730
- max: (max, message) => (value) => {
2731
- if (typeof value === "number" && value > max) {
2732
- return message || `Must be at most ${max}`;
2733
- }
2734
- },
2735
- pattern: (regex, message = "Invalid format") => (value) => {
2736
- if (typeof value === "string" && !regex.test(value)) {
2737
- return message;
2738
- }
2739
- },
2740
- email: (message = "Invalid email address") => (value) => {
2741
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2742
- if (typeof value === "string" && !emailRegex.test(value)) {
2743
- return message;
2744
- }
2745
- },
2746
- url: (message = "Invalid URL") => (value) => {
2747
- try {
2748
- if (typeof value === "string" && value) {
2749
- new URL(value);
2750
- }
2751
- } catch {
2752
- return message;
2753
- }
2754
- },
2755
- match: (field, message) => (value, values) => {
2756
- if (value !== values[field]) {
2757
- return message || `Must match ${field}`;
2758
- }
2759
- },
2760
- custom: (validator) => validator
2761
- };
2762
- function useField(name, options = {}) {
2763
- const { validate: validateFn, defaultValue = "" } = options;
2764
- const value = signal(defaultValue);
2765
- const error = signal(null);
2766
- const isTouched = signal(false);
2767
- const isDirty = signal(false);
2768
- async function validate() {
2769
- if (!validateFn) return true;
2770
- const result = await validateFn(value.peek());
2771
- error.set(result || null);
2772
- return !result;
2773
- }
2774
- return {
2775
- name,
2776
- value: () => value(),
2777
- error: () => error(),
2778
- isTouched: () => isTouched(),
2779
- isDirty: () => isDirty(),
2780
- setValue: (v) => {
2781
- value.set(v);
2782
- isDirty.set(true);
2783
- },
2784
- setError: (e) => error.set(e),
2785
- validate,
2786
- reset: () => {
2787
- value.set(defaultValue);
2788
- error.set(null);
2789
- isTouched.set(false);
2790
- isDirty.set(false);
2791
- },
2792
- inputProps: () => ({
2793
- name,
2794
- value: value(),
2795
- onInput: (e) => {
2796
- value.set(e.target.value);
2797
- isDirty.set(true);
2798
- },
2799
- onBlur: () => {
2800
- isTouched.set(true);
2801
- validate();
2802
- }
2803
- })
2804
- };
2805
- }
2806
- function Input(props) {
2807
- const { register, error, ...rest } = props;
2808
- const registered = register ? register(props.name) : {};
2809
- return h("input", {
2810
- ...rest,
2811
- ...registered,
2812
- "aria-invalid": error ? "true" : void 0
2813
- });
2814
- }
2815
- function Textarea(props) {
2816
- const { register, error, ...rest } = props;
2817
- const registered = register ? register(props.name) : {};
2818
- return h("textarea", {
2819
- ...rest,
2820
- ...registered,
2821
- "aria-invalid": error ? "true" : void 0
2822
- });
2823
- }
2824
- function Select(props) {
2825
- const { register, error, children, ...rest } = props;
2826
- const registered = register ? register(props.name) : {};
2827
- return h("select", {
2828
- ...rest,
2829
- ...registered,
2830
- "aria-invalid": error ? "true" : void 0
2831
- }, children);
2832
- }
2833
- function Checkbox(props) {
2834
- const { register, ...rest } = props;
2835
- const registered = register ? register(props.name) : {};
2836
- return h("input", {
2837
- type: "checkbox",
2838
- ...rest,
2839
- ...registered,
2840
- checked: registered.value
2841
- });
2842
- }
2843
- function Radio(props) {
2844
- const { register, value: radioValue, ...rest } = props;
2845
- const registered = register ? register(props.name) : {};
2846
- return h("input", {
2847
- type: "radio",
2848
- value: radioValue,
2849
- ...rest,
2850
- checked: registered.value === radioValue,
2851
- onChange: (e) => {
2852
- if (e.target.checked && registered.onInput) {
2853
- registered.onInput({ target: { value: radioValue } });
2854
- }
2855
- }
2856
- });
2857
- }
2858
- function ErrorMessage({ name, formState, errors, render }) {
2859
- const error = formState && typeof formState.error === "function" ? formState.error(name) : (formState?.errors != null ? formState.errors : typeof errors === "function" ? errors() : errors)?.[name] || null;
2860
- if (!error) return null;
2861
- if (render) {
2862
- return render({ message: error.message, type: error.type });
2863
- }
2864
- return h("span", { class: "what-error", role: "alert" }, error.message);
2865
- }
2866
-
2867
- // packages/core/src/errors.js
2868
- var ERROR_CODES = {
2869
- INFINITE_EFFECT: {
2870
- code: "ERR_INFINITE_EFFECT",
2871
- severity: "error",
2872
- template: 'Effect "{{effectName}}" exceeded 25 flush iterations \u2014 likely an infinite loop.',
2873
- suggestion: "An effect is writing to a signal it also reads, creating a cycle. Use untrack() to read the signal without subscribing, or restructure so the write and read are in separate effects.",
2874
- codeExample: `// Bad \u2014 reads and writes count, creating a cycle:
2875
- effect(() => { count(count() + 1); });
2876
-
2877
- // Good \u2014 use untrack() so the read doesn't subscribe:
2878
- effect(() => { count(untrack(count) + 1); });
2879
-
2880
- // Better \u2014 split into separate logic:
2881
- const doubled = computed(() => count() * 2);`
2882
- },
2883
- MISSING_SIGNAL_READ: {
2884
- code: "ERR_MISSING_SIGNAL_READ",
2885
- severity: "warning",
2886
- template: 'Signal "{{signalName}}" used without calling () \u2014 renders as "[Function]" instead of its value.',
2887
- suggestion: "Signals are functions. Call them to read: count() not count. In JSX: {count()} not {count}.",
2888
- codeExample: `// Bad \u2014 signal reference, not value:
2889
- <span>{count}</span> // renders "[Function]"
2890
-
2891
- // Good \u2014 call the signal:
2892
- <span>{count()}</span> // renders the actual value`
2893
- },
2894
- HYDRATION_MISMATCH: {
2895
- code: "ERR_HYDRATION_MISMATCH",
2896
- severity: "error",
2897
- template: 'Hydration mismatch in component "{{component}}": server rendered "{{serverHTML}}" but client expects "{{clientHTML}}".',
2898
- suggestion: "Ensure server and client render identical initial HTML. Avoid reading browser-only APIs (window, localStorage) during the initial render. Use onMount() for client-only logic.",
2899
- codeExample: `// Bad \u2014 different on server vs client:
2900
- function App() {
2901
- return <p>{window.innerWidth}</p>;
2902
- }
2903
-
2904
- // Good \u2014 use onMount for client-only values:
2905
- function App() {
2906
- const width = signal(0);
2907
- onMount(() => width(window.innerWidth));
2908
- return <p>{width()}</p>;
2909
- }`
2910
- },
2911
- ORPHAN_EFFECT: {
2912
- code: "ERR_ORPHAN_EFFECT",
2913
- severity: "warning",
2914
- template: 'Effect "{{effectName}}" was created outside a reactive root \u2014 it will never be cleaned up.',
2915
- suggestion: "Wrap effect creation in createRoot() or create effects inside component functions where they are automatically tracked.",
2916
- codeExample: `// Bad \u2014 orphaned, leaks memory:
2917
- effect(() => console.log(count()));
2918
-
2919
- // Good \u2014 inside a root with cleanup:
2920
- createRoot(dispose => {
2921
- effect(() => console.log(count()));
2922
- // later: dispose() cleans up
2923
- });`
2924
- },
2925
- SIGNAL_WRITE_IN_RENDER: {
2926
- code: "ERR_SIGNAL_WRITE_IN_RENDER",
2927
- severity: "error",
2928
- template: 'Signal "{{signalName}}" written during render of component "{{component}}". This triggers re-execution.',
2929
- suggestion: "Move signal writes into event handlers, effects, or onMount(). The component body should only read signals, not write them.",
2930
- codeExample: `// Bad \u2014 write during render:
2931
- function Counter() {
2932
- count(count() + 1); // triggers infinite loop
2933
- return <span>{count()}</span>;
2934
- }
2935
-
2936
- // Good \u2014 write in event handler:
2937
- function Counter() {
2938
- return <button onclick={() => count(c => c + 1)}>{count()}</button>;
2939
- }`
2940
- },
2941
- MISSING_CLEANUP: {
2942
- code: "ERR_MISSING_CLEANUP",
2943
- severity: "warning",
2944
- template: 'Effect sets up "{{resource}}" but does not return a cleanup function.',
2945
- suggestion: "Effects that add event listeners, set timers, or open connections should return a cleanup function to prevent memory leaks.",
2946
- codeExample: `// Bad \u2014 no cleanup:
2947
- effect(() => {
2948
- window.addEventListener('resize', handler);
2949
- });
2950
-
2951
- // Good \u2014 return cleanup:
2952
- effect(() => {
2953
- window.addEventListener('resize', handler);
2954
- return () => window.removeEventListener('resize', handler);
2955
- });`
2956
- },
2957
- UNSAFE_INNERHTML: {
2958
- code: "ERR_UNSAFE_INNERHTML",
2959
- severity: "warning",
2960
- template: "innerHTML set on element without using the __html safety marker.",
2961
- suggestion: "Use the html tagged template literal or pass { __html: content } to mark innerHTML as intentional and reviewed.",
2962
- codeExample: `// Bad \u2014 raw innerHTML (XSS risk):
2963
- <div innerHTML={userInput} />
2964
-
2965
- // Good \u2014 explicit opt-in:
2966
- <div innerHTML={{ __html: sanitizedContent }} />
2967
-
2968
- // Better \u2014 use the html template literal:
2969
- html\`<div>\${sanitizedContent}</div>\``
2970
- },
2971
- MISSING_KEY: {
2972
- code: "ERR_MISSING_KEY",
2973
- severity: "warning",
2974
- template: 'List rendered without key prop in component "{{component}}". Items may re-order incorrectly.',
2975
- suggestion: "Add a unique key prop to each item in a list. Use a stable identifier (like an ID), not the array index.",
2976
- codeExample: `// Bad \u2014 no key:
2977
- <For each={items()}>{item => <li>{item.name}</li>}</For>
2978
-
2979
- // Good \u2014 stable key:
2980
- <For each={items()}>{item => <li key={item.id}>{item.name}</li>}</For>`
2981
- }
2982
- };
2983
- var WhatError = class extends Error {
2984
- constructor({ code, message, suggestion, file, line, component, signal: signal2, effect: effect2 }) {
2985
- super(message);
2986
- this.name = "WhatError";
2987
- this.code = code;
2988
- this.suggestion = suggestion;
2989
- this.file = file;
2990
- this.line = line;
2991
- this.component = component;
2992
- this.signal = signal2;
2993
- this.effect = effect2;
2994
- }
2995
- toJSON() {
2996
- return {
2997
- code: this.code,
2998
- message: this.message,
2999
- suggestion: this.suggestion,
3000
- file: this.file,
3001
- line: this.line,
3002
- component: this.component,
3003
- signal: this.signal,
3004
- effect: this.effect
3005
- };
3006
- }
3007
- };
3008
- function createWhatError(errorCode, context = {}) {
3009
- const def = typeof errorCode === "string" ? ERROR_CODES[errorCode] : errorCode;
3010
- if (!def) {
3011
- return new WhatError({
3012
- code: "ERR_UNKNOWN",
3013
- message: `Unknown error: ${errorCode}`,
3014
- suggestion: "Check the error code and try again."
3015
- });
3016
- }
3017
- let message = def.template;
3018
- for (const [key, val] of Object.entries(context)) {
3019
- message = message.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), String(val));
3020
- }
3021
- message = message.replace(/\{\{[^}]+\}\}/g, "(unknown)");
3022
- return new WhatError({
3023
- code: def.code,
3024
- message,
3025
- suggestion: def.suggestion,
3026
- file: context.file,
3027
- line: context.line,
3028
- component: context.component,
3029
- signal: context.signal || context.signalName,
3030
- effect: context.effect || context.effectName
3031
- });
3032
- }
3033
- var collectedErrors = [];
3034
- var MAX_COLLECTED = 200;
3035
- function collectError(whatError) {
3036
- if (!__DEV__) return;
3037
- collectedErrors.push({
3038
- ...whatError.toJSON(),
3039
- timestamp: Date.now()
3040
- });
3041
- if (collectedErrors.length > MAX_COLLECTED) {
3042
- collectedErrors = collectedErrors.slice(-MAX_COLLECTED);
3043
- }
3044
- }
3045
- function getCollectedErrors(since) {
3046
- if (since) return collectedErrors.filter((e) => e.timestamp > since);
3047
- return collectedErrors.slice();
3048
- }
3049
- function clearCollectedErrors() {
3050
- collectedErrors = [];
3051
- }
3052
- function classifyError(err, context = {}) {
3053
- const msg = err?.message || String(err);
3054
- if (msg.includes("infinite effect loop") || msg.includes("25 iterations")) {
3055
- return createWhatError("INFINITE_EFFECT", context);
3056
- }
3057
- if (msg.includes("hydration") || msg.includes("Hydration")) {
3058
- return createWhatError("HYDRATION_MISMATCH", context);
3059
- }
3060
- if (msg.includes("Signal.set() called inside a computed")) {
3061
- return createWhatError("SIGNAL_WRITE_IN_RENDER", {
3062
- ...context,
3063
- signalName: msg.match(/signal: (\w+)/)?.[1] || context.signalName
3064
- });
3065
- }
3066
- return new WhatError({
3067
- code: "ERR_RUNTIME",
3068
- message: msg,
3069
- suggestion: "Check the stack trace and component context for more details.",
3070
- ...context
3071
- });
3072
- }
3073
-
3074
- // packages/core/src/guardrails.js
3075
- var guardrails = {
3076
- signalReadDetection: true,
3077
- effectCycleDetection: true,
3078
- componentNaming: true,
3079
- importValidation: true
3080
- };
3081
- function configureGuardrails(overrides) {
3082
- Object.assign(guardrails, overrides);
3083
- }
3084
- function getGuardrailConfig() {
3085
- return { ...guardrails };
3086
- }
3087
- function installSignalReadGuardrail(signalFn, debugName) {
3088
- if (!__DEV__ || !guardrails.signalReadDetection) return signalFn;
3089
- const originalToString = signalFn.toString;
3090
- signalFn.toString = function() {
3091
- const err = createWhatError("MISSING_SIGNAL_READ", {
3092
- signalName: debugName || "(unnamed)"
3093
- });
3094
- console.warn(`[what] ${err.message}
3095
- Suggestion: ${err.suggestion}`);
3096
- collectError(err);
3097
- return String(signalFn());
3098
- };
3099
- signalFn.valueOf = function() {
3100
- const err = createWhatError("MISSING_SIGNAL_READ", {
3101
- signalName: debugName || "(unnamed)"
3102
- });
3103
- console.warn(`[what] ${err.message}
3104
- Suggestion: ${err.suggestion}`);
3105
- collectError(err);
3106
- return signalFn();
3107
- };
3108
- return signalFn;
3109
- }
3110
- function checkComponentName(name) {
3111
- if (!__DEV__ || !guardrails.componentNaming) return null;
3112
- if (!name) return null;
3113
- if (/^[A-Z]/.test(name)) return null;
3114
- const suggestion = `Component "${name}" should use PascalCase (e.g., "${capitalize(name)}"). PascalCase distinguishes components from HTML elements in JSX and is required by the What Framework compiler.`;
3115
- console.warn(`[what] ${suggestion}`);
3116
- return { code: "WARN_COMPONENT_NAMING", name, suggestion };
3117
- }
3118
- function capitalize(str) {
3119
- return str.charAt(0).toUpperCase() + str.slice(1);
3120
- }
3121
- var VALID_EXPORTS = /* @__PURE__ */ new Set([
3122
- // Reactive primitives
3123
- "signal",
3124
- "computed",
3125
- "effect",
3126
- "signalMemo",
3127
- "batch",
3128
- "untrack",
3129
- "flushSync",
3130
- "createRoot",
3131
- "getOwner",
3132
- "runWithOwner",
3133
- "onRootCleanup",
3134
- "__setDevToolsHooks",
3135
- // Rendering
3136
- "template",
3137
- "_template",
3138
- "svgTemplate",
3139
- "insert",
3140
- "mapArray",
3141
- "spread",
3142
- "setProp",
3143
- "delegateEvents",
3144
- "on",
3145
- "classList",
3146
- "hydrate",
3147
- "isHydrating",
3148
- "_$createComponent",
3149
- // JSX
3150
- "h",
3151
- "Fragment",
3152
- "html",
3153
- // DOM
3154
- "mount",
3155
- // Hooks
3156
- "useState",
3157
- "useSignal",
3158
- "useComputed",
3159
- "useEffect",
3160
- "useMemo",
3161
- "useCallback",
3162
- "useRef",
3163
- "useContext",
3164
- "useReducer",
3165
- "createContext",
3166
- "onMount",
3167
- "onCleanup",
3168
- "createResource",
3169
- // Components
3170
- "memo",
3171
- "lazy",
3172
- "Suspense",
3173
- "ErrorBoundary",
3174
- "Show",
3175
- "For",
3176
- "Switch",
3177
- "Match",
3178
- "Island",
3179
- // Store
3180
- "createStore",
3181
- "derived",
3182
- "storeComputed",
3183
- "atom",
3184
- // Head
3185
- "Head",
3186
- "clearHead",
3187
- // Utilities
3188
- "each",
3189
- "cls",
3190
- "style",
3191
- "debounce",
3192
- "throttle",
3193
- "useMediaQuery",
3194
- "useLocalStorage",
3195
- "useClickOutside",
3196
- "Portal",
3197
- "transition",
3198
- // Scheduler
3199
- "scheduleRead",
3200
- "scheduleWrite",
3201
- "flushScheduler",
3202
- "measure",
3203
- "mutate",
3204
- "useScheduledEffect",
3205
- "nextFrame",
3206
- "raf",
3207
- "onResize",
3208
- "onIntersect",
3209
- "smoothScrollTo",
3210
- // Text insertion hook (for external text engines)
3211
- "_setTextInsertHook",
3212
- // Animation
3213
- "spring",
3214
- "tween",
3215
- "easings",
3216
- "useTransition",
3217
- "useGesture",
3218
- "useAnimatedValue",
3219
- "createTransitionClasses",
3220
- "cssTransition",
3221
- // Accessibility
3222
- "useFocus",
3223
- "useFocusRestore",
3224
- "useFocusTrap",
3225
- "FocusTrap",
3226
- "announce",
3227
- "announceAssertive",
3228
- "SkipLink",
3229
- "useAriaExpanded",
3230
- "useAriaSelected",
3231
- "useAriaChecked",
3232
- "useRovingTabIndex",
3233
- "VisuallyHidden",
3234
- "LiveRegion",
3235
- "useId",
3236
- "useIds",
3237
- "useDescribedBy",
3238
- "useLabelledBy",
3239
- "Keys",
3240
- "onKey",
3241
- "onKeys",
3242
- // Skeleton
3243
- "Skeleton",
3244
- "SkeletonText",
3245
- "SkeletonAvatar",
3246
- "SkeletonCard",
3247
- "SkeletonTable",
3248
- "IslandSkeleton",
3249
- "useSkeleton",
3250
- "Placeholder",
3251
- "LoadingDots",
3252
- "Spinner",
3253
- // Data fetching
3254
- "useFetch",
3255
- "useSWR",
3256
- "useQuery",
3257
- "useInfiniteQuery",
3258
- "invalidateQueries",
3259
- "prefetchQuery",
3260
- "setQueryData",
3261
- "getQueryData",
3262
- "clearCache",
3263
- "__getCacheSnapshot",
3264
- // Form
3265
- "useForm",
3266
- "useField",
3267
- "rules",
3268
- "simpleResolver",
3269
- "zodResolver",
3270
- "yupResolver",
3271
- "Input",
3272
- "Textarea",
3273
- "Select",
3274
- "Checkbox",
3275
- "Radio",
3276
- "ErrorMessage"
3277
- ]);
3278
- function validateImports(importNames) {
3279
- if (!__DEV__ || !guardrails.importValidation) return [];
3280
- const invalid = [];
3281
- for (const name of importNames) {
3282
- if (!VALID_EXPORTS.has(name)) {
3283
- invalid.push({
3284
- name,
3285
- message: `"${name}" is not a valid export from what-framework.`,
3286
- suggestion: `Check the API reference. Did you mean: ${findClosest(name)}?`
3287
- });
3288
- }
3289
- }
3290
- return invalid;
3291
- }
3292
- function findClosest(input) {
3293
- const lower = input.toLowerCase();
3294
- let best = null;
3295
- let bestDist = Infinity;
3296
- for (const name of VALID_EXPORTS) {
3297
- const dist = levenshtein(lower, name.toLowerCase());
3298
- if (dist < bestDist) {
3299
- bestDist = dist;
3300
- best = name;
3301
- }
3302
- }
3303
- return bestDist <= 3 ? best : "(no close match found)";
3304
- }
3305
- function levenshtein(a, b) {
3306
- if (a.length === 0) return b.length;
3307
- if (b.length === 0) return a.length;
3308
- const matrix = [];
3309
- for (let i = 0; i <= b.length; i++) matrix[i] = [i];
3310
- for (let j = 0; j <= a.length; j++) matrix[0][j] = j;
3311
- for (let i = 1; i <= b.length; i++) {
3312
- for (let j = 1; j <= a.length; j++) {
3313
- const cost = b[i - 1] === a[j - 1] ? 0 : 1;
3314
- matrix[i][j] = Math.min(
3315
- matrix[i - 1][j] + 1,
3316
- matrix[i][j - 1] + 1,
3317
- matrix[i - 1][j - 1] + cost
3318
- );
3319
- }
3320
- }
3321
- return matrix[b.length][a.length];
3322
- }
3323
-
3324
- // packages/core/src/agent-context.js
3325
- var VERSION = "0.6.0";
3326
- var mountedComponents = [];
3327
- function registerComponent(component) {
3328
- if (!__DEV__) return;
3329
- mountedComponents.push(component);
3330
- }
3331
- function unregisterComponent(component) {
3332
- if (!__DEV__) return;
3333
- const idx = mountedComponents.indexOf(component);
3334
- if (idx >= 0) mountedComponents.splice(idx, 1);
3335
- }
3336
- function getMountedComponents() {
3337
- return mountedComponents.slice();
3338
- }
3339
- var activeSignals = [];
3340
- function registerSignal(sig) {
3341
- if (!__DEV__) return;
3342
- activeSignals.push(sig);
3343
- }
3344
- function unregisterSignal(sig) {
3345
- if (!__DEV__) return;
3346
- const idx = activeSignals.indexOf(sig);
3347
- if (idx >= 0) activeSignals.splice(idx, 1);
3348
- }
3349
- function getActiveSignals() {
3350
- return activeSignals.slice();
3351
- }
3352
- function getHealth() {
3353
- const errors = getCollectedErrors();
3354
- const recentErrors = errors.filter((e) => Date.now() - e.timestamp < 6e4);
3355
- const cycleErrors = errors.filter((e) => e.code === "ERR_INFINITE_EFFECT");
3356
- const effectCycleRisk = cycleErrors.length > 0;
3357
- const orphanErrors = errors.filter((e) => e.code === "ERR_ORPHAN_EFFECT");
3358
- const signalLeaks = activeSignals.filter((s) => {
3359
- if (s._subs && s._subs.size === 0) return true;
3360
- return false;
3361
- }).length;
3362
- const totalSignals = activeSignals.length;
3363
- const memoryPressure = totalSignals > 1e4 ? "high" : totalSignals > 1e3 ? "medium" : "low";
3364
- return {
3365
- effectCycleRisk,
3366
- orphanEffects: orphanErrors.length,
3367
- signalLeaks,
3368
- memoryPressure,
3369
- recentErrorCount: recentErrors.length,
3370
- totalSignals,
3371
- totalComponents: mountedComponents.length
3372
- };
3373
- }
3374
- function installAgentContext() {
3375
- if (!__DEV__) return;
3376
- if (typeof globalThis === "undefined") return;
3377
- globalThis.__WHAT_AGENT__ = {
3378
- framework: "what-framework",
3379
- version: VERSION,
3380
- mode: "development",
3381
- features: ["signals", "effects", "computed", "ssr", "islands", "router", "stores", "forms", "animations", "a11y"],
3382
- // Live accessors — always return current state
3383
- components: () => getMountedComponents().map((c) => ({
3384
- id: c.id,
3385
- name: c.name || c.displayName || c.constructor?.name
3386
- })),
3387
- signals: () => getActiveSignals().map((s, i) => ({
3388
- id: i,
3389
- name: s._debugName || `signal_${i}`,
3390
- value: typeof s === "function" ? s.peek?.() : void 0,
3391
- subscriberCount: s._subs ? s._subs.size : 0
3392
- })),
3393
- errors: () => getCollectedErrors(),
3394
- health: () => getHealth(),
3395
- // Metadata for agents
3396
- api: {
3397
- reactive: ["signal", "computed", "effect", "batch", "untrack", "flushSync", "createRoot", "memo"],
3398
- hooks: ["useState", "useSignal", "useComputed", "useEffect", "useMemo", "useCallback", "useRef", "useContext", "onMount", "onCleanup"],
3399
- components: ["Show", "For", "Switch", "Match", "Suspense", "ErrorBoundary", "lazy", "Island"],
3400
- data: ["useSWR", "useQuery", "useFetch", "useInfiniteQuery"],
3401
- store: ["createStore", "derived", "atom"]
3402
- }
3403
- };
3404
- }
3405
- export {
3406
- Checkbox,
3407
- ERROR_CODES,
3408
- ErrorBoundary,
3409
- ErrorMessage,
3410
- FocusTrap,
3411
- For,
3412
- Fragment,
3413
- Head,
3414
- Input,
3415
- Island,
3416
- IslandSkeleton,
3417
- Keys,
3418
- LiveRegion,
3419
- LoadingDots,
3420
- Match,
3421
- Placeholder,
3422
- Portal,
3423
- Radio,
3424
- Select,
3425
- Show,
3426
- Skeleton,
3427
- SkeletonAvatar,
3428
- SkeletonCard,
3429
- SkeletonTable,
3430
- SkeletonText,
3431
- SkipLink,
3432
- Spinner,
3433
- Suspense,
3434
- Switch,
3435
- Textarea,
3436
- VisuallyHidden,
3437
- WhatError,
3438
- _$createComponent,
3439
- _$templateImpl as _$template,
3440
- __drainPreinstallBuffer,
3441
- __getCacheSnapshot,
3442
- __readHydrationData,
3443
- __resetHydrationData,
3444
- __setDevToolsHooks,
3445
- _setTextInsertHook,
3446
- template as _template,
3447
- announce,
3448
- announceAssertive,
3449
- atom,
3450
- batch,
3451
- beginHeadCollection,
3452
- checkComponentName,
3453
- classList,
3454
- classifyError,
3455
- clearCache,
3456
- clearCollectedErrors,
3457
- clearHead,
3458
- cls,
3459
- collectError,
3460
- computed,
3461
- configureGuardrails,
3462
- createContext,
3463
- createResource,
3464
- createRoot,
3465
- createStore,
3466
- createTransitionClasses,
3467
- createWhatError,
3468
- cssTransition,
3469
- debounce,
3470
- delegateEvents,
3471
- derived,
3472
- each,
3473
- easings,
3474
- effect,
3475
- endHeadCollection,
3476
- flushScheduler,
3477
- flushSync,
3478
- getActiveSignals,
3479
- getCollectedErrors,
3480
- getGuardrailConfig,
3481
- getHealth,
3482
- getLoaderData,
3483
- getMountedComponents,
3484
- getOwner,
3485
- getQueryData,
3486
- getResource,
3487
- getServerContext,
3488
- h,
3489
- html,
3490
- hydrate,
3491
- insert,
3492
- installAgentContext,
3493
- installSignalReadGuardrail,
3494
- invalidateQueries,
3495
- isHydrating,
3496
- lazy,
3497
- mapArray,
3498
- measure,
3499
- memo2 as memo,
3500
- mount,
3501
- mutate,
3502
- nextFrame,
3503
- on,
3504
- onCleanup2 as onCleanup,
3505
- onIntersect,
3506
- onKey,
3507
- onKeys,
3508
- onMount,
3509
- onResize,
3510
- onCleanup as onRootCleanup,
3511
- prefetchQuery,
3512
- raf,
3513
- registerComponent,
3514
- registerSignal,
3515
- rules,
3516
- runWithOwner,
3517
- runWithServerContext,
3518
- scheduleRead,
3519
- scheduleWrite,
3520
- setProp,
3521
- setQueryData,
3522
- setServerContext,
3523
- signal,
3524
- memo as signalMemo,
3525
- simpleResolver,
3526
- smoothScrollTo,
3527
- spread,
3528
- spring,
3529
- storeComputed,
3530
- style,
3531
- svgTemplate,
3532
- template,
3533
- throttle,
3534
- transition,
3535
- tween,
3536
- unregisterComponent,
3537
- unregisterSignal,
3538
- untrack,
3539
- useAnimatedValue,
3540
- useAriaChecked,
3541
- useAriaExpanded,
3542
- useAriaSelected,
3543
- useCallback,
3544
- useClickOutside,
3545
- useComputed,
3546
- useContext,
3547
- useDescribedBy,
3548
- useEffect,
3549
- useFetch,
3550
- useField,
3551
- useFocus,
3552
- useFocusRestore,
3553
- useFocusTrap,
3554
- useForm,
3555
- useGesture,
3556
- useId,
3557
- useIds,
3558
- useInfiniteQuery,
3559
- useLabelledBy,
3560
- useLoaderData,
3561
- useLocalStorage,
3562
- useMediaQuery,
3563
- useMemo,
3564
- useQuery,
3565
- useReducer,
3566
- useRef,
3567
- useRovingTabIndex,
3568
- useSWR,
3569
- useScheduledEffect,
3570
- useSignal,
3571
- useSkeleton,
3572
- useState,
3573
- useTransition,
3574
- validateImports,
3575
- yupResolver,
3576
- zodResolver
3577
- };
3578
- //# sourceMappingURL=index.js.map