leaner 0.0.1 → 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/README.md +25 -2
- package/dist/core.js +257 -193
- package/dist/web.js +263 -103
- package/package.json +21 -10
- package/types/core.d.ts +47 -0
- package/types/web.d.ts +16 -0
package/dist/web.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { withScope, destroyScope, reactive, constant } from 'leaner';
|
|
2
2
|
|
|
3
3
|
function appendToArray( item, target ) {
|
|
4
4
|
if ( Array.isArray( item ) )
|
|
@@ -40,8 +40,10 @@ function createContext( parent ) {
|
|
|
40
40
|
return {
|
|
41
41
|
parent,
|
|
42
42
|
children: null,
|
|
43
|
+
scope: [],
|
|
43
44
|
mount: null,
|
|
44
45
|
destroy: null,
|
|
46
|
+
services: null,
|
|
45
47
|
};
|
|
46
48
|
}
|
|
47
49
|
|
|
@@ -61,7 +63,7 @@ function withContext( context, callback ) {
|
|
|
61
63
|
const last = current;
|
|
62
64
|
current = context;
|
|
63
65
|
try {
|
|
64
|
-
return callback
|
|
66
|
+
return withScope( current.scope, callback );
|
|
65
67
|
} finally {
|
|
66
68
|
current = last;
|
|
67
69
|
}
|
|
@@ -70,7 +72,7 @@ function withContext( context, callback ) {
|
|
|
70
72
|
function withChildContext( callback ) {
|
|
71
73
|
current = createChildContext();
|
|
72
74
|
try {
|
|
73
|
-
return callback
|
|
75
|
+
return withScope( current.scope, callback );
|
|
74
76
|
} finally {
|
|
75
77
|
current = current.parent;
|
|
76
78
|
}
|
|
@@ -108,20 +110,43 @@ function destroyContext( context ) {
|
|
|
108
110
|
if ( context.destroy != null ) {
|
|
109
111
|
for ( const callback of context.destroy )
|
|
110
112
|
callback();
|
|
113
|
+
context.destroy = null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
context.mounted = null;
|
|
117
|
+
|
|
118
|
+
if ( context.scope.length > 0 ) {
|
|
119
|
+
destroyScope( context.scope );
|
|
120
|
+
context.scope = [];
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
if ( context.children != null ) {
|
|
114
124
|
for ( const child of context.children )
|
|
115
125
|
destroyContext( child );
|
|
116
|
-
|
|
117
126
|
context.children = null;
|
|
118
127
|
}
|
|
119
128
|
}
|
|
120
129
|
|
|
130
|
+
function provide( key, value ) {
|
|
131
|
+
if ( current == null )
|
|
132
|
+
throw new Error( 'provide() cannot be called outside of a component' );
|
|
133
|
+
|
|
134
|
+
if ( current.services == null )
|
|
135
|
+
current.services = new Map();
|
|
136
|
+
|
|
137
|
+
current.services.set( key, value );
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function inject( key ) {
|
|
141
|
+
for ( let context = current; context != null; context = context.parent ) {
|
|
142
|
+
if ( context.services != null && context.services.has( key ) )
|
|
143
|
+
return context.services.get( key );
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
121
147
|
function setClasses( element, classes ) {
|
|
122
148
|
if ( typeof classes == 'function' ) {
|
|
123
|
-
|
|
124
|
-
const value = classes();
|
|
149
|
+
reactive( classes, value => {
|
|
125
150
|
if ( Array.isArray( value ) ) {
|
|
126
151
|
element.className = '';
|
|
127
152
|
element.classList.add( ...value );
|
|
@@ -141,11 +166,14 @@ function setClasses( element, classes ) {
|
|
|
141
166
|
function setClassesObject( element, classes ) {
|
|
142
167
|
for ( const [ key, value ] of Object.entries( classes ) ) {
|
|
143
168
|
if ( typeof value == 'function' ) {
|
|
144
|
-
|
|
145
|
-
if (
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
169
|
+
reactive( value, ( newValue, value ) => {
|
|
170
|
+
if ( newValue ) {
|
|
171
|
+
if ( !value )
|
|
172
|
+
element.classList.add( key );
|
|
173
|
+
} else {
|
|
174
|
+
if ( value )
|
|
175
|
+
element.classList.remove( key );
|
|
176
|
+
}
|
|
149
177
|
} );
|
|
150
178
|
} else if ( value ) {
|
|
151
179
|
element.classList.add( key );
|
|
@@ -156,18 +184,16 @@ function setClassesObject( element, classes ) {
|
|
|
156
184
|
function setClassesArray( element, classes ) {
|
|
157
185
|
for ( const item of classes ) {
|
|
158
186
|
if ( typeof item == 'function' ) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
element.classList.replace( value, newValue );
|
|
170
|
-
value = newValue;
|
|
187
|
+
reactive( item, ( newValue, value ) => {
|
|
188
|
+
if ( newValue ) {
|
|
189
|
+
if ( value )
|
|
190
|
+
element.classList.replace( value, newValue );
|
|
191
|
+
else
|
|
192
|
+
element.classList.add( newValue );
|
|
193
|
+
} else {
|
|
194
|
+
if ( value )
|
|
195
|
+
element.classList.remove( value );
|
|
196
|
+
}
|
|
171
197
|
} );
|
|
172
198
|
} else if ( isPlainObject( item ) ) {
|
|
173
199
|
setClassesObject( element, item );
|
|
@@ -180,38 +206,45 @@ function setClassesArray( element, classes ) {
|
|
|
180
206
|
class DynamicNode {
|
|
181
207
|
constructor( content ) {
|
|
182
208
|
this.content = content;
|
|
209
|
+
this.parentNode = null;
|
|
183
210
|
}
|
|
184
211
|
}
|
|
185
212
|
|
|
186
|
-
function appendNode( node,
|
|
213
|
+
function appendNode( node, parent ) {
|
|
187
214
|
if ( Array.isArray( node ) ) {
|
|
188
215
|
if ( node.some( item => item instanceof DynamicNode ) ) {
|
|
189
216
|
for ( const item of node ) {
|
|
190
|
-
if ( item instanceof DynamicNode )
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
217
|
+
if ( item instanceof DynamicNode ) {
|
|
218
|
+
item.parentNode = parent;
|
|
219
|
+
appendNode( item.content, parent );
|
|
220
|
+
} else {
|
|
221
|
+
parent.append( item );
|
|
222
|
+
}
|
|
194
223
|
}
|
|
195
224
|
} else {
|
|
196
|
-
|
|
225
|
+
parent.append( ...node );
|
|
197
226
|
}
|
|
198
227
|
} else if ( node instanceof DynamicNode ) {
|
|
199
|
-
|
|
228
|
+
node.parentNode = parent;
|
|
229
|
+
appendNode( node.content, parent );
|
|
200
230
|
} else {
|
|
201
|
-
|
|
231
|
+
parent.append( node );
|
|
202
232
|
}
|
|
203
233
|
}
|
|
204
234
|
|
|
205
235
|
function insertBefore( node, parent, before ) {
|
|
206
236
|
if ( Array.isArray( node ) ) {
|
|
207
237
|
for ( const item of node ) {
|
|
208
|
-
if ( item instanceof DynamicNode )
|
|
238
|
+
if ( item instanceof DynamicNode ) {
|
|
239
|
+
item.parentNode = parent;
|
|
209
240
|
insertBefore( item.content, parent, before );
|
|
210
|
-
else
|
|
241
|
+
} else {
|
|
211
242
|
parent.insertBefore( item, before );
|
|
243
|
+
}
|
|
212
244
|
}
|
|
213
245
|
} else if ( node instanceof DynamicNode ) {
|
|
214
|
-
|
|
246
|
+
node.parentNode = parent;
|
|
247
|
+
insertBefore( node.content, parent, before );
|
|
215
248
|
} else {
|
|
216
249
|
parent.insertBefore( node, before );
|
|
217
250
|
}
|
|
@@ -219,40 +252,133 @@ function insertBefore( node, parent, before ) {
|
|
|
219
252
|
|
|
220
253
|
function removeNode( node ) {
|
|
221
254
|
if ( Array.isArray( node ) ) {
|
|
222
|
-
let parent = null, before = null;
|
|
223
255
|
for ( const item of node ) {
|
|
224
256
|
if ( item instanceof DynamicNode ) {
|
|
225
|
-
|
|
257
|
+
removeNode( item.content );
|
|
258
|
+
item.parentNode = null;
|
|
226
259
|
} else {
|
|
227
|
-
|
|
228
|
-
before = item.nextSibling;
|
|
229
|
-
parent.removeChild( item );
|
|
260
|
+
item.parentNode.removeChild( item );
|
|
230
261
|
}
|
|
231
262
|
}
|
|
232
|
-
|
|
263
|
+
} else if ( node instanceof DynamicNode ) {
|
|
264
|
+
removeNode( node.content );
|
|
265
|
+
node.parentNode = null;
|
|
266
|
+
} else {
|
|
267
|
+
node.parentNode.removeChild( node );
|
|
233
268
|
}
|
|
234
|
-
|
|
235
|
-
if ( node instanceof DynamicNode )
|
|
236
|
-
return removeNode( node.content );
|
|
237
|
-
|
|
238
|
-
const parent = node.parentNode;
|
|
239
|
-
const before = node.nextSibling;
|
|
240
|
-
|
|
241
|
-
parent.removeChild( node );
|
|
242
|
-
|
|
243
|
-
return [ parent, before ];
|
|
244
269
|
}
|
|
245
270
|
|
|
246
271
|
function replaceNode( newNode, node ) {
|
|
247
272
|
if ( newNode instanceof Node && node instanceof Node ) {
|
|
248
273
|
node.parentNode.replaceChild( newNode, node );
|
|
249
|
-
} else {
|
|
250
|
-
|
|
274
|
+
} else if ( Array.isArray( newNode ) && Array.isArray( node ) ) {
|
|
275
|
+
let newStart = 0, start = 0;
|
|
276
|
+
let newEnd = newNode.length, end = node.length;
|
|
277
|
+
let parent = null, before = null;
|
|
278
|
+
|
|
279
|
+
while ( newStart < newEnd || start < end ) {
|
|
280
|
+
// skip equal nodes at the start
|
|
281
|
+
if ( newNode[ newStart ] == node[ start ] ) {
|
|
282
|
+
newStart++;
|
|
283
|
+
start++;
|
|
284
|
+
before = null;
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// skip equal nodes at the end
|
|
289
|
+
while ( newNode[ newEnd - 1 ] == node[ end - 1 ] ) {
|
|
290
|
+
newEnd--;
|
|
291
|
+
end--;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// insert new node
|
|
295
|
+
if ( newStart < newEnd && newNode[ newStart ].parentNode == null ) {
|
|
296
|
+
if ( before == null ) {
|
|
297
|
+
if ( start < end ) {
|
|
298
|
+
before = node[ start ];
|
|
299
|
+
if ( before instanceof DynamicNode )
|
|
300
|
+
before = findFirstChild( before.content );
|
|
301
|
+
parent = before.parentNode;
|
|
302
|
+
} else {
|
|
303
|
+
let after = newNode[ newStart - 1 ];
|
|
304
|
+
if ( after instanceof DynamicNode )
|
|
305
|
+
after = findLastChild( after.content );
|
|
306
|
+
before = after.nextSibling;
|
|
307
|
+
parent = after.parentNode;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
insertBefore( newNode[ newStart ], parent, before );
|
|
311
|
+
newStart++;
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// swap nodes
|
|
316
|
+
if ( newNode[ newStart ] == node[ end - 1 ] && newNode[ newEnd - 1 ] == node[ start ] ) {
|
|
317
|
+
let after, before2;
|
|
318
|
+
if ( end - start > 2 ) {
|
|
319
|
+
after = node[ end - 1 ];
|
|
320
|
+
if ( after instanceof DynamicNode )
|
|
321
|
+
after = findLastChild( after.content );
|
|
322
|
+
before2 = after.nextSibling;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if ( before == null ) {
|
|
326
|
+
before = node[ start ];
|
|
327
|
+
if ( before instanceof DynamicNode )
|
|
328
|
+
before = findFirstChild( before.content );
|
|
329
|
+
parent = before.parentNode;
|
|
330
|
+
}
|
|
331
|
+
insertBefore( node[ end - 1 ], parent, before );
|
|
332
|
+
|
|
333
|
+
if ( after != null )
|
|
334
|
+
insertBefore( node[ start ], parent, before2 );
|
|
335
|
+
|
|
336
|
+
start++;
|
|
337
|
+
newStart++;
|
|
338
|
+
end--;
|
|
339
|
+
newEnd--;
|
|
251
340
|
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// remove node
|
|
345
|
+
removeNode( node[ start ] );
|
|
346
|
+
start++;
|
|
347
|
+
before = null;
|
|
348
|
+
}
|
|
349
|
+
} else {
|
|
350
|
+
const after = findLastChild( node );
|
|
351
|
+
const before = after.nextSibling;
|
|
352
|
+
const parent = after.parentNode;
|
|
353
|
+
removeNode( node );
|
|
252
354
|
insertBefore( newNode, parent, before );
|
|
253
355
|
}
|
|
254
356
|
}
|
|
255
357
|
|
|
358
|
+
function findFirstChild( node ) {
|
|
359
|
+
if ( Array.isArray( node ) ) {
|
|
360
|
+
const item = node[ 0 ];
|
|
361
|
+
if ( item instanceof DynamicNode )
|
|
362
|
+
return findFirstChild( item.content );
|
|
363
|
+
return item;
|
|
364
|
+
}
|
|
365
|
+
if ( node instanceof DynamicNode )
|
|
366
|
+
return findFirstChild( node.content );
|
|
367
|
+
return node;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function findLastChild( node ) {
|
|
371
|
+
if ( Array.isArray( node ) ) {
|
|
372
|
+
const item = node[ node.length - 1 ];
|
|
373
|
+
if ( item instanceof DynamicNode )
|
|
374
|
+
return findLastChild( item.content );
|
|
375
|
+
return item;
|
|
376
|
+
}
|
|
377
|
+
if ( node instanceof DynamicNode )
|
|
378
|
+
return findLastChild( node.content );
|
|
379
|
+
return node;
|
|
380
|
+
}
|
|
381
|
+
|
|
256
382
|
function ensureNotEmpty( node ) {
|
|
257
383
|
if ( isEmpty( node ) ) {
|
|
258
384
|
const comment = document.createComment( '' );
|
|
@@ -305,7 +431,7 @@ function createDynamicDirective( template ) {
|
|
|
305
431
|
|
|
306
432
|
const context = createChildContext();
|
|
307
433
|
|
|
308
|
-
|
|
434
|
+
reactive( type, update );
|
|
309
435
|
|
|
310
436
|
return result;
|
|
311
437
|
|
|
@@ -318,6 +444,8 @@ function createForDirective( template ) {
|
|
|
318
444
|
if ( template.length != 3 || typeof template[ 1 ] != 'function' || typeof template[ 2 ] != 'function' )
|
|
319
445
|
throw new TypeError( 'Invalid for template' );
|
|
320
446
|
|
|
447
|
+
const itemsGetter = template[ 1 ];
|
|
448
|
+
|
|
321
449
|
let length = 0;
|
|
322
450
|
let items = null;
|
|
323
451
|
|
|
@@ -327,25 +455,16 @@ function createForDirective( template ) {
|
|
|
327
455
|
|
|
328
456
|
const context = createChildContext();
|
|
329
457
|
|
|
330
|
-
|
|
458
|
+
withScope( context.scope, () => {
|
|
459
|
+
// initially only watch the length of the items array
|
|
460
|
+
reactive( itemsGetter.length, updateLength );
|
|
461
|
+
} );
|
|
331
462
|
|
|
332
463
|
return result;
|
|
333
464
|
|
|
334
|
-
function watchLength() {
|
|
335
|
-
if ( !watchingContent )
|
|
336
|
-
return template[ 1 ].length();
|
|
337
|
-
}
|
|
338
|
-
|
|
339
465
|
function updateLength( newLength ) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
length = newLength;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
function watchContent() {
|
|
347
|
-
// clone the array to watch all elements
|
|
348
|
-
return [ ...template[ 1 ]() ];
|
|
466
|
+
update( itemsGetter() );
|
|
467
|
+
length = newLength;
|
|
349
468
|
}
|
|
350
469
|
|
|
351
470
|
function updateContent( newItems ) {
|
|
@@ -364,6 +483,13 @@ function createForDirective( template ) {
|
|
|
364
483
|
|
|
365
484
|
let containsMatchedByValue = false;
|
|
366
485
|
|
|
486
|
+
let oldIndexMap = null;
|
|
487
|
+
if ( watchingContent && items.length != 0 && newItems.length != 0 ) {
|
|
488
|
+
oldIndexMap = new Map();
|
|
489
|
+
for ( let i = 0; i < items.length; i++ )
|
|
490
|
+
oldIndexMap.set( items[ i ], i );
|
|
491
|
+
}
|
|
492
|
+
|
|
367
493
|
for ( let index = 0; index < newItems.length; index++ ) {
|
|
368
494
|
const value = newItems[ index ];
|
|
369
495
|
|
|
@@ -372,20 +498,20 @@ function createForDirective( template ) {
|
|
|
372
498
|
if ( isMatchedByValue )
|
|
373
499
|
containsMatchedByValue = true;
|
|
374
500
|
|
|
375
|
-
let oldIndex =
|
|
501
|
+
let oldIndex = null;
|
|
376
502
|
|
|
377
503
|
// reuse existing items - objects and arrays are matched by value, other items by index
|
|
378
504
|
if ( result.content != null ) {
|
|
379
505
|
if ( isMatchedByValue ) {
|
|
380
|
-
if (
|
|
381
|
-
oldIndex =
|
|
506
|
+
if ( oldIndexMap != null )
|
|
507
|
+
oldIndex = oldIndexMap.get( value );
|
|
382
508
|
} else if ( index < length ) {
|
|
383
509
|
if ( items == null || !isPlainObjectOrArray( items[ index ] ) )
|
|
384
510
|
oldIndex = index;
|
|
385
511
|
}
|
|
386
512
|
}
|
|
387
513
|
|
|
388
|
-
if ( oldIndex
|
|
514
|
+
if ( oldIndex != null ) {
|
|
389
515
|
nodes.push( result.content[ oldIndex ] );
|
|
390
516
|
|
|
391
517
|
const itemContext = context.children[ oldIndex ];
|
|
@@ -401,7 +527,7 @@ function createForDirective( template ) {
|
|
|
401
527
|
newItemContexts = [];
|
|
402
528
|
newItemContexts.push( itemContext );
|
|
403
529
|
|
|
404
|
-
const item = isMatchedByValue ?
|
|
530
|
+
const item = isMatchedByValue ? constant( value ) : itemsGetter[ index ];
|
|
405
531
|
|
|
406
532
|
const itemTemplate = template[ 2 ]( item, index );
|
|
407
533
|
|
|
@@ -437,7 +563,12 @@ function createForDirective( template ) {
|
|
|
437
563
|
context.children = null;
|
|
438
564
|
|
|
439
565
|
if ( containsMatchedByValue && !watchingContent ) {
|
|
440
|
-
|
|
566
|
+
destroyScope( context.scope );
|
|
567
|
+
context.scope = [];
|
|
568
|
+
withScope( context.scope, () => {
|
|
569
|
+
// clone the array to watch all elements
|
|
570
|
+
reactive( () => [ ...itemsGetter() ], updateContent );
|
|
571
|
+
} );
|
|
441
572
|
watchingContent = true;
|
|
442
573
|
}
|
|
443
574
|
}
|
|
@@ -463,7 +594,7 @@ function createIfDirective( template ) {
|
|
|
463
594
|
|
|
464
595
|
const context = createChildContext();
|
|
465
596
|
|
|
466
|
-
|
|
597
|
+
reactive( watchState, update );
|
|
467
598
|
|
|
468
599
|
return result;
|
|
469
600
|
|
|
@@ -490,8 +621,7 @@ function createIfDirective( template ) {
|
|
|
490
621
|
|
|
491
622
|
function setStyles( element, styles ) {
|
|
492
623
|
if ( typeof styles == 'function' ) {
|
|
493
|
-
|
|
494
|
-
const value = styles();
|
|
624
|
+
reactive( styles, value => {
|
|
495
625
|
if ( isPlainObject( value ) ) {
|
|
496
626
|
element.style = '';
|
|
497
627
|
for ( const [ key, value ] of Object.entries( value ) )
|
|
@@ -510,7 +640,7 @@ function setStyles( element, styles ) {
|
|
|
510
640
|
function setStylesObject( element, styles ) {
|
|
511
641
|
for ( const [ key, value ] of Object.entries( styles ) ) {
|
|
512
642
|
if ( typeof value == 'function' )
|
|
513
|
-
|
|
643
|
+
reactive( value, value => element.style[ key ] = value );
|
|
514
644
|
else
|
|
515
645
|
setStyleProperty( element, key, value );
|
|
516
646
|
}
|
|
@@ -523,12 +653,20 @@ function setStyleProperty( element, key, value ) {
|
|
|
523
653
|
element.style[ key ] = value;
|
|
524
654
|
}
|
|
525
655
|
|
|
526
|
-
const
|
|
656
|
+
const Directives = {
|
|
527
657
|
if: createIfDirective,
|
|
528
658
|
for: createForDirective,
|
|
529
659
|
dynamic: createDynamicDirective,
|
|
530
660
|
};
|
|
531
661
|
|
|
662
|
+
const Properties = new Set( [ 'value', 'checked', 'textContent', 'innerHTML' ] );
|
|
663
|
+
|
|
664
|
+
const BooleanAttributes = new Set( [
|
|
665
|
+
'allowfullscreen', 'async', 'autofocus', 'autoplay', 'checked', 'controls', 'default', 'defer', 'disabled', 'formnovalidate', 'hidden',
|
|
666
|
+
'inert', 'ismap', 'itemscope', 'loop', 'multiple', 'muted', 'nomodule', 'novalidate', 'open', 'playsinline', 'readonly',
|
|
667
|
+
'required', 'reversed', 'seamless', 'scoped', 'selected',
|
|
668
|
+
] );
|
|
669
|
+
|
|
532
670
|
function make( template ) {
|
|
533
671
|
if ( template == null )
|
|
534
672
|
return [];
|
|
@@ -547,8 +685,8 @@ function make( template ) {
|
|
|
547
685
|
if ( typeof template[ 0 ] == 'string' ) {
|
|
548
686
|
const tag = template[ 0 ];
|
|
549
687
|
|
|
550
|
-
if (
|
|
551
|
-
return
|
|
688
|
+
if ( Directives.hasOwnProperty( tag ) )
|
|
689
|
+
return Directives[ tag ]( template );
|
|
552
690
|
|
|
553
691
|
const element = document.createElement( tag );
|
|
554
692
|
|
|
@@ -570,7 +708,7 @@ function make( template ) {
|
|
|
570
708
|
|
|
571
709
|
if ( typeof template == 'function' ) {
|
|
572
710
|
const textNode = document.createTextNode( '' );
|
|
573
|
-
|
|
711
|
+
reactive( template, value => textNode.textContent = value );
|
|
574
712
|
return textNode;
|
|
575
713
|
}
|
|
576
714
|
|
|
@@ -600,39 +738,61 @@ function setElementProperties( element, properties ) {
|
|
|
600
738
|
}
|
|
601
739
|
|
|
602
740
|
function setElementProperty( element, key, value ) {
|
|
603
|
-
if ( key
|
|
604
|
-
|
|
605
|
-
|
|
741
|
+
if ( key.startsWith( 'on' ) ) {
|
|
742
|
+
element.addEventListener( key.substring( 2 ), value );
|
|
743
|
+
} else if ( Properties.has( key ) ) {
|
|
744
|
+
if ( typeof value == 'function' )
|
|
745
|
+
reactive( value, value => element[ key ] = value );
|
|
606
746
|
else
|
|
607
747
|
element[ key ] = value;
|
|
608
748
|
} else {
|
|
609
749
|
if ( typeof value == 'function' )
|
|
610
|
-
|
|
750
|
+
reactive( value, value => setElementAttribute( element, key, value ) );
|
|
611
751
|
else
|
|
612
|
-
|
|
752
|
+
setElementAttribute( element, key, value );
|
|
613
753
|
}
|
|
614
754
|
}
|
|
615
755
|
|
|
616
|
-
function
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
756
|
+
function setElementAttribute( element, name, value ) {
|
|
757
|
+
if ( BooleanAttributes.has( name ) ) {
|
|
758
|
+
if ( value || value === '' )
|
|
759
|
+
element.setAttribute( name, '' );
|
|
760
|
+
else
|
|
761
|
+
element.removeAttribute( name );
|
|
762
|
+
} else {
|
|
763
|
+
if ( value != null )
|
|
764
|
+
element.setAttribute( name, value );
|
|
765
|
+
else
|
|
766
|
+
element.removeAttribute( name );
|
|
767
|
+
}
|
|
768
|
+
}
|
|
623
769
|
|
|
624
|
-
|
|
770
|
+
function createApp( component ) {
|
|
771
|
+
const context = createContext( null );
|
|
625
772
|
|
|
626
|
-
|
|
773
|
+
let root;
|
|
627
774
|
|
|
628
775
|
return {
|
|
629
|
-
|
|
776
|
+
mount( target ) {
|
|
777
|
+
root = withContext( context, () => make( component( {}, [] ) ) );
|
|
778
|
+
appendNode( root, target );
|
|
779
|
+
mountContext( context );
|
|
780
|
+
},
|
|
781
|
+
|
|
782
|
+
destroy() {
|
|
783
|
+
destroyContext( context );
|
|
784
|
+
removeNode( root );
|
|
785
|
+
root = null;
|
|
786
|
+
},
|
|
787
|
+
|
|
788
|
+
provide( key, value ) {
|
|
789
|
+
withContext( context, () => provide( key, value ) );
|
|
790
|
+
},
|
|
791
|
+
|
|
792
|
+
use( callback ) {
|
|
793
|
+
withContext( context, callback );
|
|
794
|
+
},
|
|
630
795
|
};
|
|
631
|
-
|
|
632
|
-
function destroy() {
|
|
633
|
-
destroyContext( context );
|
|
634
|
-
removeNode( root );
|
|
635
|
-
}
|
|
636
796
|
}
|
|
637
797
|
|
|
638
|
-
export {
|
|
798
|
+
export { createApp, inject, onDestroy, onMount, provide };
|
package/package.json
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leaner",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Thin, reactive wrapper for DOM",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
|
-
"dist"
|
|
7
|
+
"dist",
|
|
8
|
+
"types"
|
|
8
9
|
],
|
|
9
10
|
"exports": {
|
|
10
|
-
".":
|
|
11
|
-
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./types/core.d.ts",
|
|
13
|
+
"default": "./dist/core.js"
|
|
14
|
+
},
|
|
15
|
+
"./web": {
|
|
16
|
+
"types": "./types/web.d.ts",
|
|
17
|
+
"default": "./dist/web.js"
|
|
18
|
+
},
|
|
12
19
|
"./dist/*": "./dist/*",
|
|
13
20
|
"./package.json": "./package.json"
|
|
14
21
|
},
|
|
15
22
|
"scripts": {
|
|
16
|
-
"build": "rollup -c"
|
|
23
|
+
"build": "rollup -c",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest watch"
|
|
17
26
|
},
|
|
18
27
|
"repository": {
|
|
19
28
|
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/
|
|
29
|
+
"url": "git+https://github.com/leaner-js/leaner.git"
|
|
21
30
|
},
|
|
22
31
|
"keywords": [
|
|
23
32
|
"leaner",
|
|
@@ -27,10 +36,12 @@
|
|
|
27
36
|
"author": "Michał Męciński",
|
|
28
37
|
"license": "MIT",
|
|
29
38
|
"bugs": {
|
|
30
|
-
"url": "https://github.com/
|
|
39
|
+
"url": "https://github.com/leaner-js/leaner/issues"
|
|
31
40
|
},
|
|
32
|
-
"homepage": "https://
|
|
41
|
+
"homepage": "https://leanerjs.org/",
|
|
33
42
|
"devDependencies": {
|
|
34
|
-
"
|
|
43
|
+
"jsdom": "^24.0.0",
|
|
44
|
+
"rollup": "^4.17.2",
|
|
45
|
+
"vitest": "^1.6.0"
|
|
35
46
|
}
|
|
36
47
|
}
|