@dereekb/dbx-form 13.10.5 → 13.10.7
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/fesm2022/dereekb-dbx-form-calendar.mjs +43 -69
- package/fesm2022/dereekb-dbx-form-calendar.mjs.map +1 -1
- package/fesm2022/dereekb-dbx-form-mapbox.mjs +24 -46
- package/fesm2022/dereekb-dbx-form-mapbox.mjs.map +1 -1
- package/fesm2022/dereekb-dbx-form.mjs +124 -224
- package/fesm2022/dereekb-dbx-form.mjs.map +1 -1
- package/package.json +8 -8
- package/types/dereekb-dbx-form-calendar.d.ts +15 -6
- package/types/dereekb-dbx-form-mapbox.d.ts +1 -2
- package/types/dereekb-dbx-form.d.ts +16 -24
|
@@ -6,13 +6,13 @@ import * as i0 from '@angular/core';
|
|
|
6
6
|
import { Injectable, inject, Directive, Optional, SkipSelf, Injector, ChangeDetectionStrategy, Component, viewChild, input, effect, computed, ElementRef, output, InjectionToken, NgModule } from '@angular/core';
|
|
7
7
|
import { FieldType } from '@ngx-formly/material';
|
|
8
8
|
import { switchMap, first, tap, map, distinctUntilChanged, shareReplay, of, combineLatestWith, BehaviorSubject, filter, combineLatest, EMPTY, startWith, throttleTime, skip } from 'rxjs';
|
|
9
|
-
import { filterMaybe, distinctUntilHasDifferentValues,
|
|
9
|
+
import { filterMaybe, distinctUntilHasDifferentValues, asObservableFromGetter, asObservable } from '@dereekb/rxjs';
|
|
10
10
|
import { DateCellScheduleDayCode, expandDateCellScheduleDayCodesToDayOfWeekSet, dateCellTimingStartsAtForStartOfDay, dateCellTimingRelativeIndexFactory, dateCellDayOfWeekFactory, dateTimezoneUtcNormal, findMaxDate, findMinDate, isSameDateRange, isSameDateDay, isSameDate, dateCellTimingDateFactory, expandDateCellScheduleRange, formatToISO8601DayStringForSystem, changeDateCellScheduleDateRangeToTimezone, isSameDateCellScheduleDateRange, dateCellTimingRelativeIndexArrayFactory, isInfiniteDateRange, copyDateCellScheduleDateFilterConfig, SYSTEM_DATE_TIMEZONE_UTC_NORMAL_INSTANCE, dateCellScheduleDateFilter, fullDateCellScheduleRange, dateCellTimingTimezoneNormalInstance, expandDateCellScheduleDayCodes, fullWeekDateCellScheduleDayCodes, dateCellScheduleDayCodesAreSetsEquivalent, simplifyDateCellScheduleDayCodes, dateCellTimingStartDateFactory, isDateInDateRangeFunction, isDateWithinDateCellRangeFunction, dateCellScheduleEncodedWeek, enabledDaysFromDateCellScheduleDayCodes, dateCellScheduleDayCodesFromEnabledDays, formatToMonthDayString, dateRange, DateRangeType } from '@dereekb/date';
|
|
11
11
|
import { isInAllowedDaysOfWeekSet, mapValuesToSet, unique, mergeArrays, iterableToArray, isIterable, firstValueFromIterable, minAndMaxNumber, range, toggleInSet, removeFromSet, addToSet, isIndexNumberInIndexRangeFunction, getDaysOfWeekNames, reduceBooleansWithAnd, mergeObjects, KeyValueTypleValueFilter, filterFromPOJO } from '@dereekb/util';
|
|
12
12
|
import { ComponentStore } from '@ngrx/component-store';
|
|
13
13
|
import { endOfDay, startOfDay, isBefore, endOfWeek } from 'date-fns';
|
|
14
14
|
import * as i1$1 from '@dereekb/dbx-core';
|
|
15
|
-
import { TimezoneAbbreviationPipe, switchMapDbxInjectionComponentConfig, DbxInjectionComponent } from '@dereekb/dbx-core';
|
|
15
|
+
import { completeOnDestroy, cleanSubscription, TimezoneAbbreviationPipe, switchMapDbxInjectionComponentConfig, DbxInjectionComponent } from '@dereekb/dbx-core';
|
|
16
16
|
import { toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
17
17
|
import { MatDialog } from '@angular/material/dialog';
|
|
18
18
|
import { CalendarMonthViewComponent, CalendarDatePipe } from 'angular-calendar';
|
|
@@ -241,6 +241,18 @@ class DbxCalendarScheduleSelectionStore extends ComponentStore {
|
|
|
241
241
|
currentSelectionValueStart$ = this.currentSelectionValue$.pipe(map((x) => x?.dateScheduleRange.start), distinctUntilChanged(isSameDate), shareReplay(1));
|
|
242
242
|
currentSelectionValueDateCellTimingDateFactory$ = this.currentSelectionValue$.pipe(map((x) => (x ? dateCellTimingDateFactory({ startsAt: x.dateScheduleRange.start, timezone: x.dateScheduleRange.timezone }) : undefined)), shareReplay(1));
|
|
243
243
|
currentSelectionValueDateCellDurationSpanExpansion$ = this.currentSelectionValue$.pipe(map((x) => (x ? expandDateCellScheduleRange({ dateCellScheduleRange: x.dateScheduleRange }) : [])), shareReplay(1));
|
|
244
|
+
/**
|
|
245
|
+
* State-anchored coordinate contract: the emitted indexes are anchored at
|
|
246
|
+
* `state.start` (== `filter.start` when a filter is set, otherwise `today` from
|
|
247
|
+
* `initialCalendarScheduleSelectionState()`). Consumers can use them directly
|
|
248
|
+
* with `state.indexFactory(date)`.
|
|
249
|
+
*
|
|
250
|
+
* This holds because `currentSelectionValue.dateScheduleRange.start` always
|
|
251
|
+
* equals `state.start` for filter-relative outputs, so the expansion's `i`
|
|
252
|
+
* values share the same anchor. If a future change re-introduces a non-
|
|
253
|
+
* `state.start` output anchor, translate output indexes back via
|
|
254
|
+
* `state.indexFactory(dateScheduleRange.start)` here.
|
|
255
|
+
*/
|
|
244
256
|
selectionValueSelectedIndexes$ = this.currentSelectionValueDateCellDurationSpanExpansion$.pipe(map((x) => new Set(x.map((y) => y.i))), distinctUntilHasDifferentValues(), shareReplay(1));
|
|
245
257
|
selectionValueSelectedDates$ = this.currentSelectionValueDateCellTimingDateFactory$.pipe(switchMap((dateFactory) => {
|
|
246
258
|
return dateFactory ? this.selectionValueSelectedIndexes$.pipe(map((x) => mapValuesToSet(x, (y) => formatToISO8601DayStringForSystem(dateFactory(y))))) : of(new Set());
|
|
@@ -577,11 +589,14 @@ function updateStateWithDateCellScheduleRangeValue(state, inputChange) {
|
|
|
577
589
|
return state;
|
|
578
590
|
}
|
|
579
591
|
if (change != null) {
|
|
580
|
-
//
|
|
581
|
-
//
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
592
|
+
// After the legacy-restored output anchor, change.ex is already state-anchored
|
|
593
|
+
// (change.start equals state.start for filter-relative outputs), so no offset
|
|
594
|
+
// is applied. inputStart is clamped to state.minMaxDateRange.start when set so
|
|
595
|
+
// the round-trip preserves the clamp and pre-clamp days don't re-render via the
|
|
596
|
+
// "toggled outside range" branch.
|
|
597
|
+
const minMaxStart = state.minMaxDateRange?.start;
|
|
598
|
+
const clampedInputStart = minMaxStart && minMaxStart.getTime() > change.start.getTime() ? minMaxStart : change.start;
|
|
599
|
+
const nextState = { ...state, inputStart: clampedInputStart, inputEnd: change.end, toggledIndexes: new Set(change.ex ?? []) };
|
|
585
600
|
return updateStateWithChangedScheduleDays(finalizeNewCalendarScheduleSelectionState(nextState), expandDateCellScheduleDayCodes(change.w || '89'));
|
|
586
601
|
}
|
|
587
602
|
return noSelectionCalendarScheduleSelectionState(state); // clear selection, retain disabled days
|
|
@@ -923,26 +938,8 @@ function computeScheduleSelectionValue(state) {
|
|
|
923
938
|
const rangeStartIndex = systemIndexFactory(rangeStart);
|
|
924
939
|
const startIndex = systemIndexFactory(startInSystemTimezone);
|
|
925
940
|
const filterStartIndexOffset = rangeStartIndex - startIndex;
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
// This prevents outputting a start date that violates the minMaxDateRange
|
|
929
|
-
// and avoids the round-trip corruption when the value is synced back to the store.
|
|
930
|
-
if (filterStartIndexOffset > 0 && state.minMaxDateRange?.start) {
|
|
931
|
-
// rangeStart already respects minMaxDateRange. Convert it to the filter's timezone for the output.
|
|
932
|
-
if (filter.timezone) {
|
|
933
|
-
const filterNormal = dateTimezoneUtcNormal(filter.timezone);
|
|
934
|
-
start = filterNormal.startOfDayInTargetTimezone(rangeStart);
|
|
935
|
-
}
|
|
936
|
-
else {
|
|
937
|
-
start = rangeStart;
|
|
938
|
-
}
|
|
939
|
-
// No filter offset exclusions needed since start is at the selection start.
|
|
940
|
-
// indexOffset stays as dateCellRange.i (relative to state.start → rangeStart).
|
|
941
|
-
}
|
|
942
|
-
else {
|
|
943
|
-
filterOffsetExcludedRange = range(0, filterStartIndexOffset);
|
|
944
|
-
indexOffset = indexOffset - filterStartIndexOffset;
|
|
945
|
-
}
|
|
941
|
+
filterOffsetExcludedRange = range(0, filterStartIndexOffset);
|
|
942
|
+
indexOffset = indexOffset - filterStartIndexOffset;
|
|
946
943
|
}
|
|
947
944
|
const excluded = computeSelectionResultRelativeToFilter
|
|
948
945
|
? allExcluded.filter((x) => {
|
|
@@ -1205,9 +1202,9 @@ class DbxScheduleSelectionCalendarDateRangeComponent {
|
|
|
1205
1202
|
this.range.enable();
|
|
1206
1203
|
}
|
|
1207
1204
|
}, ...(ngDevMode ? [{ debugName: "_disabledEffect" }] : /* istanbul ignore next */ []));
|
|
1208
|
-
_pickerOpened = new BehaviorSubject(false);
|
|
1209
|
-
_syncSub =
|
|
1210
|
-
_valueSub =
|
|
1205
|
+
_pickerOpened = completeOnDestroy(new BehaviorSubject(false));
|
|
1206
|
+
_syncSub = cleanSubscription();
|
|
1207
|
+
_valueSub = cleanSubscription();
|
|
1211
1208
|
range = new FormGroup({
|
|
1212
1209
|
start: new FormControl(null),
|
|
1213
1210
|
end: new FormControl(null)
|
|
@@ -1301,10 +1298,6 @@ class DbxScheduleSelectionCalendarDateRangeComponent {
|
|
|
1301
1298
|
}
|
|
1302
1299
|
});
|
|
1303
1300
|
}
|
|
1304
|
-
ngOnDestroy() {
|
|
1305
|
-
this._syncSub.destroy();
|
|
1306
|
-
this._valueSub.destroy();
|
|
1307
|
-
}
|
|
1308
1301
|
clickedDateRangeInput() {
|
|
1309
1302
|
if (this.openPickerOnTextClick()) {
|
|
1310
1303
|
const picker = this.picker();
|
|
@@ -1583,7 +1576,7 @@ class DbxScheduleSelectionCalendarComponent {
|
|
|
1583
1576
|
clickEvent = output();
|
|
1584
1577
|
config = input(...(ngDevMode ? [undefined, { debugName: "config" }] : /* istanbul ignore next */ []));
|
|
1585
1578
|
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
1586
|
-
_centerRangeSub =
|
|
1579
|
+
_centerRangeSub = cleanSubscription();
|
|
1587
1580
|
config$ = toObservable(this.config).pipe(distinctUntilChanged(), shareReplay(1));
|
|
1588
1581
|
readonly$ = this.config$.pipe(switchMap((x) => (x?.readonly != null ? asObservableFromGetter(x.readonly) : of(undefined))), combineLatestWith(toObservable(this.readonly)), map(([configReadonly, inputReadonly]) => {
|
|
1589
1582
|
return configReadonly || inputReadonly || false;
|
|
@@ -1650,9 +1643,6 @@ class DbxScheduleSelectionCalendarComponent {
|
|
|
1650
1643
|
}
|
|
1651
1644
|
});
|
|
1652
1645
|
}
|
|
1653
|
-
ngOnDestroy() {
|
|
1654
|
-
this._centerRangeSub.destroy();
|
|
1655
|
-
}
|
|
1656
1646
|
dayClicked({ date }) {
|
|
1657
1647
|
if (!this.readonlySignal()) {
|
|
1658
1648
|
this.dbxCalendarScheduleSelectionStore.toggleSelectedDates(date);
|
|
@@ -1758,14 +1748,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
|
|
|
1758
1748
|
class DbxFormCalendarDateScheduleRangeFieldComponent extends FieldType {
|
|
1759
1749
|
compact = inject(CompactContextStore, { optional: true });
|
|
1760
1750
|
dbxCalendarScheduleSelectionStore = inject(DbxCalendarScheduleSelectionStore);
|
|
1761
|
-
_syncSub =
|
|
1762
|
-
_valueSub =
|
|
1763
|
-
_timezoneSub =
|
|
1764
|
-
_minMaxDateRangeSub =
|
|
1765
|
-
_defaultWeekSub =
|
|
1766
|
-
_filterSub =
|
|
1767
|
-
_exclusionsSub =
|
|
1768
|
-
_formControlObs = new BehaviorSubject(undefined);
|
|
1751
|
+
_syncSub = cleanSubscription();
|
|
1752
|
+
_valueSub = cleanSubscription();
|
|
1753
|
+
_timezoneSub = cleanSubscription();
|
|
1754
|
+
_minMaxDateRangeSub = cleanSubscription();
|
|
1755
|
+
_defaultWeekSub = cleanSubscription();
|
|
1756
|
+
_filterSub = cleanSubscription();
|
|
1757
|
+
_exclusionsSub = cleanSubscription();
|
|
1758
|
+
_formControlObs = completeOnDestroy(new BehaviorSubject(undefined));
|
|
1769
1759
|
formControl$ = this._formControlObs.pipe(filterMaybe());
|
|
1770
1760
|
value$ = this.formControl$.pipe(switchMap((control) => control.valueChanges.pipe(startWith(control.value))), shareReplay(1));
|
|
1771
1761
|
disableCustomize$ = this.value$.pipe(map((x) => (this.allowCustomizeWithoutDateRange ? false : !x)), distinctUntilChanged(), shareReplay(1));
|
|
@@ -1860,13 +1850,6 @@ class DbxFormCalendarDateScheduleRangeFieldComponent extends FieldType {
|
|
|
1860
1850
|
}
|
|
1861
1851
|
ngOnDestroy() {
|
|
1862
1852
|
super.ngOnDestroy();
|
|
1863
|
-
this._syncSub.destroy();
|
|
1864
|
-
this._valueSub.destroy();
|
|
1865
|
-
this._filterSub.destroy();
|
|
1866
|
-
this._timezoneSub.destroy();
|
|
1867
|
-
this._minMaxDateRangeSub.destroy();
|
|
1868
|
-
this._exclusionsSub.destroy();
|
|
1869
|
-
this._formControlObs.complete();
|
|
1870
1853
|
}
|
|
1871
1854
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: DbxFormCalendarDateScheduleRangeFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
1872
1855
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.10", type: DbxFormCalendarDateScheduleRangeFieldComponent, isStandalone: true, selector: "ng-component", providers: [provideCalendarScheduleSelectionStoreIfParentIsUnavailable()], usesInheritance: true, ngImport: i0, template: `
|
|
@@ -1987,13 +1970,13 @@ class DbxForgeCalendarDateScheduleRangeFieldComponent {
|
|
|
1987
1970
|
validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : /* istanbul ignore next */ []));
|
|
1988
1971
|
defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : /* istanbul ignore next */ []));
|
|
1989
1972
|
// Subscription management
|
|
1990
|
-
_syncSub =
|
|
1991
|
-
_valueSub =
|
|
1992
|
-
_timezoneSub =
|
|
1993
|
-
_minMaxDateRangeSub =
|
|
1994
|
-
_defaultWeekSub =
|
|
1995
|
-
_filterSub =
|
|
1996
|
-
_exclusionsSub =
|
|
1973
|
+
_syncSub = cleanSubscription();
|
|
1974
|
+
_valueSub = cleanSubscription();
|
|
1975
|
+
_timezoneSub = cleanSubscription();
|
|
1976
|
+
_minMaxDateRangeSub = cleanSubscription();
|
|
1977
|
+
_defaultWeekSub = cleanSubscription();
|
|
1978
|
+
_filterSub = cleanSubscription();
|
|
1979
|
+
_exclusionsSub = cleanSubscription();
|
|
1997
1980
|
// Field value signal (double-call pattern: field()() to get FieldState)
|
|
1998
1981
|
fieldValue = computed(() => {
|
|
1999
1982
|
const state = this.field()?.();
|
|
@@ -2080,15 +2063,6 @@ class DbxForgeCalendarDateScheduleRangeFieldComponent {
|
|
|
2080
2063
|
}
|
|
2081
2064
|
});
|
|
2082
2065
|
}
|
|
2083
|
-
ngOnDestroy() {
|
|
2084
|
-
this._syncSub.destroy();
|
|
2085
|
-
this._valueSub.destroy();
|
|
2086
|
-
this._filterSub.destroy();
|
|
2087
|
-
this._timezoneSub.destroy();
|
|
2088
|
-
this._minMaxDateRangeSub.destroy();
|
|
2089
|
-
this._defaultWeekSub.destroy();
|
|
2090
|
-
this._exclusionsSub.destroy();
|
|
2091
|
-
}
|
|
2092
2066
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: DbxForgeCalendarDateScheduleRangeFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2093
2067
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.10", type: DbxForgeCalendarDateScheduleRangeFieldComponent, isStandalone: true, selector: "dbx-forge-calendar-date-schedule-range-field", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, meta: { classPropertyName: "meta", publicName: "meta", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideCalendarScheduleSelectionStoreIfParentIsUnavailable()], ngImport: i0, template: `
|
|
2094
2068
|
<div class="dbx-schedule-selection-field">
|