@dereekb/dbx-form 13.6.11 → 13.6.13

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,14 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { forwardRef, inject, input, Directive, effect, Injectable, viewChild, signal, computed, ChangeDetectionStrategy, Component, output, NgModule, InjectionToken, ElementRef, importProvidersFrom, makeEnvironmentProviders } from '@angular/core';
3
3
  import * as i1$2 from '@dereekb/dbx-web';
4
- import { DbxActionTransitionSafetyDirective, AbstractDialogDirective, DbxDialogContentDirective, DbxActionModule, DbxButtonModule, DbxDialogContentCloseComponent, DbxAnchorComponent, DbxSectionLayoutModule, DbxFlexGroupDirective, DbxSubSectionComponent, DbxLoadingComponent, dbxValueListItemDecisionFunction, DbxListModifierModule, AbstractDbxSelectionListWrapperDirective, DbxListWrapperComponentImportsModule, provideDbxListViewWrapper, DEFAULT_LIST_WRAPPER_COMPONENT_CONFIGURATION_TEMPLATE, AbstractDbxSelectionListViewDirective, addConfigToValueListItems, DbxSelectionValueListViewContentComponent, provideDbxListView, AbstractDbxValueListViewItemComponent, DbxLoadingModule, DbxButtonComponent, DbxButtonSpacerDirective, CompactContextStore, mapCompactModeObs, DbxBarDirective } from '@dereekb/dbx-web';
4
+ import { DbxActionTransitionSafetyDirective, AbstractDialogDirective, DbxDialogContentDirective, DbxActionModule, DbxButtonModule, DbxDialogContentCloseComponent, DbxAnchorComponent, DbxSectionLayoutModule, DbxFlexGroupDirective, DbxSubSectionComponent, DbxLoadingComponent, dbxValueListItemDecisionFunction, DbxListModifierModule, AbstractDbxSelectionListWrapperDirective, DbxListWrapperComponentImportsModule, provideDbxListViewWrapper, DEFAULT_LIST_WRAPPER_COMPONENT_CONFIGURATION_TEMPLATE, AbstractDbxSelectionListViewDirective, addConfigToValueListItems, DbxSelectionValueListViewContentComponent, provideDbxListView, AbstractDbxValueListViewItemComponent, DbxLoadingModule, DbxButtonComponent, DbxButtonSpacerDirective, CompactContextStore, mapCompactModeObs, DbxBarDirective, AbstractPopoverDirective, DbxPopoverService } from '@dereekb/dbx-web';
5
5
  import { isPast, addSeconds, startOfDay, addMinutes, addDays, isBefore } from 'date-fns';
6
6
  import { map, of, shareReplay, switchMap, first, exhaustMap, catchError, delay, filter, combineLatest, distinctUntilChanged, BehaviorSubject, Subject, startWith, throttleTime, scan, timer, merge, EMPTY, mergeMap, debounceTime, tap, skip, combineLatestWith, interval } from 'rxjs';
7
7
  import * as i2 from '@dereekb/dbx-core';
8
8
  import { DbxActionContextStoreSourceInstance, cleanLockSet, cleanWithLockSet, cleanSubscription, DbxInjectionComponent, mergeDbxInjectionComponentConfigs, GetValuePipe, DateDistancePipe, TimeDistancePipe } from '@dereekb/dbx-core';
9
9
  import { makeIsModifiedFunctionObservable, SubscriptionObject, asObservable, LockSet, filterMaybe, switchMapFilterMaybe, scanCount, errorOnEmissionsInPeriod, asObservableFromGetter, maybeValueFromObservableOrValue, valueFromFinishedLoadingState, switchMapMaybeDefault, SimpleLoadingContext, distinctUntilHasDifferentValues, startWithBeginLoading, mapLoadingStateResults, successResult, listLoadingStateContext, mapIsListLoadingStateWithEmptyValue, isLoadingStateInLoadingState, skipUntilTimeElapsedAfterLastEmission, isLoadingStateWithDefinedValue, isLoadingStateLoading, beginLoading, mapLoadingStateValueWithOperator, loadingStateContext, skipAllInitialMaybe, asyncPusherCache } from '@dereekb/rxjs';
10
10
  import { toObservable, toSignal } from '@angular/core/rxjs-interop';
11
- import { BooleanStringKeyArrayUtility, iterablesAreSetEquivalent, objectIsEmpty, mergeObjectsFunction, filterFromPOJOFunction, mergeObjects, filterFromPOJO, asArray, objectHasNoKeys, addPlusPrefixToNumber, convertMaybeToArray, isSelectedDecisionFunctionFactory, readKeysFrom, hasDifferentValues, makeValuesGroupMap, separateValues, filterUniqueValues, searchStringFilterFunction, caseInsensitiveFilterByIndexOfDecisionFactory, sortByStringFunction, mergeArraysIntoArray, lastValue, arrayToMap, setContainsAllValues, addToSetCopy, setsAreEquivalent, filterMaybeArrayValues, mergeArrays, firstValue, cachedGetter, makeGetter, asDecisionFunction, getValueFromGetter, asGetter, dateFromMinuteOfDay, dateToMinuteOfDay, isISO8601DayStringStart, mapIdentityFunction, MS_IN_MINUTE, isMonthDaySlashDate, HAS_WEBSITE_DOMAIN_NAME_REGEX, KeyValueTypleValueFilter, valuesFromPOJO, allObjectsAreEqual, isNumberDivisibleBy, nearestDivisibleValues, isE164PhoneNumber as isE164PhoneNumber$1, isValidPhoneExtensionNumber, e164PhoneNumberExtensionPair, isWebsiteUrlWithPrefix, websiteUrlDetails, mapMaybeFunction, transformNumberFunction, concatArrays, DOLLAR_AMOUNT_PRECISION, e164PhoneNumberFromE164PhoneNumberExtensionPair, transformStringFunction, US_STATE_CODE_STRING_REGEX, ZIP_CODE_STRING_REGEX, LAT_LNG_PATTERN, capitalizeFirstLetter } from '@dereekb/util';
11
+ import { BooleanStringKeyArrayUtility, iterablesAreSetEquivalent, objectIsEmpty, mergeObjectsFunction, filterFromPOJOFunction, mergeObjects, filterFromPOJO, asArray, objectHasNoKeys, addPlusPrefixToNumber, convertMaybeToArray, isSelectedDecisionFunctionFactory, readKeysFrom, hasDifferentValues, makeValuesGroupMap, separateValues, filterUniqueValues, searchStringFilterFunction, caseInsensitiveFilterByIndexOfDecisionFactory, sortByStringFunction, mergeArraysIntoArray, lastValue, arrayToMap, setContainsAllValues, addToSetCopy, setsAreEquivalent, filterMaybeArrayValues, mergeArrays, firstValue, cachedGetter, makeGetter, asDecisionFunction, getValueFromGetter, asGetter, dateFromMinuteOfDay, dateToMinuteOfDay, isISO8601DayStringStart, mapIdentityFunction, MS_IN_MINUTE, isMonthDaySlashDate, millisecondsToTimeUnit, hoursAndMinutesToTimeUnit, TIME_UNIT_LABEL_MAP, TIME_UNIT_SHORT_LABEL_MAP, timeUnitToMilliseconds, ALL_TIME_UNITS, minutesToHoursAndMinutes, HAS_WEBSITE_DOMAIN_NAME_REGEX, KeyValueTypleValueFilter, valuesFromPOJO, allObjectsAreEqual, isNumberDivisibleBy, nearestDivisibleValues, isE164PhoneNumber as isE164PhoneNumber$1, isValidPhoneExtensionNumber, e164PhoneNumberExtensionPair, isWebsiteUrlWithPrefix, websiteUrlDetails, mapMaybeFunction, transformNumberFunction, concatArrays, DOLLAR_AMOUNT_PRECISION, e164PhoneNumberFromE164PhoneNumberExtensionPair, transformStringFunction, US_STATE_CODE_STRING_REGEX, ZIP_CODE_STRING_REGEX, LAT_LNG_PATTERN, capitalizeFirstLetter } from '@dereekb/util';
12
12
  import * as i1 from '@angular/forms';
13
13
  import { FormGroup, FormsModule, ReactiveFormsModule, FormControl, Validators } from '@angular/forms';
14
14
  import * as i1$1 from '@ngx-formly/core';
