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.
Files changed (56) hide show
  1. package/dist/lilact.development.js +127 -114
  2. package/dist/lilact.development.js.map +2 -2
  3. package/dist/lilact.development.min.js +19 -19
  4. package/dist/lilact.development.min.js.map +3 -3
  5. package/dist/lilact.production.min.js +17 -17
  6. package/docs/assets/hierarchy.js +1 -1
  7. package/docs/assets/navigation.js +1 -1
  8. package/docs/assets/search.js +1 -1
  9. package/docs/classes/accessories.ErrorBoundary.html +8 -8
  10. package/docs/classes/accessories.Suspense.html +7 -7
  11. package/docs/classes/components.Component.html +11 -11
  12. package/docs/classes/components.HTMLComponent.html +11 -11
  13. package/docs/classes/components.RootComponent.html +11 -11
  14. package/docs/functions/components.createComponent.html +1 -1
  15. package/docs/functions/components.createRoot.html +1 -1
  16. package/docs/functions/components.memo.html +7 -0
  17. package/docs/functions/components.render.html +1 -1
  18. package/docs/functions/hooks.startTransition.html +1 -1
  19. package/docs/functions/hooks.useActionState.html +1 -1
  20. package/docs/functions/hooks.useDebugValue.html +3 -3
  21. package/docs/functions/hooks.useDeferredValue.html +1 -1
  22. package/docs/functions/hooks.useEffect.html +4 -3
  23. package/docs/functions/hooks.useImperativeHandle.html +1 -1
  24. package/docs/functions/hooks.useInsertionEffect.html +4 -3
  25. package/docs/functions/hooks.useLayoutEffect.html +4 -3
  26. package/docs/functions/hooks.useMemo.html +4 -3
  27. package/docs/functions/hooks.useReducer.html +1 -1
  28. package/docs/functions/misc.deepEqual.html +1 -1
  29. package/docs/functions/misc.isAsync.html +1 -1
  30. package/docs/functions/misc.isClass.html +1 -1
  31. package/docs/functions/misc.isError.html +1 -1
  32. package/docs/functions/misc.isThenable.html +1 -1
  33. package/docs/functions/misc.shallowEqual.html +3 -2
  34. package/docs/functions/misc.toBool.html +1 -1
  35. package/docs/functions/timers.timeoutPromise.html +3 -3
  36. package/docs/hierarchy.html +1 -1
  37. package/docs/modules/components.html +1 -1
  38. package/docs/static/demos/memo.jsx +26 -0
  39. package/docs/static/index.html +2 -1
  40. package/docs/static/lilact.development.js +127 -114
  41. package/docs/static/lilact.development.js.map +2 -2
  42. package/docs/static/lilact.development.min.js +19 -19
  43. package/docs/static/lilact.development.min.js.map +3 -3
  44. package/docs/static/lilact.production.min.js +17 -17
  45. package/examples/demos/memo.jsx +26 -0
  46. package/examples/index.html +2 -1
  47. package/examples/lilact.development.js +127 -114
  48. package/examples/lilact.development.js.map +2 -2
  49. package/examples/lilact.development.min.js +19 -19
  50. package/examples/lilact.development.min.js.map +3 -3
  51. package/examples/lilact.production.min.js +17 -17
  52. package/package.json +1 -1
  53. package/src/components.jsx +59 -28
  54. package/src/hooks.jsx +10 -6
  55. package/src/lilact.jsx +1 -1
  56. package/src/misc.jsx +4 -3
@@ -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
- if(this.element) this.arrangeOutlet();
315
+ if(this.element) this.arrangeOutlet();
312
316
 
313
- if(this.component.componentDidUpdate) {
314
- this.component.componentDidUpdate(prev_props, prev_state, this.last_snapshot);
315
- }
317
+ if(this.component.componentDidUpdate) {
318
+ this.component.componentDidUpdate(prev_props, prev_state, this.last_snapshot);
319
+ }
316
320
 
317
- if(this.last_snapshot) delete this.last_snapshot;
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
- if(typeof(core.entity)==='string') {
639
- comp = new HTMLComponent(core.entity, core.props);
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(core.entity) ) {
644
- if(core.entity?.defaultProps) {
645
- core.props = { ...core.entity.defaultProps, ...core.props };
656
+ if( isClass(entity) ) {
657
+ if(entity?.defaultProps) {
658
+ core.props = { ...entity.defaultProps, ...core.props };
646
659
  }
647
660
 
648
- comp = new core.entity(core.props);
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(core.entity)==='function') {
683
+ else if(typeof(entity)==='function') {
671
684
 
672
- if(core.entity?.defaultProps) {
673
- core.props = { ...core.entity.defaultProps, ...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 = core.entity.bind(comp);
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("Invalid entity for createComponent.");
698
+ throw new Error("Error in constructing component.");
686
699
  }
687
700
 
688
- comp[CORE].entity = 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
- if(typeof(entity)!=='string' && typeof(entity)!=='function') {
1093
- throw new Error("Invalid entity for createComponent.");
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 - Optional dependency list (or an object for shallow comparison) used to determine when to re-run the effect.
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 - Optional dependency list (or an object for shallow comparison) used to determine when to re-run the effect.
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 - Optional dependency list (or an object for shallow comparison) used to determine when to re-run the effect.
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 - Optional dependency list (or an object for shallow comparison) used to determine when to re-run the effect.
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. At the moment it only logs the output, but it can be overrided
529
- * for each development environment.
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
@@ -92,7 +92,7 @@ export {transpileJSX, transpilerConfig} from "./jsx";
92
92
  export const Lilact =
93
93
  {
94
94
 
95
- VERSION: "beta.17",
95
+ VERSION: "beta.18",
96
96
 
97
97
  // Configuration
98
98
 
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
  }