ng-hub-ui-forms 22.18.1 → 22.19.0

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.
@@ -7498,6 +7498,8 @@ class HubDatepickerComponent extends HubFieldControl {
7498
7498
  ...(ngDevMode ? [{ debugName: "_emitsRange" }] : /* istanbul ignore next */ []));
7499
7499
  _hour12 = computed(() => resolveHour12(this.locale(), this._hourFormat()), /* @ts-ignore */
7500
7500
  ...(ngDevMode ? [{ debugName: "_hour12" }] : /* istanbul ignore next */ []));
7501
+ /** Last range actually published, so an abandoned half-selection has somewhere to return to. */
7502
+ #committed = { start: null, end: null };
7501
7503
  rangeStart = computed(() => this._start(), /* @ts-ignore */
7502
7504
  ...(ngDevMode ? [{ debugName: "rangeStart" }] : /* istanbul ignore next */ []));
7503
7505
  rangeEnd = computed(() => (this._isRange() ? this._end() : null), /* @ts-ignore */
@@ -7617,6 +7619,7 @@ class HubDatepickerComponent extends HubFieldControl {
7617
7619
  : incomingEnd;
7618
7620
  this._start.set(start ? startOfUnit(start, granularity) : null);
7619
7621
  this._end.set(end ? startOfUnit(end, granularity) : null);
7622
+ this.#committed = { start: this._start(), end: this._end() };
7620
7623
  this.#anchor(start ?? new Date());
7621
7624
  return;
7622
7625
  }
@@ -7640,6 +7643,7 @@ class HubDatepickerComponent extends HubFieldControl {
7640
7643
  if (!this._open()) {
7641
7644
  return;
7642
7645
  }
7646
+ this.#rollbackPendingRange();
7643
7647
  this._open.set(false);
7644
7648
  this._previewTarget.set(null);
7645
7649
  this.onTouched?.();
@@ -7856,6 +7860,20 @@ class HubDatepickerComponent extends HubFieldControl {
7856
7860
  this.close();
7857
7861
  }
7858
7862
  }
7863
+ /**
7864
+ * Drops a range that was only half picked when the panel closed.
7865
+ *
7866
+ * The first click of a span is a question, not an answer, and {@link #emit} never published
7867
+ * it. Leaving it on screen would show a selection the model does not hold, so the panel goes
7868
+ * back to the last value that was actually committed.
7869
+ */
7870
+ #rollbackPendingRange() {
7871
+ if (!this._emitsRange() || !this._start() || this._end()) {
7872
+ return;
7873
+ }
7874
+ this._start.set(this.#committed.start);
7875
+ this._end.set(this.#committed.end);
7876
+ }
7859
7877
  /** Keeps the two endpoints ordered after a time edit has moved one past the other. */
7860
7878
  #reorderIfNeeded() {
7861
7879
  const start = this._start();
@@ -7955,12 +7973,21 @@ class HubDatepickerComponent extends HubFieldControl {
7955
7973
  const start = this._start();
7956
7974
  if (this._emitsRange()) {
7957
7975
  const end = this._end();
7976
+ // A half-open range is not an answer, so it is not published. Emitting the first pick
7977
+ // used to destroy a complete value the instant the user began choosing a new span —
7978
+ // and if they then clicked away, the control was left holding `{ start, end: null }`,
7979
+ // a shape no consumer asked for and every consumer has to defend against. The pick
7980
+ // stays on screen; the model keeps what it had until the second end lands.
7981
+ if (start && !end) {
7982
+ return;
7983
+ }
7958
7984
  const value = start || end
7959
7985
  ? {
7960
7986
  start: serializeValue(start, granularity, valueFormat),
7961
7987
  end: serializeValue(end, granularity, valueFormat)
7962
7988
  }
7963
7989
  : null;
7990
+ this.#committed = { start, end };
7964
7991
  this.onChange?.(value);
7965
7992
  this.valueChange.emit(value);
7966
7993
  return;