@@ -43,7 +43,7 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
43
43
  import { MatFormFieldModule, MatError, MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
44
44
  import { FormlyMatCheckboxModule } from '@ngx-formly/material/checkbox';
45
45
  import { FormlyMatToggleModule } from '@ngx-formly/material/toggle';
46
- import { toJsDate, parseJsDateString, parseISO8601DayStringToDate, formatToISO8601DateString, formatToISO8601DayStringForSystem, isSameDateHoursAndMinutes, safeToJsDate, guessCurrentTimezone, dateTimezoneUtcNormal, toJsDayDate, isSameDateDay, toLocalReadableTimeString, getTimezoneAbbreviation, utcDayForDate, readableTimeStringToDate, findMinDate, dateFromLogicalDate, findMaxDate, isSameDate, dateTimeMinuteWholeDayDecisionFunction, DateTimeMinuteInstance, dateTimeMinuteDecisionFunction, limitDateTimeInstance, isSameDateDayRange, dateRange, clampDateRangeToDateRange, isDateInDateRange, isSameDateRange, allTimezoneInfos, timezoneInfoForSystem, searchTimezoneInfos } from '@dereekb/date';
46
+ import { toJsDate, parseJsDateString, parseISO8601DayStringToDate, formatToISO8601DateString, formatToISO8601DayStringForSystem, isSameDateHoursAndMinutes, safeToJsDate, guessCurrentTimezone, dateTimezoneUtcNormal, toJsDayDate, isSameDateDay, toLocalReadableTimeString, getTimezoneAbbreviation, utcDayForDate, readableTimeStringToDate, findMinDate, dateFromLogicalDate, findMaxDate, isSameDate, dateTimeMinuteWholeDayDecisionFunction, DateTimeMinuteInstance, dateTimeMinuteDecisionFunction, limitDateTimeInstance, isSameDateDayRange, dateRange, clampDateRangeToDateRange, isDateInDateRange, isSameDateRange, durationDataToMilliseconds, getDurationDataValue, setDurationDataValue, millisecondsToDurationData, formatDurationString, parseDurationString, allTimezoneInfos, timezoneInfoForSystem, searchTimezoneInfos } from '@dereekb/date';
47
47
  import * as i1$7 from '@angular/material/datepicker';
48
48
  import { MatDatepickerModule, MatCalendar, DateRange, MAT_DATE_RANGE_SELECTION_STRATEGY } from '@angular/material/datepicker';
49
49
  import { FlexLayoutModule } from '@ngbracket/ngx-layout';
@@ -1018,15 +1018,43 @@ const INVALID_PHONE_NUMBER_MESSAGE = { name: 'validatePhoneNumber', message: 'Th
1018
1018
  * Validation message option for invalid phone number extensions.
1019
1019
  */
1020
1020
  const INVALID_PHONE_NUMBER_EXTENSION_MESSAGE = { name: 'validatePhoneNumberExtension', message: 'This is not a valid phone number extension.' };
1021
+ /**
1022
+ * Returns a validation message indicating the duration is below the minimum allowed.
1023
+ *
1024
+ * @param err - The validation error object containing `min` and `actual` values.
1025
+ * @param field - The Formly field configuration.
1026
+ * @returns A human-readable validation message string.
1027
+ */
1028
+ function durationMinValidationMessage(err, field) {
1029
+ return `Duration must be at least ${err.min} ${err.unit} (currently ${err.actual} ${err.unit}).`;
1030
+ }
1031
+ /**
1032
+ * Returns a validation message indicating the duration exceeds the maximum allowed.
1033
+ *
1034
+ * @param err - The validation error object containing `max`, `actual`, and `unit` values.
1035
+ * @param field - The Formly field configuration.
1036
+ * @returns A human-readable validation message string.
1037
+ */
1038
+ function durationMaxValidationMessage(err, field) {
1039
+ return `Duration must be at most ${err.max} ${err.unit} (currently ${err.actual} ${err.unit}).`;
1040
+ }
1041
+ /**
1042
+ * Validation message option for duration minimum violations.
1043
+ */
1044
+ const DURATION_MIN_VALIDATION_MESSAGE = { name: 'durationMin', message: durationMinValidationMessage };
1045
+ /**
1046
+ * Validation message option for duration maximum violations.
1047
+ */
1048
+ const DURATION_MAX_VALIDATION_MESSAGE = { name: 'durationMax', message: durationMaxValidationMessage };
1021
1049
  /**
1022
1050
  * Returns the full set of default validation messages used by the form system.
1023
1051
  *
1024
- * Includes messages for: required, minLength, maxLength, min, max, phone number, and phone number extension.
1052
+ * Includes messages for: required, minLength, maxLength, min, max, phone number, phone number extension, and duration min/max.
1025
1053
  *
1026
1054
  * @returns An array of {@link ValidationMessageOption} objects.
1027
1055
  */
1028
1056
  function defaultValidationMessages() {
1029
- return [REQUIRED_VALIDATION_MESSAGE, MIN_LENGTH_VALIDATION_MESSAGE, MAX_LENGTH_VALIDATION_MESSAGE, MIN_VALIDATION_MESSAGE, MAX_VALIDATION_MESSAGE, INVALID_PHONE_NUMBER_MESSAGE, INVALID_PHONE_NUMBER_EXTENSION_MESSAGE];
1057
+ return [REQUIRED_VALIDATION_MESSAGE, MIN_LENGTH_VALIDATION_MESSAGE, MAX_LENGTH_VALIDATION_MESSAGE, MIN_VALIDATION_MESSAGE, MAX_VALIDATION_MESSAGE, INVALID_PHONE_NUMBER_MESSAGE, INVALID_PHONE_NUMBER_EXTENSION_MESSAGE, DURATION_MIN_VALIDATION_MESSAGE, DURATION_MAX_VALIDATION_MESSAGE];
1030
1058
  }
1031
1059
 
1032
1060
  // MARK: Default
@@ -1633,7 +1661,7 @@ const WORKING_WRAPPER_KEY = 'working';
1633
1661
  */
1634
1662
  const EXPAND_WRAPPER_KEY = 'expand';
1635
1663
 
1636
- const importsAndExports$g = [
1664
+ const importsAndExports$h = [
1637
1665
  AutoTouchFieldWrapperComponent,
1638
1666
  DbxFormSectionWrapperComponent,
1639
1667
  DbxFormSubsectionWrapperComponent,
@@ -1703,7 +1731,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
1703
1731
  type: NgModule,
1704
1732
  args: [{
1705
1733
  imports: [
1706
- ...importsAndExports$g,
1734
+ ...importsAndExports$h,
1707
1735
  FormlyModule.forChild({
1708
1736
  wrappers: [
1709
1737
  { name: AUTO_TOUCH_WRAPPER_KEY, component: AutoTouchFieldWrapperComponent },
@@ -1718,11 +1746,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
1718
1746
  ]
1719
1747
  })
1720
1748
  ],
1721
- exports: importsAndExports$g
1749
+ exports: importsAndExports$h
1722
1750
  }]
1723
1751
  }] });
1724
1752
 
1725
- const importsAndExports$f = [DbxChecklistItemFieldComponent, DbxChecklistItemContentComponent, DbxDefaultChecklistItemFieldDisplayComponent];
1753
+ const importsAndExports$g = [DbxChecklistItemFieldComponent, DbxChecklistItemContentComponent, DbxDefaultChecklistItemFieldDisplayComponent];
1726
1754
  /**
1727
1755
  * Registers the `checklistitem` Formly field type with wrapper support.
1728
1756
  */
@@ -1738,13 +1766,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
1738
1766
  type: NgModule,
1739
1767
  args: [{
1740
1768
  imports: [
1741
- ...importsAndExports$f,
1769
+ ...importsAndExports$g,
1742
1770
  DbxFormFormlyWrapperModule,
1743
1771
  FormlyModule.forChild({
1744
1772
  types: [{ name: 'checklistitem', component: DbxChecklistItemFieldComponent }]
1745
1773
  })
1746
1774
  ],
1747
- exports: importsAndExports$f
1775
+ exports: importsAndExports$g
1748
1776
  }]
1749
1777
  }] });
1750
1778
 
@@ -2047,14 +2075,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
2047
2075
  }]
2048
2076
  }] });
2049
2077
 
2050
- const importsAndExports$e = [DbxFormComponentFieldComponent];
2078
+ const importsAndExports$f = [DbxFormComponentFieldComponent];
2051
2079
  /**
2052
2080
  * Registers the `component` Formly field type for custom Angular component injection.
2053
2081
  */
2054
2082
  class DbxFormFormlyComponentFieldModule {
2055
2083
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyComponentFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2056
2084
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyComponentFieldModule, imports: [DbxFormComponentFieldComponent, i1$1.FormlyModule], exports: [DbxFormComponentFieldComponent] });
2057
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyComponentFieldModule, imports: [importsAndExports$e, FormlyModule.forChild({
2085
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyComponentFieldModule, imports: [importsAndExports$f, FormlyModule.forChild({
2058
2086
  types: [{ name: 'component', component: DbxFormComponentFieldComponent }]
2059
2087
  })] });
2060
2088
  }
@@ -2062,12 +2090,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
2062
2090
  type: NgModule,
2063
2091
  args: [{
2064
2092
  imports: [
2065
- ...importsAndExports$e,
2093
+ ...importsAndExports$f,
2066
2094
  FormlyModule.forChild({
2067
2095
  types: [{ name: 'component', component: DbxFormComponentFieldComponent }]
2068
2096
  })
2069
2097
  ],
2070
- exports: importsAndExports$e
2098
+ exports: importsAndExports$f
2071
2099
  }]
2072
2100
  }] });
2073
2101
 
@@ -2200,14 +2228,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
2200
2228
  args: [{ imports: [DbxListModifierModule, DbxInjectionComponent, MatDividerModule], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-list-item-field\" dbxListItemModifier [dbxListItemIsSelectedModifier]=\"isSelectedModifierFunctionSignal()\">\n @if (label) {\n <span class=\"dbx-label dbx-label-padded\">{{ label }}</span>\n }\n <div class=\"dbx-list-item-field-content\">\n <dbx-injection [config]=\"configSignal()\"></dbx-injection>\n </div>\n <mat-divider></mat-divider>\n @if (description) {\n <div class=\"dbx-form-description\">{{ description }}</div>\n }\n</div>\n" }]
2201
2229
  }] });
2202
2230
 
2203
- const importsAndExports$d = [DbxItemListFieldComponent];
2231
+ const importsAndExports$e = [DbxItemListFieldComponent];
2204
2232
  /**
2205
2233
  * Registers the `dbxlistfield` Formly field type for item list selection.
2206
2234
  */
2207
2235
  class DbxFormFormlyDbxListFieldModule {
2208
2236
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDbxListFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2209
2237
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDbxListFieldModule, imports: [DbxItemListFieldComponent, i1$1.FormlyModule], exports: [DbxItemListFieldComponent] });
2210
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDbxListFieldModule, imports: [importsAndExports$d, FormlyModule.forChild({
2238
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDbxListFieldModule, imports: [importsAndExports$e, FormlyModule.forChild({
2211
2239
  types: [{ name: 'dbxlistfield', component: DbxItemListFieldComponent }]
2212
2240
  })] });
2213
2241
  }
@@ -2215,12 +2243,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
2215
2243
  type: NgModule,
2216
2244
  args: [{
2217
2245
  imports: [
2218
- ...importsAndExports$d,
2246
+ ...importsAndExports$e,
2219
2247
  FormlyModule.forChild({
2220
2248
  types: [{ name: 'dbxlistfield', component: DbxItemListFieldComponent }]
2221
2249
  })
2222
2250
  ],
2223
- exports: importsAndExports$d
2251
+ exports: importsAndExports$e
2224
2252
  }]
2225
2253
  }] });
2226
2254
 
