lilact 0.17.0 → 0.18.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/lilact.development.js +127 -114
- package/dist/lilact.development.js.map +2 -2
- package/dist/lilact.development.min.js +19 -19
- package/dist/lilact.development.min.js.map +3 -3
- package/dist/lilact.production.min.js +17 -17
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/accessories.ErrorBoundary.html +8 -8
- package/docs/classes/accessories.Suspense.html +7 -7
- package/docs/classes/components.Component.html +11 -11
- package/docs/classes/components.HTMLComponent.html +11 -11
- package/docs/classes/components.RootComponent.html +11 -11
- package/docs/functions/components.createComponent.html +1 -1
- package/docs/functions/components.createRoot.html +1 -1
- package/docs/functions/components.memo.html +7 -0
- package/docs/functions/components.render.html +1 -1
- package/docs/functions/hooks.startTransition.html +1 -1
- package/docs/functions/hooks.useActionState.html +1 -1
- package/docs/functions/hooks.useDebugValue.html +3 -3
- package/docs/functions/hooks.useDeferredValue.html +1 -1
- package/docs/functions/hooks.useEffect.html +4 -3
- package/docs/functions/hooks.useImperativeHandle.html +1 -1
- package/docs/functions/hooks.useInsertionEffect.html +4 -3
- package/docs/functions/hooks.useLayoutEffect.html +4 -3
- package/docs/functions/hooks.useMemo.html +4 -3
- package/docs/functions/hooks.useReducer.html +1 -1
- package/docs/functions/misc.deepEqual.html +1 -1
- package/docs/functions/misc.isAsync.html +1 -1
- package/docs/functions/misc.isClass.html +1 -1
- package/docs/functions/misc.isError.html +1 -1
- package/docs/functions/misc.isThenable.html +1 -1
- package/docs/functions/misc.shallowEqual.html +3 -2
- package/docs/functions/misc.toBool.html +1 -1
- package/docs/functions/timers.timeoutPromise.html +3 -3
- package/docs/hierarchy.html +1 -1
- package/docs/modules/components.html +1 -1
- package/docs/static/demos/memo.jsx +26 -0
- package/docs/static/index.html +2 -1
- package/docs/static/lilact.development.js +127 -114
- package/docs/static/lilact.development.js.map +2 -2
- package/docs/static/lilact.development.min.js +19 -19
- package/docs/static/lilact.development.min.js.map +3 -3
- package/docs/static/lilact.production.min.js +17 -17
- package/examples/demos/memo.jsx +26 -0
- package/examples/index.html +2 -1
- package/examples/lilact.development.js +127 -114
- package/examples/lilact.development.js.map +2 -2
- package/examples/lilact.development.min.js +19 -19
- package/examples/lilact.development.min.js.map +3 -3
- package/examples/lilact.production.min.js +17 -17
- package/package.json +1 -1
- package/src/components.jsx +59 -28
- package/src/hooks.jsx +10 -6
- package/src/lilact.jsx +1 -1
- package/src/misc.jsx +4 -3
package/src/components.jsx
CHANGED
|
@@ -162,19 +162,23 @@ class ComponentCore
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
/*
|
|
165
|
-
//let do_rerender = true;
|
|
166
|
-
|
|
167
|
-
// if(this.outlet && this.entity[MEMOIZED]) {
|
|
168
|
-
// if(shallowEqual(this.props, next_props)) do_rerender=false;
|
|
169
|
-
// delete this.entity[MEMOIZED];
|
|
170
|
-
// }
|
|
171
|
-
|
|
172
|
-
if(do_rerender) {
|
|
173
165
|
*/
|
|
174
166
|
// TODO: should componentDidUpdate be called after arranging/appending the outlet or before?
|
|
175
167
|
apply(next_props = this.props, next_state = this.next_state || this.state)
|
|
176
168
|
{
|
|
177
169
|
|
|
170
|
+
let do_rerender = true;
|
|
171
|
+
|
|
172
|
+
if(this.outlet && this?.[MEMOIZED]) {
|
|
173
|
+
|
|
174
|
+
if( shallowEqual(this.props, next_props, "children") &&
|
|
175
|
+
shallowEqual(this.props?.children, next_props?.children) ) {
|
|
176
|
+
do_rerender=false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if(do_rerender) {
|
|
181
|
+
|
|
178
182
|
if(DEBUG) {
|
|
179
183
|
|
|
180
184
|
if(this.entity?.propTypes) {
|
|
@@ -308,13 +312,14 @@ if(DEBUG) {
|
|
|
308
312
|
if(this.cache) this.cache.commit();
|
|
309
313
|
|
|
310
314
|
|
|
311
|
-
|
|
315
|
+
if(this.element) this.arrangeOutlet();
|
|
312
316
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
317
|
+
if(this.component.componentDidUpdate) {
|
|
318
|
+
this.component.componentDidUpdate(prev_props, prev_state, this.last_snapshot);
|
|
319
|
+
}
|
|
316
320
|
|
|
317
|
-
|
|
321
|
+
if(this.last_snapshot) delete this.last_snapshot;
|
|
322
|
+
}
|
|
318
323
|
|
|
319
324
|
}
|
|
320
325
|
|
|
@@ -635,17 +640,25 @@ function constructFunc(core, parent) // returns {text} or component, and not com
|
|
|
635
640
|
// do nothing...
|
|
636
641
|
}
|
|
637
642
|
else {
|
|
638
|
-
|
|
639
|
-
|
|
643
|
+
let entity = core.entity;
|
|
644
|
+
let memoized = false;
|
|
645
|
+
|
|
646
|
+
if(typeof(entity)==='object' && entity[MEMOIZED]) {
|
|
647
|
+
memoized = true;
|
|
648
|
+
entity = entity[MEMOIZED];
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
if(typeof(entity)==='string') {
|
|
652
|
+
comp = new HTMLComponent(entity, core.props);
|
|
640
653
|
}
|
|
641
654
|
else {
|
|
642
655
|
|
|
643
|
-
if( isClass(
|
|
644
|
-
if(
|
|
645
|
-
core.props = { ...
|
|
656
|
+
if( isClass(entity) ) {
|
|
657
|
+
if(entity?.defaultProps) {
|
|
658
|
+
core.props = { ...entity.defaultProps, ...core.props };
|
|
646
659
|
}
|
|
647
660
|
|
|
648
|
-
comp = new
|
|
661
|
+
comp = new entity(core.props);
|
|
649
662
|
|
|
650
663
|
const desc = Object.getOwnPropertyDescriptor(comp, "state");
|
|
651
664
|
if(desc) {
|
|
@@ -667,35 +680,35 @@ function constructFunc(core, parent) // returns {text} or component, and not com
|
|
|
667
680
|
}
|
|
668
681
|
}
|
|
669
682
|
}
|
|
670
|
-
else if(typeof(
|
|
683
|
+
else if(typeof(entity)==='function') {
|
|
671
684
|
|
|
672
|
-
if(
|
|
673
|
-
core.props = { ...
|
|
685
|
+
if(entity?.defaultProps) {
|
|
686
|
+
core.props = { ...entity.defaultProps, ...core.props };
|
|
674
687
|
}
|
|
675
688
|
|
|
676
689
|
comp = new Component(core.props);
|
|
677
690
|
|
|
678
691
|
// the binding is not necessary and is not according to the specs,
|
|
679
692
|
// probably not even recommended! but helpful.
|
|
680
|
-
comp.render =
|
|
693
|
+
comp.render = entity.bind(comp);
|
|
681
694
|
comp[CORE].hooks = [];
|
|
682
695
|
comp[CORE].hook_index = 0;
|
|
683
696
|
}
|
|
684
697
|
else {
|
|
685
|
-
throw new Error("
|
|
698
|
+
throw new Error("Error in constructing component.");
|
|
686
699
|
}
|
|
687
700
|
|
|
688
|
-
comp[CORE].entity =
|
|
701
|
+
comp[CORE].entity = entity;
|
|
689
702
|
|
|
690
703
|
if(core.container) {
|
|
691
704
|
comp[CORE].container = core.container;
|
|
692
705
|
}
|
|
693
706
|
}
|
|
694
707
|
|
|
708
|
+
if(memoized) comp[CORE][MEMOIZED] = true;
|
|
695
709
|
}
|
|
696
710
|
|
|
697
711
|
if(parent instanceof ComponentCore) comp[CORE].parent = parent;
|
|
698
|
-
|
|
699
712
|
return comp;
|
|
700
713
|
}
|
|
701
714
|
|
|
@@ -1089,8 +1102,12 @@ export class RootComponent extends HTMLComponent
|
|
|
1089
1102
|
|
|
1090
1103
|
export function createComponent(entity, props={}, ...children)
|
|
1091
1104
|
{
|
|
1092
|
-
|
|
1093
|
-
|
|
1105
|
+
|
|
1106
|
+
if (typeof(entity)!=='string' && typeof(entity)!=='function' )
|
|
1107
|
+
{
|
|
1108
|
+
if(typeof(entity)!=='object' || !entity[MEMOIZED]) {
|
|
1109
|
+
throw new Error("Invalid entity for createComponent.");
|
|
1110
|
+
}
|
|
1094
1111
|
}
|
|
1095
1112
|
|
|
1096
1113
|
for(let i=0; i<children.length; i++) {
|
|
@@ -1181,6 +1198,20 @@ export function render(component, element)
|
|
|
1181
1198
|
return createRoot(element).render(component);
|
|
1182
1199
|
}
|
|
1183
1200
|
|
|
1201
|
+
/**
|
|
1202
|
+
* Memoizes the given component. The memoized component will only rerender if its props or children are modified.
|
|
1203
|
+
* Unlike React, Lilact memo also works on class components.
|
|
1204
|
+
*
|
|
1205
|
+
* @param {Object} component - Component instance to render.
|
|
1206
|
+
*
|
|
1207
|
+
* @returns {component} - Memoized component.
|
|
1208
|
+
*/
|
|
1209
|
+
|
|
1210
|
+
export function memo(component)
|
|
1211
|
+
{
|
|
1212
|
+
return { [MEMOIZED]: component }
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1184
1215
|
|
|
1185
1216
|
/** @ignore */
|
|
1186
1217
|
export const createElement = createComponent;
|
package/src/hooks.jsx
CHANGED
|
@@ -269,7 +269,8 @@ export function useRef(initialValue = null)
|
|
|
269
269
|
* Runs an effect synchronously after all DOM mutations but before the browser paints.
|
|
270
270
|
*
|
|
271
271
|
* @param {Function} effect - Effect callback.
|
|
272
|
-
* @param deps
|
|
272
|
+
* @param {Array<any>} [deps] Optional dependency list (or an object for shallow comparison)
|
|
273
|
+
* used to determine when to re-run the effect.
|
|
273
274
|
* @returns {void}
|
|
274
275
|
*/
|
|
275
276
|
export function useLayoutEffect(effect, deps=undefined)
|
|
@@ -299,7 +300,8 @@ export function useLayoutEffect(effect, deps=undefined)
|
|
|
299
300
|
* Runs a side effect after render commits.
|
|
300
301
|
*
|
|
301
302
|
* @param effect - Callback invoked.
|
|
302
|
-
* @param deps
|
|
303
|
+
* @param {Array<any>} [deps] Optional dependency list (or an object for shallow comparison)
|
|
304
|
+
* used to determine when to re-run the effect.
|
|
303
305
|
* @returns {void}
|
|
304
306
|
*/
|
|
305
307
|
export function useEffect(effect, deps=undefined)
|
|
@@ -330,7 +332,8 @@ export function useEffect(effect, deps=undefined)
|
|
|
330
332
|
* Executes a side effect after the DOM updates have been committed.
|
|
331
333
|
*
|
|
332
334
|
* @param effect - Callback invoked after render commit.
|
|
333
|
-
* @param deps
|
|
335
|
+
* @param {Array<any>} [deps] Optional dependency list (or an object for shallow comparison)
|
|
336
|
+
* used to determine when to re-run the effect.
|
|
334
337
|
* @returns void
|
|
335
338
|
*/
|
|
336
339
|
export function useInsertionEffect(effect, deps=undefined)
|
|
@@ -361,7 +364,8 @@ export function useInsertionEffect(effect, deps=undefined)
|
|
|
361
364
|
* Memoizes a computed value until dependencies change.
|
|
362
365
|
*
|
|
363
366
|
* @param {Function} factory - Function that creates the value.
|
|
364
|
-
* @param deps
|
|
367
|
+
* @param {Array<any>} [deps] Optional dependency list (or an object for shallow comparison)
|
|
368
|
+
* used to determine when to recompute the value.
|
|
365
369
|
* @returns {any} Memoized value.
|
|
366
370
|
*/
|
|
367
371
|
export function useMemo(factory,deps=undefined)
|
|
@@ -525,8 +529,8 @@ export function useImperativeHandle(ref, factory, deps=undefined)
|
|
|
525
529
|
|
|
526
530
|
|
|
527
531
|
/**
|
|
528
|
-
* A hook for debug purposes.
|
|
529
|
-
* for
|
|
532
|
+
* A hook for debug purposes. By default it only logs the output to console, but it can be overrided
|
|
533
|
+
* for the development environment.
|
|
530
534
|
*
|
|
531
535
|
* @param {any} val
|
|
532
536
|
* The debug value.
|
package/src/lilact.jsx
CHANGED
package/src/misc.jsx
CHANGED
|
@@ -220,9 +220,10 @@ export function isEmpty(value) {
|
|
|
220
220
|
*
|
|
221
221
|
* @param source - First object to compare.
|
|
222
222
|
* @param target - Second object to compare.
|
|
223
|
+
* @param ignore - specific property/index to be ignored in comparison.
|
|
223
224
|
* @returns True if shallowly equal; otherwise false.
|
|
224
225
|
*/
|
|
225
|
-
export const shallowEqual = (source, target) => {
|
|
226
|
+
export const shallowEqual = (source, target, ignore) => {
|
|
226
227
|
if (typeOf(source) !== typeOf(target)) {
|
|
227
228
|
return false;
|
|
228
229
|
}
|
|
@@ -231,9 +232,9 @@ export const shallowEqual = (source, target) => {
|
|
|
231
232
|
if (source.length !== target.length) {
|
|
232
233
|
return false;
|
|
233
234
|
}
|
|
234
|
-
return source.every((el, index) => el === target[index]);
|
|
235
|
+
return source.every((el, index) => el === target[index] || index===ignore );
|
|
235
236
|
} else if (typeOf(source) === "object") {
|
|
236
|
-
return Object.keys(source).every((key) => source[key] === target[key]);
|
|
237
|
+
return Object.keys(source).every((key) => source[key] === target[key] || key===ignore );
|
|
237
238
|
} else if (typeOf(source) === "date") {
|
|
238
239
|
return source.getTime() === target.getTime();
|
|
239
240
|
}
|