@ngutil/common 0.0.21 → 0.0.26

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.
@@ -1,6 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, inject, DestroyRef, computed, isSignal, Injectable, Inject, SkipSelf, Optional, input } from '@angular/core';
3
- import { Subject, share, take, takeUntil, BehaviorSubject, scan, tap, map, shareReplay, Observable, finalize, isObservable, throwError, combineLatest, filter, switchMap } from 'rxjs';
2
+ import { Directive, inject, DestroyRef, computed, isSignal, Injectable, Inject, SkipSelf, Optional, input, signal, effect, ElementRef } from '@angular/core';
3
+ import { Subject, share, take, takeUntil, BehaviorSubject, scan, tap, map, shareReplay, Observable, finalize, isObservable, throwError, combineLatest, filter, switchMap, ReplaySubject, concat, catchError, of, from, forkJoin } from 'rxjs';
4
+ import { NgControl } from '@angular/forms';
4
5
  import { toSignal, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
5
6
  import { isEqual, cloneDeep, isPlainObject as isPlainObject$1 } from 'lodash';
6
7
  export { isPrimitive } from 'utility-types';
@@ -85,132 +86,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.6", ngImpor
85
86
  type: Directive
86
87
  }] });
87
88
 
88
- const specials = ["auto", "inherit"];
89
- const UNIT_REGEX = "v[h|w|min|max]|p[c|t|x]|[re|e|c|m]m|[l|c]h|%|in|Q|ex|m?s";
90
- const NUMBER_REGEX = "[+-]?(?:\\d*\\.\\d+|\\d+\\.\\d*|\\d+)";
91
- const regex = new RegExp(`^(${NUMBER_REGEX})\\s*(${UNIT_REGEX})?$`);
92
- class NumberWithUnit {
93
- static coerce(value, defaultUnit) {
94
- if (specials.includes(value)) {
95
- return new NumberWithUnit(NaN, value);
96
- }
97
- else if (typeof value === "string") {
98
- const match = value.match(regex);
99
- if (match) {
100
- return new NumberWithUnit(Number(match[1]), match[2] || defaultUnit);
101
- }
102
- }
103
- else if (typeof value === "number") {
104
- return new NumberWithUnit(value, defaultUnit);
105
- }
106
- throw new Error(`Not implemented number with unit: ${value}`);
107
- }
108
- constructor(value, unit) {
109
- this.value = value;
110
- this.unit = unit;
111
- }
112
- toString() {
113
- if (isNaN(this.value)) {
114
- return this.unit;
115
- }
116
- else if (this.unit != null) {
117
- return `${this.value}${this.unit}`;
118
- }
119
- else {
120
- return `${this.value}`;
121
- }
122
- }
123
- }
124
-
125
- function coerceBoolAttr(value) {
126
- return value != null && `${value}` !== "false";
127
- }
128
-
129
- const Zone = window.Zone;
130
- function __zone_symbol__(val) {
131
- const symbol = typeof Zone !== "undefined" && Zone.__symbol__
132
- ? Zone.__symbol__(val)
133
- : `__zone_symbol__${val}`;
134
- return typeof window[symbol] !== "undefined" ? symbol : val;
135
- }
136
- const rawSetTimeout = window[__zone_symbol__("setTimeout")];
137
- const rawClearTimeout = window[__zone_symbol__("clearTimeout")];
138
- const rawSetInterval = window[__zone_symbol__("setInterval")];
139
- const rawClearInterval = window[__zone_symbol__("clearInterval")];
140
- const rawRequestAnimationFrame = window[__zone_symbol__("requestAnimationFrame")];
141
- const rawCancelAnimationFrame = window[__zone_symbol__("cancelAnimationFrame")];
142
-
143
- class _FastDOM {
144
- #rafId;
145
- #mutate = [];
146
- #measure = [];
147
- mutate(handler) {
148
- this.#mutate.push(handler);
149
- this._schedule();
150
- }
151
- mutateNext(handler) {
152
- this.#mutate.push(() => {
153
- this.#mutate.push(handler);
154
- });
155
- this._schedule();
156
- }
157
- measure(handler) {
158
- this.#measure.push(handler);
159
- this._schedule();
160
- }
161
- setStyle(el, style, chain) {
162
- this.mutate(() => {
163
- for (const [k, v] of Object.entries(style)) {
164
- if (v == null) {
165
- el.style.removeProperty(k);
166
- }
167
- else {
168
- el.style.setProperty(k, v);
169
- }
170
- }
171
- chain && chain();
172
- });
173
- }
174
- setAttributes(el, attrs, chain) {
175
- this.mutate(() => {
176
- for (const [k, v] of Object.entries(attrs)) {
177
- if (v == null) {
178
- el.removeAttribute(k);
179
- }
180
- else {
181
- el.setAttribute(k, v);
182
- }
183
- }
184
- chain && chain();
185
- });
186
- }
187
- _schedule() {
188
- if (!this.#rafId) {
189
- this.#rafId = rawRequestAnimationFrame(this._apply.bind(this));
190
- }
191
- }
192
- _apply() {
193
- this.#rafId = null;
194
- const measure = this.#measure.slice();
195
- const mutate = this.#mutate.slice();
196
- this.#measure.length = 0;
197
- this.#mutate.length = 0;
198
- runQ(measure);
199
- runQ(mutate);
200
- if (this.#measure.length || this.#mutate.length) {
201
- this._schedule();
202
- }
203
- }
204
- }
205
- function runQ(items) {
206
- let item;
207
- while ((item = items.shift())) {
208
- item();
209
- }
210
- }
211
- const FastDOM = new _FastDOM();
212
-
213
- class BusyState {
89
+ class BusyTrackerState {
214
90
  constructor() {
215
91
  this.#events = new BehaviorSubject(null);
216
92
  this.#data = {};
@@ -272,7 +148,7 @@ class BusyState {
272
148
  return Object.entries(this.#data);
273
149
  }
274
150
  connect(o, prefix) {
275
- if (o instanceof BusyState) {
151
+ if (o instanceof BusyTrackerState) {
276
152
  return this.connect(o.current$, prefix);
277
153
  }
278
154
  else {
@@ -318,7 +194,7 @@ class BusyTracker {
318
194
  this.destroyRef = inject(DestroyRef);
319
195
  this._state = this.parent
320
196
  ? this.parent._state
321
- : new BusyState();
197
+ : new BusyTrackerState();
322
198
  this.state$ = this._state.current$;
323
199
  this.state = toSignal(this.state$, { requireSync: true });
324
200
  this.any = computed(() => this.state().isBusy);
@@ -385,6 +261,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.6", ngImpor
385
261
  }, {
386
262
  type: Optional
387
263
  }] }] });
264
+ // TODO: BusyState directive
388
265
  /**
389
266
  * ```ts
390
267
  * @Component({
@@ -455,6 +332,341 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.6", ngImpor
455
332
  }]
456
333
  }] });
457
334
 
335
+ var _a;
336
+ /**
337
+ * @example
338
+ * ```typescript
339
+ * @Component({
340
+ * standalone: true,
341
+ * hostDirectives: [DisabledState],
342
+ * template: `<button [disabled]="disabledState.isDisabled()">Submit</button>`,
343
+ * })
344
+ * export class Button {
345
+ * readonly disabledState = inject(DisabledState)
346
+ * }
347
+ * ```
348
+ */
349
+ class DisabledState {
350
+ #parent;
351
+ #busy;
352
+ #disabled;
353
+ constructor() {
354
+ this.#parent = inject(_a, { skipSelf: true, optional: true });
355
+ this.#busy = inject(Busy, { self: true, optional: true });
356
+ this.#disabled = signal(false);
357
+ this.isDisabled = computed(() => !!(this.#parent?.isDisabled() || this.#busy?.isOthersBusy() || this.#disabled()));
358
+ effect(() => this.isDisabled());
359
+ }
360
+ set(value) {
361
+ this.#disabled.set(value);
362
+ }
363
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.6", ngImport: i0, type: DisabledState, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
364
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.6", type: DisabledState, isStandalone: true, host: { properties: { "attr.disabled": "isDisabled()" } }, exportAs: ["nuDisabled"], ngImport: i0 }); }
365
+ }
366
+ _a = DisabledState;
367
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.6", ngImport: i0, type: DisabledState, decorators: [{
368
+ type: Directive,
369
+ args: [{
370
+ standalone: true,
371
+ exportAs: "nuDisabled",
372
+ host: {
373
+ "[attr.disabled]": "isDisabled()"
374
+ }
375
+ }]
376
+ }], ctorParameters: () => [] });
377
+ /**
378
+ * @example
379
+ * ```html
380
+ * <form nuDisabled nuBusy="submit">
381
+ * <button [nuDisabled]="form.invalid" nuBusy="submit">Submit</button>
382
+ * </form>
383
+ * ```
384
+ */
385
+ class Disabled {
386
+ #state;
387
+ #control;
388
+ constructor() {
389
+ this.#state = inject(DisabledState, { self: true });
390
+ this.#control = inject(NgControl, { self: true, optional: true });
391
+ this.nuDisabled = input(false);
392
+ effect(() => this.#state.set(this.nuDisabled()), { allowSignalWrites: true });
393
+ effect(() => {
394
+ const control = this.#control?.control;
395
+ if (!control) {
396
+ // TODO: retry
397
+ return;
398
+ }
399
+ if (this.#state.isDisabled()) {
400
+ control.enabled && control.disable();
401
+ }
402
+ else {
403
+ control.disabled && control.enable();
404
+ }
405
+ });
406
+ }
407
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.6", ngImport: i0, type: Disabled, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
408
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "17.3.6", type: Disabled, isStandalone: true, selector: "[nuDisabled]", inputs: { nuDisabled: { classPropertyName: "nuDisabled", publicName: "nuDisabled", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: DisabledState }], ngImport: i0 }); }
409
+ }
410
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.6", ngImport: i0, type: Disabled, decorators: [{
411
+ type: Directive,
412
+ args: [{
413
+ standalone: true,
414
+ selector: "[nuDisabled]",
415
+ hostDirectives: [DisabledState]
416
+ }]
417
+ }], ctorParameters: () => [] });
418
+
419
+ const specials = ["auto", "inherit"];
420
+ const UNIT_REGEX = "v[h|w|min|max]|p[c|t|x]|[re|e|c|m]m|[l|c]h|%|in|Q|ex|m?s";
421
+ const NUMBER_REGEX = "[+-]?(?:\\d*\\.\\d+|\\d+\\.\\d*|\\d+)";
422
+ const regex = new RegExp(`^(${NUMBER_REGEX})\\s*(${UNIT_REGEX})?$`);
423
+ class NumberWithUnit {
424
+ static coerce(value, defaultUnit) {
425
+ if (specials.includes(value)) {
426
+ return new NumberWithUnit(NaN, value);
427
+ }
428
+ else if (typeof value === "string") {
429
+ const match = value.match(regex);
430
+ if (match) {
431
+ return new NumberWithUnit(Number(match[1]), match[2] || defaultUnit);
432
+ }
433
+ }
434
+ else if (typeof value === "number") {
435
+ return new NumberWithUnit(value, defaultUnit);
436
+ }
437
+ throw new Error(`Not implemented number with unit: ${value}`);
438
+ }
439
+ constructor(value, unit) {
440
+ this.value = value;
441
+ this.unit = unit;
442
+ }
443
+ toString() {
444
+ if (isNaN(this.value)) {
445
+ return this.unit;
446
+ }
447
+ else if (this.unit != null) {
448
+ return `${this.value}${this.unit}`;
449
+ }
450
+ else {
451
+ return `${this.value}`;
452
+ }
453
+ }
454
+ }
455
+
456
+ function coerceBoolAttr(value) {
457
+ return value != null && `${value}` !== "false";
458
+ }
459
+
460
+ function coerceElement(value) {
461
+ if (value instanceof ElementRef) {
462
+ return value.nativeElement;
463
+ }
464
+ return value;
465
+ }
466
+
467
+ class StopStateChain extends Error {
468
+ }
469
+ class StateChain {
470
+ #executed;
471
+ #handlers;
472
+ #current;
473
+ constructor(states) {
474
+ this.#executed = [];
475
+ this.#handlers = {};
476
+ this.#current = new ReplaySubject(1);
477
+ this.current$ = this.#current.asObservable();
478
+ this.states = { ...states };
479
+ for (const value of Object.values(states)) {
480
+ if (value.order == null) {
481
+ value.order = "parallel";
482
+ }
483
+ }
484
+ }
485
+ on(state, fn) {
486
+ if (state in this.#handlers) {
487
+ this.#handlers[state].push(fn);
488
+ }
489
+ else {
490
+ this.#handlers[state] = [fn];
491
+ }
492
+ return () => {
493
+ const idx = this.#handlers[state].indexOf(fn);
494
+ if (idx > -1) {
495
+ this.#handlers[state].splice(idx, 1);
496
+ }
497
+ };
498
+ }
499
+ /**
500
+ * Run this state changes on other state
501
+ */
502
+ control(state, remap) {
503
+ const remove = [];
504
+ for (const selfState of Object.keys(this.states)) {
505
+ const otherState = remap?.[selfState] || selfState;
506
+ if (otherState in state.states) {
507
+ remove.push(this.on(selfState, () => state.run([otherState])));
508
+ }
509
+ }
510
+ return () => {
511
+ for (const fn of remove) {
512
+ fn();
513
+ }
514
+ };
515
+ }
516
+ run(states) {
517
+ if (states.length === 0) {
518
+ throw new Error("Missing states");
519
+ }
520
+ const executed = [];
521
+ return concat(...states.map(state => this.#run(state).pipe(tap(s => s && executed.push(s))))).pipe(catchError(err => (err instanceof StopStateChain ? of(executed) : throwError(() => err))));
522
+ }
523
+ #run(state) {
524
+ const options = this.states[state];
525
+ return new Observable(dst => {
526
+ if (this.#executed.includes(state)) {
527
+ dst.next(state);
528
+ dst.complete();
529
+ return;
530
+ }
531
+ this.#executed.push(state);
532
+ this.#current.next(state);
533
+ const handlers = this.#handlers[state];
534
+ if (handlers == null || handlers.length === 0) {
535
+ dst.next(state);
536
+ dst.complete();
537
+ return;
538
+ }
539
+ const observables = handlers
540
+ .map(handler => {
541
+ const result = handler();
542
+ if (result == null) {
543
+ return of(null);
544
+ }
545
+ else {
546
+ return from(result);
547
+ }
548
+ })
549
+ .map(handler => handler.pipe(catchError(err => {
550
+ if (err instanceof StopStateChain) {
551
+ const idx = this.#executed.indexOf(state);
552
+ if (idx > -1) {
553
+ this.#executed.splice(idx, 1);
554
+ }
555
+ dst.error(err);
556
+ dst.complete();
557
+ return of(null);
558
+ }
559
+ else {
560
+ return throwError(() => err);
561
+ }
562
+ })));
563
+ if (observables.length === 1) {
564
+ return observables[0].pipe(map(() => state)).subscribe(dst);
565
+ }
566
+ else {
567
+ if (options.order === "parallel") {
568
+ return forkJoin(observables)
569
+ .pipe(map(() => state))
570
+ .subscribe(dst);
571
+ }
572
+ else {
573
+ return concat(...observables)
574
+ .pipe(map(() => state))
575
+ .subscribe(dst);
576
+ }
577
+ }
578
+ });
579
+ }
580
+ destroy() {
581
+ ;
582
+ this.#handlers = null;
583
+ }
584
+ }
585
+
586
+ const Zone = window.Zone;
587
+ function __zone_symbol__(val) {
588
+ const symbol = typeof Zone !== "undefined" && Zone.__symbol__
589
+ ? Zone.__symbol__(val)
590
+ : `__zone_symbol__${val}`;
591
+ return typeof window[symbol] !== "undefined" ? symbol : val;
592
+ }
593
+ const rawSetTimeout = window[__zone_symbol__("setTimeout")];
594
+ const rawClearTimeout = window[__zone_symbol__("clearTimeout")];
595
+ const rawSetInterval = window[__zone_symbol__("setInterval")];
596
+ const rawClearInterval = window[__zone_symbol__("clearInterval")];
597
+ const rawRequestAnimationFrame = window[__zone_symbol__("requestAnimationFrame")];
598
+ const rawCancelAnimationFrame = window[__zone_symbol__("cancelAnimationFrame")];
599
+
600
+ class _FastDOM {
601
+ #rafId;
602
+ #mutate = [];
603
+ #measure = [];
604
+ mutate(handler) {
605
+ this.#mutate.push(handler);
606
+ this._schedule();
607
+ }
608
+ mutateNext(handler) {
609
+ this.#mutate.push(() => {
610
+ this.#mutate.push(handler);
611
+ });
612
+ this._schedule();
613
+ }
614
+ measure(handler) {
615
+ this.#measure.push(handler);
616
+ this._schedule();
617
+ }
618
+ setStyle(el, style, chain) {
619
+ this.mutate(() => {
620
+ for (const [k, v] of Object.entries(style)) {
621
+ if (v == null) {
622
+ el.style.removeProperty(k);
623
+ }
624
+ else {
625
+ el.style.setProperty(k, v);
626
+ }
627
+ }
628
+ chain && chain();
629
+ });
630
+ }
631
+ setAttributes(el, attrs, chain) {
632
+ this.mutate(() => {
633
+ for (const [k, v] of Object.entries(attrs)) {
634
+ if (v == null) {
635
+ el.removeAttribute(k);
636
+ }
637
+ else {
638
+ el.setAttribute(k, v);
639
+ }
640
+ }
641
+ chain && chain();
642
+ });
643
+ }
644
+ _schedule() {
645
+ if (!this.#rafId) {
646
+ this.#rafId = rawRequestAnimationFrame(this._apply.bind(this));
647
+ }
648
+ }
649
+ _apply() {
650
+ this.#rafId = null;
651
+ const measure = this.#measure.slice();
652
+ const mutate = this.#mutate.slice();
653
+ this.#measure.length = 0;
654
+ this.#mutate.length = 0;
655
+ runQ(measure);
656
+ runQ(mutate);
657
+ if (this.#measure.length || this.#mutate.length) {
658
+ this._schedule();
659
+ }
660
+ }
661
+ }
662
+ function runQ(items) {
663
+ let item;
664
+ while ((item = items.shift())) {
665
+ item();
666
+ }
667
+ }
668
+ const FastDOM = new _FastDOM();
669
+
458
670
  // export { deepFreeze }