@@ -2669,14 +2697,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
2669
2697
  args: [{ imports: [DbxPickableListFieldItemListComponent, NgTemplateOutlet, FormsModule, ReactiveFormsModule, MatInputModule, MatDivider, DbxLoadingComponent, DbxInjectionComponent], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-pickable-item-field\">\n <dbx-loading [context]=\"context\">\n @if (showFilterInput) {\n <ng-container *ngTemplateOutlet=\"filterTemplate\"></ng-container>\n }\n <!-- Content -->\n <div class=\"dbx-pickable-item-field-list\">\n <div class=\"dbx-pickable-item-field-list-content\">\n <dbx-form-pickable-item-field-item-list [disabled]=\"isReadonlyOrDisabled\" [state]=\"filterItemsLoadingState$\" (selectionChange)=\"onSelectionChange($event)\"></dbx-form-pickable-item-field-item-list>\n </div>\n <dbx-injection [config]=\"footerConfig\"></dbx-injection>\n </div>\n </dbx-loading>\n</div>\n\n<!-- Filter Input -->\n<ng-template #filterTemplate>\n <div class=\"dbx-pickable-item-field-filter\">\n <div class=\"dbx-label\">{{ filterLabel }}</div>\n <input [name]=\"name\" autocomplete=\"{{ autocomplete }}\" #filterMatInput=\"matInput\" matInput [placeholder]=\"placeholder\" [formControl]=\"inputCtrl\" [attr.aria-label]=\"filterLabel || 'Filter items'\" />\n <mat-divider></mat-divider>\n <dbx-loading [linear]=\"true\" [context]=\"filterResultsContext\"></dbx-loading>\n <!-- No items found. -->\n @if (noItemsAvailableSignal()) {\n <p class=\"dbx-label\" role=\"status\">No items match this filter.</p>\n }\n </div>\n</ng-template>\n" }]
2670
2698
  }] });
2671
2699
 
2672
- const importsAndExports$c = [DbxPickableChipListFieldComponent, DbxPickableListFieldComponent, DbxPickableListFieldItemListComponent, DbxPickableListFieldItemListViewComponent, DbxPickableListFieldItemListViewItemComponent];
2700
+ const importsAndExports$d = [DbxPickableChipListFieldComponent, DbxPickableListFieldComponent, DbxPickableListFieldItemListComponent, DbxPickableListFieldItemListViewComponent, DbxPickableListFieldItemListViewItemComponent];
2673
2701
  /**
2674
2702
  * Registers the `pickablechipfield` and `pickablelistfield` Formly field types.
2675
2703
  */
2676
2704
  class DbxFormFormlyPickableFieldModule {
2677
2705
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyPickableFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2678
2706
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyPickableFieldModule, imports: [DbxPickableChipListFieldComponent, DbxPickableListFieldComponent, DbxPickableListFieldItemListComponent, DbxPickableListFieldItemListViewComponent, DbxPickableListFieldItemListViewItemComponent, i1$1.FormlyModule], exports: [DbxPickableChipListFieldComponent, DbxPickableListFieldComponent, DbxPickableListFieldItemListComponent, DbxPickableListFieldItemListViewComponent, DbxPickableListFieldItemListViewItemComponent] });
2679
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyPickableFieldModule, imports: [importsAndExports$c, FormlyModule.forChild({
2707
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyPickableFieldModule, imports: [importsAndExports$d, FormlyModule.forChild({
2680
2708
  types: [
2681
2709
  { name: 'pickablechipfield', component: DbxPickableChipListFieldComponent, wrappers: ['form-field'] },
2682
2710
  { name: 'pickablelistfield', component: DbxPickableListFieldComponent, wrappers: ['form-field'] }
@@ -2687,7 +2715,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
2687
2715
  type: NgModule,
2688
2716
  args: [{
2689
2717
  imports: [
2690
- ...importsAndExports$c,
2718
+ ...importsAndExports$d,
2691
2719
  FormlyModule.forChild({
2692
2720
  types: [
2693
2721
  { name: 'pickablechipfield', component: DbxPickableChipListFieldComponent, wrappers: ['form-field'] },
@@ -2695,7 +2723,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
2695
2723
  ]
2696
2724
  })
2697
2725
  ],
2698
- exports: importsAndExports$c
2726
+ exports: importsAndExports$d
2699
2727
  }]
2700
2728
  }] });
2701
2729
 
@@ -3442,14 +3470,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
3442
3470
  args: [{ imports: [FormsModule, MatInput, NgClass, ReactiveFormsModule, DbxLoadingModule, MatOptionModule, MatAutocompleteModule, MatChipsModule, MatIconModule, DbxSearchableFieldAutocompleteItemComponent], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-searchable-text-field\" [ngClass]=\"{ 'dbx-searchable-text-field-has-value': hasValueSignal(), 'dbx-searchable-text-field-show-value': showSelectedValue }\">\n <!-- Result View -->\n @if (showSelectedDisplayValueSignal()) {\n <div class=\"dbx-searchable-text-field-value mat-option mat-option-text\">\n <dbx-searchable-field-autocomplete-item [displayValue]=\"selectedDisplayValueSignal()!\"></dbx-searchable-field-autocomplete-item>\n </div>\n }\n <div class=\"dbx-searchable-text-field-input\">\n @if (searchLabel) {\n <div class=\"dbx-label\">{{ searchLabel }}</div>\n }\n <!-- View -->\n <input type=\"search\" [name]=\"name\" matInput #textInput [placeholder]=\"searchInputPlaceholder\" [formControl]=\"inputCtrl\" [matAutocomplete]=\"auto\" [matAutocompleteDisabled]=\"readonly || disabled\" autocomplete=\"{{ autocomplete }}\" [attr.aria-label]=\"searchLabel || searchInputPlaceholder || 'Search'\" />\n <div class=\"searchable-field-form-loading\">\n <dbx-loading [linear]=\"true\" [context]=\"searchContext\"></dbx-loading>\n </div>\n </div>\n</div>\n\n<!-- Autocomplete -->\n<mat-autocomplete class=\"dbx-searchable-text-field-autocomplete\" #auto (optionSelected)=\"selected($event)\">\n @for (displayValue of searchResultsSignal(); track displayValue.value) {\n <mat-option [value]=\"displayValue\">\n <dbx-searchable-field-autocomplete-item [displayValue]=\"displayValue\"></dbx-searchable-field-autocomplete-item>\n </mat-option>\n }\n <!-- If No Results -->\n @if (searchResultsSignal()?.length === 0) {\n @if (!isLoadingSearchResultsSignal()) {\n <mat-option value=\"\" disabled>\n <p class=\"dbx-clear-hint text-center\">No results found.</p>\n </mat-option>\n } @else {\n <mat-option value=\"\" disabled>\n <p class=\"dbx-clear-hint text-center\">Loading...</p>\n </mat-option>\n }\n }\n <!-- Add/Pick String Value -->\n @if (allowStringValues && inputValueSignal()) {\n <mat-option [value]=\"{ value: inputValueSignal() }\">\n <p class=\"dbx-clear-hint text-center\">\"{{ inputValueSignal() }}\"</p>\n </mat-option>\n }\n <!-- Show clear value -->\n @if (showClearValue && hasValueSignal()) {\n <mat-option value=\"\">\n <p class=\"dbx-clear-hint text-center\">Clear</p>\n </mat-option>\n }\n</mat-autocomplete>\n" }]
3443
3471
  }] });
3444
3472
 
3445
- const importsAndExports$b = [DbxSearchableChipFieldComponent, DbxSearchableTextFieldComponent, DbxSearchableFieldAutocompleteItemComponent, DbxDefaultSearchableFieldDisplayComponent];
3473
+ const importsAndExports$c = [DbxSearchableChipFieldComponent, DbxSearchableTextFieldComponent, DbxSearchableFieldAutocompleteItemComponent, DbxDefaultSearchableFieldDisplayComponent];
3446
3474
  /**
3447
3475
  * Registers the `searchablechipfield` and `searchabletextfield` Formly field types.
3448
3476
  */
3449
3477
  class DbxFormFormlySearchableFieldModule {
3450
3478
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlySearchableFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3451
3479
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlySearchableFieldModule, imports: [DbxSearchableChipFieldComponent, DbxSearchableTextFieldComponent, DbxSearchableFieldAutocompleteItemComponent, DbxDefaultSearchableFieldDisplayComponent, i1$1.FormlyModule], exports: [DbxSearchableChipFieldComponent, DbxSearchableTextFieldComponent, DbxSearchableFieldAutocompleteItemComponent, DbxDefaultSearchableFieldDisplayComponent] });
3452
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlySearchableFieldModule, imports: [importsAndExports$b, FormlyModule.forChild({
3480
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlySearchableFieldModule, imports: [importsAndExports$c, FormlyModule.forChild({
3453
3481
  types: [
3454
3482
  { name: 'searchablechipfield', component: DbxSearchableChipFieldComponent, wrappers: ['form-field'] },
3455
3483
  { name: 'searchabletextfield', component: DbxSearchableTextFieldComponent, wrappers: ['form-field'] }
@@ -3460,7 +3488,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
3460
3488
  type: NgModule,
3461
3489
  args: [{
3462
3490
  imports: [
3463
- ...importsAndExports$b,
3491
+ ...importsAndExports$c,
3464
3492
  FormlyModule.forChild({
3465
3493
  types: [
3466
3494
  { name: 'searchablechipfield', component: DbxSearchableChipFieldComponent, wrappers: ['form-field'] },
@@ -3468,7 +3496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
3468
3496
  ]
3469
3497
  })
3470
3498
  ],
3471
- exports: importsAndExports$b
3499
+ exports: importsAndExports$c
3472
3500
  }]
3473
3501
  }] });
3474
3502
 
@@ -4074,14 +4102,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
4074
4102
  }]
4075
4103
  }] });
4076
4104
 
4077
- const importsAndExports$a = [DbxTextEditorFieldComponent];
4105
+ const importsAndExports$b = [DbxTextEditorFieldComponent];
4078
4106
  /**
4079
4107
  * Registers the `texteditor` Formly field type for rich text editing.
4080
4108
  */
4081
4109
  class DbxFormFormlyTextEditorFieldModule {
4082
4110
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyTextEditorFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
4083
4111
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyTextEditorFieldModule, imports: [DbxTextEditorFieldComponent, i1$1.FormlyModule], exports: [DbxTextEditorFieldComponent] });
4084
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyTextEditorFieldModule, imports: [importsAndExports$a, FormlyModule.forChild({
4112
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyTextEditorFieldModule, imports: [importsAndExports$b, FormlyModule.forChild({
4085
4113
  types: [{ name: 'texteditor', component: DbxTextEditorFieldComponent }]
4086
4114
  })] });
4087
4115
  }
@@ -4089,12 +4117,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
4089
4117
  type: NgModule,
4090
4118
  args: [{
4091
4119
  imports: [
4092
- ...importsAndExports$a,
4120
+ ...importsAndExports$b,
4093
4121
  FormlyModule.forChild({
4094
4122
  types: [{ name: 'texteditor', component: DbxTextEditorFieldComponent }]
4095
4123
  })
4096
4124
  ],
4097
- exports: importsAndExports$a
4125
+ exports: importsAndExports$b
4098
4126
  }]
4099
4127
  }] });
4100
4128
 
@@ -4358,14 +4386,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
4358
4386
  }]
