what-core 0.11.0 → 0.11.2

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 (93) hide show
  1. package/dist/chunk-DF3XC3WN.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 +2 -3
  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/src/agent-context.js +1 -1
  11. package/src/reactive.js +20 -4
  12. package/src/render.js +17 -1
  13. package/dist/a11y.js +0 -440
  14. package/dist/animation.js +0 -548
  15. package/dist/chunk-2IZMPODD.min.js +0 -2
  16. package/dist/chunk-2IZMPODD.min.js.map +0 -7
  17. package/dist/chunk-2P7OVL2L.js +0 -1386
  18. package/dist/chunk-2P7OVL2L.js.map +0 -7
  19. package/dist/chunk-5EQUBJWQ.js +0 -1365
  20. package/dist/chunk-5EQUBJWQ.js.map +0 -7
  21. package/dist/chunk-6DAIK77K.min.js +0 -2
  22. package/dist/chunk-6DAIK77K.min.js.map +0 -7
  23. package/dist/chunk-AW3BAPIK.js +0 -1685
  24. package/dist/chunk-AW3BAPIK.js.map +0 -7
  25. package/dist/chunk-AZP2EOGX.js +0 -188
  26. package/dist/chunk-AZP2EOGX.js.map +0 -7
  27. package/dist/chunk-CCINITLW.js +0 -1692
  28. package/dist/chunk-CCINITLW.js.map +0 -7
  29. package/dist/chunk-F2HUXI22.js +0 -1675
  30. package/dist/chunk-F2HUXI22.js.map +0 -7
  31. package/dist/chunk-GZRA4IAJ.js +0 -1699
  32. package/dist/chunk-GZRA4IAJ.js.map +0 -7
  33. package/dist/chunk-H3GA34JK.js +0 -1384
  34. package/dist/chunk-H3GA34JK.js.map +0 -7
  35. package/dist/chunk-KBM6CWG4.min.js +0 -2
  36. package/dist/chunk-KBM6CWG4.min.js.map +0 -7
  37. package/dist/chunk-KL7TNUIU.min.js +0 -2
  38. package/dist/chunk-KL7TNUIU.min.js.map +0 -7
  39. package/dist/chunk-L6XOF7P4.min.js +0 -2
  40. package/dist/chunk-L6XOF7P4.min.js.map +0 -7
  41. package/dist/chunk-M7UEET5O.js +0 -1323
  42. package/dist/chunk-M7UEET5O.js.map +0 -7
  43. package/dist/chunk-MH7L756Y.min.js +0 -2
  44. package/dist/chunk-MH7L756Y.min.js.map +0 -7
  45. package/dist/chunk-O3SKPRTY.min.js.map +0 -7
  46. package/dist/chunk-RI7T5VFD.min.js +0 -2
  47. package/dist/chunk-RI7T5VFD.min.js.map +0 -7
  48. package/dist/chunk-RN6QIBWL.min.js +0 -2
  49. package/dist/chunk-RN6QIBWL.min.js.map +0 -7
  50. package/dist/chunk-VKCFJ4OT.min.js +0 -2
  51. package/dist/chunk-VKCFJ4OT.min.js.map +0 -7
  52. package/dist/chunk-VMTTYB4L.min.js +0 -2
  53. package/dist/chunk-VMTTYB4L.min.js.map +0 -7
  54. package/dist/chunk-VP4WLF5A.js +0 -1323
  55. package/dist/chunk-VP4WLF5A.js.map +0 -7
  56. package/dist/chunk-YA3W4XKH.js +0 -1323
  57. package/dist/chunk-YA3W4XKH.js.map +0 -7
  58. package/dist/compiler.js +0 -1799
  59. package/dist/compiler.js.map +0 -7
  60. package/dist/compiler.min.js +0 -2
  61. package/dist/compiler.min.js.map +0 -7
  62. package/dist/components.js +0 -229
  63. package/dist/data.js +0 -638
  64. package/dist/devtools.js +0 -10
  65. package/dist/devtools.js.map +0 -7
  66. package/dist/devtools.min.js +0 -2
  67. package/dist/devtools.min.js.map +0 -7
  68. package/dist/dom.js +0 -439
  69. package/dist/form.js +0 -509
  70. package/dist/h.js +0 -152
  71. package/dist/head.js +0 -51
  72. package/dist/helpers.js +0 -140
  73. package/dist/hooks.js +0 -210
  74. package/dist/index.js +0 -3576
  75. package/dist/index.js.map +0 -7
  76. package/dist/index.min.js.map +0 -7
  77. package/dist/jsx-dev-runtime.js +0 -23
  78. package/dist/jsx-dev-runtime.js.map +0 -7
  79. package/dist/jsx-dev-runtime.min.js.map +0 -7
  80. package/dist/jsx-runtime.js +0 -21
  81. package/dist/jsx-runtime.js.map +0 -7
  82. package/dist/jsx-runtime.min.js.map +0 -7
  83. package/dist/reactive.js +0 -432
  84. package/dist/render.js +0 -53
  85. package/dist/render.js.map +0 -7
  86. package/dist/render.min.js.map +0 -7
  87. package/dist/scheduler.js +0 -246
  88. package/dist/skeleton.js +0 -363
  89. package/dist/store.js +0 -83
  90. package/dist/testing.js +0 -439
  91. package/dist/testing.js.map +0 -7
  92. package/dist/testing.min.js.map +0 -7
  93. package/dist/what.js +0 -117
