what-core 0.11.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 (91) hide show
  1. package/dist/{chunk-RI7T5VFD.min.js → chunk-D5YDPQ57.min.js} +1 -2
  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/dist/a11y.js +0 -440
  13. package/dist/animation.js +0 -548
  14. package/dist/chunk-2IZMPODD.min.js +0 -2
  15. package/dist/chunk-2IZMPODD.min.js.map +0 -7
  16. package/dist/chunk-2P7OVL2L.js +0 -1386
  17. package/dist/chunk-2P7OVL2L.js.map +0 -7
  18. package/dist/chunk-5EQUBJWQ.js +0 -1365
  19. package/dist/chunk-5EQUBJWQ.js.map +0 -7
  20. package/dist/chunk-6DAIK77K.min.js +0 -2
  21. package/dist/chunk-6DAIK77K.min.js.map +0 -7
  22. package/dist/chunk-AW3BAPIK.js +0 -1685
  23. package/dist/chunk-AW3BAPIK.js.map +0 -7
  24. package/dist/chunk-AZP2EOGX.js +0 -188
  25. package/dist/chunk-AZP2EOGX.js.map +0 -7
  26. package/dist/chunk-CCINITLW.js +0 -1692
  27. package/dist/chunk-CCINITLW.js.map +0 -7
  28. package/dist/chunk-F2HUXI22.js +0 -1675
  29. package/dist/chunk-F2HUXI22.js.map +0 -7
  30. package/dist/chunk-GZRA4IAJ.js +0 -1699
  31. package/dist/chunk-GZRA4IAJ.js.map +0 -7
  32. package/dist/chunk-H3GA34JK.js +0 -1384
  33. package/dist/chunk-H3GA34JK.js.map +0 -7
  34. package/dist/chunk-KBM6CWG4.min.js +0 -2
  35. package/dist/chunk-KBM6CWG4.min.js.map +0 -7
  36. package/dist/chunk-KL7TNUIU.min.js +0 -2
  37. package/dist/chunk-KL7TNUIU.min.js.map +0 -7
  38. package/dist/chunk-L6XOF7P4.min.js +0 -2
  39. package/dist/chunk-L6XOF7P4.min.js.map +0 -7
  40. package/dist/chunk-M7UEET5O.js +0 -1323
  41. package/dist/chunk-M7UEET5O.js.map +0 -7
  42. package/dist/chunk-MH7L756Y.min.js +0 -2
  43. package/dist/chunk-MH7L756Y.min.js.map +0 -7
  44. package/dist/chunk-O3SKPRTY.min.js.map +0 -7
  45. package/dist/chunk-RI7T5VFD.min.js.map +0 -7
  46. package/dist/chunk-RN6QIBWL.min.js +0 -2
  47. package/dist/chunk-RN6QIBWL.min.js.map +0 -7
  48. package/dist/chunk-VKCFJ4OT.min.js +0 -2
  49. package/dist/chunk-VKCFJ4OT.min.js.map +0 -7
  50. package/dist/chunk-VMTTYB4L.min.js +0 -2
  51. package/dist/chunk-VMTTYB4L.min.js.map +0 -7
  52. package/dist/chunk-VP4WLF5A.js +0 -1323
  53. package/dist/chunk-VP4WLF5A.js.map +0 -7
  54. package/dist/chunk-YA3W4XKH.js +0 -1323
  55. package/dist/chunk-YA3W4XKH.js.map +0 -7
  56. package/dist/compiler.js +0 -1799
  57. package/dist/compiler.js.map +0 -7
  58. package/dist/compiler.min.js +0 -2
  59. package/dist/compiler.min.js.map +0 -7
  60. package/dist/components.js +0 -229
  61. package/dist/data.js +0 -638
  62. package/dist/devtools.js +0 -10
  63. package/dist/devtools.js.map +0 -7
  64. package/dist/devtools.min.js +0 -2
  65. package/dist/devtools.min.js.map +0 -7
  66. package/dist/dom.js +0 -439
  67. package/dist/form.js +0 -509
  68. package/dist/h.js +0 -152
  69. package/dist/head.js +0 -51
  70. package/dist/helpers.js +0 -140
  71. package/dist/hooks.js +0 -210
  72. package/dist/index.js +0 -3576
  73. package/dist/index.js.map +0 -7
  74. package/dist/index.min.js.map +0 -7
  75. package/dist/jsx-dev-runtime.js +0 -23
  76. package/dist/jsx-dev-runtime.js.map +0 -7
  77. package/dist/jsx-dev-runtime.min.js.map +0 -7
  78. package/dist/jsx-runtime.js +0 -21
  79. package/dist/jsx-runtime.js.map +0 -7
  80. package/dist/jsx-runtime.min.js.map +0 -7
  81. package/dist/reactive.js +0 -432
  82. package/dist/render.js +0 -53
  83. package/dist/render.js.map +0 -7
  84. package/dist/render.min.js.map +0 -7
  85. package/dist/scheduler.js +0 -246
  86. package/dist/skeleton.js +0 -363
  87. package/dist/store.js +0 -83
  88. package/dist/testing.js +0 -439
  89. package/dist/testing.js.map +0 -7
  90. package/dist/testing.min.js.map +0 -7
  91. package/dist/what.js +0 -117