4359
4387
  }] });
4360
4388
 
4361
- const importsAndExports$9 = [DbxFormRepeatArrayTypeComponent];
4389
+ const importsAndExports$a = [DbxFormRepeatArrayTypeComponent];
4362
4390
  /**
4363
4391
  * Registers the `repeatarray` Formly field type for dynamic array fields.
4364
4392
  */
4365
4393
  class DbxFormFormlyArrayFieldModule {
4366
4394
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyArrayFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
4367
4395
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyArrayFieldModule, imports: [DbxFormRepeatArrayTypeComponent, i1$1.FormlyModule], exports: [DbxFormRepeatArrayTypeComponent] });
4368
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyArrayFieldModule, imports: [importsAndExports$9, FormlyModule.forChild({
4396
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyArrayFieldModule, imports: [importsAndExports$a, FormlyModule.forChild({
4369
4397
  types: [{ name: 'repeatarray', component: DbxFormRepeatArrayTypeComponent }]
4370
4398
  })] });
4371
4399
  }
@@ -4373,12 +4401,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
4373
4401
  type: NgModule,
4374
4402
  args: [{
4375
4403
  imports: [
4376
- ...importsAndExports$9,
4404
+ ...importsAndExports$a,
4377
4405
  FormlyModule.forChild({
4378
4406
  types: [{ name: 'repeatarray', component: DbxFormRepeatArrayTypeComponent }]
4379
4407
  })
4380
4408
  ],
4381
- exports: importsAndExports$9
4409
+ exports: importsAndExports$a
4382
4410
  }]
4383
4411
  }] });
4384
4412
 
@@ -4427,20 +4455,20 @@ function repeatArrayField(config) {
4427
4455
  });
4428
4456
  }
4429
4457
 
4430
- const importsAndExports$8 = [FormlyMaterialModule, FormlyMatCheckboxModule, FormlyMatToggleModule];
4458
+ const importsAndExports$9 = [FormlyMaterialModule, FormlyMatCheckboxModule, FormlyMatToggleModule];
4431
4459
  /**
4432
4460
  * Provides Formly Material checkbox and toggle field support.
4433
4461
  */
4434
4462
  class DbxFormFormlyBooleanFieldModule {
4435
4463
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyBooleanFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
4436
4464
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyBooleanFieldModule, imports: [FormlyMaterialModule, FormlyMatCheckboxModule, FormlyMatToggleModule], exports: [FormlyMaterialModule, FormlyMatCheckboxModule, FormlyMatToggleModule] });
4437
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyBooleanFieldModule, imports: [importsAndExports$8, FormlyMaterialModule, FormlyMatCheckboxModule, FormlyMatToggleModule] });
4465
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyBooleanFieldModule, imports: [importsAndExports$9, FormlyMaterialModule, FormlyMatCheckboxModule, FormlyMatToggleModule] });
4438
4466
  }
4439
4467
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyBooleanFieldModule, decorators: [{
4440
4468
  type: NgModule,
4441
4469
  args: [{
4442
- imports: importsAndExports$8,
4443
- exports: importsAndExports$8
4470
+ imports: importsAndExports$9,
4471
+ exports: importsAndExports$9
4444
4472
  }]
4445
4473
  }] });
4446
4474
 
@@ -5993,14 +6021,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
5993
6021
  type: Injectable
5994
6022
  }] });
5995
6023
 
5996
- const importsAndExports$7 = [DbxDateTimeFieldComponent, DbxFixedDateRangeFieldComponent, DbxFormFormlyWrapperModule];
6024
+ const importsAndExports$8 = [DbxDateTimeFieldComponent, DbxFixedDateRangeFieldComponent, DbxFormFormlyWrapperModule];
5997
6025
  /**
5998
6026
  * Registers the `datetime` and `fixeddaterange` Formly field types with style and form-field wrappers.
5999
6027
  */
