@xaendar/core 0.6.7 → 0.6.10

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.
@@ -3,6 +3,7 @@ import { Beautify } from '@xaendar/types';
3
3
  import { ClassDecorator as ClassDecorator_2 } from '@xaendar/types';
4
4
  import { Constructor } from '@xaendar/types';
5
5
  import { EffectOptions } from '@xaendar/signals';
6
+ import { Function as Function_2 } from '@xaendar/types';
6
7
  import { NoArgsFunction } from '@xaendar/types';
7
8
  import { NoArgsVoidFunction } from '@xaendar/types';
8
9
  import { NoArgsVoidFunction as NoArgsVoidFunction_2 } from '@xaendar/types';
@@ -18,10 +19,11 @@ import { VoidFunction as VoidFunction_2 } from '@xaendar/types';
18
19
  * It won't appear by intellisense but it's there.
19
20
  */
20
21
  export declare class BaseWebComponent extends HTMLElement {
22
+ [key: string]: unknown;
21
23
  /**
22
24
  * Array of functions to unwatch all the signals used in the component
23
25
  */
24
- protected unwatchFns: NoArgsVoidFunction[];
26
+ protected context: Context;
25
27
  /**
26
28
  * The root of the Web Component, where the content is rendered
27
29
  */
@@ -74,7 +76,7 @@ export declare type BaseWebComponentConstructor = Constructor<BaseWebComponent,
74
76
  */
75
77
  declare type Block = {
76
78
  condition?: NoArgsFunction<boolean>;
77
- block: NoArgsFunction<NoArgsVoidFunction[]>;
79
+ block: Function_2<[HTMLElement, Context], Context>;
78
80
  };
79
81
 
80
82
  /**
@@ -107,6 +109,55 @@ export declare type Computed<Value = any> = Signal.Computed<Value> & {
107
109
  */
108
110
  export declare function computed<Value = any>(value: Value, options?: SignalOptions<Value>): Computed<Value>;
109
111
 
112
+ /**
113
+ * Tracks identifier scope during run time template function execution
114
+ * Each `Context` instance represents one lexical scope (e.g. a `@for` loop body)
115
+ * and can be chained to a parent context for outer-scope resolution.
116
+ */
117
+ export declare class Context {
118
+ private _root;
119
+ private _parent;
120
+ private _identifiers;
121
+ /**
122
+ * Array of functions to be called when the current context is destroyed (e.g. a `@if` becomes false)
123
+ * These functions contains
124
+ * - Remove Element
125
+ * - Remove EventListener
126
+ * - Effect unsubscription Function
127
+ */
128
+ private _unwatchFns;
129
+ private _children;
130
+ private _nodes;
131
+ /**
132
+ * Creates a new scope context.
133
+ *
134
+ * @param _root - Web Component Reference to access properties and methods directly for bindings
135
+ * @param _parent Optional parent context representing the enclosing scope.
136
+ * @param _identifiers List of loop variable names declared in this scope.
137
+ */
138
+ constructor(_root: BaseWebComponent, _parent: Context, _identifiers?: Map<string, ContextIdentifier>);
139
+ addIdentifier(name: string, valueFn: NoArgsFunction<unknown>): void;
140
+ /**
141
+ * Returns the innermost identifier in the current scope chain, or
142
+ * delegates to the parent context if none is found in this scope.
143
+ *
144
+ * @returns The most recently declared identifier name, or `undefined` if none exists.
145
+ */
146
+ getIdentifier<ReturnType = unknown>(name: string): ContextIdentifier<ReturnType> | undefined;
147
+ getEventHandler(handler: string): VoidFunction;
148
+ addChild(context: Context): void;
149
+ removeChild(context: Context): void;
150
+ addNode(node: Node): void;
151
+ removeNode(nodeToRemove: Node): void;
152
+ listen(...fns: NoArgsVoidFunction[]): void;
153
+ unlisten(): void;
154
+ }
155
+
156
+ declare type ContextIdentifier<ReturnType = unknown> = {
157
+ get: NoArgsFunction<ReturnType>;
158
+ reactive: boolean;
159
+ };
160
+
110
161
  /**
111
162
  * Runs a side-effectful function and automatically re-runs it whenever any
112
163
  * Signal read during its execution changes.
@@ -156,11 +207,12 @@ export declare type EventOptions = Beautify<RequireOne<Omit<CustomEventInit, 'de
156
207
  * Reactively iterates over a list of items, re-running the loop whenever the tracked condition changes.
157
208
  * Previous iteration side-effects are cleaned up before each re-evaluation.
158
209
  *
159
- * @param unwatchFns - Array collecting cleanup functions for the parent scope.
210
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
211
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
160
212
  * @param condition - A reactive function that returns the array of items to iterate over.
161
- * @param forFn - A callback invoked for each item, receiving the item and its index. Must return an array of cleanup functions.
213
+ * @param forFn - A callback invoked for each item, receiving the parent node, the item, and its index. Must return an array of cleanup functions.
162
214
  */
163
- export declare function _for(unwatchFns: NoArgsVoidFunction[], condition: () => unknown[], forFn: (item: unknown, index: number) => NoArgsVoidFunction[]): void;
215
+ export declare function _for(parentNode: HTMLElement, parentContext: Context, condition: () => unknown[], forFn: Function_2<[parentNode: HTMLElement, context: Context, item: unknown, index: number], Context>): void;
164
216
 
165
217
  /**
166
218
  * Creates a reactive conditional structure from a list of branches.
@@ -176,12 +228,14 @@ export declare function _for(unwatchFns: NoArgsVoidFunction[], condition: () =>
176
228
  * state (which branch is active) and the related cleanup functions are only updated if
177
229
  * the active branch has actually changed.
178
230
  *
231
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
232
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
179
233
  * @param unwatchFns - Shared array that collects all active cleanup functions.
180
234
  * Mutated in place: the created effect and branch functions are added to and
181
235
  * removed from this array.
182
236
  * @param blocks - Ordered list of conditional branches to evaluate.
183
237
  */
184
- export declare function _if(unwatchFns: NoArgsVoidFunction[], blocks: Block[]): void;
238
+ export declare function _if(parentNode: HTMLElement, parentContext: Context, blocks: Block[]): void;
185
239
 
186
240
  /**
187
241
  * An `InputSignal` is a specialized `Signal.State` designed for use as a property signal in web components.
@@ -363,6 +417,8 @@ export { Signal_2 as Signal }
363
417
  * Because it delegates to `_if`, the switch benefits from the same optimisation:
364
418
  * the active branch is only re-rendered when it actually changes.
365
419
  *
420
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
421
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
366
422
  * @param unwatchFns - Shared array that collects all active cleanup functions.
367
423
  * Mutated in place by the underlying {@link _if} call.
368
424
  * @param expression - Function that evaluates the switch expression. Called
@@ -373,22 +429,11 @@ export { Signal_2 as Signal }
373
429
  * - `block`: function that applies the branch's side effects and returns
374
430
  * its cleanup functions.
375
431
  */
376
- export declare function _switch(unwatchFns: NoArgsVoidFunction[], expression: NoArgsFunction<unknown>, blocks: Array<{
432
+ export declare function _switch(parentNode: HTMLElement, parentContext: Context, expression: NoArgsFunction<unknown>, blocks: Array<{
377
433
  condition: unknown[] | null;
378
- block: NoArgsFunction<NoArgsVoidFunction[]>;
434
+ block: Function_2<[HTMLElement, Context], Context>;
379
435
  }>): void;
380
436
 
381
- /**
382
- * Executes and removes the cleanup functions of the previously active branch.
383
- *
384
- * For each local function: removes it from the shared `unwatchFns` array (if present)
385
- * and then invokes it to release resources / tear down associated subscriptions.
386
- *
387
- * @param unwatchFns - Shared array of active cleanup functions, mutated in place.
388
- * @param localUnwatchFns - Cleanup functions of the branch to deactivate.
389
- */
390
- export declare function unwatch(unwatchFns: NoArgsVoidFunction[], localUnwatchFns: NoArgsVoidFunction[]): void;
391
-
392
437
  /**
393
438
  * Decorator to define a web component
394
439
  * @param selector Name or names of the custom element
@@ -215,7 +215,7 @@ var BaseWebComponent = class extends HTMLElement {
215
215
  /**
216
216
  * Array of functions to unwatch all the signals used in the component
217
217
  */
218
- unwatchFns = new Array();
218
+ context;
219
219
  /**
220
220
  * The root of the Web Component, where the content is rendered
221
221
  */
@@ -269,8 +269,7 @@ var BaseWebComponent = class extends HTMLElement {
269
269
  * the properties initialization won't call the render method
270
270
  */
271
271
  disconnectedCallback() {
272
- this.unwatchFns.forEach((unwatch) => unwatch());
273
- this.unwatchFns = [];
272
+ this.context.unlisten();
274
273
  }
275
274
  };
276
275
  //#endregion
@@ -401,6 +400,136 @@ function signal(value, options) {
401
400
  return getter;
402
401
  }
403
402
  //#endregion
403
+ //#region ../packages/core/src/utils/context.utils.ts
404
+ /**
405
+ * Tracks identifier scope during run time template function execution
406
+ * Each `Context` instance represents one lexical scope (e.g. a `@for` loop body)
407
+ * and can be chained to a parent context for outer-scope resolution.
408
+ */
409
+ var Context = class {
410
+ _root;
411
+ _parent;
412
+ _identifiers;
413
+ /**
414
+ * Array of functions to be called when the current context is destroyed (e.g. a `@if` becomes false)
415
+ * These functions contains
416
+ * - Remove Element
417
+ * - Remove EventListener
418
+ * - Effect unsubscription Function
419
+ */
420
+ _unwatchFns = new Array();
421
+ _children = new Array();
422
+ _nodes = new Array();
423
+ /**
424
+ * Creates a new scope context.
425
+ *
426
+ * @param _root - Web Component Reference to access properties and methods directly for bindings
427
+ * @param _parent Optional parent context representing the enclosing scope.
428
+ * @param _identifiers List of loop variable names declared in this scope.
429
+ */
430
+ constructor(_root, _parent, _identifiers = /* @__PURE__ */ new Map()) {
431
+ this._root = _root;
432
+ this._parent = _parent;
433
+ this._identifiers = _identifiers;
434
+ }
435
+ addIdentifier(name, valueFn) {
436
+ if (this.getIdentifier(name)) throw new Error(`Identifier "${name}" is already declared in this scope.`);
437
+ this._identifiers.set(name, {
438
+ get: valueFn,
439
+ reactive: true
440
+ });
441
+ }
442
+ /**
443
+ * Returns the innermost identifier in the current scope chain, or
444
+ * delegates to the parent context if none is found in this scope.
445
+ *
446
+ * @returns The most recently declared identifier name, or `undefined` if none exists.
447
+ */
448
+ getIdentifier(name) {
449
+ if (this._identifiers.has(name)) return this._identifiers.get(name);
450
+ if (this._parent) return this._parent.getIdentifier(name);
451
+ return {
452
+ get: () => this._root[name],
453
+ reactive: true
454
+ };
455
+ }
456
+ getEventHandler(handler) {
457
+ return this._root[handler];
458
+ }
459
+ addChild(context) {
460
+ this._children.push(context);
461
+ }
462
+ removeChild(context) {
463
+ this._children = this._children.filter((child) => child === context);
464
+ }
465
+ addNode(node) {
466
+ this._nodes.push(node);
467
+ }
468
+ removeNode(nodeToRemove) {
469
+ this._nodes = this._nodes.filter((node) => node === nodeToRemove);
470
+ }
471
+ listen(...fns) {
472
+ this._unwatchFns.push(...fns);
473
+ }
474
+ unlisten() {
475
+ this._unwatchFns.forEach((fn) => fn());
476
+ this._children.forEach((child) => child.unlisten());
477
+ this._unwatchFns = [];
478
+ this._nodes = [];
479
+ }
480
+ };
481
+ //#endregion
482
+ //#region ../packages/core/src/utils/for.utils.ts
483
+ /**
484
+ * Reactively iterates over a list of items, re-running the loop whenever the tracked condition changes.
485
+ * Previous iteration side-effects are cleaned up before each re-evaluation.
486
+ *
487
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
488
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
489
+ * @param condition - A reactive function that returns the array of items to iterate over.
490
+ * @param forFn - A callback invoked for each item, receiving the parent node, the item, and its index. Must return an array of cleanup functions.
491
+ */
492
+ function _for(parentNode, parentContext, condition, forFn) {
493
+ let contexts = new Array();
494
+ const unlistener = effect(() => {
495
+ contexts.forEach((context) => {
496
+ context.unlisten();
497
+ parentContext.removeChild(context);
498
+ });
499
+ contexts = [];
500
+ const items = condition();
501
+ Signal.subtle.untrack(() => {
502
+ for (let i = 0; i < items.length; i++) {
503
+ const context = forFn(parentNode, parentContext, items[i], i);
504
+ contexts.push(context);
505
+ parentContext.addChild(context);
506
+ }
507
+ });
508
+ });
509
+ parentContext.listen(unlistener);
510
+ }
511
+ /**
512
+ * Builds a record of iteration context variables for a given index in the loop.
513
+ * Provides the current item, index, and convenience flags (`$first`, `$last`, `$even`, `$odd`).
514
+ *
515
+ * @param items - The full array being iterated.
516
+ * @param index - The current iteration index.
517
+ * @param itemAlias - The template alias name for the current item.
518
+ * @param indexAlias - The template alias name for the current index.
519
+ * @returns A record mapping alias names and built-in variables to their values.
520
+ */
521
+ function _iterationVariables(items, index, itemAlias, indexAlias) {
522
+ const even = index % 2 === 0;
523
+ return {
524
+ [itemAlias]: items[index],
525
+ [indexAlias]: index,
526
+ $first: index === 0,
527
+ $last: index === items.length - 1,
528
+ $even: even,
529
+ $odd: !even
530
+ };
531
+ }
532
+ //#endregion
404
533
  //#region ../packages/core/src/utils/if.utils.ts
405
534
  /**
406
535
  * Creates a reactive conditional structure from a list of branches.
@@ -416,32 +545,34 @@ function signal(value, options) {
416
545
  * state (which branch is active) and the related cleanup functions are only updated if
417
546
  * the active branch has actually changed.
418
547
  *
548
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
549
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
419
550
  * @param unwatchFns - Shared array that collects all active cleanup functions.
420
551
  * Mutated in place: the created effect and branch functions are added to and
421
552
  * removed from this array.
422
553
  * @param blocks - Ordered list of conditional branches to evaluate.
423
554
  */
424
- function _if(unwatchFns, blocks) {
425
- let state = null;
426
- let localUnwatchFns = new Array();
555
+ function _if(parentNode, parentContext, blocks) {
556
+ let state;
427
557
  let fn;
428
558
  switch (blocks.length) {
429
559
  case 1:
430
- fn = () => handleIf(blocks[0], state, unwatchFns, localUnwatchFns);
560
+ fn = (state) => handleIf(parentNode, parentContext, blocks[0], state);
431
561
  break;
432
562
  case 2:
433
- fn = () => handleIfElse(blocks[0], blocks[1], state, unwatchFns, localUnwatchFns);
563
+ fn = (state) => handleIfElse(parentNode, parentContext, blocks[0], blocks[1], state);
434
564
  break;
435
- default: fn = () => handleIfElseIf(blocks, state, unwatchFns, localUnwatchFns);
565
+ default: fn = (state) => handleIfElseIf(parentNode, parentContext, blocks, state);
436
566
  }
437
567
  const unlistener = effect(() => {
438
- const retVal = fn();
439
- if (retVal) {
440
- state = retVal.state;
441
- localUnwatchFns = retVal.fns;
568
+ if (state) {
569
+ state.context.unlisten();
570
+ parentContext.removeChild(state.context);
442
571
  }
572
+ state = fn(state);
573
+ if (state) parentContext.addChild(state.context);
443
574
  });
444
- unwatchFns.push(unlistener);
575
+ parentContext.listen(unlistener);
445
576
  }
446
577
  /**
447
578
  * Handles the simple `if` case (a single branch, no `else`).
@@ -450,32 +581,33 @@ function _if(unwatchFns, blocks) {
450
581
  * previously active branch is deactivated by resetting the state to `null` and
451
582
  * executing an empty block.
452
583
  *
584
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
585
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
453
586
  * @param ifBlock - The `if` branch to evaluate.
454
587
  * @param state - The current state (index of the active branch, or `null` if none).
455
- * @param unwatchFns - Shared array of active cleanup functions.
456
- * @param localUnwatchFns - Cleanup functions generated by the last branch activation.
457
588
  * @returns The new state and new cleanup functions if the active branch changed,
458
589
  * otherwise `undefined`.
459
590
  */
460
- function handleIf(ifBlock, state, unwatchFns, localUnwatchFns) {
461
- return ifBlock.condition() ? checkAndUpdateState(state, 0, ifBlock.block, unwatchFns, localUnwatchFns) : checkAndUpdateState(state, null, () => [], unwatchFns, localUnwatchFns);
591
+ function handleIf(parentNode, parentContext, ifBlock, state) {
592
+ if (ifBlock.condition()) return checkAndUpdateState(parentNode, parentContext, state, 0, ifBlock.block);
593
+ else parentContext.unlisten();
462
594
  }
463
595
  /**
464
596
  * Handles the `if` / `else` case (exactly two branches).
465
597
  *
466
598
  * If the `if` condition is true, the first branch is activated (state `0`); otherwise,
467
599
  * the `else` branch is activated (state `1`).
468
- *
600
+ *
601
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
602
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
469
603
  * @param ifBlock - The `if` branch to evaluate.
470
604
  * @param elseBlock - The `else` branch used when the `if` condition is false.
471
605
  * @param state - The current state (index of the active branch, or `null` if none).
472
- * @param unwatchFns - Shared array of active cleanup functions.
473
- * @param localUnwatchFns - Cleanup functions generated by the last branch activation.
474
606
  * @returns The new state and new cleanup functions if the active branch changed,
475
607
  * otherwise `undefined`.
476
608
  */
477
- function handleIfElse(ifBlock, elseBlock, state, unwatchFns, localUnwatchFns) {
478
- return ifBlock.condition() ? checkAndUpdateState(state, 0, ifBlock.block, unwatchFns, localUnwatchFns) : checkAndUpdateState(state, 1, elseBlock.block, unwatchFns, localUnwatchFns);
609
+ function handleIfElse(parentNode, parentContext, ifBlock, elseBlock, state) {
610
+ return ifBlock.condition() ? checkAndUpdateState(parentNode, parentContext, state, 0, ifBlock.block) : checkAndUpdateState(parentNode, parentContext, state, 1, elseBlock.block);
479
611
  }
480
612
  /**
481
613
  * Handles the general case of an `if` / `else if` / ... / `else` chain (three or more branches).
@@ -483,18 +615,18 @@ function handleIfElse(ifBlock, elseBlock, state, unwatchFns, localUnwatchFns) {
483
615
  * Iterates through the branches in order and activates the first one whose condition is
484
616
  * true; a branch without a condition is always considered valid and acts as the final
485
617
  * `else`. The state is set to the index of the activated branch.
486
- *
618
+ *
619
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
620
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
487
621
  * @param blocks - Ordered list of conditional branches to evaluate.
488
622
  * @param state - The current state (index of the active branch, or `null` if none).
489
- * @param unwatchFns - Shared array of active cleanup functions.
490
- * @param localUnwatchFns - Cleanup functions generated by the last branch activation.
491
623
  * @returns The new state and new cleanup functions if the active branch changed,
492
624
  * otherwise `undefined`. Also returns `undefined` if no branch matches.
493
625
  */
494
- function handleIfElseIf(blocks, state, unwatchFns, localUnwatchFns) {
626
+ function handleIfElseIf(parentNode, parentContext, blocks, state) {
495
627
  for (let i = 0; i < blocks.length; i++) {
496
628
  const { condition, block } = blocks[i];
497
- if (!condition || condition()) return checkAndUpdateState(state, i, block, unwatchFns, localUnwatchFns);
629
+ if (!condition || condition()) return checkAndUpdateState(parentNode, parentContext, state, i, block);
498
630
  }
499
631
  }
500
632
  /**
@@ -508,88 +640,24 @@ function handleIfElseIf(blocks, state, unwatchFns, localUnwatchFns) {
508
640
  *
509
641
  * If the branch has not changed, no operation is performed.
510
642
  *
643
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
644
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
511
645
  * @param state - The current state (index of the active branch, or `null` if none).
512
646
  * @param newState - The new state to set (index of the branch to activate, or `null`).
513
647
  * @param conditionalBlockFn - Branch function to execute, which returns its own
514
648
  * cleanup functions.
515
- * @param unwatchFns - Shared array of active cleanup functions.
516
- * @param localUnwatchFns - Cleanup functions of the currently active branch, to be
517
- * removed before activating the new branch.
518
649
  * @returns Il nuovo stato e le nuove funzioni di cleanup se il ramo è cambiato, altrimenti
519
650
  * `undefined`.
520
651
  */
521
- function checkAndUpdateState(state, newState, conditionalBlockFn, unwatchFns, localUnwatchFns) {
522
- if (state !== newState) {
523
- unwatch(unwatchFns, localUnwatchFns);
524
- localUnwatchFns = Signal.subtle.untrack(conditionalBlockFn);
525
- unwatchFns.push(...localUnwatchFns);
652
+ function checkAndUpdateState(parentNode, parentContext, state, newState, conditionalBlockFn) {
653
+ if (state?.activeBranch !== newState) {
654
+ state?.context.unlisten();
526
655
  return {
527
- state: newState,
528
- fns: localUnwatchFns
656
+ activeBranch: newState,
657
+ context: Signal.subtle.untrack(() => conditionalBlockFn(parentNode, parentContext))
529
658
  };
530
659
  }
531
660
  }
532
- /**
533
- * Executes and removes the cleanup functions of the previously active branch.
534
- *
535
- * For each local function: removes it from the shared `unwatchFns` array (if present)
536
- * and then invokes it to release resources / tear down associated subscriptions.
537
- *
538
- * @param unwatchFns - Shared array of active cleanup functions, mutated in place.
539
- * @param localUnwatchFns - Cleanup functions of the branch to deactivate.
540
- */
541
- function unwatch(unwatchFns, localUnwatchFns) {
542
- for (const fn of localUnwatchFns) {
543
- const index = unwatchFns.indexOf(fn);
544
- if (index !== -1) unwatchFns.splice(index, 1);
545
- fn();
546
- }
547
- }
548
- //#endregion
549
- //#region ../packages/core/src/utils/for.utils.ts
550
- /**
551
- * Reactively iterates over a list of items, re-running the loop whenever the tracked condition changes.
552
- * Previous iteration side-effects are cleaned up before each re-evaluation.
553
- *
554
- * @param unwatchFns - Array collecting cleanup functions for the parent scope.
555
- * @param condition - A reactive function that returns the array of items to iterate over.
556
- * @param forFn - A callback invoked for each item, receiving the item and its index. Must return an array of cleanup functions.
557
- */
558
- function _for(unwatchFns, condition, forFn) {
559
- const localUnwatchFns = new Array();
560
- const unlistener = effect(() => {
561
- unwatch(unwatchFns, localUnwatchFns);
562
- const items = condition();
563
- Signal.subtle.untrack(() => {
564
- for (let i = 0; i < items.length; i++) {
565
- localUnwatchFns.push(...forFn(items[i], i));
566
- unwatchFns.push(...localUnwatchFns);
567
- }
568
- });
569
- });
570
- unwatchFns.push(unlistener);
571
- }
572
- /**
573
- * Builds a record of iteration context variables for a given index in the loop.
574
- * Provides the current item, index, and convenience flags (`$first`, `$last`, `$even`, `$odd`).
575
- *
576
- * @param items - The full array being iterated.
577
- * @param index - The current iteration index.
578
- * @param itemAlias - The template alias name for the current item.
579
- * @param indexAlias - The template alias name for the current index.
580
- * @returns A record mapping alias names and built-in variables to their values.
581
- */
582
- function _iterationVariables(items, index, itemAlias, indexAlias) {
583
- const even = index % 2 === 0;
584
- return {
585
- [itemAlias]: items[index],
586
- [indexAlias]: index,
587
- $first: index === 0,
588
- $last: index === items.length - 1,
589
- $even: even,
590
- $odd: !even
591
- };
592
- }
593
661
  //#endregion
594
662
  //#region ../packages/core/src/utils/switch.utils.ts
595
663
  /**
@@ -605,6 +673,8 @@ function _iterationVariables(items, index, itemAlias, indexAlias) {
605
673
  * Because it delegates to `_if`, the switch benefits from the same optimisation:
606
674
  * the active branch is only re-rendered when it actually changes.
607
675
  *
676
+ * @param parentNode - The parent HTML element where the conditional structure is applied.
677
+ * @param parentContext - The parent Context object containing all the variables definition from the Parent Closure
608
678
  * @param unwatchFns - Shared array that collects all active cleanup functions.
609
679
  * Mutated in place by the underlying {@link _if} call.
610
680
  * @param expression - Function that evaluates the switch expression. Called
@@ -615,11 +685,11 @@ function _iterationVariables(items, index, itemAlias, indexAlias) {
615
685
  * - `block`: function that applies the branch's side effects and returns
616
686
  * its cleanup functions.
617
687
  */
618
- function _switch(unwatchFns, expression, blocks) {
619
- _if(unwatchFns, blocks.map(({ condition, block }) => ({
688
+ function _switch(parentNode, parentContext, expression, blocks) {
689
+ _if(parentNode, parentContext, blocks.map(({ condition, block }) => ({
620
690
  condition: condition ? () => condition.some((condition) => condition === expression()) : void 0,
621
691
  block
622
692
  })));
623
693
  }
624
694
  //#endregion
625
- export { BaseWebComponent, Event, Property, WebComponent, _for, _if, _iterationVariables, _switch, computed, effect, input, signal, unwatch };
695
+ export { BaseWebComponent, Context, Event, Property, WebComponent, _for, _if, _iterationVariables, _switch, computed, effect, input, signal };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xaendar/core",
3
- "version": "0.6.7",
3
+ "version": "0.6.10",
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.7",
20
- "@xaendar/types": "0.6.7"
19
+ "@xaendar/signals": "0.6.10",
20
+ "@xaendar/types": "0.6.10"
21
21
  }
22
22
  }