what-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components.js +140 -0
- package/dist/dom.js +443 -0
- package/dist/h.js +150 -0
- package/dist/head.js +51 -0
- package/dist/helpers.js +98 -0
- package/dist/hooks.js +156 -0
- package/dist/index.js +147 -0
- package/dist/reactive.js +124 -0
- package/dist/store.js +59 -0
- package/dist/what.js +114 -0
- package/index.d.ts +252 -0
- package/package.json +47 -0
- package/src/a11y.js +425 -0
- package/src/animation.js +531 -0
- package/src/components.js +204 -0
- package/src/data.js +434 -0
- package/src/dom.js +619 -0
- package/src/form.js +441 -0
- package/src/h.js +203 -0
- package/src/head.js +68 -0
- package/src/helpers.js +140 -0
- package/src/hooks.js +246 -0
- package/src/index.js +147 -0
- package/src/reactive.js +167 -0
- package/src/scheduler.js +241 -0
- package/src/skeleton.js +363 -0
- package/src/store.js +99 -0
- package/src/testing.js +367 -0
- package/testing.d.ts +103 -0
package/dist/store.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { signal, computed, batch } from './reactive.js';
|
|
2
|
+
export function createStore(definition) {
|
|
3
|
+
const signals = {};
|
|
4
|
+
const computeds = {};
|
|
5
|
+
const actions = {};
|
|
6
|
+
const state = {};
|
|
7
|
+
for (const [key, value] of Object.entries(definition)) {
|
|
8
|
+
if (typeof value === 'function' && value.length > 0 && key !== 'constructor') {
|
|
9
|
+
computeds[key] = value;
|
|
10
|
+
} else if (typeof value === 'function') {
|
|
11
|
+
actions[key] = value;
|
|
12
|
+
} else {
|
|
13
|
+
signals[key] = signal(value);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
for (const [key, fn] of Object.entries(computeds)) {
|
|
17
|
+
const proxy = new Proxy({}, {
|
|
18
|
+
get(_, prop) {
|
|
19
|
+
if (signals[prop]) return signals[prop]();
|
|
20
|
+
if (computeds[prop]) return computeds[prop]();
|
|
21
|
+
return undefined;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
computeds[key] = computed(() => fn(proxy));
|
|
25
|
+
}
|
|
26
|
+
for (const [key, fn] of Object.entries(actions)) {
|
|
27
|
+
actions[key] = (...args) => {
|
|
28
|
+
batch(() => {
|
|
29
|
+
const proxy = new Proxy({}, {
|
|
30
|
+
get(_, prop) {
|
|
31
|
+
if (signals[prop]) return signals[prop].peek();
|
|
32
|
+
return undefined;
|
|
33
|
+
},
|
|
34
|
+
set(_, prop, val) {
|
|
35
|
+
if (signals[prop]) signals[prop].set(val);
|
|
36
|
+
return true;
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
fn.apply(proxy, args);
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return function useStore() {
|
|
44
|
+
const result = {};
|
|
45
|
+
for (const [key, s] of Object.entries(signals)) {
|
|
46
|
+
Object.defineProperty(result, key, { get: () => s(), enumerable: true });
|
|
47
|
+
}
|
|
48
|
+
for (const [key, c] of Object.entries(computeds)) {
|
|
49
|
+
Object.defineProperty(result, key, { get: () => c(), enumerable: true });
|
|
50
|
+
}
|
|
51
|
+
for (const [key, fn] of Object.entries(actions)) {
|
|
52
|
+
result[key] = fn;
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function atom(initial) {
|
|
58
|
+
return signal(initial);
|
|
59
|
+
}
|
package/dist/what.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export { signal, computed, effect, batch, untrack } from './reactive.js';
|
|
2
|
+
export { h, Fragment, html } from './h.js';
|
|
3
|
+
export { mount } from './dom.js';
|
|
4
|
+
export {
|
|
5
|
+
useState,
|
|
6
|
+
useSignal,
|
|
7
|
+
useComputed,
|
|
8
|
+
useEffect,
|
|
9
|
+
useMemo,
|
|
10
|
+
useCallback,
|
|
11
|
+
useRef,
|
|
12
|
+
useContext,
|
|
13
|
+
useReducer,
|
|
14
|
+
createContext,
|
|
15
|
+
onMount,
|
|
16
|
+
onCleanup,
|
|
17
|
+
createResource,
|
|
18
|
+
} from './hooks.js';
|
|
19
|
+
export { memo, lazy, Suspense, ErrorBoundary, Show, For, Switch, Match } from './components.js';
|
|
20
|
+
export { createStore, atom } from './store.js';
|
|
21
|
+
export { Head, clearHead } from './head.js';
|
|
22
|
+
export {
|
|
23
|
+
show,
|
|
24
|
+
each,
|
|
25
|
+
cls,
|
|
26
|
+
style,
|
|
27
|
+
debounce,
|
|
28
|
+
throttle,
|
|
29
|
+
useMediaQuery,
|
|
30
|
+
useLocalStorage,
|
|
31
|
+
Portal,
|
|
32
|
+
transition,
|
|
33
|
+
} from './helpers.js';
|
|
34
|
+
export {
|
|
35
|
+
scheduleRead,
|
|
36
|
+
scheduleWrite,
|
|
37
|
+
flushScheduler,
|
|
38
|
+
measure,
|
|
39
|
+
mutate,
|
|
40
|
+
useScheduledEffect,
|
|
41
|
+
nextFrame,
|
|
42
|
+
raf,
|
|
43
|
+
onResize,
|
|
44
|
+
onIntersect,
|
|
45
|
+
smoothScrollTo,
|
|
46
|
+
} from './scheduler.js';
|
|
47
|
+
export {
|
|
48
|
+
spring,
|
|
49
|
+
tween,
|
|
50
|
+
easings,
|
|
51
|
+
useTransition,
|
|
52
|
+
useGesture,
|
|
53
|
+
useAnimatedValue,
|
|
54
|
+
createTransitionClasses,
|
|
55
|
+
cssTransition,
|
|
56
|
+
} from './animation.js';
|
|
57
|
+
export {
|
|
58
|
+
useFocus,
|
|
59
|
+
useFocusTrap,
|
|
60
|
+
FocusTrap,
|
|
61
|
+
announce,
|
|
62
|
+
announceAssertive,
|
|
63
|
+
SkipLink,
|
|
64
|
+
useAriaExpanded,
|
|
65
|
+
useAriaSelected,
|
|
66
|
+
useAriaChecked,
|
|
67
|
+
useRovingTabIndex,
|
|
68
|
+
VisuallyHidden,
|
|
69
|
+
LiveRegion,
|
|
70
|
+
useId,
|
|
71
|
+
useIds,
|
|
72
|
+
useDescribedBy,
|
|
73
|
+
useLabelledBy,
|
|
74
|
+
Keys,
|
|
75
|
+
onKey,
|
|
76
|
+
onKeys,
|
|
77
|
+
} from './a11y.js';
|
|
78
|
+
export {
|
|
79
|
+
Skeleton,
|
|
80
|
+
SkeletonText,
|
|
81
|
+
SkeletonAvatar,
|
|
82
|
+
SkeletonCard,
|
|
83
|
+
SkeletonTable,
|
|
84
|
+
IslandSkeleton,
|
|
85
|
+
useSkeleton,
|
|
86
|
+
Placeholder,
|
|
87
|
+
LoadingDots,
|
|
88
|
+
Spinner,
|
|
89
|
+
} from './skeleton.js';
|
|
90
|
+
export {
|
|
91
|
+
useFetch,
|
|
92
|
+
useSWR,
|
|
93
|
+
useQuery,
|
|
94
|
+
useInfiniteQuery,
|
|
95
|
+
invalidateQueries,
|
|
96
|
+
prefetchQuery,
|
|
97
|
+
setQueryData,
|
|
98
|
+
getQueryData,
|
|
99
|
+
clearCache,
|
|
100
|
+
} from './data.js';
|
|
101
|
+
export {
|
|
102
|
+
useForm,
|
|
103
|
+
useField,
|
|
104
|
+
rules,
|
|
105
|
+
simpleResolver,
|
|
106
|
+
zodResolver,
|
|
107
|
+
yupResolver,
|
|
108
|
+
Input,
|
|
109
|
+
Textarea,
|
|
110
|
+
Select,
|
|
111
|
+
Checkbox,
|
|
112
|
+
Radio,
|
|
113
|
+
ErrorMessage,
|
|
114
|
+
} from './form.js';
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// What Framework - TypeScript Definitions
|
|
2
|
+
|
|
3
|
+
// --- Reactive Primitives ---
|
|
4
|
+
|
|
5
|
+
/** A reactive value container */
|
|
6
|
+
export interface Signal<T> {
|
|
7
|
+
/** Read the current value (tracks dependency if inside effect) */
|
|
8
|
+
(): T;
|
|
9
|
+
/** Update the value */
|
|
10
|
+
set(value: T | ((prev: T) => T)): void;
|
|
11
|
+
/** Read without tracking */
|
|
12
|
+
peek(): T;
|
|
13
|
+
/** Subscribe to changes */
|
|
14
|
+
subscribe(fn: (value: T) => void): () => void;
|
|
15
|
+
/** Internal marker */
|
|
16
|
+
_signal: true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Create a reactive signal */
|
|
20
|
+
export function signal<T>(initial: T): Signal<T>;
|
|
21
|
+
|
|
22
|
+
/** A derived reactive value (lazy evaluation) */
|
|
23
|
+
export interface Computed<T> {
|
|
24
|
+
(): T;
|
|
25
|
+
peek(): T;
|
|
26
|
+
_signal: true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Create a computed signal */
|
|
30
|
+
export function computed<T>(fn: () => T): Computed<T>;
|
|
31
|
+
|
|
32
|
+
/** Create a side effect that re-runs when dependencies change */
|
|
33
|
+
export function effect(fn: () => void | (() => void)): () => void;
|
|
34
|
+
|
|
35
|
+
/** Batch multiple signal updates into one flush */
|
|
36
|
+
export function batch<T>(fn: () => T): T;
|
|
37
|
+
|
|
38
|
+
/** Read signals without subscribing */
|
|
39
|
+
export function untrack<T>(fn: () => T): T;
|
|
40
|
+
|
|
41
|
+
// --- Virtual DOM ---
|
|
42
|
+
|
|
43
|
+
export interface VNode<P = any> {
|
|
44
|
+
tag: string | Component<P>;
|
|
45
|
+
props: P;
|
|
46
|
+
children: VNodeChild[];
|
|
47
|
+
key: string | number | null;
|
|
48
|
+
_vnode: true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type VNodeChild = VNode | string | number | boolean | null | undefined | VNodeChild[];
|
|
52
|
+
|
|
53
|
+
export type Component<P = {}> = (props: P & { children?: VNodeChild }) => VNode | VNodeChild;
|
|
54
|
+
|
|
55
|
+
/** Create a virtual DOM node */
|
|
56
|
+
export function h<P extends {}>(
|
|
57
|
+
tag: string | Component<P>,
|
|
58
|
+
props?: P | null,
|
|
59
|
+
...children: VNodeChild[]
|
|
60
|
+
): VNode<P>;
|
|
61
|
+
|
|
62
|
+
/** Fragment component */
|
|
63
|
+
export function Fragment(props: { children?: VNodeChild }): VNodeChild;
|
|
64
|
+
|
|
65
|
+
/** Tagged template for JSX-like syntax without build step */
|
|
66
|
+
export function html(strings: TemplateStringsArray, ...values: any[]): VNode | VNode[];
|
|
67
|
+
|
|
68
|
+
// --- DOM Mounting ---
|
|
69
|
+
|
|
70
|
+
/** Mount a VNode tree into a container */
|
|
71
|
+
export function mount(vnode: VNode, container: string | Element): () => void;
|
|
72
|
+
|
|
73
|
+
// --- Hooks ---
|
|
74
|
+
|
|
75
|
+
/** State hook - returns [value, setter] */
|
|
76
|
+
export function useState<T>(initial: T | (() => T)): [T, (value: T | ((prev: T) => T)) => void];
|
|
77
|
+
|
|
78
|
+
/** Signal hook - returns raw signal */
|
|
79
|
+
export function useSignal<T>(initial: T | (() => T)): Signal<T>;
|
|
80
|
+
|
|
81
|
+
/** Computed hook */
|
|
82
|
+
export function useComputed<T>(fn: () => T): Computed<T>;
|
|
83
|
+
|
|
84
|
+
/** Effect hook with optional dependencies */
|
|
85
|
+
export function useEffect(fn: () => void | (() => void), deps?: any[]): void;
|
|
86
|
+
|
|
87
|
+
/** Memoized value hook */
|
|
88
|
+
export function useMemo<T>(fn: () => T, deps: any[]): T;
|
|
89
|
+
|
|
90
|
+
/** Memoized callback hook */
|
|
91
|
+
export function useCallback<T extends (...args: any[]) => any>(fn: T, deps: any[]): T;
|
|
92
|
+
|
|
93
|
+
/** Ref hook */
|
|
94
|
+
export function useRef<T>(initial: T): { current: T };
|
|
95
|
+
|
|
96
|
+
/** Context hook */
|
|
97
|
+
export function useContext<T>(context: Context<T>): T;
|
|
98
|
+
|
|
99
|
+
/** Reducer hook */
|
|
100
|
+
export function useReducer<S, A>(
|
|
101
|
+
reducer: (state: S, action: A) => S,
|
|
102
|
+
initialState: S,
|
|
103
|
+
init?: (initial: S) => S
|
|
104
|
+
): [S, (action: A) => void];
|
|
105
|
+
|
|
106
|
+
/** Create a context */
|
|
107
|
+
export interface Context<T> {
|
|
108
|
+
_value: T;
|
|
109
|
+
Provider: Component<{ value: T; children?: VNodeChild }>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function createContext<T>(defaultValue: T): Context<T>;
|
|
113
|
+
|
|
114
|
+
// --- Component Utilities ---
|
|
115
|
+
|
|
116
|
+
/** Skip re-render if props are equal */
|
|
117
|
+
export function memo<P>(
|
|
118
|
+
component: Component<P>,
|
|
119
|
+
areEqual?: (prev: P, next: P) => boolean
|
|
120
|
+
): Component<P>;
|
|
121
|
+
|
|
122
|
+
/** Lazy-load a component */
|
|
123
|
+
export function lazy<P>(
|
|
124
|
+
loader: () => Promise<{ default: Component<P> } | Component<P>>
|
|
125
|
+
): Component<P>;
|
|
126
|
+
|
|
127
|
+
/** Suspense boundary for lazy components */
|
|
128
|
+
export function Suspense(props: {
|
|
129
|
+
fallback: VNodeChild;
|
|
130
|
+
children?: VNodeChild;
|
|
131
|
+
}): VNode;
|
|
132
|
+
|
|
133
|
+
/** Error boundary for catching component errors */
|
|
134
|
+
export function ErrorBoundary(props: {
|
|
135
|
+
fallback: VNodeChild | ((props: { error: Error; reset: () => void }) => VNodeChild);
|
|
136
|
+
onError?: (error: Error) => void;
|
|
137
|
+
children?: VNodeChild;
|
|
138
|
+
}): VNode;
|
|
139
|
+
|
|
140
|
+
// --- Store ---
|
|
141
|
+
|
|
142
|
+
export interface StoreDefinition {
|
|
143
|
+
[key: string]: any;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export type Store<T extends StoreDefinition> = {
|
|
147
|
+
[K in keyof T]: T[K] extends (...args: any[]) => any ? T[K] : T[K];
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/** Create a global reactive store */
|
|
151
|
+
export function createStore<T extends StoreDefinition>(definition: T): () => Store<T>;
|
|
152
|
+
|
|
153
|
+
/** Create a simple global atom */
|
|
154
|
+
export function atom<T>(initial: T): Signal<T>;
|
|
155
|
+
|
|
156
|
+
// --- Utilities ---
|
|
157
|
+
|
|
158
|
+
/** Conditional rendering helper */
|
|
159
|
+
export function show<T extends VNodeChild>(condition: boolean, vnode: T, fallback?: VNodeChild): T | VNodeChild;
|
|
160
|
+
|
|
161
|
+
/** List rendering helper with optional key function */
|
|
162
|
+
export function each<T>(
|
|
163
|
+
list: T[],
|
|
164
|
+
fn: (item: T, index: number) => VNode,
|
|
165
|
+
keyFn?: (item: T, index: number) => string | number
|
|
166
|
+
): VNode[];
|
|
167
|
+
|
|
168
|
+
/** Conditional class names */
|
|
169
|
+
export function cls(...args: (string | false | null | undefined | Record<string, boolean>)[]): string;
|
|
170
|
+
|
|
171
|
+
/** Convert style object to string */
|
|
172
|
+
export function style(obj: string | Record<string, string | number | null | undefined>): string;
|
|
173
|
+
|
|
174
|
+
/** Debounce a function */
|
|
175
|
+
export function debounce<T extends (...args: any[]) => any>(fn: T, ms: number): T;
|
|
176
|
+
|
|
177
|
+
/** Throttle a function */
|
|
178
|
+
export function throttle<T extends (...args: any[]) => any>(fn: T, ms: number): T;
|
|
179
|
+
|
|
180
|
+
/** Reactive media query */
|
|
181
|
+
export function useMediaQuery(query: string): Signal<boolean>;
|
|
182
|
+
|
|
183
|
+
/** Signal synced with localStorage */
|
|
184
|
+
export function useLocalStorage<T>(key: string, initial: T): Signal<T>;
|
|
185
|
+
|
|
186
|
+
/** Render children in a different DOM container */
|
|
187
|
+
export function Portal(props: { target: string | Element; children?: VNodeChild }): VNode | null;
|
|
188
|
+
|
|
189
|
+
/** CSS transition helper */
|
|
190
|
+
export function transition(name: string, active: boolean): { class: string };
|
|
191
|
+
|
|
192
|
+
// --- Head Management ---
|
|
193
|
+
|
|
194
|
+
/** Manage document head */
|
|
195
|
+
export function Head(props: {
|
|
196
|
+
title?: string;
|
|
197
|
+
meta?: Record<string, string>[];
|
|
198
|
+
link?: Record<string, string>[];
|
|
199
|
+
script?: Record<string, string>[];
|
|
200
|
+
children?: VNodeChild;
|
|
201
|
+
}): null;
|
|
202
|
+
|
|
203
|
+
/** Clear managed head elements */
|
|
204
|
+
export function clearHead(): void;
|
|
205
|
+
|
|
206
|
+
// --- DOM Scheduler ---
|
|
207
|
+
|
|
208
|
+
/** Schedule a DOM read operation */
|
|
209
|
+
export function scheduleRead(fn: () => void): () => void;
|
|
210
|
+
|
|
211
|
+
/** Schedule a DOM write operation */
|
|
212
|
+
export function scheduleWrite(fn: () => void): () => void;
|
|
213
|
+
|
|
214
|
+
/** Flush all pending scheduler operations */
|
|
215
|
+
export function flushScheduler(): void;
|
|
216
|
+
|
|
217
|
+
/** Measure DOM (returns promise) */
|
|
218
|
+
export function measure<T>(fn: () => T): Promise<T>;
|
|
219
|
+
|
|
220
|
+
/** Mutate DOM (returns promise) */
|
|
221
|
+
export function mutate(fn: () => void): Promise<void>;
|
|
222
|
+
|
|
223
|
+
/** Effect that batches DOM operations */
|
|
224
|
+
export function useScheduledEffect(
|
|
225
|
+
readFn: () => any,
|
|
226
|
+
writeFn?: (data: any) => void
|
|
227
|
+
): () => void;
|
|
228
|
+
|
|
229
|
+
/** Returns promise that resolves on next animation frame */
|
|
230
|
+
export function nextFrame(): Promise<void> & { cancel: () => void };
|
|
231
|
+
|
|
232
|
+
/** Debounced requestAnimationFrame */
|
|
233
|
+
export function raf(key: string, fn: () => void): void;
|
|
234
|
+
|
|
235
|
+
/** Observe element resize */
|
|
236
|
+
export function onResize(
|
|
237
|
+
element: Element,
|
|
238
|
+
callback: (rect: DOMRectReadOnly) => void
|
|
239
|
+
): () => void;
|
|
240
|
+
|
|
241
|
+
/** Observe element intersection */
|
|
242
|
+
export function onIntersect(
|
|
243
|
+
element: Element,
|
|
244
|
+
callback: (entry: IntersectionObserverEntry) => void,
|
|
245
|
+
options?: IntersectionObserverInit
|
|
246
|
+
): () => void;
|
|
247
|
+
|
|
248
|
+
/** Smooth scroll to element */
|
|
249
|
+
export function smoothScrollTo(
|
|
250
|
+
element: Element,
|
|
251
|
+
options?: { duration?: number; easing?: (t: number) => number }
|
|
252
|
+
): Promise<void>;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "what-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "What Framework - The closest framework to vanilla JS",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/what.js",
|
|
7
|
+
"module": "src/index.js",
|
|
8
|
+
"types": "index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./index.d.ts",
|
|
12
|
+
"import": "./src/index.js",
|
|
13
|
+
"require": "./dist/what.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./testing": {
|
|
16
|
+
"types": "./testing.d.ts",
|
|
17
|
+
"import": "./src/testing.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"src",
|
|
22
|
+
"dist",
|
|
23
|
+
"index.d.ts",
|
|
24
|
+
"testing.d.ts"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"keywords": [
|
|
28
|
+
"framework",
|
|
29
|
+
"signals",
|
|
30
|
+
"reactive",
|
|
31
|
+
"islands",
|
|
32
|
+
"ssr",
|
|
33
|
+
"vanilla-js",
|
|
34
|
+
"lightweight",
|
|
35
|
+
"vdom"
|
|
36
|
+
],
|
|
37
|
+
"author": "",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/aspect/what-fw"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/aspect/what-fw/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/aspect/what-fw#readme"
|
|
47
|
+
}
|