6000
6028
  class DbxFormFormlyDateFieldModule {
6001
6029
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDateFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
6002
6030
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDateFieldModule, imports: [DbxDateTimeFieldComponent, DbxFixedDateRangeFieldComponent, DbxFormFormlyWrapperModule, i1$1.FormlyModule], exports: [DbxDateTimeFieldComponent, DbxFixedDateRangeFieldComponent, DbxFormFormlyWrapperModule] });
6003
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDateFieldModule, imports: [importsAndExports$7, FormlyModule.forChild({
6031
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDateFieldModule, imports: [importsAndExports$8, FormlyModule.forChild({
6004
6032
  types: [
6005
6033
  //
6006
6034
  { name: 'datetime', component: DbxDateTimeFieldComponent, wrappers: ['style', 'form-field'] },
@@ -6012,7 +6040,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
6012
6040
  type: NgModule,
6013
6041
  args: [{
6014
6042
  imports: [
6015
- ...importsAndExports$7,
6043
+ ...importsAndExports$8,
6016
6044
  FormlyModule.forChild({
6017
6045
  types: [
6018
6046
  //
@@ -6021,7 +6049,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
6021
6049
  ]
6022
6050
  })
6023
6051
  ],
6024
- exports: importsAndExports$7
6052
+ exports: importsAndExports$8
6025
6053
  }]
6026
6054
  }] });
6027
6055
 
@@ -6459,6 +6487,558 @@ const DEFAULT_DATE_TIME_FIELD_MENU_PRESETS_PRESETS = [
6459
6487
  }
6460
6488
  ];
6461
6489
 
6490
+ // MARK: Validator
6491
+ /**
6492
+ * Creates a ValidatorFn that checks the duration output value against min/max constraints.
6493
+ *
6494
+ * @param config - The duration field config containing min, max, outputUnit, and valueMode
6495
+ * @returns A ValidatorFn, or undefined if no min/max is configured
6496
+ */
6497
+ function timeDurationMinMaxValidator(config) {
6498
+ const { min, max, outputUnit = 'ms', valueMode = 'number' } = config;
6499
+ if (min == null && max == null) {
6500
+ return undefined;
6501
+ }
6502
+ return (control) => {
6503
+ const value = control.value;
6504
+ if (value == null) {
6505
+ return null;
6506
+ }
6507
+ let outputValue;
6508
+ if (valueMode === 'duration_data') {
6509
+ const data = value;
6510
+ const totalMs = durationDataToMilliseconds(data);
6511
+ outputValue = millisecondsToTimeUnit(totalMs, outputUnit);
6512
+ }
6513
+ else if (valueMode === 'hours_and_minutes') {
6514
+ const hm = value;
6515
+ const totalMs = hoursAndMinutesToTimeUnit(hm, 'ms');
6516
+ outputValue = totalMs / 60000; // compare in minutes
6517
+ }
6518
+ else {
6519
+ outputValue = value;
6520
+ }
6521
+ const unitLabel = TIME_UNIT_LABEL_MAP[valueMode === 'hours_and_minutes' ? 'min' : outputUnit].toLowerCase();
6522
+ const actualRounded = Math.round(outputValue * 100) / 100;
6523
+ const errors = {};
6524
+ if (min != null && outputValue < min) {
6525
+ errors['durationMin'] = { min, actual: actualRounded, unit: unitLabel };
6526
+ }
6527
+ if (max != null && outputValue > max) {
6528
+ errors['durationMax'] = { max, actual: actualRounded, unit: unitLabel };
6529
+ }
6530
+ return Object.keys(errors).length > 0 ? errors : null;
6531
+ };
6532
+ }
6533
+ /**
6534
+ * Creates a Formly field configuration for a time duration input.
6535
+ *
6536
+ * The field uses a text input that parses duration strings (e.g., "3d10h5m8s",
6537
+ * "2 hours 30 minutes") and a popover picker button with +/- columns for each unit.
6538
+ *
6539
+ * @param config - Time duration field configuration
6540
+ * @returns A validated {@link FormlyFieldConfig} with type `'timeduration'`
6541
+ *
6542
+ * @example
6543
+ * ```typescript
6544
+ * // Basic usage — output in milliseconds
6545
+ * const field = timeDurationField({
6546
+ * key: 'timeout',
6547
+ * label: 'Timeout',
6548
+ * outputUnit: 'ms',
6549
+ * allowedUnits: ['min', 'h', 'd']
6550
+ * });
6551
+ *
6552
+ * // With min/max constraints — output in minutes, max 8 hours
6553
+ * const constrained = timeDurationField({
6554
+ * key: 'duration',
6555
+ * label: 'Duration',
6556
+ * outputUnit: 'min',
6557
+ * min: 0,
6558
+ * max: 480
6559
+ * });
6560
+ *
6561
+ * // HoursAndMinutes output mode
6562
+ * const hoursMin = timeDurationField({
6563
+ * key: 'workTime',
6564
+ * label: 'Work Time',
6565
+ * valueMode: 'hours_and_minutes',
6566
+ * allowedUnits: ['min', 'h']
6567
+ * });
6568
+ * ```
6569
+ */
6570
+ function timeDurationField(config = {}) {
6571
+ const { key = 'duration', outputUnit, valueMode, allowedUnits, pickerUnits, min, max, carryOver, materialFormField } = config;
6572
+ const validators = [];
6573
+ const minMaxValidator = timeDurationMinMaxValidator(config);
6574
+ if (minMaxValidator) {
6575
+ validators.push(minMaxValidator);
6576
+ }
6577
+ return formlyField({
6578
+ key,
6579
+ type: 'timeduration',
6580
+ ...propsAndConfigForFieldConfig(config, {
6581
+ ...materialFormField,
6582
+ outputUnit,
6583
+ valueMode,
6584
+ allowedUnits,
6585
+ pickerUnits,
6586
+ min,
6587
+ max,
6588
+ carryOver
6589
+ }),
6590
+ ...validatorsForFieldConfig({ validators })
6591
+ });
6592
+ }
6593
+
6594
+ /**
6595
+ * Default popover key for the duration picker.
6596
+ */
6597
+ const DEFAULT_DURATION_PICKER_POPOVER_KEY = 'durationpicker';
6598
+ /**
6599
+ * Popover component that displays a horizontal duration picker with +/- buttons for each time unit.
6600
+ *
6601
+ * Each column shows the unit label, an increment button, the current value, and a decrement button.
6602
+ * Buttons are disabled when incrementing/decrementing would exceed min/max constraints.
6603
+ * Changes are applied immediately via the onChange callback and returned when the popover closes.
6604
+ *
6605
+ * @example
6606
+ * ```typescript
6607
+ * DbxDurationPickerPopoverComponent.openPopover(popoverService, {
6608
+ * origin: elementRef,
6609
+ * data: { current: { hours: 1, minutes: 30 }, units: ['h', 'min', 's'] }
6610
+ * });
6611
+ * ```
6612
+ */
6613
+ class DbxDurationPickerPopoverComponent extends AbstractPopoverDirective {
6614
+ durationData = signal(this.popover.data?.current ?? {}, ...(ngDevMode ? [{ debugName: "durationData" }] : /* istanbul ignore next */ []));
6615
+ units = [...(this.popover.data?.units ?? ['d', 'h', 'min', 's'])].reverse();
6616
+ _onChange = this.popover.data?.onChange;
6617
+ _minMs = this.popover.data?.minMs;
6618
+ _maxMs = this.popover.data?.maxMs;
6619
+ _carryOver = this.popover.data?.carryOver ?? false;
6620
+ constructor() {
6621
+ super();
6622
+ this.popover.getClosingValueFn = () => this.durationData();
6623
+ }
6624
+ /**
6625
+ * Opens the duration picker popover.
6626
+ *
6627
+ * @param popoverService - The popover service to use
6628
+ * @param config - Configuration with origin element and picker data
6629
+ * @param config.origin - The element to anchor the popover to
6630
+ * @param config.data - The picker data including current values and which units to show
6631
+ * @returns A reference to the opened popover
6632
+ */
6633
+ static openPopover(popoverService, config) {
6634
+ return popoverService.open({
6635
+ key: DEFAULT_DURATION_PICKER_POPOVER_KEY,
6636
+ origin: config.origin,
6637
+ componentClass: DbxDurationPickerPopoverComponent,
6638
+ data: config.data,
6639
+ width: `${Math.max(200, config.data.units.length * 64 + 32)}px`,
6640
+ height: '260px'
6641
+ });
6642
+ }
6643
+ /**
6644
+ * Gets the short label for a time unit.
6645
+ *
6646
+ * @param unit - The time unit
6647
+ * @returns The short label string
6648
+ */
6649
+ unitLabel(unit) {
6650
+ return TIME_UNIT_SHORT_LABEL_MAP[unit];
6651
+ }
6652
+ /**
6653
+ * Gets the current value for a specific time unit.
6654
+ *
6655
+ * @param unit - The time unit to read
6656
+ * @returns The current value for that unit
6657
+ */
6658
+ getValue(unit) {
6659
+ return getDurationDataValue(this.durationData(), unit);
6660
+ }
6661
+ /**
6662
+ * Returns true if incrementing the given unit by 1 would not exceed the maximum.
6663
+ *
6664
+ * @param unit - The time unit to check
6665
+ * @returns Whether incrementing is allowed
6666
+ */
6667
+ canIncrement(unit) {
6668
+ if (this._maxMs == null) {
6669
+ return true;
6670
+ }
6671
+ const currentMs = durationDataToMilliseconds(this.durationData());
6672
+ const incrementMs = timeUnitToMilliseconds(1, unit);
6673
+ return currentMs + incrementMs <= this._maxMs;
6674
+ }
6675
+ /**
6676
+ * Returns true if decrementing the given unit by 1 would not go below the minimum (or below 0).
6677
+ *
6678
+ * @param unit - The time unit to check
6679
+ * @returns Whether decrementing is allowed
6680
+ */
6681
+ canDecrement(unit) {
6682
+ if (this._carryOver) {
6683
+ // With carryOver, allow decrement as long as total ms after decrement >= minMs (or 0)
6684
+ const currentMs = durationDataToMilliseconds(this.durationData());
6685
+ const decrementMs = timeUnitToMilliseconds(1, unit);
6686
+ const minMs = this._minMs ?? 0;
6687
+ return currentMs - decrementMs >= minMs;
6688
+ }
6689
+ const current = getDurationDataValue(this.durationData(), unit);
6690
+ if (current <= 0) {
6691
+ return false;
6692
+ }
6693
+ if (this._minMs == null) {
6694
+ return true;
6695
+ }
6696
+ const currentMs = durationDataToMilliseconds(this.durationData());
6697
+ const decrementMs = timeUnitToMilliseconds(1, unit);
6698
+ return currentMs - decrementMs >= this._minMs;
6699
+ }
6700
+ /**
6701
+ * Increments the value for a specific time unit.
6702
+ * Holding shift doubles the step.
6703
+ *
6704
+ * @param unit - The time unit to increment
6705
+ * @param step - The amount to increment by (defaults to 1)
6706
+ */
6707
+ increment(unit, step = 1) {
6708
+ const current = getDurationDataValue(this.durationData(), unit);
6709
+ const updated = this._normalizeIfCarryOver(setDurationDataValue(this.durationData(), unit, current + step));
6710
+ this.durationData.set(updated);
6711
+ this._onChange?.(updated);
6712
+ }
6713
+ /**
6714
+ * Decrements the value for a specific time unit.
6715
+ * Holding shift doubles the step.
6716
+ *
6717
+ * @param unit - The time unit to decrement
6718
+ * @param step - The amount to decrement by (defaults to 1)
6719
+ */
6720
+ decrement(unit, step = 1) {
6721
+ const current = getDurationDataValue(this.durationData(), unit);
6722
+ const newValue = this._carryOver ? current - step : Math.max(0, current - step);
6723
+ const updated = this._normalizeIfCarryOver(setDurationDataValue(this.durationData(), unit, newValue));
6724
+ this.durationData.set(updated);
6725
+ this._onChange?.(updated);
6726
+ }
6727
+ /**
6728
+ * Returns the step size — 2 if shift is held, 1 otherwise.
6729
+ *
6730
+ * @param event - The mouse or keyboard event
6731
+ * @returns The step multiplier
6732
+ */
6733
+ stepFromEvent(event) {
6734
+ if (event && 'shiftKey' in event) {
6735
+ return event.shiftKey ? 2 : 1;
6736
+ }
6737
+ return 1;
6738
+ }
6739
+ /**
6740
+ * When carryOver is enabled, normalizes the data by converting to total milliseconds
6741
+ * and decomposing back into the picker's units (e.g., 60s becomes 1m, 7d becomes 1w).
6742
+ *
6743
+ * @returns Normalized or original data
6744
+ */
6745
+ _normalizeIfCarryOver(data) {
6746
+ if (!this._carryOver) {
6747
+ return data;
6748
+ }
6749
+ const ms = durationDataToMilliseconds(data);
6750
+ return millisecondsToDurationData(Math.max(0, ms), this.units);
6751
+ }
6752
+ // MARK: Hold-to-repeat
6753
+ _holdInterval;
6754
+ _holdTimeout;
6755
+ _holdActive = false;
6756
+ _shiftHeld = false;
6757
+ /**
6758
+ * Fires one action immediately and starts hold-to-repeat.
6759
+ * Used by both mousedown and keydown.
6760
+ *
6761
+ * @param action - The action to perform
6762
+ * @param unit - The time unit
6763
+ * @param event - The triggering event (for shift detection)
6764
+ */
6765
+ onHoldStart(action, unit, event) {
6766
+ // Only preventDefault for keyboard events (prevents page scroll).
6767
+ // Don't preventDefault on mousedown — it blocks focus transfer to the button.
6768
+ if (event instanceof KeyboardEvent) {
6769
+ event.preventDefault();
6770
+ this._shiftHeld = event.shiftKey;
6771
+ }
6772
+ else if (event instanceof MouseEvent) {
6773
+ this._shiftHeld = event.shiftKey;
6774
+ }
6775
+ if (this._holdActive) {
6776
+ return;
6777
+ }
6778
+ this._doAction(action, unit, this._currentStep);
6779
+ this._holdActive = true;
6780
+ this._holdTimeout = setTimeout(() => {
6781
+ this._holdInterval = setInterval(() => {
6782
+ if (!this._doAction(action, unit, this._currentStep)) {
6783
+ this.stopHold();
6784
+ }
6785
+ }, 80);
6786
+ }, 300);
6787
+ }
6788
+ /**
6789
+ * Returns the current step based on whether shift is held.
6790
+ */
6791
+ get _currentStep() {
6792
+ return this._shiftHeld ? 2 : 1;
6793
+ }
6794
+ /**
6795
+ * Stops the hold-to-repeat interval.
6796
+ */
6797
+ /**
6798
+ * Handles keyup events. Only stops the hold when an arrow key is released.
6799
+ * Releasing modifier keys (shift, ctrl, etc.) does not stop the hold.
6800
+ *
6801
+ * @param event - The keyboard event
6802
+ */
6803
+ onKeyUp(event) {
6804
+ this._shiftHeld = event.shiftKey;
6805
+ if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
6806
+ this.stopHold();
6807
+ }
6808
+ }
6809
+ stopHold() {
6810
+ this._holdActive = false;
6811
+ if (this._holdTimeout) {
6812
+ clearTimeout(this._holdTimeout);
6813
+ this._holdTimeout = undefined;
6814
+ }
6815
+ if (this._holdInterval) {
6816
+ clearInterval(this._holdInterval);
6817
+ this._holdInterval = undefined;
6818
+ }
6819
+ }
6820
+ /**
6821
+ * Executes an increment or decrement action if allowed.
6822
+ *
6823
+ * @returns True if the action was performed
6824
+ */
6825
+ _doAction(action, unit, step) {
6826
+ if (action === 'increment' && this.canIncrement(unit)) {
6827
+ this.increment(unit, step);
6828
+ return true;
6829
+ }
6830
+ else if (action === 'decrement' && this.canDecrement(unit)) {
6831
+ this.decrement(unit, step);
6832
+ return true;
6833
+ }
6834
+ return false;
6835
+ }
6836
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxDurationPickerPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6837
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.3", type: DbxDurationPickerPopoverComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<div class=\"dbx-duration-picker\">\n @for (unit of units; track unit) {\n <div class=\"dbx-duration-picker-column\">\n <span class=\"dbx-duration-picker-label\">{{ unitLabel(unit) }}</span>\n <button mat-icon-button type=\"button\" (mousedown)=\"onHoldStart('increment', unit, $event)\" (mouseup)=\"stopHold()\" (mouseleave)=\"stopHold()\" (keydown.arrowup)=\"onHoldStart('increment', unit, $event)\" (keydown.arrowdown)=\"onHoldStart('decrement', unit, $event)\" (keyup)=\"onKeyUp($event)\" [disabled]=\"!canIncrement(unit)\" aria-label=\"Increase\">\n <mat-icon>add</mat-icon>\n </button>\n <span class=\"dbx-duration-picker-value\">{{ getValue(unit) }}</span>\n <button mat-icon-button type=\"button\" (mousedown)=\"onHoldStart('decrement', unit, $event)\" (mouseup)=\"stopHold()\" (mouseleave)=\"stopHold()\" (keydown.arrowup)=\"onHoldStart('increment', unit, $event)\" (keydown.arrowdown)=\"onHoldStart('decrement', unit, $event)\" (keyup)=\"onKeyUp($event)\" [disabled]=\"!canDecrement(unit)\" aria-label=\"Decrease\">\n <mat-icon>remove</mat-icon>\n </button>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6838
+ }
6839
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxDurationPickerPopoverComponent, decorators: [{
6840
+ type: Component,
6841
+ args: [{ imports: [MatIconModule, MatButtonModule], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-duration-picker\">\n @for (unit of units; track unit) {\n <div class=\"dbx-duration-picker-column\">\n <span class=\"dbx-duration-picker-label\">{{ unitLabel(unit) }}</span>\n <button mat-icon-button type=\"button\" (mousedown)=\"onHoldStart('increment', unit, $event)\" (mouseup)=\"stopHold()\" (mouseleave)=\"stopHold()\" (keydown.arrowup)=\"onHoldStart('increment', unit, $event)\" (keydown.arrowdown)=\"onHoldStart('decrement', unit, $event)\" (keyup)=\"onKeyUp($event)\" [disabled]=\"!canIncrement(unit)\" aria-label=\"Increase\">\n <mat-icon>add</mat-icon>\n </button>\n <span class=\"dbx-duration-picker-value\">{{ getValue(unit) }}</span>\n <button mat-icon-button type=\"button\" (mousedown)=\"onHoldStart('decrement', unit, $event)\" (mouseup)=\"stopHold()\" (mouseleave)=\"stopHold()\" (keydown.arrowup)=\"onHoldStart('increment', unit, $event)\" (keydown.arrowdown)=\"onHoldStart('decrement', unit, $event)\" (keyup)=\"onKeyUp($event)\" [disabled]=\"!canDecrement(unit)\" aria-label=\"Decrease\">\n <mat-icon>remove</mat-icon>\n </button>\n </div>\n }\n</div>\n" }]
6842
+ }], ctorParameters: () => [] });
6843
+
6844
+ /**
6845
+ * Formly custom field type for time duration input with text parsing and a popover picker.
6846
+ *
6847
+ * The text input accepts duration strings like "3d10h5m8s", "2 hours 30 minutes", etc.
6848
+ * A picker button opens a popover with +/- columns for each time unit.
6849
+ *
6850
+ * Registered as Formly type `'timeduration'`.
6851
+ */
6852
+ class DbxTimeDurationFieldComponent extends FieldType$1 {
6853
+ _popoverService = inject(DbxPopoverService);
6854
+ _inputSync = new SubscriptionObject();
6855
+ _outputSync = new SubscriptionObject();
6856
+ _suppressOutputSync = false;
6857
+ _currentDurationData = {};
6858
+ textCtrl = new FormControl('');
6859
+ pickerButtonElement = viewChild('pickerButton', { ...(ngDevMode ? { debugName: "pickerButtonElement" } : /* istanbul ignore next */ {}), read: ElementRef });
6860
+ get outputUnit() {
6861
+ return this.props.outputUnit ?? 'ms';
6862
+ }
6863
+ get valueMode() {
6864
+ return this.props.valueMode ?? 'number';
6865
+ }
6866
+ get allowedUnits() {
6867
+ return this.props.allowedUnits ?? ALL_TIME_UNITS;
6868
+ }
6869
+ get pickerUnits() {
6870
+ return this.props.pickerUnits ?? this.allowedUnits.filter((u) => u !== 'ms');
6871
+ }
6872
+ /**
6873
+ * Units used for decomposing/displaying duration text.
6874
+ * Includes 'ms' if the smallest picker unit would leave a remainder.
6875
+ */
6876
+ get displayUnits() {
6877
+ const units = [...this.pickerUnits];
6878
+ if (!units.includes('ms')) {
6879
+ units.push('ms');
6880
+ }
6881
+ return units;
6882
+ }
6883
+ ngOnInit() {
6884
+ // Input sync: outer formControl -> text display
6885
+ this._inputSync.subscription = this.formControl.valueChanges.pipe(startWith(this.formControl.value), distinctUntilChanged()).subscribe((inputValue) => {
6886
+ this._suppressOutputSync = true;
6887
+ try {
6888
+ if (inputValue == null) {
6889
+ this._currentDurationData = {};
6890
+ this.textCtrl.setValue('');
6891
+ }
6892
+ else {
6893
+ const ms = this._outputValueToMilliseconds(inputValue);
6894
+ this._currentDurationData = millisecondsToDurationData(ms, this.displayUnits);
6895
+ this.textCtrl.setValue(formatDurationString(this._currentDurationData));
6896
+ }
6897
+ }
6898
+ finally {
6899
+ this._suppressOutputSync = false;
6900
+ }
6901
+ });
6902
+ // Text change sync: parse text on value changes (debounced via blur/enter)
6903
+ // We don't auto-parse on every keystroke — only on blur or enter
6904
+ }
6905
+ /**
6906
+ * Called when the text input loses focus. Parses the text and updates the output.
6907
+ */
6908
+ onTextBlur() {
6909
+ this._parseAndSync();
6910
+ }
6911
+ /**
6912
+ * Called when Enter is pressed in the text input.
6913
+ */
6914
+ onTextEnter(event) {
6915
+ event.preventDefault();
6916
+ this._parseAndSync();
6917
+ }
6918
+ /**
6919
+ * Opens the duration picker popover.
6920
+ */
6921
+ openPicker() {
6922
+ const origin = this.pickerButtonElement();
6923
+ if (!origin) {
6924
+ return;
6925
+ }
6926
+ const existingMs = this._currentDurationData.milliseconds;
6927
+ const onPickerChange = (data) => {
6928
+ // Preserve milliseconds from the existing data since the popover doesn't show them
6929
+ const merged = existingMs ? { ...data, milliseconds: existingMs } : data;
6930
+ this._currentDurationData = merged;
6931
+ this.textCtrl.setValue(formatDurationString(merged));
6932
+ this._syncOutputFromDurationData(merged);
6933
+ };
6934
+ const { min, max } = this.props;
6935
+ const minMs = min != null ? timeUnitToMilliseconds(min, this.outputUnit) : undefined;
6936
+ const maxMs = max != null ? timeUnitToMilliseconds(max, this.outputUnit) : undefined;
6937
+ DbxDurationPickerPopoverComponent.openPopover(this._popoverService, {
6938
+ origin,
6939
+ data: {
6940
+ current: this._currentDurationData,
6941
+ units: this.pickerUnits,
6942
+ onChange: onPickerChange,
6943
+ minMs,
6944
+ maxMs,
6945
+ carryOver: this.props.carryOver
6946
+ }
6947
+ });
6948
+ }
6949
+ ngOnDestroy() {
6950
+ super.ngOnDestroy();
6951
+ this._inputSync.destroy();
6952
+ this._outputSync.destroy();
6953
+ }
6954
+ /**
6955
+ * Parses the current text input and syncs the output value.
6956
+ */
6957
+ _parseAndSync() {
6958
+ if (this._suppressOutputSync) {
6959
+ return;
6960
+ }
6961
+ const text = this.textCtrl.value?.trim();
6962
+ if (!text) {
6963
+ this._currentDurationData = {};
6964
+ this.formControl.setValue(undefined);
6965
+ this.formControl.markAsDirty();
6966
+ this.formControl.markAsTouched();
6967
+ return;
6968
+ }
6969
+ const parsed = parseDurationString(text);
6970
+ this._currentDurationData = parsed;
6971
+ // Re-format the display text to normalize it
6972
+ this.textCtrl.setValue(formatDurationString(parsed), { emitEvent: false });
6973
+ this._syncOutputFromDurationData(parsed);
6974
+ }
6975
+ /**
6976
+ * Converts duration data to the output value and sets it on the form control.
6977
+ */
6978
+ _syncOutputFromDurationData(data) {
6979
+ const ms = durationDataToMilliseconds(data);
6980
+ let outputValue;
6981
+ if (this.valueMode === 'duration_data') {
6982
+ outputValue = data;
6983
+ }
6984
+ else if (this.valueMode === 'hours_and_minutes') {
6985
+ const totalMinutes = ms / 60000;
6986
+ outputValue = minutesToHoursAndMinutes(Math.round(totalMinutes));
6987
+ }
6988
+ else {
6989
+ outputValue = millisecondsToTimeUnit(ms, this.outputUnit);
6990
+ }
6991
+ this.formControl.setValue(outputValue);
6992
+ this.formControl.markAsDirty();
6993
+ this.formControl.markAsTouched();
6994
+ }
6995
+ /**
6996
+ * Converts an output value (number, HoursAndMinutes, or TimeDurationData) to milliseconds.
6997
+ */
6998
+ _outputValueToMilliseconds(value) {
6999
+ if (this.valueMode === 'duration_data') {
7000
+ return durationDataToMilliseconds(value);
7001
+ }
7002
+ else if (this.valueMode === 'hours_and_minutes') {
7003
+ const hm = value;
7004
+ return hoursAndMinutesToTimeUnit(hm, 'ms');
7005
+ }
7006
+ else {
7007
+ return timeUnitToMilliseconds(value, this.outputUnit);
7008
+ }
7009
+ }
7010
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxTimeDurationFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
7011
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.3", type: DbxTimeDurationFieldComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "pickerButtonElement", first: true, predicate: ["pickerButton"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"dbx-form-duration-field\">\n <input matInput type=\"text\" [formControl]=\"textCtrl\" (blur)=\"onTextBlur()\" (keydown.enter)=\"onTextEnter($event)\" class=\"dbx-form-duration-field-input\" placeholder=\"e.g. 2h30m\" [attr.aria-label]=\"props.label || 'Duration'\" />\n <button mat-icon-button type=\"button\" #pickerButton (click)=\"openPicker()\" class=\"dbx-form-duration-field-picker-btn\" aria-label=\"Open duration picker\">\n <mat-icon>schedule</mat-icon>\n </button>\n</div>\n", dependencies: [{ kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7012
+ }
7013
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxTimeDurationFieldComponent, decorators: [{
7014
+ type: Component,
7015
+ args: [{ imports: [MatInputModule, MatFormFieldModule, MatIconModule, MatButtonModule, FormsModule, ReactiveFormsModule], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-form-duration-field\">\n <input matInput type=\"text\" [formControl]=\"textCtrl\" (blur)=\"onTextBlur()\" (keydown.enter)=\"onTextEnter($event)\" class=\"dbx-form-duration-field-input\" placeholder=\"e.g. 2h30m\" [attr.aria-label]=\"props.label || 'Duration'\" />\n <button mat-icon-button type=\"button\" #pickerButton (click)=\"openPicker()\" class=\"dbx-form-duration-field-picker-btn\" aria-label=\"Open duration picker\">\n <mat-icon>schedule</mat-icon>\n </button>\n</div>\n" }]
7016
+ }], propDecorators: { pickerButtonElement: [{ type: i0.ViewChild, args: ['pickerButton', { ...{ read: ElementRef }, isSignal: true }] }] } });
7017
+
7018
+ const importsAndExports$7 = [DbxTimeDurationFieldComponent, DbxDurationPickerPopoverComponent];
7019
+ /**
7020
+ * Registers the `timeduration` Formly field type for time duration input with text parsing and popover picker.
7021
+ */
7022
+ class DbxFormFormlyDurationFieldModule {
7023
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDurationFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
7024
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDurationFieldModule, imports: [DbxTimeDurationFieldComponent, DbxDurationPickerPopoverComponent, i1$1.FormlyModule], exports: [DbxTimeDurationFieldComponent, DbxDurationPickerPopoverComponent] });
7025
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDurationFieldModule, imports: [importsAndExports$7, FormlyModule.forChild({
7026
+ types: [{ name: 'timeduration', component: DbxTimeDurationFieldComponent, wrappers: ['form-field'] }]
7027
+ })] });
7028
+ }
7029
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: DbxFormFormlyDurationFieldModule, decorators: [{
7030
+ type: NgModule,
7031
+ args: [{
7032
+ imports: [
7033
+ ...importsAndExports$7,
7034
+ FormlyModule.forChild({
7035
+ types: [{ name: 'timeduration', component: DbxTimeDurationFieldComponent, wrappers: ['form-field'] }]
7036
+ })
7037
+ ],
7038
+ exports: importsAndExports$7
7039
+ }]
7040
+ }] });
7041
+
6462
7042
  /**
6463
7043
  * Angular form validator that requires the control value to be truthy.
6464
7044
  *
@@ -8024,7 +8604,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImpor
8024
8604
  * @returns Environment providers for all Formly field declarations
8025
8605
  */
