@xaendar/core 0.6.4 → 0.6.5
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/xaendar-core.es.d.ts +74 -0
- package/dist/xaendar-core.es.js +177 -1
- package/package.json +3 -3
|
@@ -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 { NoArgsFunction } from '@xaendar/types';
|
|
6
7
|
import { NoArgsVoidFunction } from '@xaendar/types';
|
|
7
8
|
import { NoArgsVoidFunction as NoArgsVoidFunction_2 } from '@xaendar/types';
|
|
8
9
|
import { RequireOne } from '@xaendar/types';
|
|
@@ -63,6 +64,19 @@ export declare type BaseWebComponentConstructor = Constructor<BaseWebComponent,
|
|
|
63
64
|
observedAttributes: string[];
|
|
64
65
|
}>;
|
|
65
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Represents a single branch of a conditional structure (`if` / `else if` / `else`).
|
|
69
|
+
*
|
|
70
|
+
* @property condition - Function that evaluates the branch condition and returns a boolean.
|
|
71
|
+
* If absent, the branch is always considered valid (represents the `else` branch).
|
|
72
|
+
* @property block - Function that, when executed, applies the branch's side effects and
|
|
73
|
+
* returns the list of cleanup (unwatch) functions generated within it.
|
|
74
|
+
*/
|
|
75
|
+
declare type Block = {
|
|
76
|
+
condition?: NoArgsFunction<boolean>;
|
|
77
|
+
block: NoArgsFunction<NoArgsVoidFunction[]>;
|
|
78
|
+
};
|
|
79
|
+
|
|
66
80
|
/**
|
|
67
81
|
* A read-only reactive value derived from other signals.
|
|
68
82
|
*
|
|
@@ -138,6 +152,27 @@ export { Event_2 as Event }
|
|
|
138
152
|
*/
|
|
139
153
|
export declare type EventOptions = Beautify<RequireOne<Omit<CustomEventInit, 'detail'>>>;
|
|
140
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Creates a reactive conditional structure from a list of branches.
|
|
157
|
+
*
|
|
158
|
+
* Depending on the number of branches provided, the appropriate evaluation strategy
|
|
159
|
+
* is selected:
|
|
160
|
+
* - 1 branch → simple `if` (see {@link handleIf});
|
|
161
|
+
* - 2 branches → `if` / `else` (see {@link handleIfElse});
|
|
162
|
+
* - 3+ branches → `if` / `else if` / ... / `else` (see {@link handleIfElseIf}).
|
|
163
|
+
*
|
|
164
|
+
* The evaluation is wrapped in an {@link effect}, so it is automatically re-executed
|
|
165
|
+
* whenever any signal read by the conditions changes. On each re-execution, the current
|
|
166
|
+
* state (which branch is active) and the related cleanup functions are only updated if
|
|
167
|
+
* the active branch has actually changed.
|
|
168
|
+
*
|
|
169
|
+
* @param unwatchFns - Shared array that collects all active cleanup functions.
|
|
170
|
+
* Mutated in place: the created effect and branch functions are added to and
|
|
171
|
+
* removed from this array.
|
|
172
|
+
* @param blocks - Ordered list of conditional branches to evaluate.
|
|
173
|
+
*/
|
|
174
|
+
export declare function _if(unwatchFns: NoArgsVoidFunction[], blocks: Block[]): void;
|
|
175
|
+
|
|
141
176
|
/**
|
|
142
177
|
* An `InputSignal` is a specialized `Signal.State` designed for use as a property signal in web components.
|
|
143
178
|
* It extends the base `State` signal with additional functionality to handle incoming values, such as those from HTML attributes or external sources,
|
|
@@ -293,6 +328,45 @@ declare type Signal_2<Value = any> = Signal.State<Value> & {
|
|
|
293
328
|
};
|
|
294
329
|
export { Signal_2 as Signal }
|
|
295
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Creates a reactive switch/case structure by converting it into an if/else-if chain
|
|
333
|
+
* and delegating to {@link _if}.
|
|
334
|
+
*
|
|
335
|
+
* Each case block's condition values are compared against the result of the
|
|
336
|
+
* `expression` function using strict equality (`===`). A block with
|
|
337
|
+
* `condition: null` acts as the `default` branch (mapped to the `else` branch
|
|
338
|
+
* in the underlying if/else-if chain). Multiple values per case are supported
|
|
339
|
+
* (e.g. fall-through cases) and matched with `Array.some`.
|
|
340
|
+
*
|
|
341
|
+
* Because it delegates to `_if`, the switch benefits from the same optimisation:
|
|
342
|
+
* the active branch is only re-rendered when it actually changes.
|
|
343
|
+
*
|
|
344
|
+
* @param unwatchFns - Shared array that collects all active cleanup functions.
|
|
345
|
+
* Mutated in place by the underlying {@link _if} call.
|
|
346
|
+
* @param expression - Function that evaluates the switch expression. Called
|
|
347
|
+
* reactively inside an effect so that signal reads are tracked.
|
|
348
|
+
* @param blocks - Ordered list of case branches. Each entry contains:
|
|
349
|
+
* - `condition`: array of values to match against the expression result,
|
|
350
|
+
* or `null` for the default branch.
|
|
351
|
+
* - `block`: function that applies the branch's side effects and returns
|
|
352
|
+
* its cleanup functions.
|
|
353
|
+
*/
|
|
354
|
+
export declare function _switch(unwatchFns: NoArgsVoidFunction[], expression: NoArgsFunction<unknown>, blocks: Array<{
|
|
355
|
+
condition: unknown[] | null;
|
|
356
|
+
block: NoArgsFunction<NoArgsVoidFunction[]>;
|
|
357
|
+
}>): void;
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Executes and removes the cleanup functions of the previously active branch.
|
|
361
|
+
*
|
|
362
|
+
* For each local function: removes it from the shared `unwatchFns` array (if present)
|
|
363
|
+
* and then invokes it to release resources / tear down associated subscriptions.
|
|
364
|
+
*
|
|
365
|
+
* @param unwatchFns - Shared array of active cleanup functions, mutated in place.
|
|
366
|
+
* @param localUnwatchFns - Cleanup functions of the branch to deactivate.
|
|
367
|
+
*/
|
|
368
|
+
export declare function unwatch(unwatchFns: NoArgsVoidFunction[], localUnwatchFns: NoArgsVoidFunction[]): void;
|
|
369
|
+
|
|
296
370
|
/**
|
|
297
371
|
* Decorator to define a web component
|
|
298
372
|
* @param selector Name or names of the custom element
|
package/dist/xaendar-core.es.js
CHANGED
|
@@ -401,4 +401,180 @@ function signal(value, options) {
|
|
|
401
401
|
return getter;
|
|
402
402
|
}
|
|
403
403
|
//#endregion
|
|
404
|
-
|
|
404
|
+
//#region ../packages/core/src/utils/if.utils.ts
|
|
405
|
+
/**
|
|
406
|
+
* Creates a reactive conditional structure from a list of branches.
|
|
407
|
+
*
|
|
408
|
+
* Depending on the number of branches provided, the appropriate evaluation strategy
|
|
409
|
+
* is selected:
|
|
410
|
+
* - 1 branch → simple `if` (see {@link handleIf});
|
|
411
|
+
* - 2 branches → `if` / `else` (see {@link handleIfElse});
|
|
412
|
+
* - 3+ branches → `if` / `else if` / ... / `else` (see {@link handleIfElseIf}).
|
|
413
|
+
*
|
|
414
|
+
* The evaluation is wrapped in an {@link effect}, so it is automatically re-executed
|
|
415
|
+
* whenever any signal read by the conditions changes. On each re-execution, the current
|
|
416
|
+
* state (which branch is active) and the related cleanup functions are only updated if
|
|
417
|
+
* the active branch has actually changed.
|
|
418
|
+
*
|
|
419
|
+
* @param unwatchFns - Shared array that collects all active cleanup functions.
|
|
420
|
+
* Mutated in place: the created effect and branch functions are added to and
|
|
421
|
+
* removed from this array.
|
|
422
|
+
* @param blocks - Ordered list of conditional branches to evaluate.
|
|
423
|
+
*/
|
|
424
|
+
function _if(unwatchFns, blocks) {
|
|
425
|
+
let state = null;
|
|
426
|
+
let localUnwatchFns = new Array();
|
|
427
|
+
let fn;
|
|
428
|
+
switch (blocks.length) {
|
|
429
|
+
case 1:
|
|
430
|
+
fn = () => handleIf(blocks[0], state, unwatchFns, localUnwatchFns);
|
|
431
|
+
break;
|
|
432
|
+
case 2:
|
|
433
|
+
fn = () => handleIfElse(blocks[0], blocks[1], state, unwatchFns, localUnwatchFns);
|
|
434
|
+
break;
|
|
435
|
+
default: fn = () => handleIfElseIf(blocks, state, unwatchFns, localUnwatchFns);
|
|
436
|
+
}
|
|
437
|
+
const unlistener = effect(() => {
|
|
438
|
+
const retVal = fn();
|
|
439
|
+
if (retVal) {
|
|
440
|
+
state = retVal.state;
|
|
441
|
+
localUnwatchFns = retVal.fns;
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
unwatchFns.push(unlistener);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Handles the simple `if` case (a single branch, no `else`).
|
|
448
|
+
*
|
|
449
|
+
* If the condition is true, the branch is activated (state `0`); otherwise, any
|
|
450
|
+
* previously active branch is deactivated by resetting the state to `null` and
|
|
451
|
+
* executing an empty block.
|
|
452
|
+
*
|
|
453
|
+
* @param ifBlock - The `if` branch to evaluate.
|
|
454
|
+
* @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
|
+
* @returns The new state and new cleanup functions if the active branch changed,
|
|
458
|
+
* otherwise `undefined`.
|
|
459
|
+
*/
|
|
460
|
+
function handleIf(ifBlock, state, unwatchFns, localUnwatchFns) {
|
|
461
|
+
return ifBlock.condition() ? checkAndUpdateState(state, 0, ifBlock.block, unwatchFns, localUnwatchFns) : checkAndUpdateState(state, null, () => [], unwatchFns, localUnwatchFns);
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Handles the `if` / `else` case (exactly two branches).
|
|
465
|
+
*
|
|
466
|
+
* If the `if` condition is true, the first branch is activated (state `0`); otherwise,
|
|
467
|
+
* the `else` branch is activated (state `1`).
|
|
468
|
+
*
|
|
469
|
+
* @param ifBlock - The `if` branch to evaluate.
|
|
470
|
+
* @param elseBlock - The `else` branch used when the `if` condition is false.
|
|
471
|
+
* @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
|
+
* @returns The new state and new cleanup functions if the active branch changed,
|
|
475
|
+
* otherwise `undefined`.
|
|
476
|
+
*/
|
|
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);
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Handles the general case of an `if` / `else if` / ... / `else` chain (three or more branches).
|
|
482
|
+
*
|
|
483
|
+
* Iterates through the branches in order and activates the first one whose condition is
|
|
484
|
+
* true; a branch without a condition is always considered valid and acts as the final
|
|
485
|
+
* `else`. The state is set to the index of the activated branch.
|
|
486
|
+
*
|
|
487
|
+
* @param blocks - Ordered list of conditional branches to evaluate.
|
|
488
|
+
* @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
|
+
* @returns The new state and new cleanup functions if the active branch changed,
|
|
492
|
+
* otherwise `undefined`. Also returns `undefined` if no branch matches.
|
|
493
|
+
*/
|
|
494
|
+
function handleIfElseIf(blocks, state, unwatchFns, localUnwatchFns) {
|
|
495
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
496
|
+
const { condition, block } = blocks[i];
|
|
497
|
+
if (!condition || condition()) return checkAndUpdateState(state, i, block, unwatchFns, localUnwatchFns);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Updates the conditional structure state only when the active branch changes.
|
|
502
|
+
*
|
|
503
|
+
* If `newState` differs from `state`:
|
|
504
|
+
* 1. runs cleanup of the previous branch's functions (see {@link unwatch});
|
|
505
|
+
* 2. executes the new branch's block via {@link Signal.subtle.untrack} to avoid
|
|
506
|
+
* creating unwanted reactive dependencies during block execution;
|
|
507
|
+
* 3. registers the new cleanup functions in the shared `unwatchFns` array.
|
|
508
|
+
*
|
|
509
|
+
* If the branch has not changed, no operation is performed.
|
|
510
|
+
*
|
|
511
|
+
* @param state - The current state (index of the active branch, or `null` if none).
|
|
512
|
+
* @param newState - The new state to set (index of the branch to activate, or `null`).
|
|
513
|
+
* @param conditionalBlockFn - Branch function to execute, which returns its own
|
|
514
|
+
* 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
|
+
* @returns Il nuovo stato e le nuove funzioni di cleanup se il ramo è cambiato, altrimenti
|
|
519
|
+
* `undefined`.
|
|
520
|
+
*/
|
|
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);
|
|
526
|
+
return {
|
|
527
|
+
state: newState,
|
|
528
|
+
fns: localUnwatchFns
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
}
|
|
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/switch.utils.ts
|
|
550
|
+
/**
|
|
551
|
+
* Creates a reactive switch/case structure by converting it into an if/else-if chain
|
|
552
|
+
* and delegating to {@link _if}.
|
|
553
|
+
*
|
|
554
|
+
* Each case block's condition values are compared against the result of the
|
|
555
|
+
* `expression` function using strict equality (`===`). A block with
|
|
556
|
+
* `condition: null` acts as the `default` branch (mapped to the `else` branch
|
|
557
|
+
* in the underlying if/else-if chain). Multiple values per case are supported
|
|
558
|
+
* (e.g. fall-through cases) and matched with `Array.some`.
|
|
559
|
+
*
|
|
560
|
+
* Because it delegates to `_if`, the switch benefits from the same optimisation:
|
|
561
|
+
* the active branch is only re-rendered when it actually changes.
|
|
562
|
+
*
|
|
563
|
+
* @param unwatchFns - Shared array that collects all active cleanup functions.
|
|
564
|
+
* Mutated in place by the underlying {@link _if} call.
|
|
565
|
+
* @param expression - Function that evaluates the switch expression. Called
|
|
566
|
+
* reactively inside an effect so that signal reads are tracked.
|
|
567
|
+
* @param blocks - Ordered list of case branches. Each entry contains:
|
|
568
|
+
* - `condition`: array of values to match against the expression result,
|
|
569
|
+
* or `null` for the default branch.
|
|
570
|
+
* - `block`: function that applies the branch's side effects and returns
|
|
571
|
+
* its cleanup functions.
|
|
572
|
+
*/
|
|
573
|
+
function _switch(unwatchFns, expression, blocks) {
|
|
574
|
+
_if(unwatchFns, blocks.map(({ condition, block }) => ({
|
|
575
|
+
condition: condition ? () => condition.some((condition) => condition === expression()) : void 0,
|
|
576
|
+
block
|
|
577
|
+
})));
|
|
578
|
+
}
|
|
579
|
+
//#endregion
|
|
580
|
+
export { BaseWebComponent, Event, Property, WebComponent, _if, _switch, computed, effect, input, signal, unwatch };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xaendar/core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
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.
|
|
20
|
-
"@xaendar/types": "0.6.
|
|
19
|
+
"@xaendar/signals": "0.6.5",
|
|
20
|
+
"@xaendar/types": "0.6.5"
|
|
21
21
|
}
|
|
22
22
|
}
|