package/dist/scheduler.js DELETED
@@ -1,246 +0,0 @@
1
- // What Framework - DOM Scheduler
2
- // Batches DOM reads and writes to prevent layout thrashing.
3
- // Inspired by fastdom but integrated with our reactive system.
4
-
5
- // Queue phases: reads run first, then writes
6
- const readQueue = [];
7
- const writeQueue = [];
8
- let scheduled = false;
9
-
10
- // --- Schedule a DOM read operation ---
11
- // Reads should be batched together and run before writes
12
- // to avoid forced synchronous layouts.
13
- //
14
- // Example:
15
- // scheduleRead(() => {
16
- // const height = element.offsetHeight; // Read
17
- // scheduleWrite(() => {
18
- // element.style.height = height + 'px'; // Write
19
- // });
20
- // });
21
-
22
- export function scheduleRead(fn) {
23
- readQueue.push(fn);
24
- schedule();
25
- return () => {
26
- const idx = readQueue.indexOf(fn);
27
- if (idx !== -1) readQueue.splice(idx, 1);
28
- };
29
- }
30
-
31
- // --- Schedule a DOM write operation ---
32
- // Writes are batched and run after all reads complete.
33
-
34
- export function scheduleWrite(fn) {
35
- writeQueue.push(fn);
36
- schedule();
37
- return () => {
38
- const idx = writeQueue.indexOf(fn);
39
- if (idx !== -1) writeQueue.splice(idx, 1);
40
- };
41
- }
42
-
43
- // --- Flush all queued operations immediately ---
44
- // Useful when you need synchronous DOM access.
45
-
46
- export function flushScheduler() {
47
- // Run all reads first
48
- while (readQueue.length > 0) {
49
- const fn = readQueue.shift();
50
- try { fn(); } catch (e) { console.error('[what] Scheduler read error:', e); }
51
- }
52
-
53
- // Then all writes
54
- while (writeQueue.length > 0) {
55
- const fn = writeQueue.shift();
56
- try { fn(); } catch (e) { console.error('[what] Scheduler write error:', e); }
57
- }
58
-
59
- scheduled = false;
60
- }
61
-
62
- // --- Internal scheduling ---
63
-
64
- function schedule() {
65
- if (scheduled) return;
66
- scheduled = true;
67
- requestAnimationFrame(flushScheduler);
68
- }
69
-
70
- // --- Measure helper ---
71
- // Read a layout property without causing thrashing.
72
- // Returns a promise that resolves with the value.
73
-
74
- export function measure(fn) {
75
- return new Promise(resolve => {
76
- scheduleRead(() => {
77
- resolve(fn());
78
- });
79
- });
80
- }
81
-
82
- // --- Mutate helper ---
83
- // Write to DOM without causing thrashing.
84
- // Returns a promise that resolves when the write is done.
85
-
86
- export function mutate(fn) {
87
- return new Promise(resolve => {
88
- scheduleWrite(() => {
89
- fn();
90
- resolve();
91
- });
92
- });
93
- }
94
-
95
- // --- useScheduledEffect ---
96
- // Effect that automatically batches DOM operations.
97
-
98
- import { effect } from './reactive.js';
99
-
100
- export function useScheduledEffect(readFn, writeFn) {
101
- const effectKey = Symbol('scheduledEffect');
102
- return effect(() => {
103
- // Use raf() to debounce: only the latest callback runs per frame,
104
- // avoiding creating new closures on every signal change.
105
- raf(effectKey, () => {
106
- scheduleRead(() => {
107
- const data = readFn();
108
- if (writeFn) {
109
- scheduleWrite(() => writeFn(data));
110
- }
111
- });
112
- });
113
- });
114
- }
115
-
116
- // --- Animation frame helper ---
117
- // Like requestAnimationFrame but returns a cancellable promise.
118
-
119
- export function nextFrame() {
120
- let cancel;
121
- const promise = new Promise((resolve, reject) => {
122
- const id = requestAnimationFrame(resolve);
123
- cancel = () => {
124
- cancelAnimationFrame(id);
125
- reject(new Error('Cancelled'));
126
- };
127
- });
128
- promise.cancel = cancel;
129
- return promise;
130
- }
131
-
132
- // --- Debounced RAF ---
133
- // Only runs the latest callback once per frame.
134
-
135
- const debouncedCallbacks = new Map();
136
-
137
- export function raf(key, fn) {
138
- if (debouncedCallbacks.has(key)) {
139
- // Replace callback, don't schedule new frame
140
- debouncedCallbacks.set(key, fn);
141
- } else {
142
- debouncedCallbacks.set(key, fn);
143
- requestAnimationFrame(() => {
144
- const callback = debouncedCallbacks.get(key);
145
- debouncedCallbacks.delete(key);
146
- if (callback) callback();
147
- });
148
- }
149
- }
150
-
151
- // --- Resize Observer helper ---
152
- // Batched resize observations.
153
-
154
- const resizeObservers = new WeakMap();
155
- let sharedResizeObserver = null;
156
-
157
- export function onResize(element, callback) {
158
- if (typeof ResizeObserver === 'undefined') {
159
- // Fallback: just call once
160
- callback(element.getBoundingClientRect());
161
- return () => {};
162
- }
163
-
164
- if (!sharedResizeObserver) {
165
- sharedResizeObserver = new ResizeObserver(entries => {
166
- scheduleRead(() => {
167
- for (const entry of entries) {
168
- const cb = resizeObservers.get(entry.target);
169
- if (cb) {
170
- cb(entry.contentRect);
171
- }
172
- }
173
- });
174
- });
175
- }
176
-
177
- resizeObservers.set(element, callback);
178
- sharedResizeObserver.observe(element);
179
-
180
- return () => {
181
- resizeObservers.delete(element);
182
- sharedResizeObserver.unobserve(element);
183
- };
184
- }
185
-
186
- // --- Intersection Observer helper ---
187
- // Batched intersection observations.
188
-
189
- export function onIntersect(element, callback, options = {}) {
190
- if (typeof IntersectionObserver === 'undefined') {
191
- // Fallback: assume visible
192
- callback({ isIntersecting: true, intersectionRatio: 1 });
193
- return () => {};
194
- }
195
-
196
- const observer = new IntersectionObserver(entries => {
197
- scheduleRead(() => {
198
- for (const entry of entries) {
199
- callback(entry);
200
- }
201
- });
202
- }, options);
203
-
204
- observer.observe(element);
205
-
206
- return () => observer.disconnect();
207
- }
208
-
209
- // --- Smooth scrolling with scheduler ---
210
-
211
- export function smoothScrollTo(element, options = {}) {
212
- const { duration = 300, easing = t => t * (2 - t) } = options;
213
-
214
- return new Promise(resolve => {
215
- let startY;
216
- let targetY;
217
- let startTime;
218
-
219
- scheduleRead(() => {
220
- startY = window.scrollY;
221
- const rect = element.getBoundingClientRect();
222
- targetY = startY + rect.top;
223
- startTime = performance.now();
224
- tick();
225
- });
226
-
227
- function tick() {
228
- scheduleRead(() => {
229
- const elapsed = performance.now() - startTime;
230
- const progress = Math.min(elapsed / duration, 1);
231
- const easedProgress = easing(progress);
232
- const currentY = startY + (targetY - startY) * easedProgress;
233
-
234
- scheduleWrite(() => {
235
- window.scrollTo(0, currentY);
236
-
237
- if (progress < 1) {
238
- requestAnimationFrame(tick);
239
- } else {
240
- resolve();
241
- }
242
- });
243
- });
244
- }
245
- });
246
- }
package/dist/skeleton.js DELETED
@@ -1,363 +0,0 @@
1
- // What Framework - Skeleton Loaders
2
- // Loading placeholders for content, islands, and async data
3
-
4
- import { h } from './h.js';
5
- import { signal, effect } from './reactive.js';
6
-
7
- // --- Skeleton Base Styles ---
8
-
9
- const skeletonStyles = `
10
- .what-skeleton {
11
- background: linear-gradient(
12
- 90deg,
13
- var(--skeleton-base, #e0e0e0) 0%,
14
- var(--skeleton-highlight, #f0f0f0) 50%,
15
- var(--skeleton-base, #e0e0e0) 100%
16
- );
17
- background-size: 200% 100%;
18
- animation: what-skeleton-shimmer 1.5s infinite ease-in-out;
19
- border-radius: var(--skeleton-radius, 4px);
20
- }
21
-
22
- @keyframes what-skeleton-shimmer {
23
- 0% { background-position: 200% 0; }
24
- 100% { background-position: -200% 0; }
25
- }
26
-
27
- .what-skeleton-pulse {
28
- animation: what-skeleton-pulse 1.5s infinite ease-in-out;
29
- }
30
-
31
- @keyframes what-skeleton-pulse {
32
- 0%, 100% { opacity: 1; }
33
- 50% { opacity: 0.5; }
34
- }
35
-
36
- .what-skeleton-wave {
37
- position: relative;
38
- overflow: hidden;
39
- }
40
-
41
- .what-skeleton-wave::after {
42
- content: '';
43
- position: absolute;
44
- top: 0;
45
- right: 0;
46
- bottom: 0;
47
- left: 0;
48
- background: linear-gradient(
49
- 90deg,
50
- transparent 0%,
51
- rgba(255, 255, 255, 0.4) 50%,
52
- transparent 100%
53
- );
54
- animation: what-skeleton-wave 1.5s infinite;
55
- }
56
-
57
- @keyframes what-skeleton-wave {
58
- 0% { transform: translateX(-100%); }
59
- 100% { transform: translateX(100%); }
60
- }
61
- `;
62
-
63
- // Inject styles once
64
- let stylesInjected = false;
65
-
66
- function injectStyles() {
67
- if (stylesInjected || typeof document === 'undefined') return;
68
- stylesInjected = true;
69
-
70
- const style = document.createElement('style');
71
- style.textContent = skeletonStyles;
72
- document.head.appendChild(style);
73
- }
74
-
75
- // --- Skeleton Component ---
76
-
77
- export function Skeleton({
78
- width,
79
- height,
80
- variant = 'shimmer', // 'shimmer' | 'pulse' | 'wave'
81
- circle = false,
82
- class: className,
83
- style: customStyle,
84
- count = 1,
85
- }) {
86
- injectStyles();
87
-
88
- const baseClass = `what-skeleton ${variant === 'pulse' ? 'what-skeleton-pulse' : ''} ${variant === 'wave' ? 'what-skeleton-wave' : ''}`;
89
- const finalClass = className ? `${baseClass} ${className}` : baseClass;
90
-
91
- const style = {
92
- width: typeof width === 'number' ? `${width}px` : width,
93
- height: typeof height === 'number' ? `${height}px` : height,
94
- borderRadius: circle ? '50%' : undefined,
95
- ...customStyle,
96
- };
97
-
98
- if (count === 1) {
99
- return h('div', { class: finalClass, style, 'aria-hidden': 'true' });
100
- }
101
-
102
- return Array.from({ length: count }, (_, i) =>
103
- h('div', {
104
- key: i,
105
- class: finalClass,
106
- style: { ...style, marginBottom: i < count - 1 ? '8px' : undefined },
107
- 'aria-hidden': 'true',
108
- })
109
- );
110
- }
111
-
112
- // --- Skeleton Text ---
113
-
114
- export function SkeletonText({
115
- lines = 3,
116
- lastLineWidth = '60%',
117
- lineHeight = 16,
118
- gap = 8,
119
- variant = 'shimmer',
120
- }) {
121
- injectStyles();
122
-
123
- return h('div', { class: 'what-skeleton-text', 'aria-hidden': 'true' },
124
- Array.from({ length: lines }, (_, i) =>
125
- h('div', {
126
- key: i,
127
- class: `what-skeleton ${variant === 'pulse' ? 'what-skeleton-pulse' : ''}`,
128
- style: {
129
- height: `${lineHeight}px`,
130
- width: i === lines - 1 ? lastLineWidth : '100%',
131
- marginBottom: i < lines - 1 ? `${gap}px` : undefined,
132
- },
133
- })
134
- )
135
- );
136
- }
137
-
138
- // --- Skeleton Avatar ---
139
-
140
- export function SkeletonAvatar({
141
- size = 40,
142
- variant = 'shimmer',
143
- }) {
144
- return Skeleton({
145
- width: size,
146
- height: size,
147
- circle: true,
148
- variant,
149
- });
150
- }
151
-
152
- // --- Skeleton Card ---
153
-
154
- export function SkeletonCard({
155
- imageHeight = 200,
156
- lines = 3,
157
- variant = 'shimmer',
158
- }) {
159
- injectStyles();
160
-
161
- return h('div', { class: 'what-skeleton-card', 'aria-hidden': 'true' },
162
- // Image placeholder
163
- h('div', {
164
- class: `what-skeleton ${variant === 'pulse' ? 'what-skeleton-pulse' : ''}`,
165
- style: { height: `${imageHeight}px`, width: '100%', marginBottom: '16px' },
166
- }),
167
- // Title
168
- h('div', {
169
- class: `what-skeleton ${variant === 'pulse' ? 'what-skeleton-pulse' : ''}`,
170
- style: { height: '24px', width: '70%', marginBottom: '12px' },
171
- }),
172
- // Text lines
173
- SkeletonText({ lines, variant })
174
- );
175
- }
176
-
177
- // --- Skeleton Table ---
178
-
179
- export function SkeletonTable({
180
- rows = 5,
181
- columns = 4,
182
- variant = 'shimmer',
183
- }) {
184
- injectStyles();
185
-
186
- return h('div', { class: 'what-skeleton-table', 'aria-hidden': 'true' },
187
- // Header
188
- h('div', { style: { display: 'flex', gap: '16px', marginBottom: '16px' } },
189
- Array.from({ length: columns }, (_, i) =>
190
- h('div', {
191
- key: i,
192
- class: `what-skeleton ${variant === 'pulse' ? 'what-skeleton-pulse' : ''}`,
193
- style: { height: '20px', flex: 1 },
194
- })
195
- )
196
- ),
197
- // Rows
198
- Array.from({ length: rows }, (_, rowIndex) =>
199
- h('div', {
200
- key: rowIndex,
201
- style: {
202
- display: 'flex',
203
- gap: '16px',
204
- marginBottom: rowIndex < rows - 1 ? '12px' : undefined,
205
- },
206
- },
207
- Array.from({ length: columns }, (_, colIndex) =>
208
- h('div', {
209
- key: colIndex,
210
- class: `what-skeleton ${variant === 'pulse' ? 'what-skeleton-pulse' : ''}`,
211
- style: { height: '16px', flex: 1 },
212
- })
213
- )
214
- )
215
- )
216
- );
217
- }
218
-
219
- // --- Island Skeleton ---
220
- // Specific skeleton for island placeholders
221
-
222
- export function IslandSkeleton({
223
- type = 'default', // 'default' | 'card' | 'text' | 'custom'
224
- height,
225
- children,
226
- }) {
227
- injectStyles();
228
-
229
- if (type === 'card') {
230
- return SkeletonCard({});
231
- }
232
-
233
- if (type === 'text') {
234
- return SkeletonText({});
235
- }
236
-
237
- if (children) {
238
- return children;
239
- }
240
-
241
- return h('div', {
242
- class: 'what-skeleton what-island-skeleton',
243
- style: {
244
- height: typeof height === 'number' ? `${height}px` : height || '100px',
245
- width: '100%',
246
- },
247
- 'aria-hidden': 'true',
248
- });
249
- }
250
-
251
- // --- useSkeleton Hook ---
252
- // Show skeleton while loading data
253
-
254
- export function useSkeleton(asyncFn, deps = []) {
255
- const isLoading = signal(true);
256
- const data = signal(null);
257
- const error = signal(null);
258
-
259
- effect(() => {
260
- isLoading.set(true);
261
- error.set(null);
262
-
263
- Promise.resolve(asyncFn())
264
- .then(result => {
265
- data.set(result);
266
- isLoading.set(false);
267
- })
268
- .catch(err => {
269
- error.set(err);
270
- isLoading.set(false);
271
- });
272
- });
273
-
274
- return {
275
- isLoading: () => isLoading(),
276
- data: () => data(),
277
- error: () => error(),
278
- Skeleton: (props) => isLoading() ? Skeleton(props) : null,
279
- };
280
- }
281
-
282
- // --- Placeholder ---
283
- // Generic placeholder with optional shimmer
284
-
285
- export function Placeholder({
286
- width = '100%',
287
- height = 100,
288
- label = 'Loading...',
289
- showLabel = false,
290
- variant = 'shimmer',
291
- }) {
292
- injectStyles();
293
-
294
- return h('div', {
295
- class: `what-skeleton ${variant === 'pulse' ? 'what-skeleton-pulse' : ''}`,
296
- style: {
297
- width: typeof width === 'number' ? `${width}px` : width,
298
- height: typeof height === 'number' ? `${height}px` : height,
299
- display: 'flex',
300
- alignItems: 'center',
301
- justifyContent: 'center',
302
- },
303
- 'aria-label': label,
304
- role: 'status',
305
- },
306
- showLabel && h('span', {
307
- style: {
308
- color: 'var(--skeleton-text, #999)',
309
- fontSize: '14px',
310
- },
311
- }, label)
312
- );
313
- }
314
-
315
- // --- Loading Dots ---
316
-
317
- export function LoadingDots({ size = 8, color = '#666' }) {
318
- injectStyles();
319
-
320
- const dotStyle = {
321
- width: `${size}px`,
322
- height: `${size}px`,
323
- borderRadius: '50%',
324
- backgroundColor: color,
325
- animation: 'what-skeleton-pulse 1s infinite ease-in-out',
326
- };
327
-
328
- return h('div', {
329
- class: 'what-loading-dots',
330
- style: { display: 'flex', gap: `${size / 2}px` },
331
- 'aria-label': 'Loading',
332
- role: 'status',
333
- },
334
- h('div', { style: { ...dotStyle, animationDelay: '0s' } }),
335
- h('div', { style: { ...dotStyle, animationDelay: '0.2s' } }),
336
- h('div', { style: { ...dotStyle, animationDelay: '0.4s' } })
337
- );
338
- }
339
-
340
- // --- Spinner ---
341
-
342
- export function Spinner({ size = 24, color = '#666', strokeWidth = 2 }) {
343
- return h('svg', {
344
- width: size,
345
- height: size,
346
- viewBox: '0 0 24 24',
347
- style: { animation: 'spin 1s linear infinite' },
348
- 'aria-label': 'Loading',
349
- role: 'status',
350
- },
351
- h('style', null, '@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }'),
352
- h('circle', {
353
- cx: 12,
354
- cy: 12,
355
- r: 10,
356
- stroke: color,
357
- strokeWidth,
358
- fill: 'none',
359
- strokeDasharray: '31.4 31.4',
360
- strokeLinecap: 'round',
361
- })
362
- );
363
- }
package/dist/store.js DELETED
@@ -1,83 +0,0 @@
1
- import { signal, computed, batch, __DEV__ } from './reactive.js';
2
- export function derived(fn) {
3
- fn._storeComputed = true;
4
- return fn;
5
- }
6
- let _storeComputedWarned = false;
7
- export function storeComputed(fn) {
8
- if (!_storeComputedWarned) {
9
- _storeComputedWarned = true;
10
- console.warn('[what] storeComputed() is deprecated. Use derived() instead.');
11
- }
12
- return derived(fn);
13
- }
14
- export function createStore(definition) {
15
- const signals = {};
16
- const computeds = {};
17
- const actions = {};
18
- const state = {};
19
- for (const [key, value] of Object.entries(definition)) {
20
- if (typeof value === 'function' && value._storeComputed) {
21
- if (__DEV__ && value.length === 0) {
22
- console.warn(
23
- `[what] derived() for "${key}" should accept the state parameter, e.g. derived(state => ...).`
24
- );
25
- }
26
- computeds[key] = value;
27
- } else if (typeof value === 'function') {
28
- actions[key] = value;
29
- } else {
30
- signals[key] = signal(value);
31
- }
32
- }
33
- for (const [key, fn] of Object.entries(computeds)) {
34
- const proxy = new Proxy({}, {
35
- get(_, prop) {
36
- if (signals[prop]) return signals[prop]();
37
- if (computeds[prop]) return computeds[prop]();
38
- return undefined;
39
- },
40
- });
41
- computeds[key] = computed(() => fn(proxy));
42
- }
43
- for (const [key, fn] of Object.entries(actions)) {
44
- actions[key] = (...args) => {
45
- batch(() => {
46
- const proxy = new Proxy({}, {
47
- get(_, prop) {
48
- if (signals[prop]) return signals[prop].peek();
49
- if (computeds[prop]) return computeds[prop].peek();
50
- if (actions[prop]) return actions[prop];
51
- return undefined;
52
- },
53
- set(_, prop, val) {
54
- if (signals[prop]) signals[prop].set(val);
55
- return true;
56
- },
57
- });
58
- fn.apply(proxy, args);
59
- });
60
- };
61
- }
62
- return function useStore() {
63
- const result = {};
64
- for (const [key, s] of Object.entries(signals)) {
65
- Object.defineProperty(result, key, { get: () => s(), enumerable: true });
66
- }
67
- for (const [key, c] of Object.entries(computeds)) {
68
- Object.defineProperty(result, key, { get: () => c(), enumerable: true });
69
- }
70
- for (const [key, fn] of Object.entries(actions)) {
71
- result[key] = fn;
72
- }
73
- return result;
74
- };
75
- }
76
- let _atomWarned = false;
77
- export function atom(initial) {
78
- if (!_atomWarned) {
79
- _atomWarned = true;
80
- console.warn('[what] atom() is deprecated. Use signal() directly instead.');
81
- }
82
- return signal(initial);
83
- }