8026
8606
  function provideDbxFormFormlyFieldDeclarations() {
8027
- return importProvidersFrom([DbxFormFormlyArrayFieldModule, DbxFormFormlyBooleanFieldModule, DbxFormFormlyDateFieldModule, DbxFormFormlyDbxListFieldModule, DbxFormFormlyNumberFieldModule, DbxFormFormlyPhoneFieldModule, DbxFormFormlyPickableFieldModule, DbxFormFormlySearchableFieldModule, DbxFormFormlySourceSelectModule, DbxFormFormlyTextEditorFieldModule, DbxFormFormlyTextFieldModule, DbxFormFormlyWrapperModule, FormlyModule, FormlyMaterialModule]);
8607
+ return importProvidersFrom([DbxFormFormlyArrayFieldModule, DbxFormFormlyBooleanFieldModule, DbxFormFormlyDateFieldModule, DbxFormFormlyDbxListFieldModule, DbxFormFormlyDurationFieldModule, DbxFormFormlyNumberFieldModule, DbxFormFormlyPhoneFieldModule, DbxFormFormlyPickableFieldModule, DbxFormFormlySearchableFieldModule, DbxFormFormlySourceSelectModule, DbxFormFormlyTextEditorFieldModule, DbxFormFormlyTextFieldModule, DbxFormFormlyWrapperModule, FormlyModule, FormlyMaterialModule]);
8028
8608
  }
