@dereekb/dbx-form 13.2.2 → 13.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -76,20 +76,47 @@ var DbxFormState;
|
|
|
76
76
|
*/
|
|
77
77
|
DbxFormState[DbxFormState["USED"] = 1] = "USED";
|
|
78
78
|
})(DbxFormState || (DbxFormState = {}));
|
|
79
|
+
/**
|
|
80
|
+
* Default key used when disabling/enabling a form without specifying a custom key.
|
|
81
|
+
*/
|
|
79
82
|
const DEFAULT_FORM_DISABLED_KEY = 'dbx_form_disabled';
|
|
80
83
|
/**
|
|
81
84
|
* Form that has an event stream, value, and state items.
|
|
82
85
|
*/
|
|
83
86
|
class DbxForm {
|
|
84
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Mutable extension of {@link DbxForm} that supports setting values, resetting, and disabling the form.
|
|
90
|
+
*
|
|
91
|
+
* @typeParam T - The form value type.
|
|
92
|
+
*/
|
|
85
93
|
class DbxMutableForm extends DbxForm {
|
|
86
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Provides the given type as a {@link DbxForm} in Angular's dependency injection system.
|
|
97
|
+
*
|
|
98
|
+
* @param sourceType - The concrete form type to register as a provider.
|
|
99
|
+
* @returns An array of Angular providers.
|
|
100
|
+
*/
|
|
87
101
|
function provideDbxForm(sourceType) {
|
|
88
102
|
return [{ provide: DbxForm, useExisting: forwardRef(() => sourceType) }];
|
|
89
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Provides the given type as both a {@link DbxForm} and {@link DbxMutableForm} in Angular's dependency injection system.
|
|
106
|
+
*
|
|
107
|
+
* @param sourceType - The concrete mutable form type to register as a provider.
|
|
108
|
+
* @returns An array of Angular providers.
|
|
109
|
+
*/
|
|
90
110
|
function provideDbxMutableForm(sourceType) {
|
|
91
111
|
return [...provideDbxForm(sourceType), { provide: DbxMutableForm, useExisting: forwardRef(() => sourceType) }];
|
|
92
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Enables or disables an Angular form control based on the provided flag.
|
|
115
|
+
*
|
|
116
|
+
* @param form - The Angular abstract control to enable or disable.
|
|
117
|
+
* @param isDisabled - Whether to disable (`true`) or enable (`false`) the control.
|
|
118
|
+
* @param config - Optional configuration passed to the control's `disable()` or `enable()` methods.
|
|
119
|
+
*/
|
|
93
120
|
function toggleDisableFormControl(form, isDisabled, config) {
|
|
94
121
|
if (isDisabled) {
|
|
95
122
|
form.disable(config);
|
|
@@ -99,6 +126,9 @@ function toggleDisableFormControl(form, isDisabled, config) {
|
|
|
99
126
|
}
|
|
100
127
|
}
|
|
101
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Disabled key used by {@link DbxActionFormDirective} to manage the form's disabled state during action processing.
|
|
131
|
+
*/
|
|
102
132
|
const APP_ACTION_FORM_DISABLED_KEY = 'dbx_action_form';
|
|
103
133
|
/**
|
|
104
134
|
* Used with an action to bind a form to an action as it's value source.
|
|
@@ -106,6 +136,11 @@ const APP_ACTION_FORM_DISABLED_KEY = 'dbx_action_form';
|
|
|
106
136
|
* If the form has errors when the action is trigger, it will reject the action.
|
|
107
137
|
*
|
|
108
138
|
* If the source is not considered modified, the trigger will be ignored.
|
|
139
|
+
*
|
|
140
|
+
* @selector `[dbxActionForm]`
|
|
141
|
+
*
|
|
142
|
+
* @typeParam T - The form value type.
|
|
143
|
+
* @typeParam O - The output value type passed to the action source.
|
|
109
144
|
*/
|
|
110
145
|
class DbxActionFormDirective {
|
|
111
146
|
form = inject((DbxMutableForm), { host: true });
|
|
@@ -227,6 +262,13 @@ class DbxActionFormDirective {
|
|
|
227
262
|
this.form.setDisabled(APP_ACTION_FORM_DISABLED_KEY, disable);
|
|
228
263
|
});
|
|
229
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* Checks whether the given form value is both valid and modified, optionally applying override functions.
|
|
267
|
+
*
|
|
268
|
+
* @param value - The current form value to check.
|
|
269
|
+
* @param overrides - Optional override functions for the validity and modification checks.
|
|
270
|
+
* @returns An observable emitting a tuple of `[isValid, isModified]`.
|
|
271
|
+
*/
|
|
230
272
|
checkIsValidAndIsModified(value, overrides) {
|
|
231
273
|
const { isModifiedFunction: overrideIsModifiedFunction, isValidFunction: overrideIsValidFunction } = overrides ?? {};
|
|
232
274
|
const isValidFunctionObs = overrideIsValidFunction != null ? of(overrideIsValidFunction) : this.isValidFunction$;
|
|
@@ -235,9 +277,21 @@ class DbxActionFormDirective {
|
|
|
235
277
|
return combineLatest([isValid(value), isModified(value)]).pipe(map(([valid, modified]) => [valid, modified]));
|
|
236
278
|
}));
|
|
237
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* Pre-checks whether the form value is valid and modified before marking it as ready.
|
|
282
|
+
*
|
|
283
|
+
* @param value - The current form value.
|
|
284
|
+
* @returns An observable emitting a tuple of `[isValid, isModified]`.
|
|
285
|
+
*/
|
|
238
286
|
preCheckReadyValue(value) {
|
|
239
287
|
return this.checkIsValidAndIsModified(value);
|
|
240
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Transforms the form value into an action value result, applying the optional map function if provided.
|
|
291
|
+
*
|
|
292
|
+
* @param value - The validated form value.
|
|
293
|
+
* @returns An observable emitting the action value getter result.
|
|
294
|
+
*/
|
|
241
295
|
readyValue(value) {
|
|
242
296
|
return this.mapValueFunction$.pipe(switchMap((mapFunction) => {
|
|
243
297
|
if (mapFunction) {
|
|
@@ -260,12 +314,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
260
314
|
}], ctorParameters: () => [], propDecorators: { dbxActionFormDisabledOnWorking: [{ type: i0.Input, args: [{ isSignal: true, alias: "dbxActionFormDisabledOnWorking", required: false }] }], dbxActionFormIsValid: [{ type: i0.Input, args: [{ isSignal: true, alias: "dbxActionFormIsValid", required: false }] }], dbxActionFormIsEqual: [{ type: i0.Input, args: [{ isSignal: true, alias: "dbxActionFormIsEqual", required: false }] }], dbxActionFormIsModified: [{ type: i0.Input, args: [{ isSignal: true, alias: "dbxActionFormIsModified", required: false }] }], dbxActionFormMapValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "dbxActionFormMapValue", required: false }] }] } });
|
|
261
315
|
|
|
262
316
|
/**
|
|
263
|
-
* Extension of DbxActionTransitionSafetyDirective that forces the form to update
|
|
317
|
+
* Extension of {@link DbxActionTransitionSafetyDirective} that forces the form to update before
|
|
318
|
+
* evaluating transition safety. This ensures the latest form state is considered when deciding
|
|
319
|
+
* whether to block or allow a route transition.
|
|
320
|
+
*
|
|
321
|
+
* NOTE: Only works with UIRouter.
|
|
264
322
|
*
|
|
265
|
-
*
|
|
323
|
+
* @selector `[dbxActionFormSafety]`
|
|
324
|
+
*
|
|
325
|
+
* @typeParam T - The form value type.
|
|
326
|
+
* @typeParam O - The output value type passed to the action source.
|
|
266
327
|
*/
|
|
267
328
|
class DbxActionFormSafetyDirective extends DbxActionTransitionSafetyDirective {
|
|
268
329
|
dbxActionForm = inject((DbxActionFormDirective), { host: true });
|
|
330
|
+
/**
|
|
331
|
+
* The safety type that controls when transitions are blocked.
|
|
332
|
+
*
|
|
333
|
+
* Defaults to `'auto'`, which blocks transitions when the form has unsaved changes.
|
|
334
|
+
*/
|
|
269
335
|
dbxActionFormSafety = input('auto', ...(ngDevMode ? [{ debugName: "dbxActionFormSafety" }] : []));
|
|
270
336
|
_dbxActionFormSafetyUpdateEffect = effect(() => this._safetyType.next(this.dbxActionFormSafety()), ...(ngDevMode ? [{ debugName: "_dbxActionFormSafetyUpdateEffect" }] : []));
|
|
271
337
|
_handleOnBeforeTransition(transition) {
|
|
@@ -559,9 +625,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
559
625
|
}]
|
|
560
626
|
}], ctorParameters: () => [], propDecorators: { formlyForm: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FormlyForm), { isSignal: true }] }] } });
|
|
561
627
|
|
|
628
|
+
/**
|
|
629
|
+
* Creates an observable that pipes input values to a form based on the specified mode.
|
|
630
|
+
*
|
|
631
|
+
* This is a convenience wrapper around {@link dbxFormSourceObservableFromStream} that
|
|
632
|
+
* extracts the stream from the form instance.
|
|
633
|
+
*
|
|
634
|
+
* @param form - The mutable form to derive stream state from.
|
|
635
|
+
* @param inputObs - The source observable or value to pipe into the form.
|
|
636
|
+
* @param modeObs - Observable controlling when values are forwarded (reset, always, or every).
|
|
637
|
+
* @returns An observable of values to be set on the form.
|
|
638
|
+
*/
|
|
562
639
|
function dbxFormSourceObservable(form, inputObs, modeObs) {
|
|
563
640
|
return dbxFormSourceObservableFromStream(form.stream$, inputObs, modeObs);
|
|
564
641
|
}
|
|
642
|
+
/**
|
|
643
|
+
* Creates an observable that pipes input values to a form based on the form's stream state and the specified mode.
|
|
644
|
+
*
|
|
645
|
+
* - `'reset'`: Only forwards the value when the form enters the RESET state.
|
|
646
|
+
* - `'always'`: Forwards values while not initializing, with throttling and loop detection.
|
|
647
|
+
* - `'every'`: Forwards values while not initializing, without throttling or loop protection.
|
|
648
|
+
*
|
|
649
|
+
* @param streamObs - Observable of the form's state stream.
|
|
650
|
+
* @param inputObs - The source observable or value to pipe into the form.
|
|
651
|
+
* @param modeObs - Observable or value controlling when values are forwarded.
|
|
652
|
+
* @returns An observable of values to be set on the form.
|
|
653
|
+
*/
|
|
565
654
|
function dbxFormSourceObservableFromStream(streamObs, inputObs, modeObs) {
|
|
566
655
|
const value$ = asObservable(inputObs).pipe(shareReplay(1)); // catch/share the latest emission
|
|
567
656
|
const state$ = streamObs.pipe(map((x) => x.state), distinctUntilChanged());
|
|
@@ -618,11 +707,26 @@ function dbxFormSourceObservableFromStream(streamObs, inputObs, modeObs) {
|
|
|
618
707
|
}));
|
|
619
708
|
}
|
|
620
709
|
/**
|
|
621
|
-
*
|
|
710
|
+
* Directive that sets a form's value based on an input observable or value source.
|
|
711
|
+
*
|
|
712
|
+
* Supports different modes for when the value is forwarded to the form:
|
|
713
|
+
* - `'reset'` (default): Only sets the form value when the form is reset.
|
|
714
|
+
* - `'always'`: Sets the form value on every emission, with throttling and loop detection.
|
|
715
|
+
* - `'every'`: Sets the form value on every emission, without throttling.
|
|
716
|
+
*
|
|
717
|
+
* @selector `[dbxFormSource]`
|
|
718
|
+
*
|
|
719
|
+
* @typeParam T - The form value type.
|
|
622
720
|
*/
|
|
623
721
|
class DbxFormSourceDirective {
|
|
624
722
|
form = inject((DbxMutableForm), { host: true });
|
|
723
|
+
/**
|
|
724
|
+
* The mode controlling when the source value is forwarded to the form.
|
|
725
|
+
*/
|
|
625
726
|
dbxFormSourceMode = input(...(ngDevMode ? [undefined, { debugName: "dbxFormSourceMode" }] : []));
|
|
727
|
+
/**
|
|
728
|
+
* The source value or observable to pipe into the form.
|
|
729
|
+
*/
|
|
626
730
|
dbxFormSource = input(...(ngDevMode ? [undefined, { debugName: "dbxFormSource" }] : []));
|
|
627
731
|
_effectSub = cleanSubscription();
|
|
628
732
|
_setFormSourceObservableEffect = effect(() => {
|
|
@@ -648,7 +752,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
648
752
|
}], propDecorators: { dbxFormSourceMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "dbxFormSourceMode", required: false }] }], dbxFormSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dbxFormSource", required: false }] }] } });
|
|
649
753
|
|
|
650
754
|
/**
|
|
755
|
+
* A standalone dialog component that renders a dynamic Formly form within a Material dialog.
|
|
756
|
+
*
|
|
757
|
+
* Provides a header, a configurable form, and a submit button wired to an action handler.
|
|
758
|
+
* The dialog closes with the submitted form value on success, or `undefined` if dismissed.
|
|
651
759
|
*
|
|
760
|
+
* Use {@link DbxFormActionDialogComponent.openDialogWithForm} to open the dialog programmatically.
|
|
761
|
+
*
|
|
762
|
+
* @typeParam O - The form value type produced by the dialog.
|
|
652
763
|
*/
|
|
653
764
|
class DbxFormActionDialogComponent extends AbstractDialogDirective {
|
|
654
765
|
_fieldsSub = cleanSubscription();
|
|
@@ -665,10 +776,20 @@ class DbxFormActionDialogComponent extends AbstractDialogDirective {
|
|
|
665
776
|
this.context.fields = fields;
|
|
666
777
|
}));
|
|
667
778
|
}
|
|
779
|
+
/**
|
|
780
|
+
* Action handler that marks the action as successful and closes the dialog with the submitted value.
|
|
781
|
+
*/
|
|
668
782
|
handleSubmitValue = (value, context) => {
|
|
669
783
|
context.success();
|
|
670
784
|
this.close(value);
|
|
671
785
|
};
|
|
786
|
+
/**
|
|
787
|
+
* Opens a new dialog with a dynamic Formly form using the provided configuration.
|
|
788
|
+
*
|
|
789
|
+
* @param matDialog - The Angular Material dialog service.
|
|
790
|
+
* @param config - Configuration for the dialog, including fields, header, and initial value.
|
|
791
|
+
* @returns A reference to the opened dialog, which resolves to the submitted value or `undefined`.
|
|
792
|
+
*/
|
|
672
793
|
static openDialogWithForm(matDialog, config) {
|
|
673
794
|
const dialogRef = matDialog.open((DbxFormActionDialogComponent), {
|
|
674
795
|
width: '90vw',
|
|
@@ -710,15 +831,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
710
831
|
}]
|
|
711
832
|
}] });
|
|
712
833
|
|
|
834
|
+
/**
|
|
835
|
+
* Default mode for the {@link DbxFormLoadingSourceDirective}, which only passes values on form reset.
|
|
836
|
+
*/
|
|
713
837
|
const DEFAULT_DBX_FORM_LOADING_SOURCE_DIRECTIVE_MODE = 'reset';
|
|
714
838
|
/**
|
|
715
|
-
*
|
|
839
|
+
* Directive that sets a form's value from a {@link LoadingState} source once loading is complete.
|
|
716
840
|
*
|
|
717
|
-
* Only passes non-null values from the source.
|
|
841
|
+
* Only passes non-null values from the source. Extracts the value from the finished loading state
|
|
842
|
+
* and forwards it to the form using the configured mode.
|
|
843
|
+
*
|
|
844
|
+
* @selector `[dbxFormLoadingSource]`
|
|
845
|
+
*
|
|
846
|
+
* @typeParam T - The form value type (must extend object).
|
|
718
847
|
*/
|
|
719
848
|
class DbxFormLoadingSourceDirective {
|
|
720
849
|
form = inject((DbxMutableForm), { host: true });
|
|
850
|
+
/**
|
|
851
|
+
* The mode controlling when the loading source value is forwarded to the form.
|
|
852
|
+
*
|
|
853
|
+
* Defaults to `'reset'`.
|
|
854
|
+
*/
|
|
721
855
|
dbxFormLoadingSourceMode = input(DEFAULT_DBX_FORM_LOADING_SOURCE_DIRECTIVE_MODE, { ...(ngDevMode ? { debugName: "dbxFormLoadingSourceMode" } : {}), transform: (x) => x ?? DEFAULT_DBX_FORM_LOADING_SOURCE_DIRECTIVE_MODE });
|
|
856
|
+
/**
|
|
857
|
+
* The loading state source to observe. The form value is set once loading finishes with a non-null value.
|
|
858
|
+
*/
|
|
722
859
|
dbxFormLoadingSource = input(...(ngDevMode ? [undefined, { debugName: "dbxFormLoadingSource" }] : []));
|
|
723
860
|
mode$ = toObservable(this.dbxFormLoadingSourceMode);
|
|
724
861
|
source$ = toObservable(this.dbxFormLoadingSource).pipe(maybeValueFromObservableOrValue(), filterMaybe(), valueFromFinishedLoadingState());
|
|
@@ -739,12 +876,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
739
876
|
}], ctorParameters: () => [], propDecorators: { dbxFormLoadingSourceMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "dbxFormLoadingSourceMode", required: false }] }], dbxFormLoadingSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dbxFormLoadingSource", required: false }] }] } });
|
|
740
877
|
|
|
741
878
|
/**
|
|
742
|
-
*
|
|
879
|
+
* Directive that observes form value changes and emits the current value when the form is complete/valid,
|
|
880
|
+
* or `undefined` when the form is incomplete.
|
|
743
881
|
*
|
|
744
|
-
*
|
|
882
|
+
* Subscribes to the form's stream during `ngOnInit` to ensure the first emission occurs after initialization.
|
|
883
|
+
*
|
|
884
|
+
* @selector `[dbxFormValueChange]`
|
|
885
|
+
*
|
|
886
|
+
* @typeParam T - The form value type.
|
|
745
887
|
*/
|
|
746
888
|
class DbxFormValueChangeDirective {
|
|
747
889
|
form = inject((DbxForm), { host: true });
|
|
890
|
+
/**
|
|
891
|
+
* Emits the current form value when the form is complete/valid, or `undefined` when incomplete.
|
|
892
|
+
*/
|
|
748
893
|
dbxFormValueChange = output();
|
|
749
894
|
_sub = cleanSubscription();
|
|
750
895
|
ngOnInit() {
|
|
@@ -774,15 +919,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
774
919
|
/**
|
|
775
920
|
* Streams a value from the input control at the given path. If no path is specified, streams the value from the control.
|
|
776
921
|
*
|
|
777
|
-
*
|
|
778
|
-
*
|
|
779
|
-
* @
|
|
922
|
+
* Returns `undefined` if the control at the given path does not exist.
|
|
923
|
+
*
|
|
924
|
+
* @param fromControl - The root control to retrieve the target control from.
|
|
925
|
+
* @param path - Optional dot-delimited path to a nested control.
|
|
926
|
+
* @returns An observable of the control's value changes (starting with the current value), or `undefined` if the control was not found.
|
|
927
|
+
*
|
|
928
|
+
* @example
|
|
929
|
+
* ```ts
|
|
930
|
+
* const name$ = streamValueFromControl<string>(formGroup, 'user.name');
|
|
931
|
+
* ```
|
|
780
932
|
*/
|
|
781
933
|
function streamValueFromControl(fromControl, path) {
|
|
782
934
|
const control = path ? fromControl.get(path) : fromControl;
|
|
783
935
|
return control?.valueChanges.pipe(startWith(control.value));
|
|
784
936
|
}
|
|
785
937
|
|
|
938
|
+
/**
|
|
939
|
+
* Root Angular module for the dbx-form library.
|
|
940
|
+
*
|
|
941
|
+
* Serves as the base module for form-related functionality. Import this module
|
|
942
|
+
* to access the core form features provided by the library.
|
|
943
|
+
*/
|
|
786
944
|
class DbxFormModule {
|
|
787
945
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
788
946
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormModule });
|
|
@@ -795,30 +953,91 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
795
953
|
}]
|
|
796
954
|
}] });
|
|
797
955
|
|
|
956
|
+
/**
|
|
957
|
+
* Returns a validation message indicating the minimum character length was not met.
|
|
958
|
+
*
|
|
959
|
+
* @param err - The validation error object.
|
|
960
|
+
* @param field - The Formly field configuration containing `minLength` in its props.
|
|
961
|
+
* @returns A human-readable validation message string.
|
|
962
|
+
*/
|
|
798
963
|
function minLengthValidationMessage(err, field) {
|
|
799
964
|
return `Should have atleast ${field.props.minLength} characters.`;
|
|
800
965
|
}
|
|
966
|
+
/**
|
|
967
|
+
* Returns a validation message indicating the maximum character length was exceeded.
|
|
968
|
+
*
|
|
969
|
+
* @param err - The validation error object.
|
|
970
|
+
* @param field - The Formly field configuration containing `maxLength` in its props.
|
|
971
|
+
* @returns A human-readable validation message string.
|
|
972
|
+
*/
|
|
801
973
|
function maxLengthValidationMessage(err, field) {
|
|
802
974
|
return `This value should be less than ${field.props.maxLength} characters.`;
|
|
803
975
|
}
|
|
976
|
+
/**
|
|
977
|
+
* Returns a validation message indicating the value is below the minimum allowed.
|
|
978
|
+
*
|
|
979
|
+
* @param err - The validation error object.
|
|
980
|
+
* @param field - The Formly field configuration containing `min` in its props.
|
|
981
|
+
* @returns A human-readable validation message string.
|
|
982
|
+
*/
|
|
804
983
|
function minValidationMessage(err, field) {
|
|
805
984
|
return `This value should be more than or equal to ${field.props.min}.`;
|
|
806
985
|
}
|
|
986
|
+
/**
|
|
987
|
+
* Returns a validation message indicating the value exceeds the maximum allowed.
|
|
988
|
+
*
|
|
989
|
+
* @param err - The validation error object.
|
|
990
|
+
* @param field - The Formly field configuration containing `max` in its props.
|
|
991
|
+
* @returns A human-readable validation message string.
|
|
992
|
+
*/
|
|
807
993
|
function maxValidationMessage(err, field) {
|
|
808
994
|
return `This value should be less than or equal to ${field.props.max}.`;
|
|
809
995
|
}
|
|
996
|
+
/**
|
|
997
|
+
* Validation message option for required fields.
|
|
998
|
+
*/
|
|
810
999
|
const REQUIRED_VALIDATION_MESSAGE = { name: 'required', message: 'This field is required.' };
|
|
1000
|
+
/**
|
|
1001
|
+
* Validation message option for minimum length violations.
|
|
1002
|
+
*/
|
|
811
1003
|
const MIN_LENGTH_VALIDATION_MESSAGE = { name: 'minLength', message: minLengthValidationMessage };
|
|
1004
|
+
/**
|
|
1005
|
+
* Validation message option for maximum length violations.
|
|
1006
|
+
*/
|
|
812
1007
|
const MAX_LENGTH_VALIDATION_MESSAGE = { name: 'maxLength', message: maxLengthValidationMessage };
|
|
1008
|
+
/**
|
|
1009
|
+
* Validation message option for minimum value violations.
|
|
1010
|
+
*/
|
|
813
1011
|
const MIN_VALIDATION_MESSAGE = { name: 'min', message: minValidationMessage };
|
|
1012
|
+
/**
|
|
1013
|
+
* Validation message option for maximum value violations.
|
|
1014
|
+
*/
|
|
814
1015
|
const MAX_VALIDATION_MESSAGE = { name: 'max', message: maxValidationMessage };
|
|
1016
|
+
/**
|
|
1017
|
+
* Validation message option for invalid phone numbers.
|
|
1018
|
+
*/
|
|
815
1019
|
const INVALID_PHONE_NUMBER_MESSAGE = { name: 'validatePhoneNumber', message: 'This is not a valid phone number.' };
|
|
1020
|
+
/**
|
|
1021
|
+
* Validation message option for invalid phone number extensions.
|
|
1022
|
+
*/
|
|
816
1023
|
const INVALID_PHONE_NUMBER_EXTENSION_MESSAGE = { name: 'validatePhoneNumberExtension', message: 'This is not a valid phone number extension.' };
|
|
1024
|
+
/**
|
|
1025
|
+
* Returns the full set of default validation messages used by the form system.
|
|
1026
|
+
*
|
|
1027
|
+
* Includes messages for: required, minLength, maxLength, min, max, phone number, and phone number extension.
|
|
1028
|
+
*
|
|
1029
|
+
* @returns An array of {@link ValidationMessageOption} objects.
|
|
1030
|
+
*/
|
|
817
1031
|
function defaultValidationMessages() {
|
|
818
1032
|
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];
|
|
819
1033
|
}
|
|
820
1034
|
|
|
821
1035
|
// MARK: Default
|
|
1036
|
+
/**
|
|
1037
|
+
* Default display component for checklist items.
|
|
1038
|
+
*
|
|
1039
|
+
* Renders label, sublabel, and description text from the injected {@link ChecklistItemDisplayContent}.
|
|
1040
|
+
*/
|
|
822
1041
|
class DbxDefaultChecklistItemFieldDisplayComponent {
|
|
823
1042
|
_displayContentSignal = signal(undefined, ...(ngDevMode ? [{ debugName: "_displayContentSignal" }] : []));
|
|
824
1043
|
displayContentSignal = this._displayContentSignal.asReadonly();
|
|
@@ -866,6 +1085,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
866
1085
|
}]
|
|
867
1086
|
}] });
|
|
868
1087
|
|
|
1088
|
+
/**
|
|
1089
|
+
* Wrapper component that injects dynamic display content into a checklist item
|
|
1090
|
+
* via {@link DbxInjectionComponent}. Subscribes to the parent field's display content observable.
|
|
1091
|
+
*/
|
|
869
1092
|
class DbxChecklistItemContentComponent {
|
|
870
1093
|
checklistItemFieldComponent = inject((DbxChecklistItemFieldComponent));
|
|
871
1094
|
config = {
|
|
@@ -893,6 +1116,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
893
1116
|
imports: [DbxInjectionComponent]
|
|
894
1117
|
}]
|
|
895
1118
|
}] });
|
|
1119
|
+
/**
|
|
1120
|
+
* Formly field component that renders a single checklist item with a checkbox,
|
|
1121
|
+
* optional anchor link, and dynamic display content.
|
|
1122
|
+
*
|
|
1123
|
+
* The display content is provided as an observable and rendered via a configurable
|
|
1124
|
+
* component class (defaults to {@link DbxDefaultChecklistItemFieldDisplayComponent}).
|
|
1125
|
+
*/
|
|
896
1126
|
class DbxChecklistItemFieldComponent extends FieldType {
|
|
897
1127
|
_displayContentObs = signal(undefined, ...(ngDevMode ? [{ debugName: "_displayContentObs" }] : []));
|
|
898
1128
|
displayContent$ = toObservable(this._displayContentObs).pipe(switchMapFilterMaybe(), distinctUntilChanged(), shareReplay(1));
|
|
@@ -936,6 +1166,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
936
1166
|
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [ReactiveFormsModule, MatCheckboxModule, DbxAnchorComponent, MatRippleModule, MatIconModule, DbxChecklistItemContentComponent], template: "<div class=\"dbx-checklist-item-wrapper\" [formGroup]=\"formGroup\">\n @if (label) {\n <div class=\"dbx-checklist-item-label\">{{ label }}</div>\n }\n <div class=\"dbx-checklist-item\">\n <div class=\"dbx-checklist-item-check\">\n <mat-checkbox [formControlName]=\"formControlName\"></mat-checkbox>\n </div>\n <div class=\"dbx-checklist-item-content-wrapper\">\n <dbx-anchor [block]=\"true\" [anchor]=\"anchorSignal()\">\n <div class=\"dbx-checklist-item-content\" matRipple [matRippleDisabled]=\"rippleDisabledSignal()\">\n <dbx-checklist-item-content-component></dbx-checklist-item-content-component>\n <span class=\"spacer\"></span>\n @if (!rippleDisabledSignal()) {\n <mat-icon>navigate_next</mat-icon>\n }\n </div>\n </dbx-anchor>\n </div>\n </div>\n @if (description) {\n <div class=\"dbx-hint\">{{ description }}</div>\n }\n</div>\n" }]
|
|
937
1167
|
}] });
|
|
938
1168
|
|
|
1169
|
+
/**
|
|
1170
|
+
* Formly wrapper that renders a Material info icon button beside the wrapped field.
|
|
1171
|
+
* Clicking the button invokes the configured `onInfoClick` callback.
|
|
1172
|
+
*
|
|
1173
|
+
* Registered as Formly wrapper `'info'`.
|
|
1174
|
+
*/
|
|
939
1175
|
class DbxFormInfoWrapperComponent extends FieldWrapper {
|
|
940
1176
|
get infoWrapper() {
|
|
941
1177
|
return this.props;
|
|
@@ -978,6 +1214,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
978
1214
|
}]
|
|
979
1215
|
}] });
|
|
980
1216
|
|
|
1217
|
+
/**
|
|
1218
|
+
* Formly wrapper that renders the wrapped field inside a `dbx-section` layout
|
|
1219
|
+
* with an optional header and hint text.
|
|
1220
|
+
*
|
|
1221
|
+
* Registered as Formly wrapper `'section'`.
|
|
1222
|
+
*
|
|
1223
|
+
* @selector dbx-form-section-wrapper
|
|
1224
|
+
*/
|
|
981
1225
|
class DbxFormSectionWrapperComponent extends FieldWrapper {
|
|
982
1226
|
get headerConfig() {
|
|
983
1227
|
return this.props;
|
|
@@ -1004,6 +1248,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1004
1248
|
}]
|
|
1005
1249
|
}] });
|
|
1006
1250
|
|
|
1251
|
+
/**
|
|
1252
|
+
* Formly wrapper that arranges child fields in a responsive flex layout
|
|
1253
|
+
* using the `dbxFlexGroup` directive.
|
|
1254
|
+
*
|
|
1255
|
+
* Registered as Formly wrapper `'flex'`.
|
|
1256
|
+
*/
|
|
1007
1257
|
class DbxFormFlexWrapperComponent extends FieldWrapper {
|
|
1008
1258
|
get flexWrapper() {
|
|
1009
1259
|
return this.props;
|
|
@@ -1038,6 +1288,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1038
1288
|
}]
|
|
1039
1289
|
}] });
|
|
1040
1290
|
|
|
1291
|
+
/**
|
|
1292
|
+
* Formly wrapper that renders the wrapped field inside a `dbx-subsection` layout
|
|
1293
|
+
* with an optional header and hint text.
|
|
1294
|
+
*
|
|
1295
|
+
* Registered as Formly wrapper `'subsection'`.
|
|
1296
|
+
*
|
|
1297
|
+
* @selector dbx-form-subsection-wrapper
|
|
1298
|
+
*/
|
|
1041
1299
|
class DbxFormSubsectionWrapperComponent extends FieldWrapper {
|
|
1042
1300
|
get headerConfig() {
|
|
1043
1301
|
return this.props;
|
|
@@ -1064,7 +1322,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1064
1322
|
}]
|
|
1065
1323
|
}] });
|
|
1066
1324
|
|
|
1325
|
+
/**
|
|
1326
|
+
* Default value existence check that returns `true` if the object is non-empty.
|
|
1327
|
+
*/
|
|
1067
1328
|
const DEFAULT_HAS_VALUE_FN = (x) => !objectIsEmpty(x);
|
|
1329
|
+
/**
|
|
1330
|
+
* Abstract base directive for expandable form section wrappers.
|
|
1331
|
+
*
|
|
1332
|
+
* Manages the show/hide state based on whether the field has a value or
|
|
1333
|
+
* whether the user manually opened the section. Subclasses provide the
|
|
1334
|
+
* specific UI (expand button, toggle, etc.).
|
|
1335
|
+
*/
|
|
1068
1336
|
class AbstractFormExpandSectionWrapperDirective extends FieldWrapper {
|
|
1069
1337
|
_formControlObs = new BehaviorSubject(undefined);
|
|
1070
1338
|
_toggleOpen = new BehaviorSubject(undefined);
|
|
@@ -1223,6 +1491,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1223
1491
|
}]
|
|
1224
1492
|
}] });
|
|
1225
1493
|
|
|
1494
|
+
/**
|
|
1495
|
+
* Formly wrapper that applies dynamic CSS classes and inline styles to the wrapped field.
|
|
1496
|
+
*
|
|
1497
|
+
* Supports both static values and reactive observables for `[ngClass]` and `[ngStyle]`.
|
|
1498
|
+
*
|
|
1499
|
+
* Registered as Formly wrapper `'style'`.
|
|
1500
|
+
*/
|
|
1226
1501
|
class DbxFormStyleWrapperComponent extends FieldWrapper {
|
|
1227
1502
|
_style = new BehaviorSubject(undefined);
|
|
1228
1503
|
_class = new BehaviorSubject(undefined);
|
|
@@ -1309,14 +1584,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1309
1584
|
}]
|
|
1310
1585
|
}] });
|
|
1311
1586
|
|
|
1587
|
+
/** Formly wrapper key for the auto-touch behavior wrapper. */
|
|
1312
1588
|
const AUTO_TOUCH_WRAPPER_KEY = 'autotouch';
|
|
1589
|
+
/** Formly wrapper key for the toggle (slide-toggle expand/collapse) wrapper. */
|
|
1313
1590
|
const TOGGLE_WRAPPER_KEY = 'toggle';
|
|
1591
|
+
/** Formly wrapper key for the section layout wrapper. */
|
|
1314
1592
|
const SECTION_WRAPPER_KEY = 'section';
|
|
1593
|
+
/** Formly wrapper key for the subsection layout wrapper. */
|
|
1315
1594
|
const SUBSECTION_WRAPPER_KEY = 'subsection';
|
|
1595
|
+
/** Formly wrapper key for the info button wrapper. */
|
|
1316
1596
|
const INFO_WRAPPER_KEY = 'info';
|
|
1597
|
+
/** Formly wrapper key for the flex layout wrapper. */
|
|
1317
1598
|
const FLEX_WRAPPER_KEY = 'flex';
|
|
1599
|
+
/** Formly wrapper key for the dynamic style/class wrapper. */
|
|
1318
1600
|
const STYLE_WRAPPER_KEY = 'style';
|
|
1601
|
+
/** Formly wrapper key for the async loading indicator wrapper. */
|
|
1319
1602
|
const WORKING_WRAPPER_KEY = 'working';
|
|
1603
|
+
/** Formly wrapper key for the expand/collapse section wrapper. */
|
|
1320
1604
|
const EXPAND_WRAPPER_KEY = 'expand';
|
|
1321
1605
|
|
|
1322
1606
|
const importsAndExports$g = [
|
|
@@ -1333,6 +1617,7 @@ const importsAndExports$g = [
|
|
|
1333
1617
|
FormlyModule,
|
|
1334
1618
|
FormlyMaterialModule
|
|
1335
1619
|
];
|
|
1620
|
+
/** Registers all Formly field wrapper types (section, flex, expand, toggle, style, info, working, autotouch, subsection). */
|
|
1336
1621
|
class DbxFormFormlyWrapperModule {
|
|
1337
1622
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyWrapperModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1338
1623
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyWrapperModule, imports: [AutoTouchFieldWrapperComponent,
|
|
@@ -1406,6 +1691,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1406
1691
|
}] });
|
|
1407
1692
|
|
|
1408
1693
|
const importsAndExports$f = [DbxChecklistItemFieldComponent, DbxChecklistItemContentComponent, DbxDefaultChecklistItemFieldDisplayComponent];
|
|
1694
|
+
/** Registers the `checklistitem` Formly field type with wrapper support. */
|
|
1409
1695
|
class DbxFormFormlyChecklistItemFieldModule {
|
|
1410
1696
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyChecklistItemFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1411
1697
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyChecklistItemFieldModule, imports: [DbxChecklistItemFieldComponent, DbxChecklistItemContentComponent, DbxDefaultChecklistItemFieldDisplayComponent, DbxFormFormlyWrapperModule, i1$1.FormlyModule], exports: [DbxChecklistItemFieldComponent, DbxChecklistItemContentComponent, DbxDefaultChecklistItemFieldDisplayComponent] });
|
|
@@ -1454,14 +1740,28 @@ function propsAndConfigForFieldConfig(fieldConfig, override) {
|
|
|
1454
1740
|
parsers
|
|
1455
1741
|
};
|
|
1456
1742
|
}
|
|
1743
|
+
/** Keys from {@link PartialPotentialFieldConfig} that are merged into Formly props. */
|
|
1457
1744
|
const partialPotentialFieldConfigKeys = ['label', 'placeholder', 'required', 'readonly', 'description', 'autocomplete'];
|
|
1745
|
+
/** Filter configuration for extracting field config keys from objects. */
|
|
1458
1746
|
const partialPotentialFieldConfigKeysFilter = {
|
|
1459
1747
|
keysFilter: partialPotentialFieldConfigKeys
|
|
1460
1748
|
};
|
|
1749
|
+
/** Merge function that combines multiple partial field configs, picking only the recognized keys. */
|
|
1461
1750
|
const mergePropsValueObjects = mergeObjectsFunction(partialPotentialFieldConfigKeysFilter);
|
|
1751
|
+
/** Filter function that extracts only the recognized field config keys from an object. */
|
|
1462
1752
|
const filterPartialPotentialFieldConfigValuesFromObject = filterFromPOJOFunction({
|
|
1463
1753
|
filter: partialPotentialFieldConfigKeysFilter
|
|
1464
1754
|
});
|
|
1755
|
+
/**
|
|
1756
|
+
* Builds a Formly props object from a field config and optional overrides.
|
|
1757
|
+
*
|
|
1758
|
+
* Merges label, placeholder, required, readonly, description, attributes, and autocomplete
|
|
1759
|
+
* settings. When autocomplete is `false`, disables browser autofill via special attributes.
|
|
1760
|
+
*
|
|
1761
|
+
* @param fieldConfig - Base field configuration
|
|
1762
|
+
* @param override - Optional property overrides
|
|
1763
|
+
* @returns Merged props object suitable for use in a {@link FormlyFieldConfig}
|
|
1764
|
+
*/
|
|
1465
1765
|
function propsValueForFieldConfig(fieldConfig, override) {
|
|
1466
1766
|
const { label, placeholder, required, readonly, description, autocomplete } = mergePropsValueObjects([fieldConfig, override]);
|
|
1467
1767
|
const attributes = mergeObjects([fieldConfig.attributes, override?.attributes]);
|
|
@@ -1498,6 +1798,21 @@ function disableFormlyFieldAutofillAttributes() {
|
|
|
1498
1798
|
autocomplete: 'off'
|
|
1499
1799
|
};
|
|
1500
1800
|
}
|
|
1801
|
+
/**
|
|
1802
|
+
* Converts Angular validators, async validators, and validation messages into the
|
|
1803
|
+
* Formly-compatible validator configuration format.
|
|
1804
|
+
*
|
|
1805
|
+
* @param input - Validators, async validators, and messages to convert
|
|
1806
|
+
* @returns A Formly-compatible validator config, or undefined if no validators provided
|
|
1807
|
+
*
|
|
1808
|
+
* @example
|
|
1809
|
+
* ```typescript
|
|
1810
|
+
* const config = validatorsForFieldConfig({
|
|
1811
|
+
* validators: [Validators.required],
|
|
1812
|
+
* messages: { required: 'This field is required' }
|
|
1813
|
+
* });
|
|
1814
|
+
* ```
|
|
1815
|
+
*/
|
|
1501
1816
|
function validatorsForFieldConfig(input) {
|
|
1502
1817
|
const validators = asArray(input.validators);
|
|
1503
1818
|
const asyncValidators = asArray(input.asyncValidators);
|
|
@@ -1524,6 +1839,21 @@ function validatorsForFieldConfig(input) {
|
|
|
1524
1839
|
return config;
|
|
1525
1840
|
}
|
|
1526
1841
|
|
|
1842
|
+
/**
|
|
1843
|
+
* Creates a Formly field configuration for a single checklist item with a checkbox
|
|
1844
|
+
* and display content (label, sublabel, description, anchor).
|
|
1845
|
+
*
|
|
1846
|
+
* @param config - Checklist item configuration with key and display content
|
|
1847
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'checklistitem'`
|
|
1848
|
+
*
|
|
1849
|
+
* @example
|
|
1850
|
+
* ```typescript
|
|
1851
|
+
* const field = checklistItemField({
|
|
1852
|
+
* key: 'emailNotifications',
|
|
1853
|
+
* displayContent: of({ label: 'Email Notifications', description: 'Receive updates via email' })
|
|
1854
|
+
* });
|
|
1855
|
+
* ```
|
|
1856
|
+
*/
|
|
1527
1857
|
function checklistItemField(config) {
|
|
1528
1858
|
const { key, displayContent, componentClass } = config;
|
|
1529
1859
|
const fieldConfig = formlyField({
|
|
@@ -1636,6 +1966,12 @@ class ChecklistItemFieldDataSetBuilder {
|
|
|
1636
1966
|
}
|
|
1637
1967
|
}
|
|
1638
1968
|
|
|
1969
|
+
/**
|
|
1970
|
+
* Formly field component that renders a custom Angular component via dynamic injection.
|
|
1971
|
+
*
|
|
1972
|
+
* Uses {@link DbxInjectionComponent} to instantiate the component class specified in the field's
|
|
1973
|
+
* `componentField` configuration.
|
|
1974
|
+
*/
|
|
1639
1975
|
class DbxFormComponentFieldComponent extends FieldType {
|
|
1640
1976
|
get config() {
|
|
1641
1977
|
return this.field.componentField;
|
|
@@ -1658,6 +1994,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1658
1994
|
}] });
|
|
1659
1995
|
|
|
1660
1996
|
const importsAndExports$e = [DbxFormComponentFieldComponent];
|
|
1997
|
+
/** Registers the `component` Formly field type for custom Angular component injection. */
|
|
1661
1998
|
class DbxFormFormlyComponentFieldModule {
|
|
1662
1999
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyComponentFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1663
2000
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyComponentFieldModule, imports: [DbxFormComponentFieldComponent, i1$1.FormlyModule], exports: [DbxFormComponentFieldComponent] });
|
|
@@ -1678,6 +2015,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1678
2015
|
}]
|
|
1679
2016
|
}] });
|
|
1680
2017
|
|
|
2018
|
+
/**
|
|
2019
|
+
* Creates a Formly field configuration that renders a custom Angular component.
|
|
2020
|
+
*
|
|
2021
|
+
* @param config - Component field configuration
|
|
2022
|
+
* @returns A {@link DbxFormComponentFormlyFieldConfig} with type `'component'`
|
|
2023
|
+
*
|
|
2024
|
+
* @example
|
|
2025
|
+
* ```typescript
|
|
2026
|
+
* const field = componentField({ componentClass: MyCustomFormComponent });
|
|
2027
|
+
* ```
|
|
2028
|
+
*/
|
|
1681
2029
|
function componentField(config) {
|
|
1682
2030
|
return {
|
|
1683
2031
|
type: 'component',
|
|
@@ -1685,6 +2033,22 @@ function componentField(config) {
|
|
|
1685
2033
|
};
|
|
1686
2034
|
}
|
|
1687
2035
|
|
|
2036
|
+
/**
|
|
2037
|
+
* Creates a Formly field configuration for a dbx selection list field.
|
|
2038
|
+
*
|
|
2039
|
+
* @param config - List field configuration including the list component class and state observable
|
|
2040
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'dbxlistfield'`
|
|
2041
|
+
*
|
|
2042
|
+
* @example
|
|
2043
|
+
* ```typescript
|
|
2044
|
+
* const field = dbxListField({
|
|
2045
|
+
* key: 'selectedItems',
|
|
2046
|
+
* label: 'Items',
|
|
2047
|
+
* listComponentClass: MyListComponent,
|
|
2048
|
+
* state$: items$
|
|
2049
|
+
* });
|
|
2050
|
+
* ```
|
|
2051
|
+
*/
|
|
1688
2052
|
function dbxListField(config) {
|
|
1689
2053
|
const { key, listComponentClass, readKey, state$, loadMore } = config;
|
|
1690
2054
|
return formlyField({
|
|
@@ -1700,7 +2064,10 @@ function dbxListField(config) {
|
|
|
1700
2064
|
}
|
|
1701
2065
|
|
|
1702
2066
|
/**
|
|
1703
|
-
*
|
|
2067
|
+
* Formly field component that allows picking items by identifier from a dynamic DbxList component.
|
|
2068
|
+
*
|
|
2069
|
+
* The list component class is provided as an observable, enabling lazy loading. Selected items
|
|
2070
|
+
* are tracked by key and synchronized with the form control value.
|
|
1704
2071
|
*/
|
|
1705
2072
|
class DbxItemListFieldComponent extends FieldType {
|
|
1706
2073
|
_selectionEventSub = new SubscriptionObject();
|
|
@@ -1778,6 +2145,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1778
2145
|
}] });
|
|
1779
2146
|
|
|
1780
2147
|
const importsAndExports$d = [DbxItemListFieldComponent];
|
|
2148
|
+
/** Registers the `dbxlistfield` Formly field type for item list selection. */
|
|
1781
2149
|
class DbxFormFormlyDbxListFieldModule {
|
|
1782
2150
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyDbxListFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1783
2151
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyDbxListFieldModule, imports: [DbxItemListFieldComponent, i1$1.FormlyModule], exports: [DbxItemListFieldComponent] });
|
|
@@ -1799,7 +2167,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1799
2167
|
}] });
|
|
1800
2168
|
|
|
1801
2169
|
/**
|
|
1802
|
-
*
|
|
2170
|
+
* Abstract base directive for pickable item fields that manages value loading,
|
|
2171
|
+
* display caching, text filtering, and selection state.
|
|
2172
|
+
*
|
|
2173
|
+
* Subclasses provide the specific UI presentation (chips, lists, etc.).
|
|
1803
2174
|
*/
|
|
1804
2175
|
class AbstractDbxPickableItemFieldDirective extends FieldType$1 {
|
|
1805
2176
|
filterMatInput = viewChild('matInput', { ...(ngDevMode ? { debugName: "filterMatInput" } : {}), read: MatInput });
|
|
@@ -1873,6 +2244,13 @@ class AbstractDbxPickableItemFieldDirective extends FieldType$1 {
|
|
|
1873
2244
|
filterResultsContext = listLoadingStateContext({ obs: this.filteredSearchResultsState$, showLoadingOnNoValue: true });
|
|
1874
2245
|
itemsSignal = toSignal(this.items$);
|
|
1875
2246
|
noItemsAvailableSignal = toSignal(this.noItemsAvailable$);
|
|
2247
|
+
/**
|
|
2248
|
+
* Signal that is true when all visible items are currently selected.
|
|
2249
|
+
*/
|
|
2250
|
+
allSelectedSignal = computed(() => {
|
|
2251
|
+
const items = this.itemsSignal();
|
|
2252
|
+
return items != null && items.length > 0 && items.every((x) => x.selected);
|
|
2253
|
+
}, ...(ngDevMode ? [{ debugName: "allSelectedSignal" }] : []));
|
|
1876
2254
|
get readonly() {
|
|
1877
2255
|
return this.props.readonly;
|
|
1878
2256
|
}
|
|
@@ -1906,6 +2284,9 @@ class AbstractDbxPickableItemFieldDirective extends FieldType$1 {
|
|
|
1906
2284
|
get changeSelectionModeToViewOnDisabled() {
|
|
1907
2285
|
return this.pickableField.changeSelectionModeToViewOnDisabled ?? false;
|
|
1908
2286
|
}
|
|
2287
|
+
get showSelectAllButton() {
|
|
2288
|
+
return this.pickableField.showSelectAllButton ?? false;
|
|
2289
|
+
}
|
|
1909
2290
|
get sortItems() {
|
|
1910
2291
|
return this.pickableField.sortItems;
|
|
1911
2292
|
}
|
|
@@ -2033,6 +2414,31 @@ class AbstractDbxPickableItemFieldDirective extends FieldType$1 {
|
|
|
2033
2414
|
const values = this.values.filter((x) => this.hashForValue(x) !== hashToFilter);
|
|
2034
2415
|
this.setValues(values);
|
|
2035
2416
|
}
|
|
2417
|
+
/**
|
|
2418
|
+
* Selects all currently visible items.
|
|
2419
|
+
*/
|
|
2420
|
+
selectAll() {
|
|
2421
|
+
const items = this.itemsSignal() ?? [];
|
|
2422
|
+
const allValues = items.filter((x) => !x.disabled).map((x) => x.itemValue.value);
|
|
2423
|
+
this.setValues(allValues);
|
|
2424
|
+
}
|
|
2425
|
+
/**
|
|
2426
|
+
* Deselects all currently visible items.
|
|
2427
|
+
*/
|
|
2428
|
+
deselectAll() {
|
|
2429
|
+
this.setValues([]);
|
|
2430
|
+
}
|
|
2431
|
+
/**
|
|
2432
|
+
* Toggles between selecting all and deselecting all visible items.
|
|
2433
|
+
*/
|
|
2434
|
+
toggleAll() {
|
|
2435
|
+
if (this.allSelectedSignal()) {
|
|
2436
|
+
this.deselectAll();
|
|
2437
|
+
}
|
|
2438
|
+
else {
|
|
2439
|
+
this.selectAll();
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2036
2442
|
setValues(values) {
|
|
2037
2443
|
// Use to filter non-unique values.
|
|
2038
2444
|
if (this.hashForValue) {
|
|
@@ -2061,7 +2467,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2061
2467
|
}], propDecorators: { filterMatInput: [{ type: i0.ViewChild, args: ['matInput', { ...{ read: MatInput }, isSignal: true }] }] } });
|
|
2062
2468
|
|
|
2063
2469
|
/**
|
|
2064
|
-
*
|
|
2470
|
+
* Formly field component that renders pickable values as Material chips.
|
|
2471
|
+
*
|
|
2472
|
+
* Clicking a chip toggles its selection state unless the field is readonly or disabled.
|
|
2065
2473
|
*/
|
|
2066
2474
|
class DbxPickableChipListFieldComponent extends AbstractDbxPickableItemFieldDirective {
|
|
2067
2475
|
itemClicked(item) {
|
|
@@ -2075,14 +2483,17 @@ class DbxPickableChipListFieldComponent extends AbstractDbxPickableItemFieldDire
|
|
|
2075
2483
|
}
|
|
2076
2484
|
}
|
|
2077
2485
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxPickableChipListFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2078
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: DbxPickableChipListFieldComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<div class=\"dbx-pickable-item-field\">\n <dbx-loading [context]=\"context\" [linear]=\"true\">\n @if (showFilterInput) {\n <ng-container *ngTemplateOutlet=\"filterTemplate\"></ng-container>\n }\n <!-- Content -->\n <div class=\"dbx-pickable-item-field-chips\">\n <mat-chip-listbox [multiple]=\"multiSelect\" [required]=\"required\" [selectable]=\"!isReadonlyOrDisabled\" [disabled]=\"readonly\" #chipList>\n @for (item of itemsSignal(); track item.itemValue.value) {\n <mat-chip-option (click)=\"itemClicked(item)\" [selected]=\"item.selected\" [disabled]=\"isReadonlyOrDisabled || item.disabled\">\n @if (item.itemValue.icon) {\n <mat-icon matChipAvatar>{{ item.itemValue.icon }}</mat-icon>\n }\n <span class=\"dbx-chip-label\">{{ item.itemValue.label }}</span>\n @if (item.itemValue.sublabel) {\n <span class=\"dbx-chip-sublabel\">{{ item.itemValue.sublabel }}</span>\n }\n </mat-chip-option>\n }\n </mat-chip-listbox>\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\" />\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\">No items match this filter.</p>\n }\n </div>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: MatChipsModule }, { kind: "directive", type: i1$4.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "component", type: i1$4.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i1$4.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: "component", type: DbxLoadingComponent, selector: "dbx-loading", inputs: ["padding", "show", "text", "mode", "color", "diameter", "linear", "loading", "error", "context"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: DbxInjectionComponent, selector: "dbx-injection, [dbxInjection], [dbx-injection]", inputs: ["config", "template"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2486
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: DbxPickableChipListFieldComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<div class=\"dbx-pickable-item-field\">\n <dbx-loading [context]=\"context\" [linear]=\"true\">\n @if (showFilterInput) {\n <ng-container *ngTemplateOutlet=\"filterTemplate\"></ng-container>\n }\n <!-- Content -->\n <div class=\"dbx-pickable-item-field-chips\">\n <mat-chip-listbox [multiple]=\"multiSelect\" [required]=\"required\" [selectable]=\"!isReadonlyOrDisabled\" [disabled]=\"readonly\" #chipList>\n @if (showSelectAllButton && multiSelect && !isReadonlyOrDisabled) {\n <mat-chip-option (click)=\"toggleAll()\" [selected]=\"allSelectedSignal()\">\n <span class=\"dbx-chip-label\">All</span>\n </mat-chip-option>\n }\n @for (item of itemsSignal(); track item.itemValue.value) {\n <mat-chip-option (click)=\"itemClicked(item)\" [selected]=\"item.selected\" [disabled]=\"isReadonlyOrDisabled || item.disabled\">\n @if (item.itemValue.icon) {\n <mat-icon matChipAvatar>{{ item.itemValue.icon }}</mat-icon>\n }\n <span class=\"dbx-chip-label\">{{ item.itemValue.label }}</span>\n @if (item.itemValue.sublabel) {\n <span class=\"dbx-chip-sublabel\">{{ item.itemValue.sublabel }}</span>\n }\n </mat-chip-option>\n }\n </mat-chip-listbox>\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\" />\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\">No items match this filter.</p>\n }\n </div>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: MatChipsModule }, { kind: "directive", type: i1$4.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "component", type: i1$4.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i1$4.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: "component", type: DbxLoadingComponent, selector: "dbx-loading", inputs: ["padding", "show", "text", "mode", "color", "diameter", "linear", "loading", "error", "context"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: DbxInjectionComponent, selector: "dbx-injection, [dbxInjection], [dbx-injection]", inputs: ["config", "template"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2079
2487
|
}
|
|
2080
2488
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxPickableChipListFieldComponent, decorators: [{
|
|
2081
2489
|
type: Component,
|
|
2082
|
-
args: [{ imports: [MatChipsModule, NgTemplateOutlet, FormsModule, ReactiveFormsModule, MatIconModule, MatInputModule, DbxLoadingComponent, MatDivider, DbxInjectionComponent], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-pickable-item-field\">\n <dbx-loading [context]=\"context\" [linear]=\"true\">\n @if (showFilterInput) {\n <ng-container *ngTemplateOutlet=\"filterTemplate\"></ng-container>\n }\n <!-- Content -->\n <div class=\"dbx-pickable-item-field-chips\">\n <mat-chip-listbox [multiple]=\"multiSelect\" [required]=\"required\" [selectable]=\"!isReadonlyOrDisabled\" [disabled]=\"readonly\" #chipList>\n @for (item of itemsSignal(); track item.itemValue.value) {\n <mat-chip-option (click)=\"itemClicked(item)\" [selected]=\"item.selected\" [disabled]=\"isReadonlyOrDisabled || item.disabled\">\n @if (item.itemValue.icon) {\n <mat-icon matChipAvatar>{{ item.itemValue.icon }}</mat-icon>\n }\n <span class=\"dbx-chip-label\">{{ item.itemValue.label }}</span>\n @if (item.itemValue.sublabel) {\n <span class=\"dbx-chip-sublabel\">{{ item.itemValue.sublabel }}</span>\n }\n </mat-chip-option>\n }\n </mat-chip-listbox>\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\" />\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\">No items match this filter.</p>\n }\n </div>\n</ng-template>\n" }]
|
|
2490
|
+
args: [{ imports: [MatChipsModule, NgTemplateOutlet, FormsModule, ReactiveFormsModule, MatIconModule, MatInputModule, DbxLoadingComponent, MatDivider, DbxInjectionComponent], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-pickable-item-field\">\n <dbx-loading [context]=\"context\" [linear]=\"true\">\n @if (showFilterInput) {\n <ng-container *ngTemplateOutlet=\"filterTemplate\"></ng-container>\n }\n <!-- Content -->\n <div class=\"dbx-pickable-item-field-chips\">\n <mat-chip-listbox [multiple]=\"multiSelect\" [required]=\"required\" [selectable]=\"!isReadonlyOrDisabled\" [disabled]=\"readonly\" #chipList>\n @if (showSelectAllButton && multiSelect && !isReadonlyOrDisabled) {\n <mat-chip-option (click)=\"toggleAll()\" [selected]=\"allSelectedSignal()\">\n <span class=\"dbx-chip-label\">All</span>\n </mat-chip-option>\n }\n @for (item of itemsSignal(); track item.itemValue.value) {\n <mat-chip-option (click)=\"itemClicked(item)\" [selected]=\"item.selected\" [disabled]=\"isReadonlyOrDisabled || item.disabled\">\n @if (item.itemValue.icon) {\n <mat-icon matChipAvatar>{{ item.itemValue.icon }}</mat-icon>\n }\n <span class=\"dbx-chip-label\">{{ item.itemValue.label }}</span>\n @if (item.itemValue.sublabel) {\n <span class=\"dbx-chip-sublabel\">{{ item.itemValue.sublabel }}</span>\n }\n </mat-chip-option>\n }\n </mat-chip-listbox>\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\" />\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\">No items match this filter.</p>\n }\n </div>\n</ng-template>\n" }]
|
|
2083
2491
|
}] });
|
|
2084
2492
|
|
|
2085
2493
|
// MARK: Selection List
|
|
2494
|
+
/**
|
|
2495
|
+
* Wrapper component for the pickable item selection list, providing the list view container.
|
|
2496
|
+
*/
|
|
2086
2497
|
class DbxPickableListFieldItemListComponent extends AbstractDbxSelectionListWrapperDirective {
|
|
2087
2498
|
constructor() {
|
|
2088
2499
|
super({
|
|
@@ -2104,7 +2515,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2104
2515
|
}]
|
|
2105
2516
|
}], ctorParameters: () => [] });
|
|
2106
2517
|
/**
|
|
2107
|
-
*
|
|
2518
|
+
* List view component that renders pickable items with selection support.
|
|
2519
|
+
*
|
|
2520
|
+
* Input values are {@link PickableItemFieldItem}, but output selection events emit {@link PickableValueFieldDisplayValue}.
|
|
2108
2521
|
*/
|
|
2109
2522
|
class DbxPickableListFieldItemListViewComponent extends AbstractDbxSelectionListViewDirective {
|
|
2110
2523
|
dbxPickableListFieldComponent = inject((DbxPickableListFieldComponent));
|
|
@@ -2178,9 +2591,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2178
2591
|
standalone: true
|
|
2179
2592
|
}]
|
|
2180
2593
|
}] });
|
|
2181
|
-
// List Field Component
|
|
2594
|
+
// MARK: List Field Component
|
|
2182
2595
|
/**
|
|
2183
|
-
*
|
|
2596
|
+
* Formly field component that renders pickable values as a selectable list.
|
|
2597
|
+
*
|
|
2598
|
+
* Delegates to {@link DbxPickableListFieldItemListComponent} for list rendering and
|
|
2599
|
+
* handles selection change events to update the form control value.
|
|
2184
2600
|
*/
|
|
2185
2601
|
class DbxPickableListFieldComponent extends AbstractDbxPickableItemFieldDirective {
|
|
2186
2602
|
onSelectionChange(event) {
|
|
@@ -2197,6 +2613,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2197
2613
|
}] });
|
|
2198
2614
|
|
|
2199
2615
|
const importsAndExports$c = [DbxPickableChipListFieldComponent, DbxPickableListFieldComponent, DbxPickableListFieldItemListComponent, DbxPickableListFieldItemListViewComponent, DbxPickableListFieldItemListViewItemComponent];
|
|
2616
|
+
/** Registers the `pickablechipfield` and `pickablelistfield` Formly field types. */
|
|
2200
2617
|
class DbxFormFormlyPickableFieldModule {
|
|
2201
2618
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyPickableFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2202
2619
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyPickableFieldModule, imports: [DbxPickableChipListFieldComponent, DbxPickableListFieldComponent, DbxPickableListFieldItemListComponent, DbxPickableListFieldItemListViewComponent, DbxPickableListFieldItemListViewItemComponent, i1$1.FormlyModule], exports: [DbxPickableChipListFieldComponent, DbxPickableListFieldComponent, DbxPickableListFieldItemListComponent, DbxPickableListFieldItemListViewComponent, DbxPickableListFieldItemListViewItemComponent] });
|
|
@@ -2223,6 +2640,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2223
2640
|
}]
|
|
2224
2641
|
}] });
|
|
2225
2642
|
|
|
2643
|
+
/**
|
|
2644
|
+
* Creates a Formly field configuration for a pickable chip field that displays
|
|
2645
|
+
* selected values as Material chips.
|
|
2646
|
+
*
|
|
2647
|
+
* @param config - Pickable item configuration including load and display functions
|
|
2648
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'pickablechipfield'`
|
|
2649
|
+
*
|
|
2650
|
+
* @example
|
|
2651
|
+
* ```typescript
|
|
2652
|
+
* const field = pickableItemChipField({
|
|
2653
|
+
* key: 'tags',
|
|
2654
|
+
* label: 'Tags',
|
|
2655
|
+
* loadValues: () => tags$,
|
|
2656
|
+
* hashForValue: (tag) => tag.id
|
|
2657
|
+
* });
|
|
2658
|
+
* ```
|
|
2659
|
+
*/
|
|
2226
2660
|
function pickableItemChipField(config) {
|
|
2227
2661
|
const { key, materialFormField } = config;
|
|
2228
2662
|
return formlyField({
|
|
@@ -2235,6 +2669,23 @@ function pickableItemChipField(config) {
|
|
|
2235
2669
|
})
|
|
2236
2670
|
});
|
|
2237
2671
|
}
|
|
2672
|
+
/**
|
|
2673
|
+
* Creates a Formly field configuration for a pickable list field that displays
|
|
2674
|
+
* selected values in a selection list.
|
|
2675
|
+
*
|
|
2676
|
+
* @param config - Pickable item configuration including load and display functions
|
|
2677
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'pickablelistfield'`
|
|
2678
|
+
*
|
|
2679
|
+
* @example
|
|
2680
|
+
* ```typescript
|
|
2681
|
+
* const field = pickableItemListField({
|
|
2682
|
+
* key: 'categories',
|
|
2683
|
+
* label: 'Categories',
|
|
2684
|
+
* loadValues: () => categories$,
|
|
2685
|
+
* hashForValue: (cat) => cat.id
|
|
2686
|
+
* });
|
|
2687
|
+
* ```
|
|
2688
|
+
*/
|
|
2238
2689
|
function pickableItemListField(config) {
|
|
2239
2690
|
const { key, materialFormField } = config;
|
|
2240
2691
|
return formlyField({
|
|
@@ -2248,10 +2699,20 @@ function pickableItemListField(config) {
|
|
|
2248
2699
|
});
|
|
2249
2700
|
}
|
|
2250
2701
|
|
|
2702
|
+
/** Case-insensitive filter function that matches pickable display values by their label using indexOf. */
|
|
2251
2703
|
const filterPickableItemFieldValuesByLabelFilterFunction = searchStringFilterFunction({
|
|
2252
2704
|
readStrings: (x) => [x.label],
|
|
2253
2705
|
decisionFactory: caseInsensitiveFilterByIndexOfDecisionFactory
|
|
2254
2706
|
});
|
|
2707
|
+
/**
|
|
2708
|
+
* Filters pickable display values by label text, returning their underlying values.
|
|
2709
|
+
*
|
|
2710
|
+
* Returns all values when filter text is empty.
|
|
2711
|
+
*
|
|
2712
|
+
* @param filterText - Text to filter by
|
|
2713
|
+
* @param values - Display values to filter
|
|
2714
|
+
* @returns Observable emitting the filtered value array
|
|
2715
|
+
*/
|
|
2255
2716
|
function filterPickableItemFieldValuesByLabel(filterText, values) {
|
|
2256
2717
|
let filteredValues;
|
|
2257
2718
|
if (filterText) {
|
|
@@ -2262,10 +2723,33 @@ function filterPickableItemFieldValuesByLabel(filterText, values) {
|
|
|
2262
2723
|
}
|
|
2263
2724
|
return of(filteredValues.map((x) => x.value));
|
|
2264
2725
|
}
|
|
2726
|
+
/** String sort comparator that orders pickable items alphabetically by label. */
|
|
2265
2727
|
const sortPickableItemsByLabelStringFunction = sortByStringFunction((x) => x.itemValue.label);
|
|
2728
|
+
/**
|
|
2729
|
+
* Sorts pickable items alphabetically by their label.
|
|
2730
|
+
*
|
|
2731
|
+
* @param chips - Items to sort
|
|
2732
|
+
* @returns The sorted array (mutated in place)
|
|
2733
|
+
*/
|
|
2266
2734
|
function sortPickableItemsByLabel(chips) {
|
|
2267
2735
|
return chips.sort(sortPickableItemsByLabelStringFunction);
|
|
2268
2736
|
}
|
|
2737
|
+
/**
|
|
2738
|
+
* Creates `loadValues`, `displayForValue`, and `filterValues` functions from a static array of labeled values.
|
|
2739
|
+
*
|
|
2740
|
+
* Simplifies pickable field setup when all options are known upfront.
|
|
2741
|
+
*
|
|
2742
|
+
* @param input - Array of labeled values or a config object with options and unknown label
|
|
2743
|
+
* @returns Props subset for configuring a pickable field
|
|
2744
|
+
*
|
|
2745
|
+
* @example
|
|
2746
|
+
* ```typescript
|
|
2747
|
+
* const config = pickableValueFieldValuesConfigForStaticLabeledValues([
|
|
2748
|
+
* { value: 'a', label: 'Option A' },
|
|
2749
|
+
* { value: 'b', label: 'Option B' }
|
|
2750
|
+
* ]);
|
|
2751
|
+
* ```
|
|
2752
|
+
*/
|
|
2269
2753
|
function pickableValueFieldValuesConfigForStaticLabeledValues(input) {
|
|
2270
2754
|
const config = Array.isArray(input) ? { allOptions: input } : input;
|
|
2271
2755
|
const { allOptions, unknownOptionLabel = 'UNKNOWN' } = config;
|
|
@@ -2281,7 +2765,14 @@ function pickableValueFieldValuesConfigForStaticLabeledValues(input) {
|
|
|
2281
2765
|
};
|
|
2282
2766
|
}
|
|
2283
2767
|
|
|
2768
|
+
/** Injection token providing the {@link ConfiguredSearchableValueFieldDisplayValue} to autocomplete item display components. */
|
|
2284
2769
|
const DBX_SEARCHABLE_FIELD_COMPONENT_DATA_TOKEN = new InjectionToken('DbxSearchableField');
|
|
2770
|
+
/**
|
|
2771
|
+
* Renders a single autocomplete suggestion item using dynamic component injection.
|
|
2772
|
+
*
|
|
2773
|
+
* Wraps the display component in a {@link DbxAnchorComponent} and provides the display
|
|
2774
|
+
* value data via {@link DBX_SEARCHABLE_FIELD_COMPONENT_DATA_TOKEN}.
|
|
2775
|
+
*/
|
|
2285
2776
|
class DbxSearchableFieldAutocompleteItemComponent {
|
|
2286
2777
|
displayValue = input.required(...(ngDevMode ? [{ debugName: "displayValue" }] : []));
|
|
2287
2778
|
configSignal = computed(() => {
|
|
@@ -2320,6 +2811,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2320
2811
|
}]
|
|
2321
2812
|
}], propDecorators: { displayValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayValue", required: true }] }] } });
|
|
2322
2813
|
// MARK: Default
|
|
2814
|
+
/**
|
|
2815
|
+
* Abstract base directive for custom searchable field display components.
|
|
2816
|
+
*
|
|
2817
|
+
* Injects the {@link ConfiguredSearchableValueFieldDisplayValue} via the
|
|
2818
|
+
* {@link DBX_SEARCHABLE_FIELD_COMPONENT_DATA_TOKEN} for use in custom templates.
|
|
2819
|
+
*/
|
|
2323
2820
|
class AbstractDbxSearchableFieldDisplayDirective {
|
|
2324
2821
|
displayValue = inject(DBX_SEARCHABLE_FIELD_COMPONENT_DATA_TOKEN);
|
|
2325
2822
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AbstractDbxSearchableFieldDisplayDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
@@ -2328,6 +2825,11 @@ class AbstractDbxSearchableFieldDisplayDirective {
|
|
|
2328
2825
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: AbstractDbxSearchableFieldDisplayDirective, decorators: [{
|
|
2329
2826
|
type: Directive
|
|
2330
2827
|
}] });
|
|
2828
|
+
/**
|
|
2829
|
+
* Default display component for searchable field autocomplete items.
|
|
2830
|
+
*
|
|
2831
|
+
* Renders an optional icon, a label, and an optional sublabel in a horizontal flex layout.
|
|
2832
|
+
*/
|
|
2331
2833
|
class DbxDefaultSearchableFieldDisplayComponent extends AbstractDbxSearchableFieldDisplayDirective {
|
|
2332
2834
|
icon = this.displayValue.icon;
|
|
2333
2835
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxDefaultSearchableFieldDisplayComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -2564,6 +3066,7 @@ class AbstractDbxSearchableValueFieldDirective extends FieldType$1 {
|
|
|
2564
3066
|
this.inputCtrl.setValue(text.trim());
|
|
2565
3067
|
}
|
|
2566
3068
|
if (!this.inputCtrl.valid) {
|
|
3069
|
+
this.inputCtrl.markAsTouched();
|
|
2567
3070
|
return;
|
|
2568
3071
|
}
|
|
2569
3072
|
if (text) {
|
|
@@ -2571,6 +3074,21 @@ class AbstractDbxSearchableValueFieldDirective extends FieldType$1 {
|
|
|
2571
3074
|
this.addValue(value);
|
|
2572
3075
|
}
|
|
2573
3076
|
}
|
|
3077
|
+
/**
|
|
3078
|
+
* Returns the first validation error message from the input control, if any.
|
|
3079
|
+
*/
|
|
3080
|
+
get inputErrorMessage() {
|
|
3081
|
+
const errors = this.inputCtrl.errors;
|
|
3082
|
+
if (errors) {
|
|
3083
|
+
for (const key of Object.keys(errors)) {
|
|
3084
|
+
const error = errors[key];
|
|
3085
|
+
if (error?.message) {
|
|
3086
|
+
return error.message;
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
return undefined;
|
|
3091
|
+
}
|
|
2574
3092
|
addWithDisplayValue(displayValue) {
|
|
2575
3093
|
this.addValue(displayValue.value);
|
|
2576
3094
|
}
|
|
@@ -2641,6 +3159,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2641
3159
|
type: Directive
|
|
2642
3160
|
}], propDecorators: { textInput: [{ type: i0.ViewChild, args: ['textInput', { ...{ read: (ElementRef) }, isSignal: true }] }] } });
|
|
2643
3161
|
|
|
3162
|
+
/**
|
|
3163
|
+
* Formly field component that combines a search autocomplete with Material chips
|
|
3164
|
+
* for selecting multiple values.
|
|
3165
|
+
*
|
|
3166
|
+
* Supports adding values by typing (if string values are allowed), selecting from
|
|
3167
|
+
* autocomplete results, and removing chips. Handles tab and blur events to auto-add text input.
|
|
3168
|
+
*/
|
|
2644
3169
|
class DbxSearchableChipFieldComponent extends AbstractDbxSearchableValueFieldDirective {
|
|
2645
3170
|
get multiSelect() {
|
|
2646
3171
|
return this.props.multiSelect ?? true;
|
|
@@ -2684,11 +3209,11 @@ class DbxSearchableChipFieldComponent extends AbstractDbxSearchableValueFieldDir
|
|
|
2684
3209
|
this._blur.next();
|
|
2685
3210
|
}
|
|
2686
3211
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxSearchableChipFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2687
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: DbxSearchableChipFieldComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<div class=\"dbx-searchable-field\">\n <!-- View -->\n <mat-chip-grid [required]=\"required\" [disabled]=\"readonly\" #chipList>\n @for (displayValue of displayValuesSignal(); track displayValue.value) {\n <mat-chip-row [removable]=\"true\" (removed)=\"removeWithDisplayValue(displayValue)\">\n @if (displayValue.icon) {\n <mat-icon matChipAvatar>{{ displayValue.icon }}</mat-icon>\n }\n <span class=\"dbx-chip-label\">{{ displayValue.label }}</span>\n @if (displayValue.sublabel) {\n <span class=\"dbx-chip-sublabel\">{{ displayValue.sublabel }}</span>\n }\n @if (!readonly) {\n <mat-icon matChipRemove>cancel</mat-icon>\n }\n </mat-chip-row>\n }\n <input #textInput [name]=\"name\" [placeholder]=\"searchInputPlaceholder\" [formControl]=\"inputCtrl\" [matAutocomplete]=\"auto\" autocomplete=\"{{ autocomplete }}\" [matAutocompleteDisabled]=\"readonly\" [matChipInputFor]=\"chipList\" (keydown)=\"tabPressedOnInput($event)\" [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\" (matChipInputTokenEnd)=\"addChip($event)\" (blur)=\"onBlur()\" />\n </mat-chip-grid>\n <div class=\"searchable-field-form-loading\">\n <dbx-loading [linear]=\"true\" [context]=\"searchContext\"></dbx-loading>\n </div>\n</div>\n\n<!-- Autocomplete -->\n<mat-autocomplete class=\"dbx-searchable-text-field-autocomplete\" #auto=\"matAutocomplete\" (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</mat-autocomplete>\n", dependencies: [{ kind: "ngmodule", type: MatChipsModule }, { kind: "directive", type: i1$4.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "component", type: i1$4.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i1$4.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i1$4.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i1$4.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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"] }, { kind: "ngmodule", type: DbxLoadingModule }, { kind: "component", type: i1$2.DbxLoadingComponent, selector: "dbx-loading", inputs: ["padding", "show", "text", "mode", "color", "diameter", "linear", "loading", "error", "context"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i5.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i5.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: DbxSearchableFieldAutocompleteItemComponent, selector: "dbx-searchable-field-autocomplete-item", inputs: ["displayValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3212
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: DbxSearchableChipFieldComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<div class=\"dbx-searchable-field\">\n <!-- View -->\n <mat-chip-grid [required]=\"required\" [disabled]=\"readonly\" #chipList>\n @for (displayValue of displayValuesSignal(); track displayValue.value) {\n <mat-chip-row [removable]=\"true\" (removed)=\"removeWithDisplayValue(displayValue)\">\n @if (displayValue.icon) {\n <mat-icon matChipAvatar>{{ displayValue.icon }}</mat-icon>\n }\n <span class=\"dbx-chip-label\">{{ displayValue.label }}</span>\n @if (displayValue.sublabel) {\n <span class=\"dbx-chip-sublabel\">{{ displayValue.sublabel }}</span>\n }\n @if (!readonly) {\n <mat-icon matChipRemove>cancel</mat-icon>\n }\n </mat-chip-row>\n }\n <input #textInput [name]=\"name\" [placeholder]=\"searchInputPlaceholder\" [formControl]=\"inputCtrl\" [matAutocomplete]=\"auto\" autocomplete=\"{{ autocomplete }}\" [matAutocompleteDisabled]=\"readonly\" [matChipInputFor]=\"chipList\" (keydown)=\"tabPressedOnInput($event)\" [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\" (matChipInputTokenEnd)=\"addChip($event)\" (blur)=\"onBlur()\" />\n </mat-chip-grid>\n <div class=\"searchable-field-form-loading\">\n <dbx-loading [linear]=\"true\" [context]=\"searchContext\"></dbx-loading>\n </div>\n @if (inputCtrl.touched && inputErrorMessage) {\n <span class=\"dbx-chip-input-error\">{{ inputErrorMessage }}</span>\n }\n</div>\n\n<!-- Autocomplete -->\n<mat-autocomplete class=\"dbx-searchable-text-field-autocomplete\" #auto=\"matAutocomplete\" (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</mat-autocomplete>\n", dependencies: [{ kind: "ngmodule", type: MatChipsModule }, { kind: "directive", type: i1$4.MatChipAvatar, selector: "mat-chip-avatar, [matChipAvatar]" }, { kind: "component", type: i1$4.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i1$4.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i1$4.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i1$4.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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"] }, { kind: "ngmodule", type: DbxLoadingModule }, { kind: "component", type: i1$2.DbxLoadingComponent, selector: "dbx-loading", inputs: ["padding", "show", "text", "mode", "color", "diameter", "linear", "loading", "error", "context"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i5.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i5.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: DbxSearchableFieldAutocompleteItemComponent, selector: "dbx-searchable-field-autocomplete-item", inputs: ["displayValue"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2688
3213
|
}
|
|
2689
3214
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxSearchableChipFieldComponent, decorators: [{
|
|
2690
3215
|
type: Component,
|
|
2691
|
-
args: [{ imports: [MatChipsModule, MatIconModule, FormsModule, ReactiveFormsModule, DbxLoadingModule, MatAutocompleteModule, MatOptionModule, DbxSearchableFieldAutocompleteItemComponent], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-searchable-field\">\n <!-- View -->\n <mat-chip-grid [required]=\"required\" [disabled]=\"readonly\" #chipList>\n @for (displayValue of displayValuesSignal(); track displayValue.value) {\n <mat-chip-row [removable]=\"true\" (removed)=\"removeWithDisplayValue(displayValue)\">\n @if (displayValue.icon) {\n <mat-icon matChipAvatar>{{ displayValue.icon }}</mat-icon>\n }\n <span class=\"dbx-chip-label\">{{ displayValue.label }}</span>\n @if (displayValue.sublabel) {\n <span class=\"dbx-chip-sublabel\">{{ displayValue.sublabel }}</span>\n }\n @if (!readonly) {\n <mat-icon matChipRemove>cancel</mat-icon>\n }\n </mat-chip-row>\n }\n <input #textInput [name]=\"name\" [placeholder]=\"searchInputPlaceholder\" [formControl]=\"inputCtrl\" [matAutocomplete]=\"auto\" autocomplete=\"{{ autocomplete }}\" [matAutocompleteDisabled]=\"readonly\" [matChipInputFor]=\"chipList\" (keydown)=\"tabPressedOnInput($event)\" [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\" (matChipInputTokenEnd)=\"addChip($event)\" (blur)=\"onBlur()\" />\n </mat-chip-grid>\n <div class=\"searchable-field-form-loading\">\n <dbx-loading [linear]=\"true\" [context]=\"searchContext\"></dbx-loading>\n </div>\n</div>\n\n<!-- Autocomplete -->\n<mat-autocomplete class=\"dbx-searchable-text-field-autocomplete\" #auto=\"matAutocomplete\" (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</mat-autocomplete>\n" }]
|
|
3216
|
+
args: [{ imports: [MatChipsModule, MatIconModule, FormsModule, ReactiveFormsModule, DbxLoadingModule, MatAutocompleteModule, MatOptionModule, DbxSearchableFieldAutocompleteItemComponent], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-searchable-field\">\n <!-- View -->\n <mat-chip-grid [required]=\"required\" [disabled]=\"readonly\" #chipList>\n @for (displayValue of displayValuesSignal(); track displayValue.value) {\n <mat-chip-row [removable]=\"true\" (removed)=\"removeWithDisplayValue(displayValue)\">\n @if (displayValue.icon) {\n <mat-icon matChipAvatar>{{ displayValue.icon }}</mat-icon>\n }\n <span class=\"dbx-chip-label\">{{ displayValue.label }}</span>\n @if (displayValue.sublabel) {\n <span class=\"dbx-chip-sublabel\">{{ displayValue.sublabel }}</span>\n }\n @if (!readonly) {\n <mat-icon matChipRemove>cancel</mat-icon>\n }\n </mat-chip-row>\n }\n <input #textInput [name]=\"name\" [placeholder]=\"searchInputPlaceholder\" [formControl]=\"inputCtrl\" [matAutocomplete]=\"auto\" autocomplete=\"{{ autocomplete }}\" [matAutocompleteDisabled]=\"readonly\" [matChipInputFor]=\"chipList\" (keydown)=\"tabPressedOnInput($event)\" [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\" (matChipInputTokenEnd)=\"addChip($event)\" (blur)=\"onBlur()\" />\n </mat-chip-grid>\n <div class=\"searchable-field-form-loading\">\n <dbx-loading [linear]=\"true\" [context]=\"searchContext\"></dbx-loading>\n </div>\n @if (inputCtrl.touched && inputErrorMessage) {\n <span class=\"dbx-chip-input-error\">{{ inputErrorMessage }}</span>\n }\n</div>\n\n<!-- Autocomplete -->\n<mat-autocomplete class=\"dbx-searchable-text-field-autocomplete\" #auto=\"matAutocomplete\" (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</mat-autocomplete>\n" }]
|
|
2692
3217
|
}] });
|
|
2693
3218
|
|
|
2694
3219
|
/**
|
|
@@ -2725,12 +3250,35 @@ function makeMetaFilterSearchableFieldValueDisplayFn({ loadMetaForValues, makeDi
|
|
|
2725
3250
|
return allValues.pipe(switchMap(makeDisplayForValues));
|
|
2726
3251
|
};
|
|
2727
3252
|
}
|
|
3253
|
+
/**
|
|
3254
|
+
* Creates a searchable chip field pre-configured for string values.
|
|
3255
|
+
*
|
|
3256
|
+
* @param config - String-specific searchable chip field configuration
|
|
3257
|
+
* @returns A {@link FormlyFieldConfig} with type `'searchablechipfield'`
|
|
3258
|
+
*
|
|
3259
|
+
* @example
|
|
3260
|
+
* ```typescript
|
|
3261
|
+
* const field = searchableStringChipField({ key: 'tags', label: 'Tags', search: searchFn });
|
|
3262
|
+
* ```
|
|
3263
|
+
*/
|
|
2728
3264
|
function searchableStringChipField(config) {
|
|
2729
3265
|
return searchableChipField({
|
|
2730
3266
|
...config,
|
|
2731
3267
|
allowStringValues: true
|
|
2732
3268
|
});
|
|
2733
3269
|
}
|
|
3270
|
+
/**
|
|
3271
|
+
* Creates a Formly field configuration for a searchable chip field where users
|
|
3272
|
+
* can search for and select values displayed as Material chips.
|
|
3273
|
+
*
|
|
3274
|
+
* @param config - Searchable chip field configuration
|
|
3275
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'searchablechipfield'`
|
|
3276
|
+
*
|
|
3277
|
+
* @example
|
|
3278
|
+
* ```typescript
|
|
3279
|
+
* const field = searchableChipField({ key: 'skills', label: 'Skills', search: searchFn, hashForValue: (s) => s.id });
|
|
3280
|
+
* ```
|
|
3281
|
+
*/
|
|
2734
3282
|
function searchableChipField(config) {
|
|
2735
3283
|
const { key, placeholder, materialFormField } = config;
|
|
2736
3284
|
return formlyField({
|
|
@@ -2744,6 +3292,18 @@ function searchableChipField(config) {
|
|
|
2744
3292
|
})
|
|
2745
3293
|
});
|
|
2746
3294
|
}
|
|
3295
|
+
/**
|
|
3296
|
+
* Creates a Formly field configuration for a searchable text field with autocomplete
|
|
3297
|
+
* dropdown for selecting values.
|
|
3298
|
+
*
|
|
3299
|
+
* @param config - Searchable text field configuration
|
|
3300
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'searchabletextfield'`
|
|
3301
|
+
*
|
|
3302
|
+
* @example
|
|
3303
|
+
* ```typescript
|
|
3304
|
+
* const field = searchableTextField({ key: 'assignee', label: 'Assignee', search: searchFn });
|
|
3305
|
+
* ```
|
|
3306
|
+
*/
|
|
2747
3307
|
function searchableTextField(config) {
|
|
2748
3308
|
const { key, materialFormField } = config;
|
|
2749
3309
|
return formlyField({
|
|
@@ -2758,7 +3318,10 @@ function searchableTextField(config) {
|
|
|
2758
3318
|
}
|
|
2759
3319
|
|
|
2760
3320
|
/**
|
|
2761
|
-
*
|
|
3321
|
+
* Formly field component for selecting a single value via text search with autocomplete.
|
|
3322
|
+
*
|
|
3323
|
+
* Syncs the selected value's label back to the text input. Supports optional display
|
|
3324
|
+
* of the currently selected value and clear functionality.
|
|
2762
3325
|
*/
|
|
2763
3326
|
class DbxSearchableTextFieldComponent extends AbstractDbxSearchableValueFieldDirective {
|
|
2764
3327
|
allowSyncValueToInput = true;
|
|
@@ -2812,6 +3375,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2812
3375
|
}] });
|
|
2813
3376
|
|
|
2814
3377
|
const importsAndExports$b = [DbxSearchableChipFieldComponent, DbxSearchableTextFieldComponent, DbxSearchableFieldAutocompleteItemComponent, DbxDefaultSearchableFieldDisplayComponent];
|
|
3378
|
+
/** Registers the `searchablechipfield` and `searchabletextfield` Formly field types. */
|
|
2815
3379
|
class DbxFormFormlySearchableFieldModule {
|
|
2816
3380
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlySearchableFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2817
3381
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlySearchableFieldModule, imports: [DbxSearchableChipFieldComponent, DbxSearchableTextFieldComponent, DbxSearchableFieldAutocompleteItemComponent, DbxDefaultSearchableFieldDisplayComponent, i1$1.FormlyModule], exports: [DbxSearchableChipFieldComponent, DbxSearchableTextFieldComponent, DbxSearchableFieldAutocompleteItemComponent, DbxDefaultSearchableFieldDisplayComponent] });
|
|
@@ -2838,6 +3402,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2838
3402
|
}]
|
|
2839
3403
|
}] });
|
|
2840
3404
|
|
|
3405
|
+
/**
|
|
3406
|
+
* Creates a searchable chip field for freeform text entry where each entered string
|
|
3407
|
+
* becomes a chip. Values are lowercased by default unless `caseSensitive` is true.
|
|
3408
|
+
*
|
|
3409
|
+
* @param config - Text chip field configuration
|
|
3410
|
+
* @returns A {@link FormlyFieldConfig} for text chip input
|
|
3411
|
+
*
|
|
3412
|
+
* @example
|
|
3413
|
+
* ```typescript
|
|
3414
|
+
* const field = chipTextField({ key: 'tags', label: 'Tags' });
|
|
3415
|
+
* ```
|
|
3416
|
+
*/
|
|
2841
3417
|
function chipTextField(config) {
|
|
2842
3418
|
const convertStringValue = config.caseSensitive ? (x) => x : (x) => x?.toLowerCase();
|
|
2843
3419
|
return searchableChipField({
|
|
@@ -2852,7 +3428,11 @@ function chipTextField(config) {
|
|
|
2852
3428
|
}
|
|
2853
3429
|
|
|
2854
3430
|
/**
|
|
2855
|
-
*
|
|
3431
|
+
* Formly field component that renders a Material select dropdown populated from
|
|
3432
|
+
* multiple data sources (open source dialogs, loaded sources, and form control values).
|
|
3433
|
+
*
|
|
3434
|
+
* Merges values from all sources, deduplicates by value key, groups options by label,
|
|
3435
|
+
* and caches display values and metadata for performance.
|
|
2856
3436
|
*/
|
|
2857
3437
|
class DbxFormSourceSelectFieldComponent extends FieldType$2 {
|
|
2858
3438
|
_cacheMetaSub = new SubscriptionObject();
|
|
@@ -3164,6 +3744,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
3164
3744
|
args: [{ selector: 'dbx-form-sourceselectfield', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatSelect, MatOption, FormsModule, ReactiveFormsModule, DbxButtonComponent, MatOptgroup, DbxButtonSpacerDirective, DbxActionModule, DbxLoadingComponent], standalone: true, template: "<div class=\"dbx-source-select-field\">\n <div class=\"dbx-source-select-field-content\">\n <mat-select class=\"dbx-source-select-field-select\" [id]=\"id\" [formControl]=\"formControl\" [multiple]=\"props.multiple\">\n @for (value of nonGroupedValuesSignal(); track value.value) {\n <mat-option [value]=\"value.value\">\n {{ value.label }}\n </mat-option>\n }\n @for (optionGroup of groupedOptionsSignal(); track optionGroup.label) {\n <mat-optgroup [label]=\"optionGroup.label\">\n @for (value of optionGroup.values; track value.value) {\n <mat-option [value]=\"value.value\">\n {{ value.label }}\n </mat-option>\n }\n </mat-optgroup>\n }\n </mat-select>\n @if (showOpenSourceButton) {\n <dbx-button-spacer></dbx-button-spacer>\n <dbx-action dbxActionValue [dbxActionHandler]=\"handleSelectOptions\" class=\"dbx-source-select-field-button\">\n <dbx-button #button dbxActionButton [fab]=\"true\" [iconOnly]=\"true\" [icon]=\"selectButtonIcon\"></dbx-button>\n </dbx-action>\n }\n </div>\n <dbx-loading class=\"dbx-source-select-field-loading\" [linear]=\"true\" [context]=\"context\"></dbx-loading>\n</div>\n" }]
|
|
3165
3745
|
}], propDecorators: { buttonElement: [{ type: i0.ViewChild, args: ['button', { ...{ read: (ElementRef) }, isSignal: true }] }] } });
|
|
3166
3746
|
|
|
3747
|
+
/**
|
|
3748
|
+
* Creates a Formly field configuration for a source-select field that loads and
|
|
3749
|
+
* displays selectable values from one or more external data sources.
|
|
3750
|
+
*
|
|
3751
|
+
* @param config - Source-select field configuration
|
|
3752
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'sourceselectfield'`
|
|
3753
|
+
*
|
|
3754
|
+
* @example
|
|
3755
|
+
* ```typescript
|
|
3756
|
+
* const field = sourceSelectField({
|
|
3757
|
+
* key: 'source',
|
|
3758
|
+
* label: 'Source',
|
|
3759
|
+
* loadSources: () => sources$,
|
|
3760
|
+
* metaReader: (meta) => meta.id
|
|
3761
|
+
* });
|
|
3762
|
+
* ```
|
|
3763
|
+
*/
|
|
3167
3764
|
function sourceSelectField(config) {
|
|
3168
3765
|
const { key, materialFormField } = config;
|
|
3169
3766
|
return formlyField({
|
|
@@ -3177,6 +3774,7 @@ function sourceSelectField(config) {
|
|
|
3177
3774
|
});
|
|
3178
3775
|
}
|
|
3179
3776
|
|
|
3777
|
+
/** Registers the `sourceselectfield` Formly field type. */
|
|
3180
3778
|
class DbxFormFormlySourceSelectModule {
|
|
3181
3779
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlySourceSelectModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3182
3780
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlySourceSelectModule, imports: [DbxFormSourceSelectFieldComponent, i1$1.FormlyModule], exports: [DbxFormSourceSelectFieldComponent] });
|
|
@@ -3198,6 +3796,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
3198
3796
|
}]
|
|
3199
3797
|
}] });
|
|
3200
3798
|
|
|
3799
|
+
/**
|
|
3800
|
+
* Creates a Formly select field configuration with support for native/material select,
|
|
3801
|
+
* clear option, multiple selection, and "select all".
|
|
3802
|
+
*
|
|
3803
|
+
* @param config - Selection field configuration
|
|
3804
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'select'` or `'native-select'`
|
|
3805
|
+
*
|
|
3806
|
+
* @example
|
|
3807
|
+
* ```typescript
|
|
3808
|
+
* const field = valueSelectionField({
|
|
3809
|
+
* key: 'color',
|
|
3810
|
+
* label: 'Color',
|
|
3811
|
+
* options: [{ label: 'Red', value: 'red' }, { label: 'Blue', value: 'blue' }]
|
|
3812
|
+
* });
|
|
3813
|
+
* ```
|
|
3814
|
+
*/
|
|
3201
3815
|
function valueSelectionField(config) {
|
|
3202
3816
|
const { key, native = false, addClearOption = false, selectAllOption: inputSelectAllOption, options: inputOptions, materialFormField } = config;
|
|
3203
3817
|
let selectAllOptionConfig;
|
|
@@ -3221,6 +3835,13 @@ function valueSelectionField(config) {
|
|
|
3221
3835
|
parsers
|
|
3222
3836
|
});
|
|
3223
3837
|
}
|
|
3838
|
+
/**
|
|
3839
|
+
* Creates a function that prepends a "clear" option to the selection options array
|
|
3840
|
+
* if one doesn't already exist.
|
|
3841
|
+
*
|
|
3842
|
+
* @param label - Optional label for the clear option
|
|
3843
|
+
* @returns A function that transforms selection options by prepending a clear option
|
|
3844
|
+
*/
|
|
3224
3845
|
function addValueSelectionOptionFunction(label) {
|
|
3225
3846
|
return (options) => {
|
|
3226
3847
|
const hasClear = options.findIndex((x) => x.clear) !== -1;
|
|
@@ -3233,6 +3854,12 @@ function addValueSelectionOptionFunction(label) {
|
|
|
3233
3854
|
};
|
|
3234
3855
|
}
|
|
3235
3856
|
|
|
3857
|
+
/**
|
|
3858
|
+
* Formly field component providing a rich text editor powered by ngx-editor.
|
|
3859
|
+
*
|
|
3860
|
+
* Outputs HTML format and marks the form control dirty on editor value changes
|
|
3861
|
+
* while focused. Supports compact mode via {@link CompactContextStore}.
|
|
3862
|
+
*/
|
|
3236
3863
|
class DbxTextEditorFieldComponent extends FieldType$1 {
|
|
3237
3864
|
_compactContextStore = inject(CompactContextStore, { optional: true });
|
|
3238
3865
|
_editor;
|
|
@@ -3319,6 +3946,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
3319
3946
|
}] });
|
|
3320
3947
|
|
|
3321
3948
|
const importsAndExports$a = [DbxTextEditorFieldComponent];
|
|
3949
|
+
/** Registers the `texteditor` Formly field type for rich text editing. */
|
|
3322
3950
|
class DbxFormFormlyTextEditorFieldModule {
|
|
3323
3951
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyTextEditorFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3324
3952
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyTextEditorFieldModule, imports: [DbxTextEditorFieldComponent, i1$1.FormlyModule], exports: [DbxTextEditorFieldComponent] });
|
|
@@ -3339,6 +3967,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
3339
3967
|
}]
|
|
3340
3968
|
}] });
|
|
3341
3969
|
|
|
3970
|
+
/**
|
|
3971
|
+
* Creates a Formly field configuration for a rich text editor.
|
|
3972
|
+
*
|
|
3973
|
+
* The field defaults to an empty string and updates the model on blur events.
|
|
3974
|
+
*
|
|
3975
|
+
* @param config - Text editor field configuration
|
|
3976
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'texteditor'`
|
|
3977
|
+
*
|
|
3978
|
+
* @example
|
|
3979
|
+
* ```typescript
|
|
3980
|
+
* const field = textEditorField({ key: 'bio', label: 'Biography', maxLength: 2000 });
|
|
3981
|
+
* ```
|
|
3982
|
+
*/
|
|
3342
3983
|
function textEditorField(config) {
|
|
3343
3984
|
const { key, minLength, maxLength, materialFormField } = config;
|
|
3344
3985
|
const fieldConfig = formlyField({
|
|
@@ -3359,6 +4000,14 @@ function textEditorField(config) {
|
|
|
3359
4000
|
return fieldConfig;
|
|
3360
4001
|
}
|
|
3361
4002
|
|
|
4003
|
+
/**
|
|
4004
|
+
* Formly custom field type for dynamically repeatable arrays of field groups.
|
|
4005
|
+
*
|
|
4006
|
+
* Renders a list of field groups that users can add to, remove from, duplicate,
|
|
4007
|
+
* and rearrange via drag-and-drop. Enforces an optional maximum item count.
|
|
4008
|
+
*
|
|
4009
|
+
* Registered as Formly type `'repeatarray'`.
|
|
4010
|
+
*/
|
|
3362
4011
|
class DbxFormRepeatArrayTypeComponent extends FieldArrayType {
|
|
3363
4012
|
_labelForField = cachedGetter(() => {
|
|
3364
4013
|
const input = this.repeatArrayField.labelForField;
|
|
@@ -3579,6 +4228,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
3579
4228
|
}] });
|
|
3580
4229
|
|
|
3581
4230
|
const importsAndExports$9 = [DbxFormRepeatArrayTypeComponent];
|
|
4231
|
+
/** Registers the `repeatarray` Formly field type for dynamic array fields. */
|
|
3582
4232
|
class DbxFormFormlyArrayFieldModule {
|
|
3583
4233
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyArrayFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3584
4234
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyArrayFieldModule, imports: [DbxFormRepeatArrayTypeComponent, i1$1.FormlyModule], exports: [DbxFormRepeatArrayTypeComponent] });
|
|
@@ -3599,6 +4249,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
3599
4249
|
}]
|
|
3600
4250
|
}] });
|
|
3601
4251
|
|
|
4252
|
+
/**
|
|
4253
|
+
* Creates a Formly field configuration for a repeatable array of field groups.
|
|
4254
|
+
*
|
|
4255
|
+
* Users can dynamically add, remove, duplicate, and rearrange entries.
|
|
4256
|
+
*
|
|
4257
|
+
* @param config - Repeat array configuration including the template field group
|
|
4258
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'repeatarray'`
|
|
4259
|
+
*
|
|
4260
|
+
* @example
|
|
4261
|
+
* ```typescript
|
|
4262
|
+
* const field = repeatArrayField({
|
|
4263
|
+
* key: 'items',
|
|
4264
|
+
* label: 'Items',
|
|
4265
|
+
* addText: 'Add Item',
|
|
4266
|
+
* removeText: 'Remove Item',
|
|
4267
|
+
* repeatFieldGroup: [textField({ key: 'name', label: 'Name' })]
|
|
4268
|
+
* });
|
|
4269
|
+
* ```
|
|
4270
|
+
*/
|
|
3602
4271
|
function repeatArrayField(config) {
|
|
3603
4272
|
const { key, label, description, repeatFieldGroup, maxLength, addText, addTemplate, removeText, duplicateText, labelForField, disableRearrange, allowAdd, allowRemove, allowDuplicate, addDuplicateToEnd } = config;
|
|
3604
4273
|
return formlyField({
|
|
@@ -3626,6 +4295,7 @@ function repeatArrayField(config) {
|
|
|
3626
4295
|
}
|
|
3627
4296
|
|
|
3628
4297
|
const importsAndExports$8 = [FormlyMaterialModule, FormlyMatCheckboxModule, FormlyMatToggleModule];
|
|
4298
|
+
/** Provides Formly Material checkbox and toggle field support. */
|
|
3629
4299
|
class DbxFormFormlyBooleanFieldModule {
|
|
3630
4300
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyBooleanFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3631
4301
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyBooleanFieldModule, imports: [FormlyMaterialModule, FormlyMatCheckboxModule, FormlyMatToggleModule], exports: [FormlyMaterialModule, FormlyMatCheckboxModule, FormlyMatToggleModule] });
|
|
@@ -3639,6 +4309,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
3639
4309
|
}]
|
|
3640
4310
|
}] });
|
|
3641
4311
|
|
|
4312
|
+
/**
|
|
4313
|
+
* Creates a Formly field configuration for a Material slide toggle.
|
|
4314
|
+
*
|
|
4315
|
+
* Defaults to `false` when no default value is specified. Uses auto-touch and style wrappers.
|
|
4316
|
+
*
|
|
4317
|
+
* @param config - Toggle field configuration
|
|
4318
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'toggle'`
|
|
4319
|
+
*
|
|
4320
|
+
* @example
|
|
4321
|
+
* ```typescript
|
|
4322
|
+
* const field = toggleField({ key: 'active', label: 'Active', defaultValue: true });
|
|
4323
|
+
* ```
|
|
4324
|
+
*/
|
|
3642
4325
|
function toggleField(config) {
|
|
3643
4326
|
const { key, defaultValue, materialFormField } = config;
|
|
3644
4327
|
const classGetter = 'dbx-mat-form-toggle-field-wrapper';
|
|
@@ -3653,6 +4336,19 @@ function toggleField(config) {
|
|
|
3653
4336
|
})
|
|
3654
4337
|
});
|
|
3655
4338
|
}
|
|
4339
|
+
/**
|
|
4340
|
+
* Creates a Formly field configuration for a Material checkbox.
|
|
4341
|
+
*
|
|
4342
|
+
* Defaults to `false` when no default value is specified. Uses a style wrapper.
|
|
4343
|
+
*
|
|
4344
|
+
* @param config - Checkbox field configuration
|
|
4345
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'checkbox'`
|
|
4346
|
+
*
|
|
4347
|
+
* @example
|
|
4348
|
+
* ```typescript
|
|
4349
|
+
* const field = checkboxField({ key: 'agree', label: 'I agree to the terms' });
|
|
4350
|
+
* ```
|
|
4351
|
+
*/
|
|
3656
4352
|
function checkboxField(config) {
|
|
3657
4353
|
const { key, defaultValue, materialFormField } = config;
|
|
3658
4354
|
const classGetter = 'dbx-mat-form-checkbox-field-wrapper';
|
|
@@ -3713,7 +4409,19 @@ function dateTimePreset(config) {
|
|
|
3713
4409
|
};
|
|
3714
4410
|
}
|
|
3715
4411
|
|
|
4412
|
+
/**
|
|
4413
|
+
* Injection token for providing default date-time field menu presets application-wide.
|
|
4414
|
+
*/
|
|
3716
4415
|
const DBX_DATE_TIME_FIELD_MENU_PRESETS_TOKEN = new InjectionToken('DbxDateTimeFieldMenuPresetsServicePresets');
|
|
4416
|
+
/**
|
|
4417
|
+
* Service that manages default date-time preset configurations for all date-time fields.
|
|
4418
|
+
*
|
|
4419
|
+
* Presets are shown in the date-time field dropdown menu and allow users to quickly
|
|
4420
|
+
* select common date/time values (e.g., "Now", "Start of day").
|
|
4421
|
+
*
|
|
4422
|
+
* Provide default presets via {@link DBX_DATE_TIME_FIELD_MENU_PRESETS_TOKEN}, or set them
|
|
4423
|
+
* dynamically via the `configurations` setter.
|
|
4424
|
+
*/
|
|
3717
4425
|
class DbxDateTimeFieldMenuPresetsService {
|
|
3718
4426
|
_configurations = new BehaviorSubject(inject(DBX_DATE_TIME_FIELD_MENU_PRESETS_TOKEN, { optional: true }) ?? []);
|
|
3719
4427
|
configurations$ = this._configurations.asObservable();
|
|
@@ -3760,6 +4468,22 @@ var DbxDateTimeValueMode;
|
|
|
3760
4468
|
*/
|
|
3761
4469
|
DbxDateTimeValueMode[DbxDateTimeValueMode["SYSTEM_MINUTE_OF_DAY"] = 5] = "SYSTEM_MINUTE_OF_DAY";
|
|
3762
4470
|
})(DbxDateTimeValueMode || (DbxDateTimeValueMode = {}));
|
|
4471
|
+
/**
|
|
4472
|
+
* Creates a parser function that converts raw form input values (Date, string, or number)
|
|
4473
|
+
* into JavaScript Date objects based on the specified value mode.
|
|
4474
|
+
*
|
|
4475
|
+
* Handles timezone conversion when a timezone instance is provided and the mode requires it.
|
|
4476
|
+
*
|
|
4477
|
+
* @param mode - Determines how the input value is interpreted
|
|
4478
|
+
* @param timezoneInstance - Optional timezone converter for UTC-normal date handling
|
|
4479
|
+
* @returns A function that parses input values to Date objects
|
|
4480
|
+
*
|
|
4481
|
+
* @example
|
|
4482
|
+
* ```typescript
|
|
4483
|
+
* const parser = dbxDateTimeInputValueParseFactory(DbxDateTimeValueMode.DATE_STRING, timezoneInstance);
|
|
4484
|
+
* const date = parser('2024-01-15T10:00:00Z');
|
|
4485
|
+
* ```
|
|
4486
|
+
*/
|
|
3763
4487
|
function dbxDateTimeInputValueParseFactory(mode, timezoneInstance) {
|
|
3764
4488
|
let factory;
|
|
3765
4489
|
let useTimezoneInstance = true;
|
|
@@ -3820,6 +4544,22 @@ function dbxDateTimeInputValueParseFactory(mode, timezoneInstance) {
|
|
|
3820
4544
|
}
|
|
3821
4545
|
return factory;
|
|
3822
4546
|
}
|
|
4547
|
+
/**
|
|
4548
|
+
* Creates a formatter function that converts JavaScript Date objects into the appropriate
|
|
4549
|
+
* output format (Date, ISO string, timestamp, or minute-of-day) based on the specified value mode.
|
|
4550
|
+
*
|
|
4551
|
+
* Handles timezone conversion when a timezone instance is provided and the mode requires it.
|
|
4552
|
+
*
|
|
4553
|
+
* @param mode - Determines the output format
|
|
4554
|
+
* @param timezoneInstance - Optional timezone converter for UTC-normal date handling
|
|
4555
|
+
* @returns A function that formats Date objects to the target output type
|
|
4556
|
+
*
|
|
4557
|
+
* @example
|
|
4558
|
+
* ```typescript
|
|
4559
|
+
* const formatter = dbxDateTimeOutputValueFactory(DbxDateTimeValueMode.DAY_STRING, null);
|
|
4560
|
+
* const dayString = formatter(new Date()); // e.g., '2024-01-15'
|
|
4561
|
+
* ```
|
|
4562
|
+
*/
|
|
3823
4563
|
function dbxDateTimeOutputValueFactory(mode, timezoneInstance) {
|
|
3824
4564
|
let factory;
|
|
3825
4565
|
let useTimezoneInstance = true;
|
|
@@ -3856,10 +4596,26 @@ function dbxDateTimeOutputValueFactory(mode, timezoneInstance) {
|
|
|
3856
4596
|
}
|
|
3857
4597
|
return factory;
|
|
3858
4598
|
}
|
|
4599
|
+
/**
|
|
4600
|
+
* Compares two date-time field values for equality, handling Date, ISO8601DayString, and number (timestamp/minute) types.
|
|
4601
|
+
*
|
|
4602
|
+
* For string and number types, performs strict equality. For Date objects, compares hours and minutes.
|
|
4603
|
+
*
|
|
4604
|
+
* @param a - First date-time value
|
|
4605
|
+
* @param b - Second date-time value
|
|
4606
|
+
* @returns Whether the two values represent the same date-time
|
|
4607
|
+
*/
|
|
3859
4608
|
function dbxDateTimeIsSameDateTimeFieldValue(a, b) {
|
|
3860
4609
|
const typeofA = typeof a;
|
|
3861
4610
|
return a && b ? (typeofA === 'string' || typeofA === 'number' ? a === b : isSameDateHoursAndMinutes(a, b)) : a == b;
|
|
3862
4611
|
}
|
|
4612
|
+
/**
|
|
4613
|
+
* Compares two date range field values for equality by comparing both start and end values.
|
|
4614
|
+
*
|
|
4615
|
+
* @param a - First date range value
|
|
4616
|
+
* @param b - Second date range value
|
|
4617
|
+
* @returns Whether the two date ranges represent the same range
|
|
4618
|
+
*/
|
|
3863
4619
|
function dbxDateRangeIsSameDateRangeFieldValue(a, b) {
|
|
3864
4620
|
return a && b ? dbxDateTimeIsSameDateTimeFieldValue(a.start, b.start) && dbxDateTimeIsSameDateTimeFieldValue(a.end, b.end) : a == b;
|
|
3865
4621
|
}
|
|
@@ -3879,9 +4635,20 @@ var DbxDateTimeFieldTimeMode;
|
|
|
3879
4635
|
*/
|
|
3880
4636
|
DbxDateTimeFieldTimeMode["NONE"] = "none";
|
|
3881
4637
|
})(DbxDateTimeFieldTimeMode || (DbxDateTimeFieldTimeMode = {}));
|
|
4638
|
+
/**
|
|
4639
|
+
* Type guard that checks whether the input is a {@link DbxDateTimeFieldTimeDateConfig}.
|
|
4640
|
+
*/
|
|
3882
4641
|
function isDbxDateTimeFieldTimeDateConfig(input) {
|
|
3883
4642
|
return input != null && typeof input === 'object' && typeof input.path === 'string';
|
|
3884
4643
|
}
|
|
4644
|
+
/**
|
|
4645
|
+
* Creates an observable that emits the current Date value from a synced field control
|
|
4646
|
+
* matching the specified sync type ('before' or 'after').
|
|
4647
|
+
*
|
|
4648
|
+
* @param parseConfigsObs - Observable of parsed sync field configurations
|
|
4649
|
+
* @param type - The sync direction to filter for
|
|
4650
|
+
* @returns Observable of the synced date value, or null if no matching sync config
|
|
4651
|
+
*/
|
|
3885
4652
|
function syncConfigValueObs(parseConfigsObs, type) {
|
|
3886
4653
|
return parseConfigsObs.pipe(switchMap((x) => {
|
|
3887
4654
|
const config = x.find((y) => y.syncType === type);
|
|
@@ -3905,6 +4672,15 @@ const DBX_DATE_TIME_FIELD_DATE_NOT_IN_SCHEDULE_ERROR = 'dateTimeFieldDateNotInSc
|
|
|
3905
4672
|
* Error code used when the selected time/time input is not in the limited range.
|
|
3906
4673
|
*/
|
|
3907
4674
|
const DBX_DATE_TIME_FIELD_TIME_NOT_IN_RANGE_ERROR = 'dateTimeFieldTimeNotInRange';
|
|
4675
|
+
/**
|
|
4676
|
+
* Formly custom field type for date and time selection.
|
|
4677
|
+
*
|
|
4678
|
+
* Supports date-only, time-only, and combined date-time modes. Handles timezone conversion,
|
|
4679
|
+
* sync with other date fields, configurable presets, and keyboard navigation (arrow keys for
|
|
4680
|
+
* incrementing date/time).
|
|
4681
|
+
*
|
|
4682
|
+
* Registered as Formly type `'datetime'`.
|
|
4683
|
+
*/
|
|
3908
4684
|
class DbxDateTimeFieldComponent extends FieldType$1 {
|
|
3909
4685
|
dbxDateTimeFieldConfigService = inject(DbxDateTimeFieldMenuPresetsService);
|
|
3910
4686
|
_sub = new SubscriptionObject();
|
|
@@ -4593,6 +5369,15 @@ function dbxFixedDateRangeOutputValueFactory(mode, timezoneInstance) {
|
|
|
4593
5369
|
};
|
|
4594
5370
|
}
|
|
4595
5371
|
const TIME_OUTPUT_THROTTLE_TIME = 10;
|
|
5372
|
+
/**
|
|
5373
|
+
* Formly custom field type for selecting a fixed date range using an inline calendar.
|
|
5374
|
+
*
|
|
5375
|
+
* Supports multiple selection modes (single date, normal range, arbitrary range),
|
|
5376
|
+
* timezone conversion, date range input configuration, and optional text inputs for
|
|
5377
|
+
* start/end dates.
|
|
5378
|
+
*
|
|
5379
|
+
* Registered as Formly type `'fixeddaterange'`.
|
|
5380
|
+
*/
|
|
4596
5381
|
class DbxFixedDateRangeFieldComponent extends FieldType$1 {
|
|
4597
5382
|
dbxDateTimeFieldMenuPresetsService = inject(DbxDateTimeFieldMenuPresetsService);
|
|
4598
5383
|
calendar = viewChild.required(MatCalendar);
|
|
@@ -5012,6 +5797,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
5012
5797
|
}
|
|
5013
5798
|
], imports: [MatDatepickerModule, MatFormFieldModule, FormsModule, ReactiveFormsModule, MatInputModule, MatError, NgClass], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<div class=\"dbx-fixeddaterange-field\">\n <mat-calendar #calendarView [selected]=\"calendarSelectionSignal()\" [dateFilter]=\"pickerFilterSignal()\" [minDate]=\"minDateSignal()\" [maxDate]=\"maxDateSignal()\" (selectedChange)=\"selectedChange($event)\"></mat-calendar>\n <mat-form-field class=\"dbx-fixeddaterange-field-input\" appearance=\"fill\">\n @if (showRangeInput) {\n <mat-date-range-input [formGroup]=\"inputRangeForm\">\n <input #startDateInput matStartDate formControlName=\"start\" placeholder=\"Start date\" />\n <input #endDateInput [ngClass]=\"endDisabledSignal() ? 'dbx-fixeddaterange-field-input-end' : ''\" [attr.tabindex]=\"endDisabledSignal() ? -1 : 0\" matEndDate formControlName=\"end\" placeholder=\"End date\" />\n </mat-date-range-input>\n }\n </mat-form-field>\n @if (formControl.hasError('required')) {\n <mat-error>Date range is required</mat-error>\n }\n</div>\n" }]
|
|
5014
5799
|
}], propDecorators: { calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatCalendar), { isSignal: true }] }], startDateInputElement: [{ type: i0.ViewChild, args: ['startDateInput', { ...{ read: ElementRef }, isSignal: true }] }], endDateInputElement: [{ type: i0.ViewChild, args: ['endDateInput', { ...{ read: ElementRef }, isSignal: true }] }] } });
|
|
5800
|
+
/**
|
|
5801
|
+
* Custom Material date range selection strategy for the fixed date range field.
|
|
5802
|
+
*
|
|
5803
|
+
* Provides preview highlighting on the calendar based on the current selection mode
|
|
5804
|
+
* and boundary constraints.
|
|
5805
|
+
*/
|
|
5015
5806
|
class DbxFixedDateRangeFieldSelectionStrategy {
|
|
5016
5807
|
_dateAdapter = inject((DateAdapter));
|
|
5017
5808
|
dbxFixedDateRangeFieldComponent = inject(DbxFixedDateRangeFieldComponent);
|
|
@@ -5068,6 +5859,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
5068
5859
|
}] });
|
|
5069
5860
|
|
|
5070
5861
|
const importsAndExports$7 = [DbxDateTimeFieldComponent, DbxFixedDateRangeFieldComponent, DbxFormFormlyWrapperModule];
|
|
5862
|
+
/** Registers the `datetime` and `fixeddaterange` Formly field types with style and form-field wrappers. */
|
|
5071
5863
|
class DbxFormFormlyDateFieldModule {
|
|
5072
5864
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyDateFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
5073
5865
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyDateFieldModule, imports: [DbxDateTimeFieldComponent, DbxFixedDateRangeFieldComponent, DbxFormFormlyWrapperModule, i1$1.FormlyModule], exports: [DbxDateTimeFieldComponent, DbxFixedDateRangeFieldComponent, DbxFormFormlyWrapperModule] });
|
|
@@ -5096,6 +5888,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
5096
5888
|
}]
|
|
5097
5889
|
}] });
|
|
5098
5890
|
|
|
5891
|
+
/**
|
|
5892
|
+
* Wraps a Formly field config with a named wrapper and its associated props.
|
|
5893
|
+
*
|
|
5894
|
+
* @param fieldConfig - The field config to wrap
|
|
5895
|
+
* @param wrapperKey - The registered wrapper key
|
|
5896
|
+
* @param wrapperProps - Configuration props for the wrapper
|
|
5897
|
+
* @returns A new field config with the wrapper applied
|
|
5898
|
+
*
|
|
5899
|
+
* @example
|
|
5900
|
+
* ```typescript
|
|
5901
|
+
* const wrapped = addWrapperToFormlyFieldConfig(myField, 'section', { header: 'Details' });
|
|
5902
|
+
* ```
|
|
5903
|
+
*/
|
|
5099
5904
|
function addWrapperToFormlyFieldConfig(fieldConfig, wrapperKey, wrapperProps) {
|
|
5100
5905
|
return {
|
|
5101
5906
|
wrappers: [wrapperKey],
|
|
@@ -5103,30 +5908,58 @@ function addWrapperToFormlyFieldConfig(fieldConfig, wrapperKey, wrapperProps) {
|
|
|
5103
5908
|
fieldGroup: [fieldConfig]
|
|
5104
5909
|
};
|
|
5105
5910
|
}
|
|
5911
|
+
/**
|
|
5912
|
+
* Wraps a field with the auto-touch wrapper that marks the control as touched on value change.
|
|
5913
|
+
*/
|
|
5106
5914
|
function autoTouchWrapper(fieldConfig, autoTouchWrapper = {}) {
|
|
5107
5915
|
return addWrapperToFormlyFieldConfig(fieldConfig, AUTO_TOUCH_WRAPPER_KEY, autoTouchWrapper);
|
|
5108
5916
|
}
|
|
5917
|
+
/**
|
|
5918
|
+
* Wraps a field with the expand wrapper that shows/hides the field based on value or user click.
|
|
5919
|
+
*/
|
|
5109
5920
|
function expandWrapper(fieldConfig, expandWrapper = {}) {
|
|
5110
5921
|
return addWrapperToFormlyFieldConfig(fieldConfig, EXPAND_WRAPPER_KEY, expandWrapper);
|
|
5111
5922
|
}
|
|
5923
|
+
/**
|
|
5924
|
+
* Wraps a field with the toggle wrapper that uses a slide toggle to show/hide content.
|
|
5925
|
+
*/
|
|
5112
5926
|
function toggleWrapper(fieldConfig, toggleWrapper = {}) {
|
|
5113
5927
|
return addWrapperToFormlyFieldConfig(fieldConfig, TOGGLE_WRAPPER_KEY, toggleWrapper);
|
|
5114
5928
|
}
|
|
5929
|
+
/**
|
|
5930
|
+
* Wraps a field group in a section layout with an optional header and hint.
|
|
5931
|
+
*/
|
|
5115
5932
|
function sectionWrapper(fieldConfig, sectionWrapper = {}) {
|
|
5116
5933
|
return addWrapperToFormlyFieldConfig(fieldConfig, SECTION_WRAPPER_KEY, sectionWrapper);
|
|
5117
5934
|
}
|
|
5935
|
+
/**
|
|
5936
|
+
* Wraps a field group in a subsection layout with an optional header and hint.
|
|
5937
|
+
*/
|
|
5118
5938
|
function subsectionWrapper(fieldConfig, subsectionWrapper = {}) {
|
|
5119
5939
|
return addWrapperToFormlyFieldConfig(fieldConfig, SUBSECTION_WRAPPER_KEY, subsectionWrapper);
|
|
5120
5940
|
}
|
|
5941
|
+
/**
|
|
5942
|
+
* Wraps a field with an info button that triggers a callback when clicked.
|
|
5943
|
+
*/
|
|
5121
5944
|
function infoWrapper(fieldConfig, infoWrapper) {
|
|
5122
5945
|
return addWrapperToFormlyFieldConfig(fieldConfig, INFO_WRAPPER_KEY, infoWrapper);
|
|
5123
5946
|
}
|
|
5947
|
+
/**
|
|
5948
|
+
* Wraps a field with dynamic CSS class and style bindings.
|
|
5949
|
+
*/
|
|
5124
5950
|
function styleWrapper(fieldConfig, styleWrapper) {
|
|
5125
5951
|
return addWrapperToFormlyFieldConfig(fieldConfig, STYLE_WRAPPER_KEY, styleWrapper);
|
|
5126
5952
|
}
|
|
5953
|
+
/**
|
|
5954
|
+
* Wraps a field with a loading indicator that shows during async validation.
|
|
5955
|
+
*/
|
|
5127
5956
|
function workingWrapper(fieldConfig, workingWrapper = {}) {
|
|
5128
5957
|
return addWrapperToFormlyFieldConfig(fieldConfig, WORKING_WRAPPER_KEY, workingWrapper);
|
|
5129
5958
|
}
|
|
5959
|
+
/**
|
|
5960
|
+
* Type guard that checks if the input is a {@link DbxFlexLayoutWrapperGroupFieldConfig}
|
|
5961
|
+
* (has a `field` property) rather than a plain {@link FormlyFieldConfig}.
|
|
5962
|
+
*/
|
|
5130
5963
|
function checkIsFieldFlexLayoutGroupFieldConfig(input) {
|
|
5131
5964
|
if (input.field != null) {
|
|
5132
5965
|
return true;
|
|
@@ -5135,6 +5968,22 @@ function checkIsFieldFlexLayoutGroupFieldConfig(input) {
|
|
|
5135
5968
|
return false;
|
|
5136
5969
|
}
|
|
5137
5970
|
}
|
|
5971
|
+
/**
|
|
5972
|
+
* Creates a flex-layout-wrapped field group that arranges child fields horizontally
|
|
5973
|
+
* with configurable sizing, breakpoints, and responsive behavior.
|
|
5974
|
+
*
|
|
5975
|
+
* @param fieldConfigs - Array of field configs or field config pairs with size overrides
|
|
5976
|
+
* @param options - Flex layout defaults including breakpoint, relative sizing, and default size
|
|
5977
|
+
* @returns A {@link FormlyFieldConfig} with flex wrapper applied
|
|
5978
|
+
*
|
|
5979
|
+
* @example
|
|
5980
|
+
* ```typescript
|
|
5981
|
+
* const layout = flexLayoutWrapper([
|
|
5982
|
+
* { field: textField({ key: 'first' }), size: 2 },
|
|
5983
|
+
* { field: textField({ key: 'last' }), size: 2 }
|
|
5984
|
+
* ], { relative: true });
|
|
5985
|
+
* ```
|
|
5986
|
+
*/
|
|
5138
5987
|
function flexLayoutWrapper(fieldConfigs, { relative, breakpoint, breakToColumn, size: defaultSize = 2 } = {}) {
|
|
5139
5988
|
return {
|
|
5140
5989
|
wrappers: ['flex'],
|
|
@@ -5172,6 +6021,10 @@ readonly addonLeft?: Maybe<NumberFieldAddon>;
|
|
|
5172
6021
|
readonly addonRight?: Maybe<NumberFieldAddon>;
|
|
5173
6022
|
*/
|
|
5174
6023
|
|
|
6024
|
+
/**
|
|
6025
|
+
* Factory that returns an observable of a date-time picker configuration
|
|
6026
|
+
* that automatically selects the next upcoming time, rounded down to the nearest minute.
|
|
6027
|
+
*/
|
|
5175
6028
|
const TAKE_NEXT_UPCOMING_TIME_CONFIG_OBS = () => of({
|
|
5176
6029
|
takeNextUpcomingTime: true,
|
|
5177
6030
|
roundDownToMinute: true
|
|
@@ -5186,6 +6039,18 @@ function timeOnlyField(config = {}) {
|
|
|
5186
6039
|
timeOnly: true
|
|
5187
6040
|
});
|
|
5188
6041
|
}
|
|
6042
|
+
/**
|
|
6043
|
+
* Creates a Formly field configuration for a date-time picker with optional time selection,
|
|
6044
|
+
* timezone awareness, and preset values.
|
|
6045
|
+
*
|
|
6046
|
+
* @param config - Optional overrides; defaults to key `'date'`, time mode `REQUIRED`
|
|
6047
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'datetime'`
|
|
6048
|
+
*
|
|
6049
|
+
* @example
|
|
6050
|
+
* ```typescript
|
|
6051
|
+
* const field = dateTimeField({ key: 'startDate', label: 'Start', required: true });
|
|
6052
|
+
* ```
|
|
6053
|
+
*/
|
|
5189
6054
|
function dateTimeField(config = {}) {
|
|
5190
6055
|
const { key = 'date', showClearButton, dateLabel, timeLabel, allDayLabel, atTimeLabel, timeDate, timezone, minuteStep, showTimezone, timeMode = DbxDateTimeFieldTimeMode.REQUIRED, valueMode, alwaysShowDateInput, autofillDateWhenTimeIsPicked, fullDayInUTC, fullDayFieldName, pickerConfig, getSyncFieldsObs, hideDatePicker, hideDateHint, timeOnly = false, presets, materialFormField } = config;
|
|
5191
6056
|
const classGetter = 'dbx-mat-form-field-disable-underline dbx-mat-form-date-time-field-wrapper';
|
|
@@ -5220,6 +6085,18 @@ function dateTimeField(config = {}) {
|
|
|
5220
6085
|
});
|
|
5221
6086
|
return fieldConfig;
|
|
5222
6087
|
}
|
|
6088
|
+
/**
|
|
6089
|
+
* Creates a pair of date pickers for selecting a date range (start and end dates)
|
|
6090
|
+
* arranged in a flex layout. The pickers are synchronized so the start date stays before the end date.
|
|
6091
|
+
*
|
|
6092
|
+
* @param config - Date range configuration with optional start/end overrides
|
|
6093
|
+
* @returns A {@link FormlyFieldConfig} containing the start and end date field pair
|
|
6094
|
+
*
|
|
6095
|
+
* @example
|
|
6096
|
+
* ```typescript
|
|
6097
|
+
* const field = dateRangeField({ required: true, start: { key: 'from' }, end: { key: 'to' } });
|
|
6098
|
+
* ```
|
|
6099
|
+
*/
|
|
5223
6100
|
function dateRangeField(config = {}) {
|
|
5224
6101
|
const { required: inputRequired, start, end, timeDate, timezone, showTimezone, presets, valueMode, minuteStep } = config;
|
|
5225
6102
|
const required = inputRequired ?? start?.required ?? false;
|
|
@@ -5260,6 +6137,18 @@ function dateRangeField(config = {}) {
|
|
|
5260
6137
|
fieldGroup: [flexLayoutWrapper([startField, endField], { relative: true, breakToColumn: true, breakpoint: 'large' })]
|
|
5261
6138
|
};
|
|
5262
6139
|
}
|
|
6140
|
+
/**
|
|
6141
|
+
* Creates a pair of time-only pickers for selecting a time range (start and end times)
|
|
6142
|
+
* arranged in a flex layout.
|
|
6143
|
+
*
|
|
6144
|
+
* @param inputConfig - Time range configuration with optional start/end overrides
|
|
6145
|
+
* @returns A {@link FormlyFieldConfig} containing the start and end time field pair
|
|
6146
|
+
*
|
|
6147
|
+
* @example
|
|
6148
|
+
* ```typescript
|
|
6149
|
+
* const field = dateTimeRangeField({ required: true });
|
|
6150
|
+
* ```
|
|
6151
|
+
*/
|
|
5263
6152
|
function dateTimeRangeField(inputConfig = {}) {
|
|
5264
6153
|
const { required = false, start: inputStart, end: inputEnd, timezone, timeDate, showTimezone, presets, valueMode, minuteStep } = inputConfig;
|
|
5265
6154
|
function dateTimeRangeFieldConfig(config) {
|
|
@@ -5296,6 +6185,17 @@ function dateTimeRangeField(inputConfig = {}) {
|
|
|
5296
6185
|
};
|
|
5297
6186
|
return dateRangeField(config);
|
|
5298
6187
|
}
|
|
6188
|
+
/**
|
|
6189
|
+
* Creates a Formly field configuration for a fixed date range picker.
|
|
6190
|
+
*
|
|
6191
|
+
* @param config - Optional overrides; defaults to key `'dateRange'`
|
|
6192
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'fixeddaterange'`
|
|
6193
|
+
*
|
|
6194
|
+
* @example
|
|
6195
|
+
* ```typescript
|
|
6196
|
+
* const field = fixedDateRangeField({ key: 'eventDates', required: true });
|
|
6197
|
+
* ```
|
|
6198
|
+
*/
|
|
5299
6199
|
function fixedDateRangeField(config = {}) {
|
|
5300
6200
|
const { key = 'dateRange', dateRangeInput, pickerConfig, timezone, selectionMode, showTimezone, valueMode, fullDayInUTC, presets, showRangeInput, materialFormField } = config;
|
|
5301
6201
|
const classGetter = 'dbx-mat-form-field-disable-underline dbx-form-fixed-date-range-field-wrapper';
|
|
@@ -5545,31 +6445,47 @@ const IS_NOT_WEBSITE_URL_WITH_EXPECTED_DOMAIN_VALIDATION_KEY = 'isNotWebsiteUrlW
|
|
|
5545
6445
|
* @returns
|
|
5546
6446
|
*/
|
|
5547
6447
|
function isWebsiteUrlValidator(config) {
|
|
5548
|
-
const { requirePrefix, validDomains: inputValidDomains } = config ?? {};
|
|
6448
|
+
const { requirePrefix, allowPorts, validDomains: inputValidDomains } = config ?? {};
|
|
5549
6449
|
const isPrefixRequired = requirePrefix ?? true;
|
|
6450
|
+
const isAllowPorts = allowPorts ?? false;
|
|
5550
6451
|
const validDomains = asArray(inputValidDomains);
|
|
5551
6452
|
const validDomainsSet = new Set(validDomains);
|
|
5552
6453
|
const validateDomains = validDomainsSet.size > 0;
|
|
6454
|
+
function isValidUrl(details) {
|
|
6455
|
+
if (isPrefixRequired) {
|
|
6456
|
+
if (isWebsiteUrlWithPrefix(details.input)) {
|
|
6457
|
+
return true;
|
|
6458
|
+
}
|
|
6459
|
+
}
|
|
6460
|
+
else if (details.isWebsiteUrl) {
|
|
6461
|
+
return true;
|
|
6462
|
+
}
|
|
6463
|
+
if (isAllowPorts && details.hasPortNumber) {
|
|
6464
|
+
return isPrefixRequired ? details.hasHttpPrefix : true;
|
|
6465
|
+
}
|
|
6466
|
+
return false;
|
|
6467
|
+
}
|
|
6468
|
+
const portNumbersMessagePart = isAllowPorts ? '' : ' Urls with port numbers (e.g. localhost:8080) are not allowed.';
|
|
5553
6469
|
const validateWebsiteValue = isPrefixRequired
|
|
5554
6470
|
? (details) => {
|
|
5555
|
-
return
|
|
6471
|
+
return isValidUrl(details)
|
|
5556
6472
|
? null
|
|
5557
6473
|
: {
|
|
5558
6474
|
[IS_NOT_WEBSITE_URL_WITH_PREFIX_VALIDATION_KEY]: {
|
|
5559
6475
|
value: details.input,
|
|
5560
6476
|
isPrefixRequired,
|
|
5561
|
-
message: `Value is not a website url with an http/https prefix
|
|
6477
|
+
message: `Value is not a website url with an http/https prefix.${portNumbersMessagePart}`
|
|
5562
6478
|
}
|
|
5563
6479
|
};
|
|
5564
6480
|
}
|
|
5565
6481
|
: (details) => {
|
|
5566
|
-
return details
|
|
6482
|
+
return isValidUrl(details)
|
|
5567
6483
|
? null
|
|
5568
6484
|
: {
|
|
5569
6485
|
[IS_NOT_WEBSITE_URL_VALIDATION_KEY]: {
|
|
5570
6486
|
value: details.input,
|
|
5571
6487
|
isPrefixRequired,
|
|
5572
|
-
message: `Value is not a valid website url
|
|
6488
|
+
message: `Value is not a valid website url.${portNumbersMessagePart}`
|
|
5573
6489
|
}
|
|
5574
6490
|
};
|
|
5575
6491
|
};
|
|
@@ -5602,6 +6518,18 @@ function isWebsiteUrlValidator(config) {
|
|
|
5602
6518
|
};
|
|
5603
6519
|
}
|
|
5604
6520
|
|
|
6521
|
+
/**
|
|
6522
|
+
* Builds an array of value parsers for a number field, incorporating any configured
|
|
6523
|
+
* number transformation (e.g., precision, rounding) as a parser prepended to existing parsers.
|
|
6524
|
+
*
|
|
6525
|
+
* @param config - Parser and transform configuration
|
|
6526
|
+
* @returns Array of value parsers, or undefined if none configured
|
|
6527
|
+
*
|
|
6528
|
+
* @example
|
|
6529
|
+
* ```typescript
|
|
6530
|
+
* const parsers = numberFieldTransformParser({ transform: { precision: 2 } });
|
|
6531
|
+
* ```
|
|
6532
|
+
*/
|
|
5605
6533
|
function numberFieldTransformParser(config) {
|
|
5606
6534
|
const { parsers: inputParsers, transform } = config;
|
|
5607
6535
|
let parsers;
|
|
@@ -5614,6 +6542,19 @@ function numberFieldTransformParser(config) {
|
|
|
5614
6542
|
}
|
|
5615
6543
|
return parsers;
|
|
5616
6544
|
}
|
|
6545
|
+
/**
|
|
6546
|
+
* Creates a Formly field configuration for a numeric input.
|
|
6547
|
+
*
|
|
6548
|
+
* Adds a divisibility validator when both `step` and `enforceStep` are set.
|
|
6549
|
+
*
|
|
6550
|
+
* @param config - Number field configuration
|
|
6551
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'input'` and input type `'number'`
|
|
6552
|
+
*
|
|
6553
|
+
* @example
|
|
6554
|
+
* ```typescript
|
|
6555
|
+
* const field = numberField({ key: 'quantity', label: 'Quantity', min: 1, max: 100, step: 1 });
|
|
6556
|
+
* ```
|
|
6557
|
+
*/
|
|
5617
6558
|
function numberField(config) {
|
|
5618
6559
|
const { key, min, max, step, enforceStep, inputType: type = 'number', materialFormField } = config;
|
|
5619
6560
|
const parsers = numberFieldTransformParser(config);
|
|
@@ -5637,6 +6578,17 @@ function numberField(config) {
|
|
|
5637
6578
|
parsers
|
|
5638
6579
|
});
|
|
5639
6580
|
}
|
|
6581
|
+
/**
|
|
6582
|
+
* Creates a Formly field configuration for a Material slider input.
|
|
6583
|
+
*
|
|
6584
|
+
* @param config - Slider field configuration including max (required), thumb label, and tick interval
|
|
6585
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'slider'`
|
|
6586
|
+
*
|
|
6587
|
+
* @example
|
|
6588
|
+
* ```typescript
|
|
6589
|
+
* const field = numberSliderField({ key: 'rating', label: 'Rating', min: 0, max: 10, step: 1 });
|
|
6590
|
+
* ```
|
|
6591
|
+
*/
|
|
5640
6592
|
function numberSliderField(config) {
|
|
5641
6593
|
const { key, min, max, step, enforceStep, inputType: type = 'number', materialFormField, thumbLabel: inputThumbLabel, tickInterval: inputTickInterval, invertSelectionColoring: invertedSelectionColoring = false, displayWith } = config;
|
|
5642
6594
|
const parsers = numberFieldTransformParser(config);
|
|
@@ -5670,11 +6622,23 @@ function numberSliderField(config) {
|
|
|
5670
6622
|
parsers
|
|
5671
6623
|
});
|
|
5672
6624
|
}
|
|
6625
|
+
/**
|
|
6626
|
+
* Creates a number field pre-configured for dollar amount input with cent-level precision.
|
|
6627
|
+
*
|
|
6628
|
+
* @param config - Number field configuration (precision is overridden to dollar amount precision)
|
|
6629
|
+
* @returns A {@link FormlyFieldConfig} for dollar amount input
|
|
6630
|
+
*
|
|
6631
|
+
* @example
|
|
6632
|
+
* ```typescript
|
|
6633
|
+
* const field = dollarAmountField({ key: 'price', label: 'Price', min: 0, required: true });
|
|
6634
|
+
* ```
|
|
6635
|
+
*/
|
|
5673
6636
|
function dollarAmountField(config) {
|
|
5674
6637
|
return numberField({ ...config, transform: { ...config.transform, precision: config.transform?.precision ?? DOLLAR_AMOUNT_PRECISION } }); // TODO: Add wrapper addon, addonLeft: { text: '$' }
|
|
5675
6638
|
}
|
|
5676
6639
|
|
|
5677
6640
|
const importsAndExports$6 = [FormlyMaterialModule, FormlyMatSliderModule];
|
|
6641
|
+
/** Provides Formly Material number input and slider support. */
|
|
5678
6642
|
class DbxFormFormlyNumberFieldModule {
|
|
5679
6643
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyNumberFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
5680
6644
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyNumberFieldModule, imports: [FormlyMaterialModule, FormlyMatSliderModule], exports: [FormlyMaterialModule, FormlyMatSliderModule] });
|
|
@@ -5688,7 +6652,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
5688
6652
|
}]
|
|
5689
6653
|
}] });
|
|
5690
6654
|
|
|
6655
|
+
/** Default preferred countries shown at the top of the phone country dropdown. */
|
|
5691
6656
|
const DEFAULT_PREFERRED_COUNTRIES = ['us'];
|
|
6657
|
+
/**
|
|
6658
|
+
* Formly custom field type for international phone number input with optional extension support.
|
|
6659
|
+
*
|
|
6660
|
+
* Uses ngx-mat-input-tel for the country-aware phone input and manages E.164 phone number
|
|
6661
|
+
* formatting. Supports splitting phone + extension pairs for storage and display.
|
|
6662
|
+
*
|
|
6663
|
+
* Registered as Formly type `'intphone'`.
|
|
6664
|
+
*/
|
|
5692
6665
|
class DbxPhoneFieldComponent extends FieldType$1 {
|
|
5693
6666
|
inputSync = new SubscriptionObject();
|
|
5694
6667
|
outputSync = new SubscriptionObject();
|
|
@@ -5780,6 +6753,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
5780
6753
|
}] });
|
|
5781
6754
|
|
|
5782
6755
|
const importsAndExports$5 = [DbxPhoneFieldComponent];
|
|
6756
|
+
/** Registers the `intphone` Formly field type for international phone number input. */
|
|
5783
6757
|
class DbxFormFormlyPhoneFieldModule {
|
|
5784
6758
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyPhoneFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
5785
6759
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyPhoneFieldModule, imports: [DbxPhoneFieldComponent, i1$1.FormlyModule], exports: [DbxPhoneFieldComponent] });
|
|
@@ -5800,6 +6774,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
5800
6774
|
}]
|
|
5801
6775
|
}] });
|
|
5802
6776
|
|
|
6777
|
+
/**
|
|
6778
|
+
* Builds an array of value parsers for a text field, incorporating any configured
|
|
6779
|
+
* string transformation (e.g., trim, lowercase) as a parser prepended to existing parsers.
|
|
6780
|
+
*
|
|
6781
|
+
* @param config - Parser and transform configuration
|
|
6782
|
+
* @returns Array of value parsers, or undefined if none configured
|
|
6783
|
+
*
|
|
6784
|
+
* @example
|
|
6785
|
+
* ```typescript
|
|
6786
|
+
* const parsers = textFieldTransformParser({ transform: { trim: true, toLowercase: true } });
|
|
6787
|
+
* ```
|
|
6788
|
+
*/
|
|
5803
6789
|
function textFieldTransformParser(config) {
|
|
5804
6790
|
const { parsers: inputParsers, transform } = config;
|
|
5805
6791
|
let parsers;
|
|
@@ -5812,6 +6798,17 @@ function textFieldTransformParser(config) {
|
|
|
5812
6798
|
}
|
|
5813
6799
|
return parsers;
|
|
5814
6800
|
}
|
|
6801
|
+
/**
|
|
6802
|
+
* Creates a Formly field configuration for a single-line text input.
|
|
6803
|
+
*
|
|
6804
|
+
* @param config - Text field configuration including key, label, validation, and transform options
|
|
6805
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'input'`
|
|
6806
|
+
*
|
|
6807
|
+
* @example
|
|
6808
|
+
* ```typescript
|
|
6809
|
+
* const field = textField({ key: 'username', label: 'Username', maxLength: 50, required: true });
|
|
6810
|
+
* ```
|
|
6811
|
+
*/
|
|
5815
6812
|
function textField(config) {
|
|
5816
6813
|
const { transform, key, pattern, minLength, maxLength, inputType: type = 'text', materialFormField } = config;
|
|
5817
6814
|
const parsers = textFieldTransformParser(config);
|
|
@@ -5828,6 +6825,17 @@ function textField(config) {
|
|
|
5828
6825
|
parsers
|
|
5829
6826
|
});
|
|
5830
6827
|
}
|
|
6828
|
+
/**
|
|
6829
|
+
* Creates a Formly field configuration for a multi-line textarea input.
|
|
6830
|
+
*
|
|
6831
|
+
* @param config - Textarea field configuration including key, label, rows, and validation options
|
|
6832
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'textarea'`
|
|
6833
|
+
*
|
|
6834
|
+
* @example
|
|
6835
|
+
* ```typescript
|
|
6836
|
+
* const field = textAreaField({ key: 'bio', label: 'Biography', rows: 5, maxLength: 500 });
|
|
6837
|
+
* ```
|
|
6838
|
+
*/
|
|
5831
6839
|
function textAreaField(config) {
|
|
5832
6840
|
const { key, rows = 3, pattern, minLength, maxLength, materialFormField } = config;
|
|
5833
6841
|
const parsers = textFieldTransformParser(config);
|
|
@@ -5845,6 +6853,18 @@ function textAreaField(config) {
|
|
|
5845
6853
|
});
|
|
5846
6854
|
}
|
|
5847
6855
|
|
|
6856
|
+
/**
|
|
6857
|
+
* Creates a Formly field configuration for an international phone number input
|
|
6858
|
+
* with E.164 validation.
|
|
6859
|
+
*
|
|
6860
|
+
* @param config - Optional overrides; defaults to key `'phone'`, label `'Phone Number'`
|
|
6861
|
+
* @returns A validated {@link FormlyFieldConfig} with type `'intphone'`
|
|
6862
|
+
*
|
|
6863
|
+
* @example
|
|
6864
|
+
* ```typescript
|
|
6865
|
+
* const field = phoneField({ preferredCountries: ['us', 'ca'], required: true });
|
|
6866
|
+
* ```
|
|
6867
|
+
*/
|
|
5848
6868
|
function phoneField(config = {}) {
|
|
5849
6869
|
const { key = 'phone', label = 'Phone Number', preferredCountries, enableSearch, onlyCountries, allowExtension: inputAllowExtension } = config;
|
|
5850
6870
|
const allowExtension = inputAllowExtension ?? false;
|
|
@@ -5865,9 +6885,16 @@ function phoneField(config = {}) {
|
|
|
5865
6885
|
return fieldConfig;
|
|
5866
6886
|
}
|
|
5867
6887
|
/**
|
|
5868
|
-
*
|
|
5869
|
-
*
|
|
5870
|
-
*
|
|
6888
|
+
* Creates a flex-layout-wrapped pair of a phone number field and a label text field,
|
|
6889
|
+
* useful for collecting named phone numbers (e.g., "Work", "Home").
|
|
6890
|
+
*
|
|
6891
|
+
* @param config - Optional phone and label field configurations
|
|
6892
|
+
* @returns A flex-layout-wrapped {@link FormlyFieldConfig}
|
|
6893
|
+
*
|
|
6894
|
+
* @example
|
|
6895
|
+
* ```typescript
|
|
6896
|
+
* const field = wrappedPhoneAndLabelField({ phoneField: { required: true } });
|
|
6897
|
+
* ```
|
|
5871
6898
|
*/
|
|
5872
6899
|
function wrappedPhoneAndLabelField({ phoneField: phone, labelField: label } = {}) {
|
|
5873
6900
|
return flexLayoutWrapper([
|
|
@@ -5886,6 +6913,17 @@ function wrappedPhoneAndLabelField({ phoneField: phone, labelField: label } = {}
|
|
|
5886
6913
|
}
|
|
5887
6914
|
], { relative: true });
|
|
5888
6915
|
}
|
|
6916
|
+
/**
|
|
6917
|
+
* Creates a section-wrapped phone + label field pair with a configurable header.
|
|
6918
|
+
*
|
|
6919
|
+
* @param config - Optional overrides; defaults to header `'Phone Number'`
|
|
6920
|
+
* @returns A section-wrapped {@link FormlyFieldConfig}
|
|
6921
|
+
*
|
|
6922
|
+
* @example
|
|
6923
|
+
* ```typescript
|
|
6924
|
+
* const field = phoneAndLabelSectionField({ header: 'Contact Phone' });
|
|
6925
|
+
* ```
|
|
6926
|
+
*/
|
|
5889
6927
|
function phoneAndLabelSectionField({ key, header = 'Phone Number', hint, phoneField, labelField } = {}) {
|
|
5890
6928
|
return sectionWrapper({
|
|
5891
6929
|
key,
|
|
@@ -5895,6 +6933,17 @@ function phoneAndLabelSectionField({ key, header = 'Phone Number', hint, phoneFi
|
|
|
5895
6933
|
hint
|
|
5896
6934
|
});
|
|
5897
6935
|
}
|
|
6936
|
+
/**
|
|
6937
|
+
* Creates a repeat-array field that allows the user to add multiple phone number entries.
|
|
6938
|
+
*
|
|
6939
|
+
* @param repeatConfig - Optional overrides; defaults to key `'phones'`, label `'Phone Numbers'`
|
|
6940
|
+
* @returns A {@link FormlyFieldConfig} with repeat-array type for multiple phone entries
|
|
6941
|
+
*
|
|
6942
|
+
* @example
|
|
6943
|
+
* ```typescript
|
|
6944
|
+
* const field = phoneListField({ phoneAndLabel: { phoneField: { preferredCountries: ['us'] } } });
|
|
6945
|
+
* ```
|
|
6946
|
+
*/
|
|
5898
6947
|
function phoneListField(repeatConfig = {}) {
|
|
5899
6948
|
const { key = 'phones', label = 'Phone Numbers', addText = 'Add Phone Number', removeText = 'Remove Phone Number', repeatFieldGroup, phoneAndLabel } = repeatConfig;
|
|
5900
6949
|
return repeatArrayField({
|
|
@@ -5907,10 +6956,24 @@ function phoneListField(repeatConfig = {}) {
|
|
|
5907
6956
|
});
|
|
5908
6957
|
}
|
|
5909
6958
|
|
|
6959
|
+
/** Maximum character length for a phone label field. */
|
|
5910
6960
|
const PHONE_LABEL_MAX_LENGTH = 100;
|
|
6961
|
+
/** Maximum character length for a generic label string field. */
|
|
5911
6962
|
const LABEL_STRING_MAX_LENGTH = 100;
|
|
6963
|
+
/** Maximum character length for a search string field. */
|
|
5912
6964
|
const SEARCH_STRING_MAX_LENGTH = 100;
|
|
5913
6965
|
// MARK: Name Field
|
|
6966
|
+
/**
|
|
6967
|
+
* Creates a text field pre-configured for a person's full name.
|
|
6968
|
+
*
|
|
6969
|
+
* @param config - Optional overrides; defaults to key `'name'`, label `'Name'`
|
|
6970
|
+
* @returns A {@link FormlyFieldConfig} for name input
|
|
6971
|
+
*
|
|
6972
|
+
* @example
|
|
6973
|
+
* ```typescript
|
|
6974
|
+
* const field = nameField({ required: true });
|
|
6975
|
+
* ```
|
|
6976
|
+
*/
|
|
5914
6977
|
function nameField(config = {}) {
|
|
5915
6978
|
const { key = 'name', label = 'Name', placeholder = 'John Doe', required = false, minLength, maxLength, attributes } = config;
|
|
5916
6979
|
return textField({
|
|
@@ -5924,6 +6987,17 @@ function nameField(config = {}) {
|
|
|
5924
6987
|
attributes
|
|
5925
6988
|
});
|
|
5926
6989
|
}
|
|
6990
|
+
/**
|
|
6991
|
+
* Creates a text field pre-configured for email address input with built-in email validation.
|
|
6992
|
+
*
|
|
6993
|
+
* @param config - Optional overrides; defaults to key `'email'`, label `'Email Address'`
|
|
6994
|
+
* @returns A {@link FormlyFieldConfig} with email validation
|
|
6995
|
+
*
|
|
6996
|
+
* @example
|
|
6997
|
+
* ```typescript
|
|
6998
|
+
* const field = emailField({ required: true });
|
|
6999
|
+
* ```
|
|
7000
|
+
*/
|
|
5927
7001
|
function emailField(config = {}) {
|
|
5928
7002
|
const { key = 'email', label = 'Email Address', placeholder = 'you@example.com' } = config;
|
|
5929
7003
|
const emailFieldConfig = textField({
|
|
@@ -5941,6 +7015,17 @@ function emailField(config = {}) {
|
|
|
5941
7015
|
};
|
|
5942
7016
|
return emailFieldConfig;
|
|
5943
7017
|
}
|
|
7018
|
+
/**
|
|
7019
|
+
* Creates a text field pre-configured for city name input with autocomplete support.
|
|
7020
|
+
*
|
|
7021
|
+
* @param config - Optional overrides; defaults to key `'city'`, label `'City'`
|
|
7022
|
+
* @returns A {@link FormlyFieldConfig} for city input
|
|
7023
|
+
*
|
|
7024
|
+
* @example
|
|
7025
|
+
* ```typescript
|
|
7026
|
+
* const field = cityField({ required: true });
|
|
7027
|
+
* ```
|
|
7028
|
+
*/
|
|
5944
7029
|
function cityField(config = {}) {
|
|
5945
7030
|
const { key = 'city', placeholder = '', label = 'City', autocomplete = 'city', maxLength = ADDRESS_CITY_MAX_LENGTH, required = false } = config;
|
|
5946
7031
|
return textField({
|
|
@@ -5953,6 +7038,19 @@ function cityField(config = {}) {
|
|
|
5953
7038
|
maxLength
|
|
5954
7039
|
});
|
|
5955
7040
|
}
|
|
7041
|
+
/**
|
|
7042
|
+
* Creates a text field pre-configured for US state input with optional state code validation.
|
|
7043
|
+
*
|
|
7044
|
+
* When `asCode` is true, enforces the 2-letter state code pattern and auto-uppercases input.
|
|
7045
|
+
*
|
|
7046
|
+
* @param config - Optional overrides; defaults to key `'state'`, label `'State'`
|
|
7047
|
+
* @returns A {@link FormlyFieldConfig} for state input
|
|
7048
|
+
*
|
|
7049
|
+
* @example
|
|
7050
|
+
* ```typescript
|
|
7051
|
+
* const field = stateField({ asCode: true, required: true });
|
|
7052
|
+
* ```
|
|
7053
|
+
*/
|
|
5956
7054
|
function stateField(config = {}) {
|
|
5957
7055
|
const { asCode = false, pattern = asCode ? US_STATE_CODE_STRING_REGEX : undefined, key = 'state', placeholder = '', label = 'State', autocomplete = 'state', maxLength = asCode ? ADDRESS_STATE_CODE_MAX_LENGTH : ADDRESS_STATE_MAX_LENGTH, transform, required = false } = config;
|
|
5958
7056
|
return textField({
|
|
@@ -5970,6 +7068,17 @@ function stateField(config = {}) {
|
|
|
5970
7068
|
}
|
|
5971
7069
|
});
|
|
5972
7070
|
}
|
|
7071
|
+
/**
|
|
7072
|
+
* Creates a text field pre-configured for country name input with autocomplete support.
|
|
7073
|
+
*
|
|
7074
|
+
* @param config - Optional overrides; defaults to key `'country'`, label `'Country'`
|
|
7075
|
+
* @returns A {@link FormlyFieldConfig} for country input
|
|
7076
|
+
*
|
|
7077
|
+
* @example
|
|
7078
|
+
* ```typescript
|
|
7079
|
+
* const field = countryField({ required: true });
|
|
7080
|
+
* ```
|
|
7081
|
+
*/
|
|
5973
7082
|
function countryField(config = {}) {
|
|
5974
7083
|
const { key = 'country', placeholder = '', label = 'Country', autocomplete = 'country', maxLength = ADDRESS_COUNTRY_MAX_LENGTH, required = false } = config;
|
|
5975
7084
|
return textField({
|
|
@@ -5982,6 +7091,17 @@ function countryField(config = {}) {
|
|
|
5982
7091
|
maxLength
|
|
5983
7092
|
});
|
|
5984
7093
|
}
|
|
7094
|
+
/**
|
|
7095
|
+
* Creates a text field pre-configured for US zip code input with pattern validation.
|
|
7096
|
+
*
|
|
7097
|
+
* @param config - Optional overrides; defaults to key `'zip'`, label `'Zip Code'`
|
|
7098
|
+
* @returns A {@link FormlyFieldConfig} for zip code input
|
|
7099
|
+
*
|
|
7100
|
+
* @example
|
|
7101
|
+
* ```typescript
|
|
7102
|
+
* const field = zipCodeField({ required: true });
|
|
7103
|
+
* ```
|
|
7104
|
+
*/
|
|
5985
7105
|
function zipCodeField(config = {}) {
|
|
5986
7106
|
const { key = 'zip', placeholder = '', label = 'Zip Code', autocomplete = 'postal-code', pattern = ZIP_CODE_STRING_REGEX, maxLength = ADDRESS_ZIP_MAX_LENGTH, required = false } = config;
|
|
5987
7107
|
return textField({
|
|
@@ -5996,8 +7116,21 @@ function zipCodeField(config = {}) {
|
|
|
5996
7116
|
});
|
|
5997
7117
|
}
|
|
5998
7118
|
// MARK: LatLng Text Field
|
|
7119
|
+
/** Default placeholder text for a latitude/longitude text field. */
|
|
5999
7120
|
const DEFAULT_LAT_LNG_TEXT_FIELD_PLACEHOLDER = '12.345,-67.8910';
|
|
7121
|
+
/** Default validation error message for invalid coordinate input. */
|
|
6000
7122
|
const DEFAULT_LAT_LNG_TEXT_FIELD_PATTERN_MESSAGE = `Invalid/unknown coordinates`;
|
|
7123
|
+
/**
|
|
7124
|
+
* Creates a text field pre-configured for latitude/longitude coordinate input with pattern validation.
|
|
7125
|
+
*
|
|
7126
|
+
* @param config - Optional overrides; defaults to key `'latLng'`
|
|
7127
|
+
* @returns A {@link FormlyFieldConfig} for coordinate input
|
|
7128
|
+
*
|
|
7129
|
+
* @example
|
|
7130
|
+
* ```typescript
|
|
7131
|
+
* const field = latLngTextField();
|
|
7132
|
+
* ```
|
|
7133
|
+
*/
|
|
6001
7134
|
function latLngTextField({ key = 'latLng' } = {}) {
|
|
6002
7135
|
const field = {
|
|
6003
7136
|
...textField({
|
|
@@ -6016,6 +7149,18 @@ function latLngTextField({ key = 'latLng' } = {}) {
|
|
|
6016
7149
|
return field;
|
|
6017
7150
|
}
|
|
6018
7151
|
|
|
7152
|
+
/**
|
|
7153
|
+
* Creates a text field for a single address line with autocomplete support.
|
|
7154
|
+
*
|
|
7155
|
+
* @param config - Optional overrides; line number determines key and label
|
|
7156
|
+
* @returns A {@link FormlyFieldConfig} for address line input
|
|
7157
|
+
*
|
|
7158
|
+
* @example
|
|
7159
|
+
* ```typescript
|
|
7160
|
+
* const line1 = addressLineField({ line: 1, required: true });
|
|
7161
|
+
* const line2 = addressLineField({ line: 2 });
|
|
7162
|
+
* ```
|
|
7163
|
+
*/
|
|
6019
7164
|
function addressLineField(config = {}) {
|
|
6020
7165
|
const { line = 1 } = config;
|
|
6021
7166
|
const lineCode = Math.max(1, line); // minimum of line 1
|
|
@@ -6030,6 +7175,18 @@ function addressLineField(config = {}) {
|
|
|
6030
7175
|
maxLength
|
|
6031
7176
|
});
|
|
6032
7177
|
}
|
|
7178
|
+
/**
|
|
7179
|
+
* Creates the full set of address form fields (lines, city, state, zip, and optionally country)
|
|
7180
|
+
* arranged in a flex layout.
|
|
7181
|
+
*
|
|
7182
|
+
* @param config - Address fields configuration
|
|
7183
|
+
* @returns Array of {@link FormlyFieldConfig} for a complete address form section
|
|
7184
|
+
*
|
|
7185
|
+
* @example
|
|
7186
|
+
* ```typescript
|
|
7187
|
+
* const fields = addressFormlyFields({ required: true, includeCountry: false });
|
|
7188
|
+
* ```
|
|
7189
|
+
*/
|
|
6033
7190
|
function addressFormlyFields(config = {}) {
|
|
6034
7191
|
const { required = true, includeLine2 = true, includeCountry = true } = config;
|
|
6035
7192
|
const singleLineFields = [
|
|
@@ -6057,6 +7214,17 @@ function addressFormlyFields(config = {}) {
|
|
|
6057
7214
|
}
|
|
6058
7215
|
return [...lines, flexLayoutWrapper(singleLineFields, { size: 1, relative: true })];
|
|
6059
7216
|
}
|
|
7217
|
+
/**
|
|
7218
|
+
* Creates a section-wrapped address field group containing all address sub-fields.
|
|
7219
|
+
*
|
|
7220
|
+
* @param config - Optional overrides; defaults to key `'address'`, header `'Address'`
|
|
7221
|
+
* @returns A section-wrapped {@link FormlyFieldConfig} containing address fields
|
|
7222
|
+
*
|
|
7223
|
+
* @example
|
|
7224
|
+
* ```typescript
|
|
7225
|
+
* const field = addressField({ required: true, includeCountry: true });
|
|
7226
|
+
* ```
|
|
7227
|
+
*/
|
|
6060
7228
|
function addressField(config = {}) {
|
|
6061
7229
|
const { key = 'address', header = 'Address', hint, required = false } = config;
|
|
6062
7230
|
return sectionWrapper({
|
|
@@ -6070,6 +7238,17 @@ function addressField(config = {}) {
|
|
|
6070
7238
|
hint
|
|
6071
7239
|
});
|
|
6072
7240
|
}
|
|
7241
|
+
/**
|
|
7242
|
+
* Creates a repeat-array field that allows the user to add multiple addresses.
|
|
7243
|
+
*
|
|
7244
|
+
* @param config - Optional overrides; defaults to key `'addresses'`, max 6 entries
|
|
7245
|
+
* @returns A {@link FormlyFieldConfig} with repeat-array type for multiple addresses
|
|
7246
|
+
*
|
|
7247
|
+
* @example
|
|
7248
|
+
* ```typescript
|
|
7249
|
+
* const field = addressListField({ maxAddresses: 3, required: true });
|
|
7250
|
+
* ```
|
|
7251
|
+
*/
|
|
6073
7252
|
function addressListField(config = {}) {
|
|
6074
7253
|
const { key = 'addresses', required = false, maxAddresses = 6 } = config;
|
|
6075
7254
|
return repeatArrayField({
|
|
@@ -6085,6 +7264,7 @@ function addressListField(config = {}) {
|
|
|
6085
7264
|
}
|
|
6086
7265
|
|
|
6087
7266
|
const importsAndExports$4 = [DbxFormFormlyArrayFieldModule, FormlyMaterialModule, FormlyMatInputModule, DbxFormFormlyWrapperModule];
|
|
7267
|
+
/** Aggregates Formly Material input, array field, and wrapper modules for text field support. */
|
|
6088
7268
|
class DbxFormFormlyTextFieldModule {
|
|
6089
7269
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyTextFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6090
7270
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyTextFieldModule, imports: [DbxFormFormlyArrayFieldModule, FormlyMaterialModule, FormlyMatInputModule, DbxFormFormlyWrapperModule], exports: [DbxFormFormlyArrayFieldModule, FormlyMaterialModule, FormlyMatInputModule, DbxFormFormlyWrapperModule] });
|
|
@@ -6098,6 +7278,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
6098
7278
|
}]
|
|
6099
7279
|
}] });
|
|
6100
7280
|
|
|
7281
|
+
/**
|
|
7282
|
+
* Creates a Formly field configuration for a hidden field with no visual representation.
|
|
7283
|
+
*
|
|
7284
|
+
* Useful for passing programmatic values through the form model without user interaction.
|
|
7285
|
+
*
|
|
7286
|
+
* @param config - Key and optional required flag
|
|
7287
|
+
* @returns A validated {@link FormlyFieldConfig} with no visible type
|
|
7288
|
+
*
|
|
7289
|
+
* @example
|
|
7290
|
+
* ```typescript
|
|
7291
|
+
* const field = hiddenField({ key: 'userId', required: true });
|
|
7292
|
+
* ```
|
|
7293
|
+
*/
|
|
6101
7294
|
function hiddenField({ key, required = false }) {
|
|
6102
7295
|
return formlyField({
|
|
6103
7296
|
key,
|
|
@@ -6106,6 +7299,7 @@ function hiddenField({ key, required = false }) {
|
|
|
6106
7299
|
}
|
|
6107
7300
|
|
|
6108
7301
|
const importsAndExports$3 = [DbxFormFormlyChecklistItemFieldModule, DbxFormFormlyComponentFieldModule, DbxFormFormlyTextEditorFieldModule, DbxFormFormlyWrapperModule];
|
|
7302
|
+
/** Aggregates all custom Formly field type modules (checklist, component, texteditor) and wrappers. */
|
|
6109
7303
|
class DbxFormFormlyFieldModule {
|
|
6110
7304
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6111
7305
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormFormlyFieldModule, imports: [DbxFormFormlyChecklistItemFieldModule, DbxFormFormlyComponentFieldModule, DbxFormFormlyTextEditorFieldModule, DbxFormFormlyWrapperModule], exports: [DbxFormFormlyChecklistItemFieldModule, DbxFormFormlyComponentFieldModule, DbxFormFormlyTextEditorFieldModule, DbxFormFormlyWrapperModule] });
|
|
@@ -6259,6 +7453,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
6259
7453
|
}]
|
|
6260
7454
|
}], propDecorators: { search: [{ type: i0.Output, args: ["search"] }] } });
|
|
6261
7455
|
|
|
7456
|
+
/**
|
|
7457
|
+
* Creates a text field with an async validator that checks whether the entered value is available.
|
|
7458
|
+
*
|
|
7459
|
+
* The field is wrapped in a working wrapper to display a loading indicator during the async check.
|
|
7460
|
+
*
|
|
7461
|
+
* @param config - Configuration for the text field and availability validation.
|
|
7462
|
+
* @returns A Formly field configuration with async availability validation.
|
|
7463
|
+
*
|
|
7464
|
+
* @example
|
|
7465
|
+
* ```ts
|
|
7466
|
+
* const usernameField = textIsAvailableField({
|
|
7467
|
+
* key: 'username',
|
|
7468
|
+
* label: 'Username',
|
|
7469
|
+
* isAvailable: (value) => checkUsernameAvailable(value),
|
|
7470
|
+
* isNotAvailableErrorMessage: 'Username is already taken'
|
|
7471
|
+
* });
|
|
7472
|
+
* ```
|
|
7473
|
+
*/
|
|
6262
7474
|
function textIsAvailableField(config) {
|
|
6263
7475
|
const field = textField(config);
|
|
6264
7476
|
field.asyncValidators = {
|
|
@@ -6275,6 +7487,11 @@ function textIsAvailableField(config) {
|
|
|
6275
7487
|
}
|
|
6276
7488
|
|
|
6277
7489
|
const importsAndExports$2 = [DbxFormFormlyTextFieldModule, DbxFormFormlyWrapperModule];
|
|
7490
|
+
/**
|
|
7491
|
+
* Angular module that provides the dependencies needed for the text availability field template.
|
|
7492
|
+
*
|
|
7493
|
+
* Imports and re-exports the text field and wrapper modules required by {@link textIsAvailableField}.
|
|
7494
|
+
*/
|
|
6278
7495
|
class DbxFormTextAvailableFieldModule {
|
|
6279
7496
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormTextAvailableFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6280
7497
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormTextAvailableFieldModule, imports: [DbxFormFormlyTextFieldModule, DbxFormFormlyWrapperModule], exports: [DbxFormFormlyTextFieldModule, DbxFormFormlyWrapperModule] });
|
|
@@ -6289,10 +7506,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
6289
7506
|
}] });
|
|
6290
7507
|
|
|
6291
7508
|
/**
|
|
6292
|
-
*
|
|
7509
|
+
* Creates a simple text password field with the input type set to `'password'`.
|
|
6293
7510
|
*
|
|
6294
|
-
*
|
|
6295
|
-
*
|
|
7511
|
+
* Defaults to the key `'password'` and label `'Password'` unless overridden.
|
|
7512
|
+
*
|
|
7513
|
+
* @param config - Optional configuration for the password field.
|
|
7514
|
+
* @returns A Formly field configuration for a password input.
|
|
6296
7515
|
*/
|
|
6297
7516
|
function textPasswordField(config) {
|
|
6298
7517
|
return textField({
|
|
@@ -6304,10 +7523,12 @@ function textPasswordField(config) {
|
|
|
6304
7523
|
});
|
|
6305
7524
|
}
|
|
6306
7525
|
/**
|
|
6307
|
-
*
|
|
7526
|
+
* Creates a verify/confirm password field, typically used alongside a primary password field.
|
|
6308
7527
|
*
|
|
6309
|
-
*
|
|
6310
|
-
*
|
|
7528
|
+
* Defaults to the key `'verifyPassword'` and label `'Verify Password'` unless overridden.
|
|
7529
|
+
*
|
|
7530
|
+
* @param config - Optional configuration for the verify password field.
|
|
7531
|
+
* @returns A Formly field configuration for a verify password input.
|
|
6311
7532
|
*/
|
|
6312
7533
|
function textVerifyPasswordField(config) {
|
|
6313
7534
|
return textPasswordField({
|
|
@@ -6317,6 +7538,13 @@ function textVerifyPasswordField(config) {
|
|
|
6317
7538
|
required: true
|
|
6318
7539
|
});
|
|
6319
7540
|
}
|
|
7541
|
+
/**
|
|
7542
|
+
* Creates a Formly field group containing a password field and a verify password field
|
|
7543
|
+
* with a cross-field validator that ensures both values match.
|
|
7544
|
+
*
|
|
7545
|
+
* @param config - Configuration for the password and verify password fields.
|
|
7546
|
+
* @returns A Formly field group configuration with password matching validation.
|
|
7547
|
+
*/
|
|
6320
7548
|
function textPasswordWithVerifyFieldGroup(config) {
|
|
6321
7549
|
const passwordFieldConfig = textPasswordField(config.password);
|
|
6322
7550
|
const verifyPasswordFieldKey = config.verifyPassword?.key ?? `verify${capitalizeFirstLetter(String(passwordFieldConfig.key))}`;
|
|
@@ -6351,6 +7579,13 @@ function usernamePasswordLoginFields({ username, password, verifyPassword }) {
|
|
|
6351
7579
|
const passwordField = verifyPassword ? textPasswordWithVerifyFieldGroup({ password, verifyPassword: verifyPassword === true ? undefined : verifyPassword }) : textPasswordField(password);
|
|
6352
7580
|
return [usernameField, passwordField];
|
|
6353
7581
|
}
|
|
7582
|
+
/**
|
|
7583
|
+
* Creates a single username field for a login form. Supports email or plain text input
|
|
7584
|
+
* based on the provided configuration.
|
|
7585
|
+
*
|
|
7586
|
+
* @param username - Either `'email'`, `'username'`, or a full {@link UsernameLoginFieldUsernameConfig}.
|
|
7587
|
+
* @returns A Formly field configuration for the username input.
|
|
7588
|
+
*/
|
|
6354
7589
|
function usernameLoginField(username) {
|
|
6355
7590
|
let usernameField;
|
|
6356
7591
|
let usernameFieldConfig = username;
|
|
@@ -6377,6 +7612,11 @@ function usernameLoginField(username) {
|
|
|
6377
7612
|
}
|
|
6378
7613
|
|
|
6379
7614
|
const importsAndExports$1 = [DbxFormFormlyTextFieldModule];
|
|
7615
|
+
/**
|
|
7616
|
+
* Angular module that provides the dependencies needed for login form field templates.
|
|
7617
|
+
*
|
|
7618
|
+
* Imports and re-exports the text field module required by the username/password login field functions.
|
|
7619
|
+
*/
|
|
6380
7620
|
class DbxFormLoginFieldModule {
|
|
6381
7621
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormLoginFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6382
7622
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormLoginFieldModule, imports: [DbxFormFormlyTextFieldModule], exports: [DbxFormFormlyTextFieldModule] });
|
|
@@ -6390,6 +7630,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
6390
7630
|
}]
|
|
6391
7631
|
}] });
|
|
6392
7632
|
|
|
7633
|
+
/**
|
|
7634
|
+
* Creates a search function for timezone strings that searches across all known timezone infos.
|
|
7635
|
+
*
|
|
7636
|
+
* When the search string is empty, the system timezone is returned first, followed by all timezones.
|
|
7637
|
+
*
|
|
7638
|
+
* @returns A {@link SearchableValueFieldStringSearchFn} for searching timezone values.
|
|
7639
|
+
*/
|
|
6393
7640
|
function timezoneStringSearchFunction() {
|
|
6394
7641
|
const timezoneInfos = allTimezoneInfos();
|
|
6395
7642
|
return (search) => {
|
|
@@ -6403,6 +7650,12 @@ function timezoneStringSearchFunction() {
|
|
|
6403
7650
|
return of(searchResults.map((meta) => ({ value: meta.timezone, meta })));
|
|
6404
7651
|
};
|
|
6405
7652
|
}
|
|
7653
|
+
/**
|
|
7654
|
+
* Display function for timezone string values in a searchable field.
|
|
7655
|
+
*
|
|
7656
|
+
* Maps each timezone value to a display object with the timezone name as the label
|
|
7657
|
+
* and its abbreviation as the sublabel.
|
|
7658
|
+
*/
|
|
6406
7659
|
const DISPLAY_FOR_TIMEZONE_STRING_VALUE = (values) => {
|
|
6407
7660
|
const timezoneInfos = allTimezoneInfos();
|
|
6408
7661
|
const displayValues = values.map((x) => {
|
|
@@ -6413,10 +7666,13 @@ const DISPLAY_FOR_TIMEZONE_STRING_VALUE = (values) => {
|
|
|
6413
7666
|
return obs;
|
|
6414
7667
|
};
|
|
6415
7668
|
/**
|
|
6416
|
-
*
|
|
7669
|
+
* Creates a searchable text field for selecting a timezone.
|
|
6417
7670
|
*
|
|
6418
|
-
*
|
|
6419
|
-
*
|
|
7671
|
+
* Defaults to the key `'timezone'` and label `'Timezone'`. Searches all known timezones
|
|
7672
|
+
* and displays the timezone name with its abbreviation.
|
|
7673
|
+
*
|
|
7674
|
+
* @param config - Optional configuration overrides for the timezone field.
|
|
7675
|
+
* @returns A Formly field configuration for timezone selection.
|
|
6420
7676
|
*/
|
|
6421
7677
|
function timezoneStringField(config = {}) {
|
|
6422
7678
|
return searchableTextField({
|
|
@@ -6434,6 +7690,11 @@ function timezoneStringField(config = {}) {
|
|
|
6434
7690
|
}
|
|
6435
7691
|
|
|
6436
7692
|
const importsAndExports = [DbxFormFormlySearchableFieldModule];
|
|
7693
|
+
/**
|
|
7694
|
+
* Angular module that provides the dependencies needed for the timezone string field template.
|
|
7695
|
+
*
|
|
7696
|
+
* Imports and re-exports the searchable field module required by {@link timezoneStringField}.
|
|
7697
|
+
*/
|
|
6437
7698
|
class DbxFormTimezoneStringFieldModule {
|
|
6438
7699
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormTimezoneStringFieldModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6439
7700
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.0", ngImport: i0, type: DbxFormTimezoneStringFieldModule, imports: [DbxFormFormlySearchableFieldModule], exports: [DbxFormFormlySearchableFieldModule] });
|
|
@@ -6448,10 +7709,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
6448
7709
|
}] });
|
|
6449
7710
|
|
|
6450
7711
|
/**
|
|
6451
|
-
*
|
|
7712
|
+
* Creates a text field configured for website URL input with URL validation.
|
|
6452
7713
|
*
|
|
6453
|
-
*
|
|
6454
|
-
*
|
|
7714
|
+
* Defaults to the key `'website'` and label `'Website Url'` unless overridden in the config.
|
|
7715
|
+
*
|
|
7716
|
+
* @param config - Optional configuration for the website URL field.
|
|
7717
|
+
* @returns A Formly field configuration with website URL validation.
|
|
6455
7718
|
*/
|
|
6456
7719
|
function websiteUrlField(config) {
|
|
6457
7720
|
const validators = [isWebsiteUrlValidator(config)];
|
|
@@ -6493,6 +7756,10 @@ function provideDbxFormFormlyFieldDeclarations() {
|
|
|
6493
7756
|
|
|
6494
7757
|
/**
|
|
6495
7758
|
* Provides vertical spacing after a form.
|
|
7759
|
+
*
|
|
7760
|
+
* Can be used as an element (`<dbx-form-spacer>`), attribute (`[dbxFormSpacer]`), or CSS class (`.dbx-form-spacer`).
|
|
7761
|
+
*
|
|
7762
|
+
* @selector `dbx-form-spacer,[dbxFormSpacer],.dbx-form-spacer`
|
|
6496
7763
|
*/
|
|
6497
7764
|
class DbxFormSpacerDirective {
|
|
6498
7765
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: DbxFormSpacerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|