@xaendar/core 0.6.18 → 0.6.20

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.
@@ -273,9 +273,10 @@ export declare type EventOptions = Beautify<RequireOne<Omit<CustomEventInit, 'de
273
273
  * @param parentNode - The parent HTML element where the conditional structure is applied.
274
274
  * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
275
275
  * @param condition - A reactive function that returns the array of items to iterate over.
276
+ * @param trackExpression - An expression used to identify univocally single iterations to not duplicate DOM elements between different renders
276
277
  * @param forFn - A callback invoked for each item, receiving the parent node, the item, and its index. Must return an array of cleanup functions.
277
278
  */
278
- export declare function _for(parentNode: HTMLElement, parentContext: Context, condition: () => unknown[], forFn: Function_2<[parentNode: HTMLElement, context: Context, items: unknown[], index: number], Context>): void;
279
+ export declare function _for(parentNode: HTMLElement, parentContext: Context, condition: () => unknown[], trackExpression: Function_2<[unknown], string | number>, forFn: Function_2<[parentNode: HTMLElement, context: Context, items: unknown[], index: number], Context>): void;
279
280
 
280
281
  /**
281
282
  * Creates a reactive conditional structure from a list of branches.
@@ -382,6 +383,19 @@ export declare function _iterationVariables(items: unknown[], index: number, ite
382
383
  $odd: string;
383
384
  }): Record<string, unknown>;
384
385
 
386
+ /**
387
+ * Mounts a node into the DOM and binds it to the context lifecycle.
388
+ *
389
+ * Registers the node with the context, appends it to `parentNode`, and
390
+ * schedules a cleanup listener that removes the node from both the context
391
+ * and the DOM when the context is destroyed.
392
+ *
393
+ * @param node - The node to mount.
394
+ * @param parentNode - The parent HTML element to append the node to.
395
+ * @param context - The current template execution scope that owns the node's lifecycle.
396
+ */
397
+ export declare function mountNode(node: Node, parentNode: HTMLElement, context: Context): void;
398
+
385
399
  /**
386
400
  * Represents the output type returned by an `@Event` decorator in a web component.
387
401
  *
@@ -510,7 +524,7 @@ declare type RenderElementEvent = {
510
524
  /**
511
525
  * Event Parameters
512
526
  */
513
- parameters: NoArgsFunction<unknown>[];
527
+ parameters: Function_2<[Event], unknown>[];
514
528
  };
515
529
 
516
530
  /**
@@ -607,6 +621,13 @@ export declare function _switch(parentNode: HTMLElement, parentContext: Context,
607
621
  block: Function_2<[HTMLElement, Context], Context>;
608
622
  }>): void;
609
623
 
624
+ /**
625
+ * Executes a function without tracking any dependencies.
626
+ * @param fn - The function to execute without tracking.
627
+ * @returns The result of the function execution.
628
+ */
629
+ export declare const untracked: typeof Signal.subtle.untrack;
630
+
610
631
  /**
611
632
  * Decorator that registers a class as a custom web component.
612
633
  *
@@ -486,6 +486,14 @@ function signal(value, options) {
486
486
  return getter;
487
487
  }
488
488
  //#endregion
489
+ //#region ../packages/core/src/signals/untracked.ts
490
+ /**
491
+ * Executes a function without tracking any dependencies.
492
+ * @param fn - The function to execute without tracking.
493
+ * @returns The result of the function execution.
494
+ */
495
+ var untracked = Signal.subtle.untrack;
496
+ //#endregion
489
497
  //#region ../packages/core/src/utils/context.util.ts