package/dist/a11y.js DELETED
@@ -1,440 +0,0 @@
1
- // What Framework - Accessibility Utilities
2
- // Focus management, ARIA helpers, screen reader announcements
3
-
4
- import { signal, effect } from './reactive.js';
5
- import { h } from './h.js';
6
- import { getCurrentComponent } from './dom.js';
7
-
8
- // --- Focus Management ---
9
-
10
- // Track currently focused element
11
- const focusedElement = signal(null);
12
-
13
- if (typeof document !== 'undefined') {
14
- document.addEventListener('focusin', (e) => {
15
- focusedElement.set(e.target);
16
- });
17
- }
18
-
19
- export function useFocus() {
20
- return {
21
- current: () => focusedElement(),
22
- focus: (element) => element?.focus(),
23
- blur: () => document.activeElement?.blur(),
24
- };
25
- }
26
-
27
- // --- Focus Trap ---
28
- // Keep focus within a container (for modals, dialogs, etc.)
29
-
30
- export function useFocusTrap(containerRef) {
31
- let previousFocus = null;
32
-
33
- function activate() {
34
- if (typeof document === 'undefined') return;
35
-
36
- previousFocus = document.activeElement;
37
- const container = containerRef.current || containerRef;
38
-
39
- if (!container) return;
40
-
41
- // Find all focusable elements
42
- const focusables = getFocusableElements(container);
43
- if (focusables.length === 0) return;
44
-
45
- // Focus first element
46
- focusables[0].focus();
47
-
48
- // Handle Tab key
49
- function handleKeydown(e) {
50
- if (e.key !== 'Tab') return;
51
-
52
- const focusables = getFocusableElements(container);
53
- const first = focusables[0];
54
- const last = focusables[focusables.length - 1];
55
-
56
- if (e.shiftKey) {
57
- // Shift+Tab: if on first, go to last
58
- if (document.activeElement === first) {
59
- e.preventDefault();
60
- last.focus();
61
- }
62
- } else {
63
- // Tab: if on last, go to first
64
- if (document.activeElement === last) {
65
- e.preventDefault();
66
- first.focus();
67
- }
68
- }
69
- }
70
-
71
- container.addEventListener('keydown', handleKeydown);
72
-
73
- return () => {
74
- container.removeEventListener('keydown', handleKeydown);
75
- };
76
- }
77
-
78
- function deactivate() {
79
- if (previousFocus && typeof previousFocus.focus === 'function') {
80
- previousFocus.focus();
81
- }
82
- }
83
-
84
- return { activate, deactivate };
85
- }
86
-
87
- function getFocusableElements(container) {
88
- const selector = [
89
- 'button:not([disabled])',
90
- 'a[href]',
91
- 'input:not([disabled])',
92
- 'select:not([disabled])',
93
- 'textarea:not([disabled])',
94
- '[tabindex]:not([tabindex="-1"])',
95
- ].join(',');
96
-
97
- return Array.from(container.querySelectorAll(selector)).filter(el => {
98
- return el.offsetParent !== null; // Visible
99
- });
100
- }
101
-
102
- // --- Focus Scope ---
103
- // Component wrapper that traps focus
104
-
105
- export function FocusTrap({ children, active = true }) {
106
- const containerRef = { current: null };
107
- const trap = useFocusTrap(containerRef);
108
-
109
- // Scope the effect to the component lifecycle so it disposes on unmount
110
- const dispose = effect(() => {
111
- if (active) {
112
- const cleanup = trap.activate();
113
- return () => {
114
- cleanup?.();
115
- trap.deactivate();
116
- };
117
- }
118
- });
119
-
120
- // Register cleanup on component context
121
- const ctx = getCurrentComponent?.();
122
- if (ctx) {
123
- ctx._cleanupCallbacks = ctx._cleanupCallbacks || [];
124
- ctx._cleanupCallbacks.push(dispose);
125
- }
126
-
127
- return h('div', { ref: containerRef }, children);
128
- }
129
-
130
- // --- Screen Reader Announcements ---
131
-
132
- let announcer = null;
133
- let announcerId = 0;
134
-
135
- function getAnnouncer() {
136
- if (typeof document === 'undefined') return null;
137
-
138
- if (!announcer) {
139
- announcer = document.createElement('div');
140
- announcer.id = 'what-announcer';
141
- announcer.setAttribute('aria-live', 'polite');
142
- announcer.setAttribute('aria-atomic', 'true');
143
- announcer.style.cssText = `
144
- position: absolute;
145
- width: 1px;
146
- height: 1px;
147
- padding: 0;
148
- margin: -1px;
149
- overflow: hidden;
150
- clip: rect(0, 0, 0, 0);
151
- white-space: nowrap;
152
- border: 0;
153
- `;
154
- document.body.appendChild(announcer);
155
- }
156
- return announcer;
157
- }
158
-
159
- export function announce(message, options = {}) {
160
- const { priority = 'polite', timeout = 1000 } = options;
161
- const announcer = getAnnouncer();
162
- if (!announcer) return;
163
-
164
- announcer.setAttribute('aria-live', priority);
165
-
166
- // Clear and re-announce (required for some screen readers)
167
- const id = ++announcerId;
168
- announcer.textContent = '';
169
-
170
- requestAnimationFrame(() => {
171
- if (announcerId === id) {
172
- announcer.textContent = message;
173
- }
174
- });
175
-
176
- // Clear after timeout
177
- setTimeout(() => {
178
- if (announcerId === id) {
179
- announcer.textContent = '';
180
- }
181
- }, timeout);
182
- }
183
-
184
- export function announceAssertive(message) {
185
- return announce(message, { priority: 'assertive' });
186
- }
187
-
188
- // --- Skip Link ---
189
- // Accessible skip navigation
190
-
191
- export function SkipLink({ href = '#main', children = 'Skip to content' }) {
192
- return h('a', {
193
- href,
194
- class: 'what-skip-link',
195
- onClick: (e) => {
196
- e.preventDefault();
197
- const target = document.querySelector(href);
198
- if (target) {
199
- target.focus();
200
- target.scrollIntoView();
201
- }
202
- },
203
- style: {
204
- position: 'absolute',
205
- top: '-40px',
206
- left: '0',
207
- padding: '8px',
208
- background: '#000',
209
- color: '#fff',
210
- textDecoration: 'none',
211
- zIndex: '10000',
212
- },
213
- onFocus: (e) => {
214
- e.target.style.top = '0';
215
- },
216
- onBlur: (e) => {
217
- e.target.style.top = '-40px';
218
- },
219
- }, children);
220
- }
221
-
222
- // --- ARIA Helpers ---
223
-
224
- export function useAriaExpanded(initialExpanded = false) {
225
- const expanded = signal(initialExpanded);
226
-
227
- return {
228
- expanded: () => expanded(),
229
- toggle: () => expanded.set(!expanded.peek()),
230
- open: () => expanded.set(true),
231
- close: () => expanded.set(false),
232
- buttonProps: () => ({
233
- 'aria-expanded': expanded(),
234
- onClick: () => expanded.set(!expanded.peek()),
235
- }),
236
- panelProps: () => ({
237
- hidden: !expanded(),
238
- }),
239
- };
240
- }
241
-
242
- export function useAriaSelected(initialSelected = null) {
243
- const selected = signal(initialSelected);
244
-
245
- return {
246
- selected: () => selected(),
247
- select: (value) => selected.set(value),
248
- isSelected: (value) => selected() === value,
249
- itemProps: (value) => ({
250
- 'aria-selected': selected() === value,
251
- onClick: () => selected.set(value),
252
- }),
253
- };
254
- }
255
-
256
- export function useAriaChecked(initialChecked = false) {
257
- const checked = signal(initialChecked);
258
-
259
- return {
260
- checked: () => checked(),
261
- toggle: () => checked.set(!checked.peek()),
262
- set: (value) => checked.set(value),
263
- checkboxProps: () => ({
264
- role: 'checkbox',
265
- 'aria-checked': checked(),
266
- tabIndex: 0,
267
- onClick: () => checked.set(!checked.peek()),
268
- onKeyDown: (e) => {
269
- if (e.key === ' ' || e.key === 'Enter') {
270
- e.preventDefault();
271
- checked.set(!checked.peek());
272
- }
273
- },
274
- }),
275
- };
276
- }
277
-
278
- // --- Roving Tab Index ---
279
- // For keyboard navigation in lists, toolbars, etc.
280
-
281
- export function useRovingTabIndex(itemCountOrSignal) {
282
- // Accept either a static number or a signal/getter for dynamic lists
283
- const getCount = typeof itemCountOrSignal === 'function'
284
- ? itemCountOrSignal
285
- : () => itemCountOrSignal;
286
- const focusIndex = signal(0);
287
-
288
- function handleKeyDown(e) {
289
- const count = getCount();
290
- if (count <= 0) return;
291
- switch (e.key) {
292
- case 'ArrowDown':
293
- case 'ArrowRight':
294
- e.preventDefault();
295
- focusIndex.set((focusIndex.peek() + 1) % count);
296
- break;
297
- case 'ArrowUp':
298
- case 'ArrowLeft':
299
- e.preventDefault();
300
- focusIndex.set((focusIndex.peek() - 1 + count) % count);
301
- break;
302
- case 'Home':
303
- e.preventDefault();
304
- focusIndex.set(0);
305
- break;
306
- case 'End':
307
- e.preventDefault();
308
- focusIndex.set(count - 1);
309
- break;
310
- }
311
- }
312
-
313
- return {
314
- focusIndex: () => focusIndex(),
315
- setFocusIndex: (i) => focusIndex.set(i),
316
- getItemProps: (index) => ({
317
- tabIndex: focusIndex() === index ? 0 : -1,
318
- onKeyDown: handleKeyDown,
319
- onFocus: () => focusIndex.set(index),
320
- }),
321
- containerProps: () => ({
322
- role: 'listbox',
323
- }),
324
- };
325
- }
326
-
327
- // --- Visually Hidden ---
328
- // Hide content visually but keep accessible to screen readers
329
-
330
- export function VisuallyHidden({ children, as = 'span' }) {
331
- return h(as, {
332
- style: {
333
- position: 'absolute',
334
- width: '1px',
335
- height: '1px',
336
- padding: '0',
337
- margin: '-1px',
338
- overflow: 'hidden',
339
- clip: 'rect(0, 0, 0, 0)',
340
- whiteSpace: 'nowrap',
341
- border: '0',
342
- },
343
- }, children);
344
- }
345
-
346
- // --- Live Region Component ---
347
-
348
- export function LiveRegion({ children, priority = 'polite', atomic = true }) {
349
- return h('div', {
350
- 'aria-live': priority,
351
- 'aria-atomic': atomic,
352
- }, children);
353
- }
354
-
355
- // --- ID Generator ---
356
- // Generate unique IDs for ARIA attributes
357
-
358
- let idCounter = 0;
359
-
360
- export function useId(prefix = 'what') {
361
- const id = `${prefix}-${++idCounter}`;
362
- return () => id;
363
- }
364
-
365
- export function useIds(count, prefix = 'what') {
366
- const ids = [];
367
- for (let i = 0; i < count; i++) {
368
- ids.push(`${prefix}-${++idCounter}`);
369
- }
370
- return ids;
371
- }
372
-
373
- // --- Describe ---
374
- // Associate description with an element
375
-
376
- export function useDescribedBy(description) {
377
- const id = useId('desc');
378
-
379
- return {
380
- descriptionId: id,
381
- descriptionProps: () => ({
382
- id: id(),
383
- style: { display: 'none' },
384
- }),
385
- describedByProps: () => ({
386
- 'aria-describedby': id(),
387
- }),
388
- Description: () => h('div', {
389
- id: id(),
390
- style: { display: 'none' },
391
- }, description),
392
- };
393
- }
394
-
395
- // --- Labelledby ---
396
-
397
- export function useLabelledBy(label) {
398
- const id = useId('label');
399
-
400
- return {
401
- labelId: id,
402
- labelProps: () => ({
403
- id: id(),
404
- }),
405
- labelledByProps: () => ({
406
- 'aria-labelledby': id(),
407
- }),
408
- };
409
- }
410
-
411
- // --- Keyboard Navigation Helpers ---
412
-
413
- export const Keys = {
414
- Enter: 'Enter',
415
- Space: ' ',
416
- Escape: 'Escape',
417
- ArrowUp: 'ArrowUp',
418
- ArrowDown: 'ArrowDown',
419
- ArrowLeft: 'ArrowLeft',
420
- ArrowRight: 'ArrowRight',
421
- Home: 'Home',
422
- End: 'End',
423
- Tab: 'Tab',
424
- };
425
-
426
- export function onKey(key, handler) {
427
- return (e) => {
428
- if (e.key === key) {
429
- handler(e);
430
- }
431
- };
432
- }
433
-
434
- export function onKeys(keys, handler) {
435
- return (e) => {
436
- if (keys.includes(e.key)) {
437
- handler(e);
438
- }
439
- };
440
- }