pulse-js-framework 1.4.3 → 1.4.5
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/README.md +22 -0
- package/cli/index.js +23 -20
- package/cli/logger.js +122 -0
- package/cli/mobile.js +48 -71
- package/compiler/parser.js +57 -136
- package/compiler/transformer.js +75 -197
- package/index.js +8 -2
- package/package.json +53 -8
- package/runtime/dom.js +6 -3
- package/runtime/index.js +2 -0
- package/runtime/logger.js +304 -0
- package/runtime/native.js +7 -4
- package/runtime/pulse.js +308 -25
- package/runtime/store.js +227 -19
- package/types/dom.d.ts +288 -0
- package/types/index.d.ts +135 -0
- package/types/logger.d.ts +122 -0
- package/types/pulse.d.ts +149 -0
- package/types/router.d.ts +197 -0
- package/types/store.d.ts +170 -0
package/runtime/store.js
CHANGED
|
@@ -1,13 +1,71 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pulse Store - Global state management
|
|
3
|
+
* @module pulse-js-framework/runtime/store
|
|
3
4
|
*
|
|
4
|
-
* A simple but powerful store that integrates with Pulse reactivity
|
|
5
|
+
* A simple but powerful store that integrates with Pulse reactivity.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import { createStore, createActions, createGetters } from './store.js';
|
|
9
|
+
*
|
|
10
|
+
* const store = createStore({ count: 0, name: 'App' });
|
|
11
|
+
* const actions = createActions(store, {
|
|
12
|
+
* increment: (store) => store.count.update(n => n + 1)
|
|
13
|
+
* });
|
|
14
|
+
*
|
|
15
|
+
* actions.increment();
|
|
5
16
|
*/
|
|
6
17
|
|
|
7
18
|
import { pulse, computed, effect, batch } from './pulse.js';
|
|
19
|
+
import { loggers, createLogger } from './logger.js';
|
|
20
|
+
|
|
21
|
+
const log = loggers.store;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {Object} StoreOptions
|
|
25
|
+
* @property {boolean} [persist=false] - Persist state to localStorage
|
|
26
|
+
* @property {string} [storageKey='pulse-store'] - Key for localStorage persistence
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {Object} Store
|
|
31
|
+
* @property {function(): Object} $getState - Get current state snapshot
|
|
32
|
+
* @property {function(Object): void} $setState - Update multiple values at once
|
|
33
|
+
* @property {function(): void} $reset - Reset to initial state
|
|
34
|
+
* @property {function(function): function} $subscribe - Subscribe to state changes
|
|
35
|
+
* @property {Object.<string, Pulse>} $pulses - Access underlying pulse objects
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @typedef {Object} ModuleDef
|
|
40
|
+
* @property {Object} [state] - Initial module state
|
|
41
|
+
* @property {Object.<string, function>} [actions] - Module actions
|
|
42
|
+
* @property {Object.<string, function>} [getters] - Module getters
|
|
43
|
+
*/
|
|
8
44
|
|
|
9
45
|
/**
|
|
10
|
-
*
|
|
46
|
+
* @typedef {function(Store): Store} StorePlugin
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Create a global store with reactive state properties.
|
|
51
|
+
* @template T
|
|
52
|
+
* @param {T} [initialState={}] - Initial state object
|
|
53
|
+
* @param {StoreOptions} [options={}] - Store configuration
|
|
54
|
+
* @returns {T & Store} Store with reactive properties and helper methods
|
|
55
|
+
* @example
|
|
56
|
+
* // Basic store
|
|
57
|
+
* const store = createStore({ count: 0, user: null });
|
|
58
|
+
* store.count.get(); // 0
|
|
59
|
+
* store.count.set(5);
|
|
60
|
+
*
|
|
61
|
+
* // With persistence
|
|
62
|
+
* const store = createStore(
|
|
63
|
+
* { theme: 'dark', lang: 'en' },
|
|
64
|
+
* { persist: true, storageKey: 'app-settings' }
|
|
65
|
+
* );
|
|
66
|
+
*
|
|
67
|
+
* // Batch updates
|
|
68
|
+
* store.$setState({ theme: 'light', lang: 'fr' });
|
|
11
69
|
*/
|
|
12
70
|
export function createStore(initialState = {}, options = {}) {
|
|
13
71
|
const { persist = false, storageKey = 'pulse-store' } = options;
|
|
@@ -21,14 +79,22 @@ export function createStore(initialState = {}, options = {}) {
|
|
|
21
79
|
state = { ...initialState, ...JSON.parse(saved) };
|
|
22
80
|
}
|
|
23
81
|
} catch (e) {
|
|
24
|
-
|
|
82
|
+
log.warn('Failed to load persisted state:', e);
|
|
25
83
|
}
|
|
26
84
|
}
|
|
27
85
|
|
|
28
86
|
// Create pulses for each state property
|
|
87
|
+
/** @type {Object.<string, Pulse>} */
|
|
29
88
|
const pulses = {};
|
|
30
89
|
const store = {};
|
|
31
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Create a pulse for a state value, handling nested objects
|
|
93
|
+
* @private
|
|
94
|
+
* @param {string} key - State key
|
|
95
|
+
* @param {*} value - Initial value
|
|
96
|
+
* @returns {Pulse|Object} Pulse or nested object of pulses
|
|
97
|
+
*/
|
|
32
98
|
function createPulse(key, value) {
|
|
33
99
|
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
34
100
|
// Nested object - create nested store
|
|
@@ -59,13 +125,14 @@ export function createStore(initialState = {}, options = {}) {
|
|
|
59
125
|
try {
|
|
60
126
|
localStorage.setItem(storageKey, JSON.stringify(snapshot));
|
|
61
127
|
} catch (e) {
|
|
62
|
-
|
|
128
|
+
log.warn('Failed to persist state:', e);
|
|
63
129
|
}
|
|
64
130
|
});
|
|
65
131
|
}
|
|
66
132
|
|
|
67
133
|
/**
|
|
68
|
-
* Get a snapshot of the current state
|
|
134
|
+
* Get a snapshot of the current state (without tracking)
|
|
135
|
+
* @returns {Object} Plain object with current values
|
|
69
136
|
*/
|
|
70
137
|
function getState() {
|
|
71
138
|
const snapshot = {};
|
|
@@ -76,7 +143,9 @@ export function createStore(initialState = {}, options = {}) {
|
|
|
76
143
|
}
|
|
77
144
|
|
|
78
145
|
/**
|
|
79
|
-
* Set multiple values at once
|
|
146
|
+
* Set multiple values at once (batched)
|
|
147
|
+
* @param {Object} updates - Key-value pairs to update
|
|
148
|
+
* @returns {void}
|
|
80
149
|
*/
|
|
81
150
|
function setState(updates) {
|
|
82
151
|
batch(() => {
|
|
@@ -90,6 +159,7 @@ export function createStore(initialState = {}, options = {}) {
|
|
|
90
159
|
|
|
91
160
|
/**
|
|
92
161
|
* Reset state to initial values
|
|
162
|
+
* @returns {void}
|
|
93
163
|
*/
|
|
94
164
|
function reset() {
|
|
95
165
|
batch(() => {
|
|
@@ -103,6 +173,8 @@ export function createStore(initialState = {}, options = {}) {
|
|
|
103
173
|
|
|
104
174
|
/**
|
|
105
175
|
* Subscribe to all state changes
|
|
176
|
+
* @param {function(Object): void} callback - Called with current state on each change
|
|
177
|
+
* @returns {function(): void} Unsubscribe function
|
|
106
178
|
*/
|
|
107
179
|
function subscribe(callback) {
|
|
108
180
|
return effect(() => {
|
|
@@ -122,7 +194,23 @@ export function createStore(initialState = {}, options = {}) {
|
|
|
122
194
|
}
|
|
123
195
|
|
|
124
196
|
/**
|
|
125
|
-
* Create actions that can modify the store
|
|
197
|
+
* Create bound actions that can modify the store.
|
|
198
|
+
* Actions receive the store as their first argument.
|
|
199
|
+
* @template T
|
|
200
|
+
* @param {Store} store - The store to bind actions to
|
|
201
|
+
* @param {Object.<string, function(Store, ...any): any>} actions - Action definitions
|
|
202
|
+
* @returns {Object.<string, function(...any): any>} Bound action functions
|
|
203
|
+
* @example
|
|
204
|
+
* const store = createStore({ count: 0 });
|
|
205
|
+
*
|
|
206
|
+
* const actions = createActions(store, {
|
|
207
|
+
* increment: (store) => store.count.update(n => n + 1),
|
|
208
|
+
* decrement: (store) => store.count.update(n => n - 1),
|
|
209
|
+
* add: (store, amount) => store.count.update(n => n + amount)
|
|
210
|
+
* });
|
|
211
|
+
*
|
|
212
|
+
* actions.increment();
|
|
213
|
+
* actions.add(10);
|
|
126
214
|
*/
|
|
127
215
|
export function createActions(store, actions) {
|
|
128
216
|
const boundActions = {};
|
|
@@ -137,7 +225,24 @@ export function createActions(store, actions) {
|
|
|
137
225
|
}
|
|
138
226
|
|
|
139
227
|
/**
|
|
140
|
-
* Create
|
|
228
|
+
* Create computed getters for the store.
|
|
229
|
+
* Getters are memoized and update automatically when dependencies change.
|
|
230
|
+
* @param {Store} store - The store to create getters for
|
|
231
|
+
* @param {Object.<string, function(Store): any>} getters - Getter definitions
|
|
232
|
+
* @returns {Object.<string, Pulse>} Object of computed pulses
|
|
233
|
+
* @example
|
|
234
|
+
* const store = createStore({ items: [], filter: '' });
|
|
235
|
+
*
|
|
236
|
+
* const getters = createGetters(store, {
|
|
237
|
+
* filteredItems: (store) => {
|
|
238
|
+
* const items = store.items.get();
|
|
239
|
+
* const filter = store.filter.get();
|
|
240
|
+
* return items.filter(i => i.includes(filter));
|
|
241
|
+
* },
|
|
242
|
+
* itemCount: (store) => store.items.get().length
|
|
243
|
+
* });
|
|
244
|
+
*
|
|
245
|
+
* getters.filteredItems.get(); // Computed value
|
|
141
246
|
*/
|
|
142
247
|
export function createGetters(store, getters) {
|
|
143
248
|
const boundGetters = {};
|
|
@@ -150,7 +255,21 @@ export function createGetters(store, getters) {
|
|
|
150
255
|
}
|
|
151
256
|
|
|
152
257
|
/**
|
|
153
|
-
* Combine multiple stores
|
|
258
|
+
* Combine multiple stores into a single object.
|
|
259
|
+
* Each store is namespaced under its key.
|
|
260
|
+
* @param {Object.<string, Store>} stores - Stores to combine
|
|
261
|
+
* @returns {Object.<string, Store>} Combined stores object
|
|
262
|
+
* @example
|
|
263
|
+
* const userStore = createStore({ name: '', email: '' });
|
|
264
|
+
* const settingsStore = createStore({ theme: 'dark' });
|
|
265
|
+
*
|
|
266
|
+
* const rootStore = combineStores({
|
|
267
|
+
* user: userStore,
|
|
268
|
+
* settings: settingsStore
|
|
269
|
+
* });
|
|
270
|
+
*
|
|
271
|
+
* rootStore.user.name.get();
|
|
272
|
+
* rootStore.settings.theme.set('light');
|
|
154
273
|
*/
|
|
155
274
|
export function combineStores(stores) {
|
|
156
275
|
const combined = {};
|
|
@@ -163,7 +282,35 @@ export function combineStores(stores) {
|
|
|
163
282
|
}
|
|
164
283
|
|
|
165
284
|
/**
|
|
166
|
-
* Create a module-based store
|
|
285
|
+
* Create a module-based store similar to Vuex modules.
|
|
286
|
+
* Each module has its own state, actions, and getters.
|
|
287
|
+
* @param {Object.<string, ModuleDef>} modules - Module definitions
|
|
288
|
+
* @returns {Object} Root store with namespaced modules
|
|
289
|
+
* @example
|
|
290
|
+
* const store = createModuleStore({
|
|
291
|
+
* user: {
|
|
292
|
+
* state: { name: '', loggedIn: false },
|
|
293
|
+
* actions: {
|
|
294
|
+
* login: (store, name) => {
|
|
295
|
+
* store.name.set(name);
|
|
296
|
+
* store.loggedIn.set(true);
|
|
297
|
+
* }
|
|
298
|
+
* },
|
|
299
|
+
* getters: {
|
|
300
|
+
* displayName: (store) => store.loggedIn.get() ? store.name.get() : 'Guest'
|
|
301
|
+
* }
|
|
302
|
+
* },
|
|
303
|
+
* cart: {
|
|
304
|
+
* state: { items: [] },
|
|
305
|
+
* actions: {
|
|
306
|
+
* addItem: (store, item) => store.items.update(arr => [...arr, item])
|
|
307
|
+
* }
|
|
308
|
+
* }
|
|
309
|
+
* });
|
|
310
|
+
*
|
|
311
|
+
* store.user.login('John');
|
|
312
|
+
* store.cart.addItem({ id: 1, name: 'Product' });
|
|
313
|
+
* store.$getState(); // { user: {...}, cart: {...} }
|
|
167
314
|
*/
|
|
168
315
|
export function createModuleStore(modules) {
|
|
169
316
|
const stores = {};
|
|
@@ -186,7 +333,10 @@ export function createModuleStore(modules) {
|
|
|
186
333
|
rootStore[name] = stores[name];
|
|
187
334
|
}
|
|
188
335
|
|
|
189
|
-
|
|
336
|
+
/**
|
|
337
|
+
* Get combined state from all modules
|
|
338
|
+
* @returns {Object} State from all modules
|
|
339
|
+
*/
|
|
190
340
|
rootStore.$getState = () => {
|
|
191
341
|
const state = {};
|
|
192
342
|
for (const [name, store] of Object.entries(stores)) {
|
|
@@ -195,6 +345,10 @@ export function createModuleStore(modules) {
|
|
|
195
345
|
return state;
|
|
196
346
|
};
|
|
197
347
|
|
|
348
|
+
/**
|
|
349
|
+
* Reset all modules to initial state
|
|
350
|
+
* @returns {void}
|
|
351
|
+
*/
|
|
198
352
|
rootStore.$reset = () => {
|
|
199
353
|
for (const store of Object.values(stores)) {
|
|
200
354
|
store.$reset();
|
|
@@ -205,35 +359,72 @@ export function createModuleStore(modules) {
|
|
|
205
359
|
}
|
|
206
360
|
|
|
207
361
|
/**
|
|
208
|
-
*
|
|
362
|
+
* Apply a plugin to a store.
|
|
363
|
+
* Plugins can extend store functionality.
|
|
364
|
+
* @param {Store} store - The store to enhance
|
|
365
|
+
* @param {StorePlugin} plugin - Plugin function
|
|
366
|
+
* @returns {Store} Enhanced store
|
|
367
|
+
* @example
|
|
368
|
+
* const store = createStore({ count: 0 });
|
|
369
|
+
* usePlugin(store, loggerPlugin);
|
|
370
|
+
* usePlugin(store, historyPlugin);
|
|
209
371
|
*/
|
|
210
372
|
export function usePlugin(store, plugin) {
|
|
211
373
|
return plugin(store);
|
|
212
374
|
}
|
|
213
375
|
|
|
214
376
|
/**
|
|
215
|
-
* Logger plugin - logs all state changes
|
|
377
|
+
* Logger plugin - logs all state changes to console.
|
|
378
|
+
* Useful for debugging store updates.
|
|
379
|
+
* @param {Store} store - The store to add logging to
|
|
380
|
+
* @returns {Store} Store with logging enabled
|
|
381
|
+
* @example
|
|
382
|
+
* const store = createStore({ count: 0 });
|
|
383
|
+
* usePlugin(store, loggerPlugin);
|
|
384
|
+
*
|
|
385
|
+
* store.$setState({ count: 5 });
|
|
386
|
+
* // Console: [Store:Update] State Change
|
|
387
|
+
* // Previous: { count: 0 }
|
|
388
|
+
* // Updates: { count: 5 }
|
|
389
|
+
* // Next: { count: 5 }
|
|
216
390
|
*/
|
|
217
391
|
export function loggerPlugin(store) {
|
|
218
392
|
const originalSetState = store.$setState;
|
|
393
|
+
const pluginLog = createLogger('Store:Update');
|
|
219
394
|
|
|
220
395
|
store.$setState = (updates) => {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
396
|
+
pluginLog.group('State Change');
|
|
397
|
+
pluginLog.debug('Previous:', store.$getState());
|
|
398
|
+
pluginLog.debug('Updates:', updates);
|
|
224
399
|
originalSetState(updates);
|
|
225
|
-
|
|
226
|
-
|
|
400
|
+
pluginLog.debug('Next:', store.$getState());
|
|
401
|
+
pluginLog.groupEnd();
|
|
227
402
|
};
|
|
228
403
|
|
|
229
404
|
return store;
|
|
230
405
|
}
|
|
231
406
|
|
|
232
407
|
/**
|
|
233
|
-
* History plugin - enables undo/redo
|
|
408
|
+
* History plugin - enables undo/redo functionality.
|
|
409
|
+
* Tracks state changes and allows reverting to previous states.
|
|
410
|
+
* @param {Store} store - The store to add history to
|
|
411
|
+
* @param {number} [maxHistory=50] - Maximum number of history states to keep
|
|
412
|
+
* @returns {Store & {$undo: function, $redo: function, $canUndo: function, $canRedo: function}} Store with history methods
|
|
413
|
+
* @example
|
|
414
|
+
* const store = createStore({ count: 0 });
|
|
415
|
+
* usePlugin(store, (s) => historyPlugin(s, 100));
|
|
416
|
+
*
|
|
417
|
+
* store.$setState({ count: 1 });
|
|
418
|
+
* store.$setState({ count: 2 });
|
|
419
|
+
*
|
|
420
|
+
* store.$canUndo(); // true
|
|
421
|
+
* store.$undo(); // count = 1
|
|
422
|
+
* store.$redo(); // count = 2
|
|
234
423
|
*/
|
|
235
424
|
export function historyPlugin(store, maxHistory = 50) {
|
|
425
|
+
/** @type {Array<Object>} */
|
|
236
426
|
const history = [store.$getState()];
|
|
427
|
+
/** @type {number} */
|
|
237
428
|
let currentIndex = 0;
|
|
238
429
|
|
|
239
430
|
const originalSetState = store.$setState;
|
|
@@ -255,6 +446,10 @@ export function historyPlugin(store, maxHistory = 50) {
|
|
|
255
446
|
}
|
|
256
447
|
};
|
|
257
448
|
|
|
449
|
+
/**
|
|
450
|
+
* Undo the last state change
|
|
451
|
+
* @returns {void}
|
|
452
|
+
*/
|
|
258
453
|
store.$undo = () => {
|
|
259
454
|
if (currentIndex > 0) {
|
|
260
455
|
currentIndex--;
|
|
@@ -269,6 +464,10 @@ export function historyPlugin(store, maxHistory = 50) {
|
|
|
269
464
|
}
|
|
270
465
|
};
|
|
271
466
|
|
|
467
|
+
/**
|
|
468
|
+
* Redo a previously undone state change
|
|
469
|
+
* @returns {void}
|
|
470
|
+
*/
|
|
272
471
|
store.$redo = () => {
|
|
273
472
|
if (currentIndex < history.length - 1) {
|
|
274
473
|
currentIndex++;
|
|
@@ -283,7 +482,16 @@ export function historyPlugin(store, maxHistory = 50) {
|
|
|
283
482
|
}
|
|
284
483
|
};
|
|
285
484
|
|
|
485
|
+
/**
|
|
486
|
+
* Check if undo is available
|
|
487
|
+
* @returns {boolean} True if there are states to undo
|
|
488
|
+
*/
|
|
286
489
|
store.$canUndo = () => currentIndex > 0;
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Check if redo is available
|
|
493
|
+
* @returns {boolean} True if there are states to redo
|
|
494
|
+
*/
|
|
287
495
|
store.$canRedo = () => currentIndex < history.length - 1;
|
|
288
496
|
|
|
289
497
|
return store;
|
package/types/dom.d.ts
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pulse Framework - DOM Helpers Type Definitions
|
|
3
|
+
* @module pulse-js-framework/runtime
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Pulse } from './pulse';
|
|
7
|
+
|
|
8
|
+
/** Value or getter function */
|
|
9
|
+
export type MaybeGetter<T> = T | (() => T);
|
|
10
|
+
|
|
11
|
+
/** Value, getter, or Pulse */
|
|
12
|
+
export type Reactive<T> = T | (() => T) | Pulse<T>;
|
|
13
|
+
|
|
14
|
+
/** Child content type for elements */
|
|
15
|
+
export type Child =
|
|
16
|
+
| string
|
|
17
|
+
| number
|
|
18
|
+
| Node
|
|
19
|
+
| null
|
|
20
|
+
| undefined
|
|
21
|
+
| (() => Child | Child[])
|
|
22
|
+
| Child[];
|
|
23
|
+
|
|
24
|
+
/** Parsed selector result */
|
|
25
|
+
export interface ParsedSelector {
|
|
26
|
+
tag: string;
|
|
27
|
+
id: string | null;
|
|
28
|
+
classes: string[];
|
|
29
|
+
attrs: Record<string, string>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Parse CSS selector into configuration
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseSelector(selector: string): ParsedSelector;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create element from CSS selector syntax
|
|
39
|
+
* @example el('div.container#main', 'Hello')
|
|
40
|
+
* @example el('input[type=text][placeholder=Name]')
|
|
41
|
+
*/
|
|
42
|
+
export declare function el(selector: string, ...children: Child[]): HTMLElement;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create reactive text node
|
|
46
|
+
*/
|
|
47
|
+
export declare function text(getValue: MaybeGetter<string | number>): Text;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Bind attribute reactively
|
|
51
|
+
* @returns Element (chainable)
|
|
52
|
+
*/
|
|
53
|
+
export declare function bind<E extends HTMLElement>(
|
|
54
|
+
element: E,
|
|
55
|
+
attr: string,
|
|
56
|
+
getValue: MaybeGetter<string | boolean | number | null>
|
|
57
|
+
): E;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Bind property reactively
|
|
61
|
+
* @returns Element (chainable)
|
|
62
|
+
*/
|
|
63
|
+
export declare function prop<E extends HTMLElement>(
|
|
64
|
+
element: E,
|
|
65
|
+
propName: string,
|
|
66
|
+
getValue: MaybeGetter<unknown>
|
|
67
|
+
): E;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Bind CSS class reactively
|
|
71
|
+
* @returns Element (chainable)
|
|
72
|
+
*/
|
|
73
|
+
export declare function cls<E extends HTMLElement>(
|
|
74
|
+
element: E,
|
|
75
|
+
className: string,
|
|
76
|
+
condition: MaybeGetter<boolean>
|
|
77
|
+
): E;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Bind style property reactively
|
|
81
|
+
* @returns Element (chainable)
|
|
82
|
+
*/
|
|
83
|
+
export declare function style<E extends HTMLElement>(
|
|
84
|
+
element: E,
|
|
85
|
+
prop: string,
|
|
86
|
+
getValue: MaybeGetter<string>
|
|
87
|
+
): E;
|
|
88
|
+
|
|
89
|
+
/** Event handler options */
|
|
90
|
+
export interface EventOptions {
|
|
91
|
+
capture?: boolean;
|
|
92
|
+
once?: boolean;
|
|
93
|
+
passive?: boolean;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Attach event listener
|
|
98
|
+
* @returns Element (chainable)
|
|
99
|
+
*/
|
|
100
|
+
export declare function on<E extends HTMLElement, K extends keyof HTMLElementEventMap>(
|
|
101
|
+
element: E,
|
|
102
|
+
event: K,
|
|
103
|
+
handler: (e: HTMLElementEventMap[K]) => void,
|
|
104
|
+
options?: EventOptions
|
|
105
|
+
): E;
|
|
106
|
+
export declare function on<E extends HTMLElement>(
|
|
107
|
+
element: E,
|
|
108
|
+
event: string,
|
|
109
|
+
handler: (e: Event) => void,
|
|
110
|
+
options?: EventOptions
|
|
111
|
+
): E;
|
|
112
|
+
|
|
113
|
+
/** Key function for list rendering */
|
|
114
|
+
export type KeyFn<T> = (item: T, index: number) => unknown;
|
|
115
|
+
|
|
116
|
+
/** Template function for list items */
|
|
117
|
+
export type ListTemplate<T> = (item: T, index: number) => Node | Node[];
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Render reactive list with efficient keyed diffing
|
|
121
|
+
*/
|
|
122
|
+
export declare function list<T>(
|
|
123
|
+
getItems: Reactive<T[]>,
|
|
124
|
+
template: ListTemplate<T>,
|
|
125
|
+
keyFn?: KeyFn<T>
|
|
126
|
+
): DocumentFragment;
|
|
127
|
+
|
|
128
|
+
/** Template function for conditional rendering */
|
|
129
|
+
export type ConditionTemplate = () => Node | Node[] | null;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Conditional rendering (removes unmounted elements)
|
|
133
|
+
*/
|
|
134
|
+
export declare function when(
|
|
135
|
+
condition: Reactive<boolean>,
|
|
136
|
+
thenTemplate: ConditionTemplate,
|
|
137
|
+
elseTemplate?: ConditionTemplate
|
|
138
|
+
): DocumentFragment;
|
|
139
|
+
|
|
140
|
+
/** Match cases object */
|
|
141
|
+
export interface MatchCases<T extends string | number | symbol = string> {
|
|
142
|
+
[key: string]: ConditionTemplate;
|
|
143
|
+
default?: ConditionTemplate;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Switch/case rendering
|
|
148
|
+
*/
|
|
149
|
+
export declare function match<T extends string | number>(
|
|
150
|
+
getValue: Reactive<T>,
|
|
151
|
+
cases: MatchCases
|
|
152
|
+
): Comment;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Two-way binding for form inputs
|
|
156
|
+
* @returns Element (chainable)
|
|
157
|
+
*/
|
|
158
|
+
export declare function model<E extends HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>(
|
|
159
|
+
element: E,
|
|
160
|
+
pulseValue: Pulse<string | number | boolean>
|
|
161
|
+
): E;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Mount element to DOM target
|
|
165
|
+
* @returns Unmount function
|
|
166
|
+
*/
|
|
167
|
+
export declare function mount(
|
|
168
|
+
target: string | HTMLElement,
|
|
169
|
+
element: Node
|
|
170
|
+
): () => void;
|
|
171
|
+
|
|
172
|
+
/** Component context object */
|
|
173
|
+
export interface ComponentContext {
|
|
174
|
+
/** Create reactive state */
|
|
175
|
+
state: <T extends Record<string, unknown>>(initial: T) => T;
|
|
176
|
+
/** Create methods bound to component */
|
|
177
|
+
methods: <T extends Record<string, (...args: unknown[]) => unknown>>(fns: T) => T;
|
|
178
|
+
/** Component props */
|
|
179
|
+
props: Record<string, unknown>;
|
|
180
|
+
/** Create pulse */
|
|
181
|
+
pulse: <T>(value: T) => Pulse<T>;
|
|
182
|
+
/** Create element */
|
|
183
|
+
el: typeof el;
|
|
184
|
+
/** Create text node */
|
|
185
|
+
text: typeof text;
|
|
186
|
+
/** Render list */
|
|
187
|
+
list: typeof list;
|
|
188
|
+
/** Conditional render */
|
|
189
|
+
when: typeof when;
|
|
190
|
+
/** Attach event */
|
|
191
|
+
on: typeof on;
|
|
192
|
+
/** Bind attribute */
|
|
193
|
+
bind: typeof bind;
|
|
194
|
+
/** Two-way binding */
|
|
195
|
+
model: typeof model;
|
|
196
|
+
/** Register mount callback */
|
|
197
|
+
onMount: (fn: () => void) => void;
|
|
198
|
+
/** Register unmount callback */
|
|
199
|
+
onUnmount: (fn: () => void) => void;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Component setup function */
|
|
203
|
+
export type ComponentSetup = (ctx: ComponentContext) => Node;
|
|
204
|
+
|
|
205
|
+
/** Component factory function */
|
|
206
|
+
export type ComponentFactory = (props?: Record<string, unknown>) => Node;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Create component with lifecycle support
|
|
210
|
+
*/
|
|
211
|
+
export declare function component(setup: ComponentSetup): ComponentFactory;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Register mount callback
|
|
215
|
+
*/
|
|
216
|
+
export declare function onMount(fn: () => void): void;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Register unmount callback
|
|
220
|
+
*/
|
|
221
|
+
export declare function onUnmount(fn: () => void): void;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Toggle visibility without removing from DOM
|
|
225
|
+
* @returns Element (chainable)
|
|
226
|
+
*/
|
|
227
|
+
export declare function show<E extends HTMLElement>(
|
|
228
|
+
condition: Reactive<boolean>,
|
|
229
|
+
element: E
|
|
230
|
+
): E;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Render content into different DOM location
|
|
234
|
+
*/
|
|
235
|
+
export declare function portal(
|
|
236
|
+
children: Node | Node[] | (() => Node | Node[]),
|
|
237
|
+
target: string | HTMLElement
|
|
238
|
+
): Comment;
|
|
239
|
+
|
|
240
|
+
/** Error fallback function */
|
|
241
|
+
export type ErrorFallback = (error: Error) => Node | Node[];
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Error boundary for child components
|
|
245
|
+
*/
|
|
246
|
+
export declare function errorBoundary(
|
|
247
|
+
children: Node | Node[] | (() => Node | Node[]),
|
|
248
|
+
fallback?: ErrorFallback
|
|
249
|
+
): DocumentFragment;
|
|
250
|
+
|
|
251
|
+
/** Transition options */
|
|
252
|
+
export interface TransitionOptions {
|
|
253
|
+
enter?: string;
|
|
254
|
+
exit?: string;
|
|
255
|
+
duration?: number;
|
|
256
|
+
onEnter?: (el: HTMLElement) => void;
|
|
257
|
+
onExit?: (el: HTMLElement) => void;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Element with transition methods */
|
|
261
|
+
export interface TransitionElement extends HTMLElement {
|
|
262
|
+
_pulseTransitionExit?: () => void;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Animate element enter/exit
|
|
267
|
+
*/
|
|
268
|
+
export declare function transition<E extends HTMLElement>(
|
|
269
|
+
element: E,
|
|
270
|
+
options?: TransitionOptions
|
|
271
|
+
): E & TransitionElement;
|
|
272
|
+
|
|
273
|
+
/** WhenTransition options */
|
|
274
|
+
export interface WhenTransitionOptions {
|
|
275
|
+
duration?: number;
|
|
276
|
+
enterClass?: string;
|
|
277
|
+
exitClass?: string;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Conditional rendering with transitions
|
|
282
|
+
*/
|
|
283
|
+
export declare function whenTransition(
|
|
284
|
+
condition: Reactive<boolean>,
|
|
285
|
+
thenTemplate: ConditionTemplate,
|
|
286
|
+
elseTemplate?: ConditionTemplate,
|
|
287
|
+
options?: WhenTransitionOptions
|
|
288
|
+
): DocumentFragment;
|