490
498
  /**
491
499
  * Tracks identifier scope during run time template function execution
@@ -586,6 +594,25 @@ var Context = class {
586
594
  this._nodes = [];
587
595
  }
588
596
  };
597
+ /**
598
+ * Mounts a node into the DOM and binds it to the context lifecycle.
599
+ *
600
+ * Registers the node with the context, appends it to `parentNode`, and
601
+ * schedules a cleanup listener that removes the node from both the context
602
+ * and the DOM when the context is destroyed.
603
+ *
604
+ * @param node - The node to mount.
605
+ * @param parentNode - The parent HTML element to append the node to.
606
+ * @param context - The current template execution scope that owns the node's lifecycle.
607
+ */
608
+ function mountNode(node, parentNode, context) {
609
+ context.addNode(node);
610
+ parentNode.appendChild(node);
611
+ context.listen(() => {
612
+ context.removeNode(node);
613
+ parentNode.removeChild(node);
614
+ });
615
+ }
589
616
  //#endregion
590
617
  //#region ../packages/core/src/utils/for.util.ts
591
618
  /**
@@ -595,9 +622,10 @@ var Context = class {
595
622
  * @param parentNode - The parent HTML element where the conditional structure is applied.
596
623
  * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
597
624
  * @param condition - A reactive function that returns the array of items to iterate over.
625
+ * @param trackExpression - An expression used to identify univocally single iterations to not duplicate DOM elements between different renders
598
626
  * @param forFn - A callback invoked for each item, receiving the parent node, the item, and its index. Must return an array of cleanup functions.
599
627
  */
