13
13
*/
14
14
const isFunction = fn => typeof fn === 'function' ;
15
15
16
+ /**
17
+ * Recursively nest a map
18
+ *
19
+ * @param {Map } map - map to nest
20
+ * @param {...any } args - key(s) to nest the map under
21
+ * @returns {Map } nested map
22
+ */
23
+ const nestMap = ( map , ...args ) => {
24
+ const key = args . shift ( ) ;
25
+ ! map . has ( key ) && map . set ( key , new Map ( ) ) ;
26
+ return args . length ? nestMap ( map . get ( key ) , ...args ) : map . get ( key ) ;
27
+ }
28
+
29
+ /**
30
+ * Recursively unnest a map
31
+ *
32
+ * @param {Map } map - map to unnest
33
+ * @returns {any[] } unnested array
34
+ */
35
+ const unnestMap = map => {
36
+ const result = [ ] ;
37
+ for ( const [ key , value ] of map ) {
38
+ ( value instanceof Map ) ? result . push ( key , ...unnestMap ( value ) ) : result . push ( key , value ) ;
39
+ }
40
+ return result ;
41
+ }
42
+
16
43
// hold the currently active effect
17
- let activeEffect ;
44
+ let active ;
18
45
19
46
/**
20
47
* Define a reactive state
@@ -24,31 +51,23 @@ let activeEffect;
24
51
* @returns {import('./types').FxState } getter function for the current value with a `set` method to update the value
25
52
*/
26
53
const cause = value => {
27
- const s = ( ) => { // getter function
28
- activeEffect && s . e . add ( activeEffect ) ;
54
+ const state = ( ) => { // getter function
55
+ active && state . effects . add ( active ) ;
29
56
return value ;
30
57
} ;
31
- s . e = new Set ( ) ; // set of listeners
32
- s . set = ( /** @type {any } */ updater ) => { // setter function
58
+ state . effects = new Set ( ) ; // set of listeners
59
+ state . set = ( /** @type {any } */ updater ) => { // setter function
33
60
const old = value ;
34
61
value = isFunction ( updater ) && ! isFunction ( value . set ) ? updater ( old ) : updater ;
35
62
if ( ! Object . is ( value , old ) ) {
36
- for ( const e of s . e ) e ( ) ;
63
+ for ( const effect of state . effects ) effect ( ) ;
37
64
}
38
65
} ;
39
- return s ;
66
+ return state ;
40
67
} ;
41
68
42
69
/* === Exported functions === */
43
70
44
- /**
45
- * Recursivlely unwrap a given variable if it is a function
46
- *
47
- * @param {any } value
48
- * @returns {any } unwrapped variable
49
- */
50
- const unwrap = value => isFunction ( value ) ? unwrap ( value ( ) ) : value ;
51
-
52
71
/**
53
72
* Define what happens when a reactive state changes
54
73
*
@@ -60,42 +79,42 @@ const effect = fn => {
60
79
61
80
/**
62
81
* @since 0.6.1
63
- *
64
82
* @param {Element } element - target element
65
83
* @param {import('./types').FxDOMInstruction } domFn
66
- * @param {any } key
67
- * @param {any } value
84
+ * @param {any } key
85
+ * @param {any } value
68
86
*/
69
- const enqueue = ( element , domFn , key , value ) => {
70
- ! targets . has ( element ) && targets . set ( element , new Map ( ) ) ;
71
- const instructions = targets . get ( element ) ;
72
- ! instructions . has ( domFn ) && instructions . set ( domFn , new Map ( ) ) ;
73
- const argsMap = instructions . get ( domFn ) ;
74
- key && argsMap . set ( key , value ) ;
75
- } ;
87
+ const enqueue = ( element , domFn , key , value ) => nestMap ( targets , element , domFn ) . set ( key , value ) ;
76
88
77
89
// effect callback function
78
90
const next = ( ) => queueMicrotask ( ( ) => {
79
- const prev = activeEffect ;
80
- activeEffect = next ;
91
+ const prev = active ;
92
+ active = next ;
81
93
const cleanup = fn ( enqueue ) ;
82
- activeEffect = prev ;
94
+ active = prev ;
83
95
// flush all queued instructions
84
- for ( const [ element , instructions ] of targets . entries ( ) ) {
85
- for ( const [ domFn , argsMap ] of instructions . entries ( ) ) {
86
- for ( const [ key , value ] of argsMap . entries ( ) ) domFn ( element , key , value ) ;
87
- }
88
- }
96
+ const [ element , domFn , key , value ] = unnestMap ( targets ) ;
97
+ isFunction ( domFn ) && domFn ( element , key , value ) ;
89
98
// @ts -ignore
90
99
isFunction ( cleanup ) && cleanup ( ) ;
91
100
} ) ;
92
101
next . targets = targets ;
93
102
next ( ) ;
94
103
}
95
104
105
+ /**
106
+ * Recursivlely unwrap a given variable if it is a function
107
+ *
108
+ * @since 0.7.0
109
+ * @param {any } value
110
+ * @returns {any } unwrapped variable
111
+ */
112
+ const unwrap = value => isFunction ( value ) ? unwrap ( value ( ) ) : value ;
113
+
96
114
/**
97
115
* Parse a boolean attribute to an actual boolean value
98
116
*
117
+ * @since 0.7.0
99
118
* @param {string|undefined } value
100
119
* @returns {boolean }
101
120
*/
@@ -104,6 +123,7 @@ const asBoolean = value => typeof value === 'string';
104
123
/**
105
124
* Parse an attribute to a number forced to integer
106
125
*
126
+ * @since 0.7.0
107
127
* @param {string } value
108
128
* @returns {number }
109
129
*/
@@ -112,6 +132,7 @@ const asInteger = value => parseInt(value, 10);
112
132
/**
113
133
* Parse an attribute to a number
114
134
*
135
+ * @since 0.7.0
115
136
* @param {string } value
116
137
* @returns {number }
117
138
*/
@@ -120,6 +141,7 @@ const asNumber = value => parseFloat(value);
120
141
/**
121
142
* Parse an attribute to a string
122
143
*
144
+ * @since 0.7.0
123
145
* @param {string } value
124
146
* @returns {string }
125
147
*/
@@ -229,7 +251,7 @@ export default class UIElement extends HTMLElement {
229
251
}
230
252
231
253
/**
232
- * Pass states to a child element
254
+ * Passes states from the current UIElement to another UIElement
233
255
*
234
256
* @since 0.5.0
235
257
* @param {import('./types').UIElement } element - child element to pass the states to
@@ -244,16 +266,15 @@ export default class UIElement extends HTMLElement {
244
266
}
245
267
246
268
/**
247
- * Return a set of elements that have effects dependent on the given state
269
+ * Return a Set of elements that have effects dependent on the given state
248
270
*
249
271
* @since 0.7.0
250
- *
251
272
* @param {PropertyKey } key - state to get targets for
252
273
* @returns {Set<Element> } set of elements that have effects dependent on the given state
253
274
*/
254
275
targets ( key ) {
255
276
const targets = new Set ( ) ;
256
- for ( const effect of this . #state. get ( key ) . e ) {
277
+ for ( const effect of this . #state. get ( key ) . effects ) {
257
278
for ( const target of effect . targets . keys ( ) ) targets . add ( target ) ;
258
279
}
259
280
return targets ;
0 commit comments