459
671
  const deepClone = typeof structuredClone === "function" ? structuredClone : cloneDeep;
460
672
  // export const deepFreeze: <T>(obj: T) => DeepReadonly<T> = o => Object.freeze(o) as any
@@ -510,5 +722,5 @@ function toSorted(items, fn) {
510
722
  * Generated bundle index. Do not edit.
511
723
  */
512
724
 
513
- export { Busy, BusyState, BusyTracker, Destruct, Destructible, FastDOM, NUMBER_REGEX, NumberWithUnit, UNIT_REGEX, coerceBoolAttr, deepClone, deepFreeze, isPlainObject, rawCancelAnimationFrame, rawClearInterval, rawClearTimeout, rawRequestAnimationFrame, rawSetInterval, rawSetTimeout, toSorted };
725
+ export { Busy, BusyTracker, BusyTrackerState, Destruct, Destructible, Disabled, DisabledState, FastDOM, NUMBER_REGEX, NumberWithUnit, StateChain, UNIT_REGEX, __zone_symbol__, coerceBoolAttr, coerceElement, deepClone, deepFreeze, isPlainObject, rawCancelAnimationFrame, rawClearInterval, rawClearTimeout, rawRequestAnimationFrame, rawSetInterval, rawSetTimeout, toSorted };
514
726
  //# sourceMappingURL=ngutil-common.mjs.map