600
- function _for(parentNode, parentContext, condition, forFn) {
628
+ function _for(parentNode, parentContext, condition, trackExpression, forFn) {
601
629
  let contexts = new Array();
602
630
  const unlistener = effect(() => {
603
631
  contexts.forEach((context) => {
@@ -606,7 +634,7 @@ function _for(parentNode, parentContext, condition, forFn) {
606
634
  });
607
635
  contexts = [];
608
636
  const items = condition();
609
- Signal.subtle.untrack(() => {
637
+ untracked(() => {
610
638
  for (let i = 0; i < items.length; i++) {
611
639
  const context = forFn(parentNode, parentContext, items, i);
612
640
  contexts.push(context);
@@ -766,50 +794,12 @@ function checkAndUpdateState(parentNode, parentContext, state, newState, conditi
766
794
  state?.context.unlisten();
767
795
  return {
768
796
  activeBranch: newState,
769
- context: Signal.subtle.untrack(() => conditionalBlockFn(parentNode, parentContext))
797
+ context: untracked(() => conditionalBlockFn(parentNode, parentContext))
770
798
  };
771
799
  }
772
800
  }
773
801
  //#endregion
774
- //#region ../packages/core/src/utils/render-text.util.ts
775
- /**
776
- * Creates a reactive text node bound to a named identifier in the current scope.
777
- *
778
- * Appends a `Text` node to `parentNode` with the initial value of the identifier.
779
- * If the identifier is reactive, wraps the text update in an effect so the node
780
- * content is kept in sync whenever the underlying signal changes.
781
- *
782
- * @param parentNode - The parent HTML element to append the text node to.
783
- * @param context - The current template execution scope used to resolve `text`.
784
- * @param text - The identifier name to resolve as the text content.
785
- */
786
- function _renderText(parentNode, context, textFn) {
787
- const node = document.createTextNode(textFn());
788
- parentNode.appendChild(node);
789
- context.listen(() => {
790
- context.removeNode(node);
791
- parentNode.removeChild(node);
792
- });
793
- context.listen(effect(() => node.textContent = textFn()));
794
- }
795
- /**
796
- * Creates a static (non-reactive) text node with a literal string value.
797
- *
798
- * Appends a `Text` node containing `text` directly to `parentNode` and
799
- * registers a cleanup function that removes the node when the context is
800
- * destroyed.
801
- *
802
- * @param parentNode - The parent HTML element to append the text node to.
803
- * @param context - The current template execution scope.
804
- * @param text - The literal string to render as text content.
805
- */
806
- function _renderLiteralText(parentNode, context, text) {
807
- const node = document.createTextNode(text);
808
- parentNode.appendChild(node);
809
- context.listen(() => parentNode.removeChild(node));
810
- }
811
- //#endregion
812
- //#region ../packages/core/src/utils/render-util.ts
802
+ //#region ../packages/core/src/utils/render-element.util.ts
813
803
  /**
814
804
  * Creates a DOM element, applies attributes and event listeners, appends it
815
805
  * to the parent, and registers cleanup functions in the current context.
@@ -829,16 +819,12 @@ function _renderLiteralText(parentNode, context, text) {
829
819
  */
830
820
  function _renderElement(parentNode, context, tagName, attributes, events) {
831
821
  const element = document.createElement(tagName);
832
- parentNode.appendChild(element);
833
- context.listen(() => {
834
- context.removeNode(element);
835
- parentNode.removeChild(element);
836
- });
822
+ mountNode(element, parentNode, context);
837
823
  attributes.forEach(({ name, value, literal }) => {
838
824
  literal ? element.setAttribute(name, String(value())) : context.listen(effect(() => element.setAttribute(name, String(value()))));
839
825
  });
840
826
  events.forEach((event) => {
841
- const handler = ($event) => context.getEventHandler(event.handler)(...event.parameters.map((event) => event()));
827
+ const handler = ($event) => context.getEventHandler(event.handler)(...event.parameters.map((event) => event($event)));
842
828
  const name = event.name;
843
829
  element.addEventListener(name, handler);
844
830
  context.listen(() => element.removeEventListener(name, handler));
@@ -846,6 +832,38 @@ function _renderElement(parentNode, context, tagName, attributes, events) {
846
832
  return element;
847
833
  }
848
834
  //#endregion
835
+ //#region ../packages/core/src/utils/render-text.util.ts
836
+ /**
837
+ * Creates a reactive text node bound to a named identifier in the current scope.
838
+ *
839
+ * Appends a `Text` node to `parentNode` with the initial value of the identifier.
840
+ * If the identifier is reactive, wraps the text update in an effect so the node
841
+ * content is kept in sync whenever the underlying signal changes.
842
+ *
843
+ * @param parentNode - The parent HTML element to append the text node to.
844
+ * @param context - The current template execution scope used to resolve `text`.
845
+ * @param text - The identifier name to resolve as the text content.
846
+ */
847
+ function _renderText(parentNode, context, textFn) {
848
+ const node = document.createTextNode(textFn());
849
+ mountNode(node, parentNode, context);
850
+ context.listen(effect(() => node.textContent = textFn()));
851
+ }
852
+ /**
853
+ * Creates a static (non-reactive) text node with a literal string value.
854
+ *
855
+ * Appends a `Text` node containing `text` directly to `parentNode` and
856
+ * registers a cleanup function that removes the node when the context is
857
+ * destroyed.
858
+ *
859
+ * @param parentNode - The parent HTML element to append the text node to.
860
+ * @param context - The current template execution scope.
861
+ * @param text - The literal string to render as text content.
862
+ */
863
+ function _renderLiteralText(parentNode, context, text) {
864
+ mountNode(document.createTextNode(text), parentNode, context);
865
+ }
866
+ //#endregion
849
867
  //#region ../packages/core/src/utils/switch.util.ts
850
868
  /**
851
869
  * Creates a reactive switch/case structure by converting it into an if/else-if chain
@@ -879,4 +897,4 @@ function _switch(parentNode, parentContext, expression, blocks) {
879
897
  })));
880
898
  }
881
899
  //#endregion
882
- export { BaseWebComponent, Context, Event, Property, WebComponent, _for, _if, _iterationVariables, _renderElement, _renderLiteralText, _renderText, _switch, computed, effect, input, signal };
900
+ export { BaseWebComponent, Context, Event, Property, WebComponent, _for, _if, _iterationVariables, _renderElement, _renderLiteralText, _renderText, _switch, computed, effect, input, mountNode, signal, untracked };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xaendar/core",
3
- "version": "0.6.18",
3
+ "version": "0.6.20",
4
4
  "description": "A library containing core utils such as webcomponent base classes and theming support",
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
  }
17
17
  },
18
18
  "dependencies": {
19
- "@xaendar/signals": "0.6.18",
20
- "@xaendar/types": "0.6.18"
19
+ "@xaendar/signals": "0.6.20",
20
+ "@xaendar/types": "0.6.20"
21
21
  }
22
22
  }