8029
8609
 
8030
8610
  /**
@@ -8098,5 +8678,5 @@ function provideDbxFormConfiguration(config) {
8098
8678
  * Generated bundle index. Do not edit.
8099
8679
  */
8100
8680
 
8101
- export { APP_ACTION_FORM_DISABLED_KEY, AbstractAsyncFormlyFormDirective, AbstractConfigAsyncFormlyFormDirective, AbstractDbxPickableItemFieldDirective, AbstractDbxSearchableFieldDisplayDirective, AbstractDbxSearchableValueFieldDirective, AbstractFormExpandSectionWrapperDirective, AbstractFormlyFormDirective, AbstractSyncFormlyFormDirective, AutoTouchFieldWrapperComponent, ChecklistItemFieldDataSetBuilder, DBX_DATE_TIME_FIELD_DATE_NOT_IN_SCHEDULE_ERROR, DBX_DATE_TIME_FIELD_MENU_PRESETS_TOKEN, DBX_DATE_TIME_FIELD_TIME_NOT_IN_RANGE_ERROR, DBX_FORMLY_FORM_COMPONENT_TEMPLATE, DBX_SEARCHABLE_FIELD_COMPONENT_DATA_TOKEN, DEFAULT_DATE_TIME_FIELD_MENU_PRESETS_PRESETS, DEFAULT_FORM_DISABLED_KEY, DEFAULT_HAS_VALUE_FN, DEFAULT_LAT_LNG_TEXT_FIELD_PATTERN_MESSAGE, DEFAULT_LAT_LNG_TEXT_FIELD_PLACEHOLDER, DEFAULT_PREFERRED_COUNTRIES, DISPLAY_FOR_TIMEZONE_STRING_VALUE, DbxActionFormDirective, DbxActionFormSafetyDirective, DbxChecklistItemContentComponent, DbxChecklistItemFieldComponent, DbxDateTimeFieldComponent, DbxDateTimeFieldMenuPresetsService, DbxDateTimeFieldTimeMode, DbxDateTimeValueMode, DbxDefaultChecklistItemFieldDisplayComponent, DbxDefaultSearchableFieldDisplayComponent, DbxFixedDateRangeFieldComponent, DbxFixedDateRangeFieldSelectionStrategy, DbxForm, DbxFormActionDialogComponent, DbxFormComponentFieldComponent, DbxFormExpandWrapperComponent, DbxFormExtensionModule, DbxFormFlexWrapperComponent, DbxFormFormlyArrayFieldModule, DbxFormFormlyBooleanFieldModule, DbxFormFormlyChecklistItemFieldModule, DbxFormFormlyComponentFieldModule, DbxFormFormlyDateFieldModule, DbxFormFormlyDbxListFieldModule, DbxFormFormlyFieldModule, DbxFormFormlyNumberFieldModule, DbxFormFormlyPhoneFieldModule, DbxFormFormlyPickableFieldModule, DbxFormFormlySearchableFieldModule, DbxFormFormlySourceSelectModule, DbxFormFormlyTextEditorFieldModule, DbxFormFormlyTextFieldModule, DbxFormFormlyWrapperModule, DbxFormInfoWrapperComponent, DbxFormLoadingSourceDirective, DbxFormLoginFieldModule, DbxFormModule, DbxFormRepeatArrayTypeComponent, DbxFormSearchFormComponent, DbxFormSectionWrapperComponent, DbxFormSourceDirective, DbxFormSourceSelectFieldComponent, DbxFormSpacerDirective, DbxFormState, DbxFormStyleWrapperComponent, DbxFormSubsectionWrapperComponent, DbxFormTextAvailableFieldModule, DbxFormTimezoneStringFieldModule, DbxFormToggleWrapperComponent, DbxFormValueChangeDirective, DbxFormWorkingWrapperComponent, DbxFormlyComponent, DbxFormlyContext, DbxFormlyFieldsContextDirective, DbxFormlyFormComponentImportsModule, DbxItemListFieldComponent, DbxMutableForm, DbxPhoneFieldComponent, DbxPickableChipListFieldComponent, DbxPickableListFieldComponent, DbxPickableListFieldItemListComponent, DbxPickableListFieldItemListViewComponent, DbxPickableListFieldItemListViewItemComponent, DbxSearchableChipFieldComponent, DbxSearchableFieldAutocompleteItemComponent, DbxSearchableTextFieldComponent, DbxTextEditorFieldComponent, FIELD_VALUES_ARE_EQUAL_VALIDATION_KEY, FIELD_VALUE_IS_AVAILABLE_ERROR_VALIDATION_KEY, FIELD_VALUE_IS_AVAILABLE_VALIDATION_KEY, INVALID_PHONE_NUMBER_EXTENSION_MESSAGE, INVALID_PHONE_NUMBER_MESSAGE, IS_DIVISIBLE_BY_VALIDATION_KEY, IS_NOT_WEBSITE_URL_VALIDATION_KEY, IS_NOT_WEBSITE_URL_WITH_EXPECTED_DOMAIN_VALIDATION_KEY, IS_NOT_WEBSITE_URL_WITH_PREFIX_VALIDATION_KEY, LABEL_STRING_MAX_LENGTH, MAX_LENGTH_VALIDATION_MESSAGE, MAX_VALIDATION_MESSAGE, MIN_LENGTH_VALIDATION_MESSAGE, MIN_VALIDATION_MESSAGE, PHONE_LABEL_MAX_LENGTH, REQUIRED_VALIDATION_MESSAGE, SEARCH_STRING_MAX_LENGTH, TAKE_NEXT_UPCOMING_TIME_CONFIG_OBS, addValueSelectionOptionFunction, addWrapperToFormlyFieldConfig, addressField, addressFormlyFields, addressLineField, addressListField, autoTouchWrapper, checkIsFieldFlexLayoutGroupFieldConfig, checkboxField, checklistItemField, chipTextField, cityField, componentField, countryField, dateRangeField, dateTimeField, dateTimePreset, dateTimeRangeField, dbxDateRangeIsSameDateRangeFieldValue, dbxDateTimeInputValueParseFactory, dbxDateTimeIsSameDateTimeFieldValue, dbxDateTimeOutputValueFactory, dbxFormSearchFormFields, dbxFormSourceObservable, dbxFormSourceObservableFromStream, dbxFormlyFormComponentProviders, dbxListField, defaultValidationMessages, disableFormlyFieldAutofillAttributes, dollarAmountField, emailField, expandWrapper, fieldValueIsAvailableValidator, fieldValuesAreEqualValidator, filterPartialPotentialFieldConfigValuesFromObject, filterPickableItemFieldValuesByLabel, filterPickableItemFieldValuesByLabelFilterFunction, fixedDateRangeField, flexLayoutWrapper, formlyField, hiddenField, infoWrapper, isDbxDateTimeFieldTimeDateConfig, isDivisibleBy, isDomain, isE164PhoneNumber, isE164PhoneNumberWithValidExtension, isInRange, isPhoneExtension, isTruthy, isWebsiteUrlValidator, latLngTextField, makeMetaFilterSearchableFieldValueDisplayFn, maxLengthValidationMessage, maxValidationMessage, mergePropsValueObjects, minLengthValidationMessage, minValidationMessage, nameField, numberField, numberFieldTransformParser, numberSliderField, partialPotentialFieldConfigKeys, partialPotentialFieldConfigKeysFilter, phoneAndLabelSectionField, phoneField, phoneListField, pickableItemChipField, pickableItemListField, pickableValueFieldValuesConfigForStaticLabeledValues, propsAndConfigForFieldConfig, propsValueForFieldConfig, provideDbxForm, provideDbxFormConfiguration, provideDbxFormFormlyFieldDeclarations, provideDbxMutableForm, provideFormlyContext, repeatArrayField, searchableChipField, searchableStringChipField, searchableTextField, sectionWrapper, sortPickableItemsByLabel, sortPickableItemsByLabelStringFunction, sourceSelectField, stateField, streamValueFromControl, styleWrapper, subsectionWrapper, syncConfigValueObs, textAreaField, textEditorField, textField, textFieldTransformParser, textIsAvailableField, textPasswordField, textPasswordWithVerifyFieldGroup, textVerifyPasswordField, timeOnlyField, timezoneStringField, timezoneStringSearchFunction, toggleDisableFormControl, toggleField, toggleWrapper, usernameLoginField, usernamePasswordLoginFields, validatorsForFieldConfig, valueSelectionField, websiteUrlField, workingWrapper, wrappedPhoneAndLabelField, zipCodeField };
8681
+ export { APP_ACTION_FORM_DISABLED_KEY, AbstractAsyncFormlyFormDirective, AbstractConfigAsyncFormlyFormDirective, AbstractDbxPickableItemFieldDirective, AbstractDbxSearchableFieldDisplayDirective, AbstractDbxSearchableValueFieldDirective, AbstractFormExpandSectionWrapperDirective, AbstractFormlyFormDirective, AbstractSyncFormlyFormDirective, AutoTouchFieldWrapperComponent, ChecklistItemFieldDataSetBuilder, DBX_DATE_TIME_FIELD_DATE_NOT_IN_SCHEDULE_ERROR, DBX_DATE_TIME_FIELD_MENU_PRESETS_TOKEN, DBX_DATE_TIME_FIELD_TIME_NOT_IN_RANGE_ERROR, DBX_FORMLY_FORM_COMPONENT_TEMPLATE, DBX_SEARCHABLE_FIELD_COMPONENT_DATA_TOKEN, DEFAULT_DATE_TIME_FIELD_MENU_PRESETS_PRESETS, DEFAULT_DURATION_PICKER_POPOVER_KEY, DEFAULT_FORM_DISABLED_KEY, DEFAULT_HAS_VALUE_FN, DEFAULT_LAT_LNG_TEXT_FIELD_PATTERN_MESSAGE, DEFAULT_LAT_LNG_TEXT_FIELD_PLACEHOLDER, DEFAULT_PREFERRED_COUNTRIES, DISPLAY_FOR_TIMEZONE_STRING_VALUE, DURATION_MAX_VALIDATION_MESSAGE, DURATION_MIN_VALIDATION_MESSAGE, DbxActionFormDirective, DbxActionFormSafetyDirective, DbxChecklistItemContentComponent, DbxChecklistItemFieldComponent, DbxDateTimeFieldComponent, DbxDateTimeFieldMenuPresetsService, DbxDateTimeFieldTimeMode, DbxDateTimeValueMode, DbxDefaultChecklistItemFieldDisplayComponent, DbxDefaultSearchableFieldDisplayComponent, DbxDurationPickerPopoverComponent, DbxFixedDateRangeFieldComponent, DbxFixedDateRangeFieldSelectionStrategy, DbxForm, DbxFormActionDialogComponent, DbxFormComponentFieldComponent, DbxFormExpandWrapperComponent, DbxFormExtensionModule, DbxFormFlexWrapperComponent, DbxFormFormlyArrayFieldModule, DbxFormFormlyBooleanFieldModule, DbxFormFormlyChecklistItemFieldModule, DbxFormFormlyComponentFieldModule, DbxFormFormlyDateFieldModule, DbxFormFormlyDbxListFieldModule, DbxFormFormlyDurationFieldModule, DbxFormFormlyFieldModule, DbxFormFormlyNumberFieldModule, DbxFormFormlyPhoneFieldModule, DbxFormFormlyPickableFieldModule, DbxFormFormlySearchableFieldModule, DbxFormFormlySourceSelectModule, DbxFormFormlyTextEditorFieldModule, DbxFormFormlyTextFieldModule, DbxFormFormlyWrapperModule, DbxFormInfoWrapperComponent, DbxFormLoadingSourceDirective, DbxFormLoginFieldModule, DbxFormModule, DbxFormRepeatArrayTypeComponent, DbxFormSearchFormComponent, DbxFormSectionWrapperComponent, DbxFormSourceDirective, DbxFormSourceSelectFieldComponent, DbxFormSpacerDirective, DbxFormState, DbxFormStyleWrapperComponent, DbxFormSubsectionWrapperComponent, DbxFormTextAvailableFieldModule, DbxFormTimezoneStringFieldModule, DbxFormToggleWrapperComponent, DbxFormValueChangeDirective, DbxFormWorkingWrapperComponent, DbxFormlyComponent, DbxFormlyContext, DbxFormlyFieldsContextDirective, DbxFormlyFormComponentImportsModule, DbxItemListFieldComponent, DbxMutableForm, DbxPhoneFieldComponent, DbxPickableChipListFieldComponent, DbxPickableListFieldComponent, DbxPickableListFieldItemListComponent, DbxPickableListFieldItemListViewComponent, DbxPickableListFieldItemListViewItemComponent, DbxSearchableChipFieldComponent, DbxSearchableFieldAutocompleteItemComponent, DbxSearchableTextFieldComponent, DbxTextEditorFieldComponent, DbxTimeDurationFieldComponent, FIELD_VALUES_ARE_EQUAL_VALIDATION_KEY, FIELD_VALUE_IS_AVAILABLE_ERROR_VALIDATION_KEY, FIELD_VALUE_IS_AVAILABLE_VALIDATION_KEY, INVALID_PHONE_NUMBER_EXTENSION_MESSAGE, INVALID_PHONE_NUMBER_MESSAGE, IS_DIVISIBLE_BY_VALIDATION_KEY, IS_NOT_WEBSITE_URL_VALIDATION_KEY, IS_NOT_WEBSITE_URL_WITH_EXPECTED_DOMAIN_VALIDATION_KEY, IS_NOT_WEBSITE_URL_WITH_PREFIX_VALIDATION_KEY, LABEL_STRING_MAX_LENGTH, MAX_LENGTH_VALIDATION_MESSAGE, MAX_VALIDATION_MESSAGE, MIN_LENGTH_VALIDATION_MESSAGE, MIN_VALIDATION_MESSAGE, PHONE_LABEL_MAX_LENGTH, REQUIRED_VALIDATION_MESSAGE, SEARCH_STRING_MAX_LENGTH, TAKE_NEXT_UPCOMING_TIME_CONFIG_OBS, addValueSelectionOptionFunction, addWrapperToFormlyFieldConfig, addressField, addressFormlyFields, addressLineField, addressListField, autoTouchWrapper, checkIsFieldFlexLayoutGroupFieldConfig, checkboxField, checklistItemField, chipTextField, cityField, componentField, countryField, dateRangeField, dateTimeField, dateTimePreset, dateTimeRangeField, dbxDateRangeIsSameDateRangeFieldValue, dbxDateTimeInputValueParseFactory, dbxDateTimeIsSameDateTimeFieldValue, dbxDateTimeOutputValueFactory, dbxFormSearchFormFields, dbxFormSourceObservable, dbxFormSourceObservableFromStream, dbxFormlyFormComponentProviders, dbxListField, defaultValidationMessages, disableFormlyFieldAutofillAttributes, dollarAmountField, durationMaxValidationMessage, durationMinValidationMessage, emailField, expandWrapper, fieldValueIsAvailableValidator, fieldValuesAreEqualValidator, filterPartialPotentialFieldConfigValuesFromObject, filterPickableItemFieldValuesByLabel, filterPickableItemFieldValuesByLabelFilterFunction, fixedDateRangeField, flexLayoutWrapper, formlyField, hiddenField, infoWrapper, isDbxDateTimeFieldTimeDateConfig, isDivisibleBy, isDomain, isE164PhoneNumber, isE164PhoneNumberWithValidExtension, isInRange, isPhoneExtension, isTruthy, isWebsiteUrlValidator, latLngTextField, makeMetaFilterSearchableFieldValueDisplayFn, maxLengthValidationMessage, maxValidationMessage, mergePropsValueObjects, minLengthValidationMessage, minValidationMessage, nameField, numberField, numberFieldTransformParser, numberSliderField, partialPotentialFieldConfigKeys, partialPotentialFieldConfigKeysFilter, phoneAndLabelSectionField, phoneField, phoneListField, pickableItemChipField, pickableItemListField, pickableValueFieldValuesConfigForStaticLabeledValues, propsAndConfigForFieldConfig, propsValueForFieldConfig, provideDbxForm, provideDbxFormConfiguration, provideDbxFormFormlyFieldDeclarations, provideDbxMutableForm, provideFormlyContext, repeatArrayField, searchableChipField, searchableStringChipField, searchableTextField, sectionWrapper, sortPickableItemsByLabel, sortPickableItemsByLabelStringFunction, sourceSelectField, stateField, streamValueFromControl, styleWrapper, subsectionWrapper, syncConfigValueObs, textAreaField, textEditorField, textField, textFieldTransformParser, textIsAvailableField, textPasswordField, textPasswordWithVerifyFieldGroup, textVerifyPasswordField, timeDurationField, timeOnlyField, timezoneStringField, timezoneStringSearchFunction, toggleDisableFormControl, toggleField, toggleWrapper, usernameLoginField, usernamePasswordLoginFields, validatorsForFieldConfig, valueSelectionField, websiteUrlField, workingWrapper, wrappedPhoneAndLabelField, zipCodeField };
8102
8682
  //# sourceMappingURL=dereekb-dbx-form.mjs.map