@vsn-ux/ngx-gaia 0.14.2 → 0.14.4

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.
@@ -1864,7 +1864,6 @@ class GaDatepickerInputDirective {
1864
1864
  updateValue(value, { updateView, emitToNgModel, } = {}) {
1865
1865
  this.value.set(value);
1866
1866
  this.lastValueValid.set(true);
1867
- this.lastDateChangeEmittedValue.set(value);
1868
1867
  if (updateView) {
1869
1868
  this.formatValue();
1870
1869
  }
@@ -1874,11 +1873,37 @@ class GaDatepickerInputDirective {
1874
1873
  this.onNgTouchedFn?.();
1875
1874
  this.dateInput.emit(value);
1876
1875
  this.dateChange.emit(value);
1876
+ // The dedupe baseline must only advance when dateChange is actually
1877
+ // emitted, so the next blur can detect a real change.
1878
+ this.lastDateChangeEmittedValue.set(value);
1877
1879
  }
1878
1880
  }
1879
1881
  // ControlValueAccessor implementation
1880
1882
  writeValue(value) {
1883
+ // A form write-back echoing the value we already hold (e.g. the
1884
+ // synchronous/async round-trip triggered by `onInput` -> `onNgChangeFn`)
1885
+ // must NOT advance the dedupe baseline, otherwise a manually typed date
1886
+ // would be neutralized before `onBlur` can emit `dateChange`.
1887
+ // A genuine programmatic seed brings a new value and must advance the
1888
+ // baseline so blurring without an edit does not spuriously emit.
1889
+ const isEcho = this.valuesEqual(value, this.value());
1881
1890
  this.updateValue(value, { updateView: !this.focused });
1891
+ if (!isEcho) {
1892
+ this.lastDateChangeEmittedValue.set(value);
1893
+ }
1894
+ }
1895
+ valuesEqual(a, b) {
1896
+ if (a === b) {
1897
+ return true;
1898
+ }
1899
+ const structA = this.valueAdapter.toStruct(a);
1900
+ const structB = this.valueAdapter.toStruct(b);
1901
+ // Two unparseable (e.g. raw string) values are only equal when identical,
1902
+ // already handled above; treat them as distinct here.
1903
+ if (!structA && !structB) {
1904
+ return false;
1905
+ }
1906
+ return compareStructs(structA, structB) === 0;
1882
1907
  }
1883
1908
  registerOnChange(fn) {
1884
1909
  this.onNgChangeFn = fn;
@@ -3296,12 +3321,7 @@ class GaModalService {
3296
3321
  return this.attachContent(component, data, overlayRef);
3297
3322
  }
3298
3323
  closeAll() {
3299
- this.activeModals.update((modals) => {
3300
- while (modals.length > 0) {
3301
- modals.pop()?.close();
3302
- }
3303
- return modals;
3304
- });
3324
+ [...this.activeModals()].forEach((modal) => modal.close());
3305
3325
  }
3306
3326
  /** @ignore */
3307
3327
  attachContent(component, data, overlayRef) {
@@ -3320,18 +3340,9 @@ class GaModalService {
3320
3340
  maxHeight: `calc(100vh - 4rem * var(--ga-base-scaling-factor, 1) * (1 + ${modalStackIndex}))`,
3321
3341
  });
3322
3342
  }
3323
- this.activeModals.update((modals) => {
3324
- modals.push(modalComponent);
3325
- return modals;
3326
- });
3343
+ this.activeModals.update((modals) => [...modals, modalComponent]);
3327
3344
  modalComponent.afterClosed({ closeOnUnsubscribe: false }).subscribe(() => {
3328
- const index = this.activeModals().indexOf(modalRef.instance);
3329
- if (index > -1) {
3330
- this.activeModals.update((modals) => {
3331
- modals.splice(index, 1);
3332
- return modals;
3333
- });
3334
- }
3345
+ this.activeModals.update((modals) => modals.filter((modal) => modal !== modalRef.instance));
3335
3346
  });
3336
3347
  return modalComponent;
3337
3348
  }