@tft/crispr-forms 21.0.3 → 21.0.5

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.
Files changed (64) hide show
  1. package/fesm2022/tft-crispr-forms-autocomplete-field.component-IB92ztLj.mjs +95 -0
  2. package/fesm2022/tft-crispr-forms-autocomplete-field.component-IB92ztLj.mjs.map +1 -0
  3. package/fesm2022/tft-crispr-forms-index-2ggYh_Ev.mjs +40 -0
  4. package/fesm2022/tft-crispr-forms-index-2ggYh_Ev.mjs.map +1 -0
  5. package/fesm2022/{tft-crispr-forms-index-UAYeTe3L.mjs → tft-crispr-forms-index-BIPapWdD.mjs} +2 -2
  6. package/fesm2022/{tft-crispr-forms-index-UAYeTe3L.mjs.map → tft-crispr-forms-index-BIPapWdD.mjs.map} +1 -1
  7. package/fesm2022/{tft-crispr-forms-index-kjMTlZoq.mjs → tft-crispr-forms-index-BJb-E_LR.mjs} +2 -2
  8. package/fesm2022/{tft-crispr-forms-index-kjMTlZoq.mjs.map → tft-crispr-forms-index-BJb-E_LR.mjs.map} +1 -1
  9. package/fesm2022/{tft-crispr-forms-index-joNvlmny.mjs → tft-crispr-forms-index-BN-qHciF.mjs} +2 -2
  10. package/fesm2022/{tft-crispr-forms-index-joNvlmny.mjs.map → tft-crispr-forms-index-BN-qHciF.mjs.map} +1 -1
  11. package/fesm2022/tft-crispr-forms-index-BQWfppWN.mjs +73 -0
  12. package/fesm2022/tft-crispr-forms-index-BQWfppWN.mjs.map +1 -0
  13. package/fesm2022/tft-crispr-forms-index-Bau6o4JD.mjs +68 -0
  14. package/fesm2022/tft-crispr-forms-index-Bau6o4JD.mjs.map +1 -0
  15. package/fesm2022/tft-crispr-forms-index-C6I8JpR5.mjs +39 -0
  16. package/fesm2022/tft-crispr-forms-index-C6I8JpR5.mjs.map +1 -0
  17. package/fesm2022/tft-crispr-forms-index-CXR7Jz3T.mjs +39 -0
  18. package/fesm2022/tft-crispr-forms-index-CXR7Jz3T.mjs.map +1 -0
  19. package/fesm2022/tft-crispr-forms-index-CZ8se247.mjs +179 -0
  20. package/fesm2022/tft-crispr-forms-index-CZ8se247.mjs.map +1 -0
  21. package/fesm2022/tft-crispr-forms-index-CjxxE8O4.mjs +2 -0
  22. package/fesm2022/tft-crispr-forms-index-CjxxE8O4.mjs.map +1 -0
  23. package/fesm2022/tft-crispr-forms-index-D699lPdT.mjs +40 -0
  24. package/fesm2022/tft-crispr-forms-index-D699lPdT.mjs.map +1 -0
  25. package/fesm2022/tft-crispr-forms-index-DOaGEZK0.mjs +36 -0
  26. package/fesm2022/tft-crispr-forms-index-DOaGEZK0.mjs.map +1 -0
  27. package/fesm2022/tft-crispr-forms-index-D_9DqcSv.mjs +88 -0
  28. package/fesm2022/tft-crispr-forms-index-D_9DqcSv.mjs.map +1 -0
  29. package/fesm2022/tft-crispr-forms-index-HP6w4mnV.mjs +181 -0
  30. package/fesm2022/tft-crispr-forms-index-HP6w4mnV.mjs.map +1 -0
  31. package/fesm2022/tft-crispr-forms-index-XA--BwG_.mjs +190 -0
  32. package/fesm2022/tft-crispr-forms-index-XA--BwG_.mjs.map +1 -0
  33. package/fesm2022/tft-crispr-forms-tft-crispr-forms-BFiZ8Nhn.mjs +982 -0
  34. package/fesm2022/tft-crispr-forms-tft-crispr-forms-BFiZ8Nhn.mjs.map +1 -0
  35. package/fesm2022/tft-crispr-forms.mjs +1 -973
  36. package/fesm2022/tft-crispr-forms.mjs.map +1 -1
  37. package/package.json +1 -1
  38. package/types/tft-crispr-forms.d.ts +38 -16
  39. package/fesm2022/tft-crispr-forms-autocomplete-field.component-ChocHy3F.mjs +0 -95
  40. package/fesm2022/tft-crispr-forms-autocomplete-field.component-ChocHy3F.mjs.map +0 -1
  41. package/fesm2022/tft-crispr-forms-index-BQFuEW6x.mjs +0 -40
  42. package/fesm2022/tft-crispr-forms-index-BQFuEW6x.mjs.map +0 -1
  43. package/fesm2022/tft-crispr-forms-index-BZ9V1Ec-.mjs +0 -39
  44. package/fesm2022/tft-crispr-forms-index-BZ9V1Ec-.mjs.map +0 -1
  45. package/fesm2022/tft-crispr-forms-index-BkCdLt5V.mjs +0 -40
  46. package/fesm2022/tft-crispr-forms-index-BkCdLt5V.mjs.map +0 -1
  47. package/fesm2022/tft-crispr-forms-index-Bypm5YtY.mjs +0 -137
  48. package/fesm2022/tft-crispr-forms-index-Bypm5YtY.mjs.map +0 -1
  49. package/fesm2022/tft-crispr-forms-index-CFwkbxFk.mjs +0 -88
  50. package/fesm2022/tft-crispr-forms-index-CFwkbxFk.mjs.map +0 -1
  51. package/fesm2022/tft-crispr-forms-index-DEctfeGr.mjs +0 -2
  52. package/fesm2022/tft-crispr-forms-index-DEctfeGr.mjs.map +0 -1
  53. package/fesm2022/tft-crispr-forms-index-DcrZSpdk.mjs +0 -73
  54. package/fesm2022/tft-crispr-forms-index-DcrZSpdk.mjs.map +0 -1
  55. package/fesm2022/tft-crispr-forms-index-DmaDlaNf.mjs +0 -68
  56. package/fesm2022/tft-crispr-forms-index-DmaDlaNf.mjs.map +0 -1
  57. package/fesm2022/tft-crispr-forms-index-Hsgr_WHO.mjs +0 -190
  58. package/fesm2022/tft-crispr-forms-index-Hsgr_WHO.mjs.map +0 -1
  59. package/fesm2022/tft-crispr-forms-index-gORcx6V1.mjs +0 -36
  60. package/fesm2022/tft-crispr-forms-index-gORcx6V1.mjs.map +0 -1
  61. package/fesm2022/tft-crispr-forms-index-lrhnilye.mjs +0 -39
  62. package/fesm2022/tft-crispr-forms-index-lrhnilye.mjs.map +0 -1
  63. package/fesm2022/tft-crispr-forms-index-uu4CyAEP.mjs +0 -182
  64. package/fesm2022/tft-crispr-forms-index-uu4CyAEP.mjs.map +0 -1
@@ -1,974 +1,2 @@
1
- import * as i0 from '@angular/core';
2
- import { signal, Input, Directive, inject, DestroyRef, computed, EventEmitter, effect, Output, Pipe, NgModule, ViewChild, Component, HostListener, ChangeDetectionStrategy, Optional, Self } from '@angular/core';
3
- import * as i1 from '@angular/common';
4
- import { CommonModule } from '@angular/common';
5
- import * as i1$1 from '@angular/forms';
6
- import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
7
- import * as i6 from '@tft/form-validation-handler';
8
- import { FormValidationHandlerModule } from '@tft/form-validation-handler';
9
- import { from, of, isObservable } from 'rxjs';
10
- import { map, startWith, debounceTime, distinctUntilChanged, switchMap, shareReplay, tap } from 'rxjs/operators';
11
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
12
- import * as i1$3 from '@angular/material/button';
13
- import { MatButtonModule } from '@angular/material/button';
14
- import * as i2 from '@angular/material/icon';
15
- import { MatIconModule } from '@angular/material/icon';
16
- import * as i2$2 from '@angular/material/form-field';
17
- import { MatFormFieldModule } from '@angular/material/form-field';
18
- import * as i3 from '@angular/material/input';
19
- import { MatInputModule } from '@angular/material/input';
20
- import * as i2$1 from '@angular/material/tooltip';
21
- import { MatTooltipModule } from '@angular/material/tooltip';
22
- import * as i1$2 from '@angular/material/progress-bar';
23
- import { MatProgressBarModule } from '@angular/material/progress-bar';
24
-
25
- function valueIn(values) {
26
- return map((value) => {
27
- if (value) {
28
- return values.some(v => {
29
- if (isRegex(v)) {
30
- const trimmedStringForRegex = v.substr(1, v.length - 2);
31
- const regex = new RegExp(trimmedStringForRegex);
32
- return regex.test(value);
33
- }
34
- else {
35
- return v === value;
36
- }
37
- });
38
- }
39
- else {
40
- return false;
41
- }
42
- });
43
- }
44
- function isRegex(string) {
45
- return string.startsWith('/') && string.endsWith('/');
46
- }
47
-
48
- const DEFAULT_EMPTY_OPTIONS_MESSAGE = 'No Items';
49
-
50
- // export type ControlType = keyof typeof FIELD_COMPONENTS;
51
- var ControlType;
52
- (function (ControlType) {
53
- ControlType["AUTOCOMPLETE"] = "autocomplete";
54
- ControlType["AUTOCOMPLETE_CHIPLIST"] = "autocompleteChiplist";
55
- ControlType["BUTTON"] = "button";
56
- ControlType["CHECKBOX"] = "checkbox";
57
- ControlType["CUSTOM"] = "custom";
58
- ControlType["DATEPICKER"] = "datepicker";
59
- ControlType["DIVIDER"] = "divider";
60
- ControlType["FILE_UPLOAD"] = "fileUpload";
61
- ControlType["GROUP_LIST"] = "groupList";
62
- ControlType["HEADING"] = "heading";
63
- ControlType["IMAGE_UPLOAD"] = "imageUpload";
64
- ControlType["INPUT"] = "input";
65
- ControlType["MAP"] = "map";
66
- ControlType["RADIO"] = "radio";
67
- ControlType["SELECT"] = "select";
68
- ControlType["SLIDER"] = "slider";
69
- ControlType["SUB_GROUP"] = "subGroup";
70
- ControlType["TEXTAREA"] = "textarea";
71
- ControlType["UNIT_CONVERSION"] = "unitConversion";
72
- })(ControlType || (ControlType = {}));
73
-
74
- /**
75
- * Analyze the config and build a form control to spec. Notice we don't use FormBuilder here
76
- * as we want to keep this function pure.
77
- * @param controlConfig the configuration object for the control to build
78
- * @param value an initial value to use if passed in
79
- */
80
- function createControlForType(controlConfig, value = null) {
81
- // build form control out based on the control type
82
- const control = controlConfig.controlType === ControlType.SUB_GROUP
83
- ? buildFormGroupFromConfig(controlConfig, value)
84
- : controlConfig.controlType === ControlType.GROUP_LIST
85
- ? new FormArray([], controlConfig.validators)
86
- : new FormControl(value || null, controlConfig.validators);
87
- return control;
88
- }
89
-
90
- /**
91
- * Determines if the field config is for a form control (not a divider, heading or other non-control field)
92
- */
93
- function isControlConfig(fieldConfig) {
94
- return 'controlName' in fieldConfig;
95
- }
96
-
97
- /**
98
- * builds out form group based on config
99
- * @param config a configuration for a form group
100
- * @param value an object of initial values to pass in
101
- * @param group the form group to modify and build out
102
- */
103
- function buildFormGroupFromConfig(config, value = null, group = new FormGroup({})) {
104
- config.fields.forEach((controlConfig) => {
105
- if (isControlConfig(controlConfig)) {
106
- // then add a control to the group using the controlName from configuration
107
- const { controlName } = controlConfig;
108
- if (group.get(controlName)) {
109
- group.removeControl(controlName);
110
- }
111
- // if there's a value object and it has a non-null/undefined value for this field use it.
112
- // Otherwise, default to null
113
- const controlValue = (value && value[controlName]) ?? null;
114
- const control = createControlForType(controlConfig, controlValue);
115
- group.addControl(controlName, control);
116
- }
117
- });
118
- group.setValidators(config.validators);
119
- return group;
120
- }
121
-
122
- function callOptionsIfFunction(options, parentGroup, searchString) {
123
- return options instanceof Function ? options(parentGroup, searchString) : options;
124
- }
125
-
126
- /**
127
- * A basic filter function that filters the search string against the label of the options object
128
- * @param options the array of options to filter
129
- * @param searchString the string from the input
130
- */
131
- function filterOptionsByLabel(options, searchString) {
132
- return options.filter(option => {
133
- return option.label && option.label.toLowerCase().includes(searchString.toLowerCase());
134
- });
135
- }
136
-
137
- /**
138
- * The user can give us select options as an array, a function that resolves to a promise,
139
- * or an observable. This functions consumes any of those and returns an observable that
140
- * resolves an array of options
141
- *
142
- * @param options the options passed in from the config
143
- * @param emptyMessageOption the message to display when the array is empty
144
- */
145
- function observablifyOptions(options, parentGroup, searchString) {
146
- const calledOptions = callOptionsIfFunction(options, parentGroup, searchString);
147
- // if options are a promise
148
- const observableOptions = calledOptions instanceof Promise
149
- // convert to observable
150
- ? from(calledOptions)
151
- // if array that isn't empty
152
- : Array.isArray(calledOptions) && calledOptions.length
153
- // convert to observable
154
- ? of(calledOptions)
155
- // if observable
156
- : isObservable(calledOptions)
157
- // return it
158
- ? calledOptions
159
- // else an empty array
160
- : of([]);
161
- return observableOptions;
162
- }
163
-
164
- function convertBytesToMb(bytes) {
165
- return bytes / 1048576;
166
- }
167
- function maxFileSizeValidator(maxFileSize) {
168
- return (control) => {
169
- const controlValue = control.value;
170
- if (!(controlValue instanceof File)) {
171
- return null;
172
- }
173
- const actualFileSize = +convertBytesToMb(controlValue.size).toPrecision(3);
174
- if (maxFileSize > actualFileSize)
175
- return null;
176
- return { maxFileSize: { maxFileSize, actualFileSize } };
177
- };
178
- }
179
- function allowedFileExtValidator(allowedFileExtensions, onlyAllowFiles = true) {
180
- return (control) => {
181
- const controlValue = control.value;
182
- const isFile = controlValue instanceof File;
183
- if (!onlyAllowFiles && !isFile)
184
- return null;
185
- const actualExtension = isFile ? controlValue.name.split('.').pop().toLocaleLowerCase() : 'Not a file';
186
- const isAllowedExtension = allowedFileExtensions.includes(actualExtension);
187
- if (isAllowedExtension) {
188
- return null;
189
- }
190
- return { allowedExtension: { allowedFileExtensions, actualExtension } };
191
- };
192
- }
193
- function allowedFileType(matchExp) {
194
- return (formControl) => {
195
- const value = formControl.value;
196
- if (!(value instanceof File))
197
- return null;
198
- const type = value.type;
199
- const matches = type.match(matchExp);
200
- if (!type || !matches?.length) {
201
- return {
202
- allowedFileType: {
203
- actualType: type,
204
- allowedTypeExp: matchExp
205
- }
206
- };
207
- }
208
- else {
209
- return null;
210
- }
211
- };
212
- }
213
-
214
- class CrisprFieldComponent {
215
- constructor() {
216
- this.config = signal(null, ...(ngDevMode ? [{ debugName: "config" }] : []));
217
- }
218
- // eslint-disable-next-line @angular-eslint/no-input-rename
219
- set inputConfig(config) {
220
- this.updateConfig(config);
221
- }
222
- updateConfig(inputConfig) {
223
- const mergedConfig = this.defaultConfig ? { ...this.defaultConfig, ...inputConfig } : inputConfig;
224
- this.config.set(mergedConfig);
225
- }
226
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
227
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.6", type: CrisprFieldComponent, isStandalone: true, inputs: { inputConfig: ["config", "inputConfig"] }, ngImport: i0 }); }
228
- }
229
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprFieldComponent, decorators: [{
230
- type: Directive,
231
- args: [{
232
- standalone: true
233
- }]
234
- }], propDecorators: { inputConfig: [{
235
- type: Input,
236
- args: [{ alias: 'config' }]
237
- }] } });
238
-
239
- class CrisprControlComponent extends CrisprFieldComponent {
240
- // eslint-disable-next-line @angular-eslint/no-input-rename
241
- set inputGroup(group) {
242
- this.group.set(group);
243
- }
244
- /*
245
- * Having the input alias allows us to consume these components in the traditional Angular way as well as progammatically in the form builder
246
- */
247
- // eslint-disable-next-line @angular-eslint/no-input-rename
248
- set inputValue(value) {
249
- this.value.set(value);
250
- }
251
- constructor() {
252
- super();
253
- this.destroyRef = inject(DestroyRef);
254
- this.group = signal(null, ...(ngDevMode ? [{ debugName: "group" }] : []));
255
- this.control = computed(() => this.group()?.get(this.config().controlName), ...(ngDevMode ? [{ debugName: "control" }] : []));
256
- this.valueChanges = new EventEmitter();
257
- this.value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
258
- effect(() => {
259
- this.setControlValue(this.value());
260
- });
261
- }
262
- ngOnInit() {
263
- this.control().valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((value) => {
264
- this.valueChanges.emit(value);
265
- });
266
- // setTimeouts are ugly but this seems to be the only way to get the computed field to compute initial values
267
- setTimeout(() => {
268
- this.control().updateValueAndValidity();
269
- });
270
- }
271
- setControlValue(value) {
272
- if (value && this.control() && this.config().controlType !== ControlType.SUB_GROUP) {
273
- this.control().setValue(value);
274
- }
275
- }
276
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
277
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.6", type: CrisprControlComponent, isStandalone: true, inputs: { inputGroup: ["group", "inputGroup"], inputValue: ["value", "inputValue"] }, outputs: { valueChanges: "valueChanges" }, usesInheritance: true, ngImport: i0 }); }
278
- }
279
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprControlComponent, decorators: [{
280
- type: Directive,
281
- args: [{
282
- standalone: true
283
- }]
284
- }], ctorParameters: () => [], propDecorators: { inputGroup: [{
285
- type: Input,
286
- args: [{ alias: 'group' }]
287
- }], valueChanges: [{
288
- type: Output
289
- }], inputValue: [{
290
- type: Input,
291
- args: [{ alias: 'value' }]
292
- }] } });
293
-
294
- // eslint-disable-next-line @angular-eslint/directive-class-suffix
295
- class AbstractAutocompleteComponent extends CrisprControlComponent {
296
- constructor() {
297
- super(...arguments);
298
- // we need a separate control for the UI because of the way the material autocomplete chiplist works
299
- this.autocompleteInputControl = new FormControl('');
300
- this.config = signal(null, ...(ngDevMode ? [{ debugName: "config" }] : []));
301
- }
302
- ngOnInit() {
303
- super.ngOnInit();
304
- this.group().addControl(this.config().controlName, new FormControl());
305
- // filter options by the search string using either the default filter function or one passed in through config()
306
- this.options$ = this.autocompleteInputControl.valueChanges.pipe(
307
- // this is needed to have the options panel to open on focus
308
- startWith(''), debounceTime(this.config().typeDebounceTime), map((searchText) => typeof searchText === 'string' ? searchText?.trim() : ''), distinctUntilChanged(), switchMap((searchText) => observablifyOptions(this.config().options, this.group(), searchText)), shareReplay(1));
309
- }
310
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AbstractAutocompleteComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
311
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.6", type: AbstractAutocompleteComponent, isStandalone: true, usesInheritance: true, ngImport: i0 }); }
312
- }
313
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AbstractAutocompleteComponent, decorators: [{
314
- type: Directive
315
- }] });
316
-
317
- // eslint-disable-next-line @angular-eslint/directive-class-suffix
318
- class CrisprDisplayFieldComponent extends CrisprControlComponent {
319
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprDisplayFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
320
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.6", type: CrisprDisplayFieldComponent, isStandalone: true, usesInheritance: true, ngImport: i0 }); }
321
- }
322
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprDisplayFieldComponent, decorators: [{
323
- type: Directive
324
- }] });
325
-
326
- const FIELD_COMPONENTS = {
327
- groupList: () => Promise.resolve().then(function () { return index$1; }).then(({ FormGroupListComponent }) => FormGroupListComponent),
328
- subGroup: () => Promise.resolve().then(function () { return index; }).then(({ SubGroupComponent }) => SubGroupComponent),
329
- button: () => import('./tft-crispr-forms-index-joNvlmny.mjs').then(({ ButtonComponent }) => ButtonComponent),
330
- input: () => import('./tft-crispr-forms-index-BkCdLt5V.mjs').then(({ InputFieldComponent }) => InputFieldComponent),
331
- select: () => import('./tft-crispr-forms-index-DcrZSpdk.mjs').then(({ SelectFieldComponent }) => SelectFieldComponent),
332
- radio: () => import('./tft-crispr-forms-index-BQFuEW6x.mjs').then(({ RadioFieldComponent }) => RadioFieldComponent),
333
- autocomplete: () => import('./tft-crispr-forms-index-DEctfeGr.mjs').then(({ AutocompleteFieldComponent }) => AutocompleteFieldComponent),
334
- autocompleteChiplist: () => import('./tft-crispr-forms-index-Bypm5YtY.mjs').then(({ AutocompleteChiplistFieldComponent }) => AutocompleteChiplistFieldComponent),
335
- map: () => import('./tft-crispr-forms-index-Hsgr_WHO.mjs').then(({ MapFieldComponent }) => MapFieldComponent),
336
- textarea: () => import('./tft-crispr-forms-index-BZ9V1Ec-.mjs').then(({ TextareaFieldComponent }) => TextareaFieldComponent),
337
- checkbox: () => import('./tft-crispr-forms-index-lrhnilye.mjs').then(({ CheckboxFieldComponent }) => CheckboxFieldComponent),
338
- slider: () => import('./tft-crispr-forms-index-gORcx6V1.mjs').then(({ SliderFieldComponent }) => SliderFieldComponent),
339
- datepicker: () => import('./tft-crispr-forms-index-DmaDlaNf.mjs').then(({ DatepickerFieldComponent }) => DatepickerFieldComponent),
340
- fileUpload: () => Promise.resolve().then(function () { return index$3; }).then(({ FileUploadFieldComponent }) => FileUploadFieldComponent),
341
- imageUpload: () => import('./tft-crispr-forms-index-uu4CyAEP.mjs').then(({ ImageUploadFieldComponent }) => ImageUploadFieldComponent),
342
- heading: () => Promise.resolve().then(function () { return index$2; }).then(({ HeadingComponent }) => HeadingComponent),
343
- divider: () => import('./tft-crispr-forms-index-kjMTlZoq.mjs').then(({ DividerComponent }) => DividerComponent),
344
- unitConversion: () => import('./tft-crispr-forms-index-CFwkbxFk.mjs').then(({ UnitConversionFieldComponent }) => UnitConversionFieldComponent),
345
- };
346
- function isControlComponent(component) {
347
- return component && isControlConfig(component.config()) && 'value' in component;
348
- }
349
- function isControlOrButtonComponent(component) {
350
- return (isControlComponent(component) ||
351
- component.config().controlType === ControlType.BUTTON);
352
- }
353
-
354
- class CrisprFieldDirective {
355
- set value(value) {
356
- this._value = value;
357
- // This is needed to keep the group list from resetting control values to the initial input value
358
- this.updateComponentValue(value);
359
- }
360
- get value() {
361
- return this._value;
362
- }
363
- constructor(container, renderer, cdr) {
364
- this.container = container;
365
- this.renderer = renderer;
366
- this.cdr = cdr;
367
- }
368
- async ngOnInit() {
369
- /**
370
- * create component and set values from config on its instance
371
- */
372
- const component = this.config.component ||
373
- (await FIELD_COMPONENTS[this.config.controlType]());
374
- const componentRef = this.container.createComponent(component);
375
- this.component = componentRef.instance;
376
- componentRef.setInput('config', this.config);
377
- if (isControlOrButtonComponent(this.component)) {
378
- componentRef.setInput('group', this.group);
379
- }
380
- this.updateComponentValue(this.value);
381
- // adds any config classes to the dynamically generated component
382
- // doing this here keeps us from having to extend a base component into each field component individually
383
- if (!this.config.classes)
384
- return;
385
- this.config.classes.forEach((klass) => {
386
- // check for passing multiple classes in one array element
387
- if (klass.includes(' ')) {
388
- throw Error(`Improperly formatted class. '${klass}' cannot contain spaces.`);
389
- }
390
- else {
391
- this.renderer.addClass(componentRef.location.nativeElement, klass);
392
- }
393
- });
394
- }
395
- updateComponentValue(value) {
396
- if (isControlComponent(this.component)) {
397
- this.component.value.set(value);
398
- // SubGroups won't populate without this detectChanges
399
- this.cdr.detectChanges();
400
- }
401
- }
402
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprFieldDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
403
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.6", type: CrisprFieldDirective, isStandalone: true, selector: "[crisprField]", inputs: { config: "config", group: "group", value: "value" }, ngImport: i0 }); }
404
- }
405
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprFieldDirective, decorators: [{
406
- type: Directive,
407
- args: [{
408
- selector: '[crisprField]',
409
- standalone: true,
410
- }]
411
- }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }], propDecorators: { config: [{
412
- type: Input
413
- }], group: [{
414
- type: Input
415
- }], value: [{
416
- type: Input
417
- }] } });
418
-
419
- class InitialControlValuePipe {
420
- // TODO: does changing any to unknown break anything?
421
- transform(initialFormValue, fieldConfig) {
422
- return initialFormValue && isControlConfig(fieldConfig)
423
- ? initialFormValue[fieldConfig.controlName] || null
424
- : null;
425
- }
426
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: InitialControlValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
427
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: InitialControlValuePipe, isStandalone: false, name: "initialControlValue" }); }
428
- }
429
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: InitialControlValuePipe, decorators: [{
430
- type: Pipe,
431
- args: [{
432
- name: 'initialControlValue',
433
- standalone: false
434
- }]
435
- }] });
436
-
437
- class CrisprPipesModule {
438
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprPipesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
439
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: CrisprPipesModule, declarations: [InitialControlValuePipe], imports: [CommonModule], exports: [InitialControlValuePipe] }); }
440
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprPipesModule, imports: [CommonModule] }); }
441
- }
442
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprPipesModule, decorators: [{
443
- type: NgModule,
444
- args: [{
445
- imports: [
446
- CommonModule
447
- ],
448
- exports: [
449
- InitialControlValuePipe
450
- ],
451
- declarations: [
452
- InitialControlValuePipe
453
- ]
454
- }]
455
- }] });
456
-
457
- class CrisprFormComponent {
458
- constructor() {
459
- this.form = new FormGroup({});
460
- this.value = null;
461
- this.submitted = new EventEmitter();
462
- // proxy value and status change events through to consuming component
463
- this.valueChanges = this.form.valueChanges;
464
- this.statusChanges = this.form.statusChanges;
465
- }
466
- ngOnInit() {
467
- // build out the form, note that we pass in the form as the third argument and the function modifies it
468
- buildFormGroupFromConfig(this.config, this.value, this.form);
469
- }
470
- handleSubmit() {
471
- this.form.markAllAsTouched();
472
- this.submitted.emit(this.form);
473
- }
474
- triggerSubmit() {
475
- this.submitTrigger.nativeElement.click();
476
- }
477
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
478
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: CrisprFormComponent, isStandalone: true, selector: "crispr-form", inputs: { config: "config", form: "form", value: "value" }, outputs: { submitted: "submitted", valueChanges: "valueChanges", statusChanges: "statusChanges" }, viewQueries: [{ propertyName: "submitTrigger", first: true, predicate: ["submitTrigger"], descendants: true }], ngImport: i0, template: "<form\n class=\"crispr-form\"\n [ngClass]=\"config.classes\"\n [formGroup]=\"form\"\n (ngSubmit)=\"handleSubmit()\"\n [autocomplete]=\"config.autocomplete || 'off'\"\n [errorDictionary]=\"config.errorDictionary\"\n #ngFormElement=\"ngForm\">\n\n @for (field of config.fields; track field) {\n <ng-container\n crisprField\n [value]=\"value | initialControlValue : field\"\n [config]=\"field\"\n [group]=\"form\">\n </ng-container>\n }\n <!-- Hidden button, programmatically clicked when crispr form triggerSubmit function called.\n Uses a hidden button with type=\"submit\" because it will trigger both native form submit event\n (which the error handler has to listen for) and ngSubmit event -->\n <button #submitTrigger class=\"submit-trigger\" data-testid=\"submit-trigger\" type=\"submit\">\n </button>\n</form>\n", styles: [".submit-trigger{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: CrisprFieldDirective, selector: "[crisprField]", inputs: ["config", "group", "value"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormValidationHandlerModule }, { kind: "directive", type: i6.ControlErrorsFormDirective, selector: "form", inputs: ["errorDictionary"] }, { kind: "directive", type: i6.ControlErrorContainerDirective, selector: "[controlErrorContainer], [formGroup]" }, { kind: "ngmodule", type: CrisprPipesModule }, { kind: "pipe", type: InitialControlValuePipe, name: "initialControlValue" }], preserveWhitespaces: true }); }
479
- }
480
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprFormComponent, decorators: [{
481
- type: Component,
482
- args: [{ selector: 'crispr-form', imports: [
483
- CommonModule,
484
- CrisprFieldDirective,
485
- ReactiveFormsModule,
486
- FormValidationHandlerModule,
487
- CrisprPipesModule,
488
- ], template: "<form\n class=\"crispr-form\"\n [ngClass]=\"config.classes\"\n [formGroup]=\"form\"\n (ngSubmit)=\"handleSubmit()\"\n [autocomplete]=\"config.autocomplete || 'off'\"\n [errorDictionary]=\"config.errorDictionary\"\n #ngFormElement=\"ngForm\">\n\n @for (field of config.fields; track field) {\n <ng-container\n crisprField\n [value]=\"value | initialControlValue : field\"\n [config]=\"field\"\n [group]=\"form\">\n </ng-container>\n }\n <!-- Hidden button, programmatically clicked when crispr form triggerSubmit function called.\n Uses a hidden button with type=\"submit\" because it will trigger both native form submit event\n (which the error handler has to listen for) and ngSubmit event -->\n <button #submitTrigger class=\"submit-trigger\" data-testid=\"submit-trigger\" type=\"submit\">\n </button>\n</form>\n", styles: [".submit-trigger{display:none}\n"] }]
489
- }], propDecorators: { config: [{
490
- type: Input
491
- }], form: [{
492
- type: Input
493
- }], value: [{
494
- type: Input
495
- }], submitted: [{
496
- type: Output
497
- }], valueChanges: [{
498
- type: Output
499
- }], statusChanges: [{
500
- type: Output
501
- }], submitTrigger: [{
502
- type: ViewChild,
503
- args: ['submitTrigger']
504
- }] } });
505
-
506
- class FileDropzoneDirective {
507
- constructor() {
508
- this.fileDrop = new EventEmitter();
509
- this.crisprFileDropzone = true;
510
- }
511
- onDrop($event) {
512
- if (this.crisprFileDropzone) {
513
- $event.preventDefault();
514
- this.fileDrop.emit($event.dataTransfer.files);
515
- }
516
- }
517
- // Prevents DOM from trying to open file in browser
518
- onDragOver($event) {
519
- if (this.crisprFileDropzone) {
520
- $event.preventDefault();
521
- }
522
- }
523
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: FileDropzoneDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
524
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.6", type: FileDropzoneDirective, isStandalone: true, selector: "[crisprFileDropzone]", inputs: { crisprFileDropzone: "crisprFileDropzone" }, outputs: { fileDrop: "fileDrop" }, host: { listeners: { "drop": "onDrop($event)", "dragover": "onDragOver($event)" } }, ngImport: i0 }); }
525
- }
526
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: FileDropzoneDirective, decorators: [{
527
- type: Directive,
528
- args: [{
529
- selector: '[crisprFileDropzone]',
530
- standalone: true,
531
- }]
532
- }], propDecorators: { fileDrop: [{
533
- type: Output
534
- }], crisprFileDropzone: [{
535
- type: Input
536
- }], onDrop: [{
537
- type: HostListener,
538
- args: ['drop', ['$event']]
539
- }], onDragOver: [{
540
- type: HostListener,
541
- args: ['dragover', ['$event']]
542
- }] } });
543
-
544
- class InfoComponent {
545
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: InfoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
546
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: InfoComponent, isStandalone: true, selector: "crispr-info", inputs: { info: "info" }, ngImport: i0, template: "@if (info) {\n <mat-icon\n [matTooltip]=\"info.content\"\n [matTooltipPosition]=\"info.tooltipPosition || 'below'\">\n {{info.iconName || 'info'}}\n </mat-icon>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
547
- }
548
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: InfoComponent, decorators: [{
549
- type: Component,
550
- args: [{ selector: 'crispr-info', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
551
- MatIconModule,
552
- MatTooltipModule
553
- ], template: "@if (info) {\n <mat-icon\n [matTooltip]=\"info.content\"\n [matTooltipPosition]=\"info.tooltipPosition || 'below'\">\n {{info.iconName || 'info'}}\n </mat-icon>\n}\n" }]
554
- }], propDecorators: { info: [{
555
- type: Input
556
- }] } });
557
-
558
- const defaultConfig$1 = {
559
- typographyClass: 'mat-h3',
560
- };
561
- class HeadingComponent extends CrisprFieldComponent {
562
- constructor() {
563
- super(...arguments);
564
- this.defaultConfig = defaultConfig$1;
565
- }
566
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: HeadingComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
567
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: HeadingComponent, isStandalone: true, selector: "crispr-heading", usesInheritance: true, ngImport: i0, template: "@if (!!config()?.label) {\n <label\n [ngClass]=\"config().typographyClass\">\n {{ config().label }}\n @if (config().info) {\n <crispr-info\n matSuffix\n [info]=\"config().info\">\n </crispr-info>\n }\n </label>\n}\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "directive", type: i2$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: InfoComponent, selector: "crispr-info", inputs: ["info"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
568
- }
569
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: HeadingComponent, decorators: [{
570
- type: Component,
571
- args: [{ selector: 'crispr-heading', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, MatFormFieldModule, InfoComponent], standalone: true, template: "@if (!!config()?.label) {\n <label\n [ngClass]=\"config().typographyClass\">\n {{ config().label }}\n @if (config().info) {\n <crispr-info\n matSuffix\n [info]=\"config().info\">\n </crispr-info>\n }\n </label>\n}\n", styles: [":host{display:block}\n"] }]
572
- }] });
573
-
574
- class FieldContainerComponent {
575
- constructor() {
576
- // boolean whether field-container is inline
577
- this.inlineField = false;
578
- this.subs = [];
579
- }
580
- ngOnInit() {
581
- this.disabled$ = this.connectDisabledCallback(this.group, this.config);
582
- // we tried moving this into afterViewChecked and afterContentChecked lifecycle hooks without any luck
583
- if (this.config.computeValue) {
584
- this.subs.push(this.config
585
- .computeValue(this.group)
586
- .pipe(distinctUntilChanged(), tap((computedValue) => this.group.get(this.config.controlName).setValue(computedValue)))
587
- .subscribe());
588
- }
589
- }
590
- ngOnDestroy() {
591
- this.subs.forEach((sub) => sub.unsubscribe);
592
- }
593
- /**
594
- * Connects user defined disabledCallback function to the the view, so that the control is enabled/disabled
595
- * appropriately. It also will hide disabled fields in the UI unless `hideDisabled` is set to
596
- * false in the controls config
597
- * @param group used to get valueChanges from control
598
- * @param config configuration object used to
599
- */
600
- connectDisabledCallback(group, config = null) {
601
- const control = group.get(config.controlName);
602
- // If the disabled$ function exists on the field config then call it with the disabledCallbackConfig
603
- // as a parameter otherwise return an observable of true.
604
- return config?.disabledCallback &&
605
- config.disabledCallback instanceof Function
606
- ? config.disabledCallback(group).pipe(
607
- // This enables/disables when callback conditions are met
608
- tap((shouldDisable) => shouldDisable ? control.disable() : control.enable()))
609
- : of(false);
610
- }
611
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: FieldContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
612
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: FieldContainerComponent, isStandalone: true, selector: "crispr-field-container", inputs: { config: "config", group: "group", inlineField: "inlineField" }, ngImport: i0, template: "@if ((disabled$ | async) ? !config.hideDisabled : true) {\n <div\n [ngClass]=\"config.classes\"\n [class.inline-field]=\"inlineField\"\n class=\"field-container\">\n @if (config.heading) {\n <crispr-heading\n [config]=\"config.heading\">\n </crispr-heading>\n }\n <ng-content>\n </ng-content>\n </div>\n}\n", styles: ["::ng-deep mat-form-field.mat-mdc-form-field{display:block;padding:.25em 0}.inline-field{display:inline-block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: HeadingComponent, selector: "crispr-heading" }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
613
- }
614
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: FieldContainerComponent, decorators: [{
615
- type: Component,
616
- args: [{ selector: 'crispr-field-container', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, HeadingComponent], template: "@if ((disabled$ | async) ? !config.hideDisabled : true) {\n <div\n [ngClass]=\"config.classes\"\n [class.inline-field]=\"inlineField\"\n class=\"field-container\">\n @if (config.heading) {\n <crispr-heading\n [config]=\"config.heading\">\n </crispr-heading>\n }\n <ng-content>\n </ng-content>\n </div>\n}\n", styles: ["::ng-deep mat-form-field.mat-mdc-form-field{display:block;padding:.25em 0}.inline-field{display:inline-block}\n"] }]
617
- }], propDecorators: { config: [{
618
- type: Input
619
- }], group: [{
620
- type: Input
621
- }], inlineField: [{
622
- type: Input
623
- }] } });
624
-
625
- class SelectedFileComponent {
626
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SelectedFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
627
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SelectedFileComponent, isStandalone: true, selector: "crispr-selected-file", inputs: { fileName: "fileName", progress: "progress", showProgress: "showProgress", color: "color" }, ngImport: i0, template: "<h3 class=\"mat-h3\">{{ fileName }}</h3>\n@if (showProgress) {\n <mat-progress-bar\n mode=\"determinate\"\n [color]=\"color\"\n [value]=\"progress\">\n </mat-progress-bar>\n}\n", styles: ["mat-progress-bar{margin-bottom:8px}\n"], dependencies: [{ kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i1$2.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }], preserveWhitespaces: true }); }
628
- }
629
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SelectedFileComponent, decorators: [{
630
- type: Component,
631
- args: [{ selector: 'crispr-selected-file', imports: [
632
- MatProgressBarModule
633
- ], template: "<h3 class=\"mat-h3\">{{ fileName }}</h3>\n@if (showProgress) {\n <mat-progress-bar\n mode=\"determinate\"\n [color]=\"color\"\n [value]=\"progress\">\n </mat-progress-bar>\n}\n", styles: ["mat-progress-bar{margin-bottom:8px}\n"] }]
634
- }], propDecorators: { fileName: [{
635
- type: Input
636
- }], progress: [{
637
- type: Input
638
- }], showProgress: [{
639
- type: Input
640
- }], color: [{
641
- type: Input
642
- }] } });
643
-
644
- /* eslint-disable @nx/enforce-module-boundaries */
645
- class FileUploadFieldComponent extends CrisprControlComponent {
646
- // ngControl: NgControl = null;
647
- constructor(ngControl) {
648
- super();
649
- this.ngControl = ngControl;
650
- this.defaultConfig = {
651
- allowMultipleFiles: false,
652
- acceptedTypes: '*.*',
653
- dropZoneText: 'DROP FILE HERE',
654
- selectFilesButtonType: 'button',
655
- selectButtonText: 'SELECT',
656
- showClearFilesButton: true,
657
- clearFilesButtonText: 'CLEAR',
658
- uploadButtonText: 'UPLOAD',
659
- uploadButtonType: 'button',
660
- showUploadProgress: false,
661
- disableOnUpload: true,
662
- };
663
- this.selectedFiles = signal(null, ...(ngDevMode ? [{ debugName: "selectedFiles" }] : []));
664
- this.selectedFilesArray = computed(() => this.selectedFiles() ? Array.from(this.selectedFiles()) : [], ...(ngDevMode ? [{ debugName: "selectedFilesArray" }] : []));
665
- this.isUploaded = false;
666
- this.fileProgress = [];
667
- if (this.ngControl != null) {
668
- // Setting the value accessor directly (instead of using
669
- // the providers) to avoid running into a circular import.
670
- ngControl.valueAccessor = this;
671
- }
672
- }
673
- ngOnInit() {
674
- super.ngOnInit();
675
- this.disabled$ = this.config().disabledCallback
676
- ? this.config().disabledCallback(this.group())
677
- : of(false);
678
- }
679
- filesChanged(files) {
680
- if (files && files.length > 0) {
681
- this.selectedFiles.set(files);
682
- this.control().patchValue(files);
683
- }
684
- }
685
- uploadFiles() {
686
- if (this.selectedFiles() && this.config().uploadFiles) {
687
- this.isUploaded = true;
688
- this.config().uploadFiles(this.group(), this.selectedFiles(), this);
689
- }
690
- }
691
- resetFileInput() {
692
- this.fileInputRef.nativeElement.value = '';
693
- this.control().patchValue(null);
694
- this.isUploaded = false;
695
- }
696
- writeValue(value) {
697
- // clear file input
698
- // this.host.nativeElement.value = '';
699
- // this.file = null;
700
- }
701
- registerOnChange(fn) {
702
- this.onChange = fn;
703
- }
704
- registerOnTouched(fn) { }
705
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: FileUploadFieldComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component }); }
706
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: FileUploadFieldComponent, isStandalone: true, selector: "crispr-file-upload-field", viewQueries: [{ propertyName: "fileInputRef", first: true, predicate: ["fileInput"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<crispr-field-container\n [config]=\"config()\"\n [group]=\"group()\">\n <mat-form-field floatLabel=\"always\"\n [attr.data-testid]=\"config().controlName\"\n [color]=\"config().color\"\n appearance=\"outline\"\n [crisprFileDropzone]=\"!(disabled$ | async) && !(config().disableOnUpload && isUploaded)\"\n [formGroup]=\"group()\"\n (fileDrop)=\"filesChanged($event)\">\n\n <input [formControlName]=\"config().controlName\" matInput type=\"text\"/>\n <input\n #fileInput\n type=\"file\"\n style=\"display: none\"\n [accept]=\"config().acceptedTypes\"\n [multiple]=\"config().allowMultipleFiles\"\n (change)=\"filesChanged($event.target.files)\"/>\n <mat-label>{{config().label}}</mat-label>\n\n @if (!selectedFiles() || selectedFiles().length === 0) {\n <div class=\"drop-info\">\n <mat-icon class=\"drop-icon\" inline=\"true\">cloud_upload</mat-icon>\n <h2 class=\"mat-h2\">{{config().dropZoneText}}</h2>\n or\n <button\n mat-raised-button\n type=\"button\"\n color=\"primary\"\n [disabled]=\"(disabled$ | async) || config().disableOnUpload && isUploaded\"\n (click)=\"fileInput.click()\"\n [attr.aria-label]=\"config().controlName\">\n {{config().selectButtonText}}\n </button>\n </div>\n } @else {\n <div class=\"selected-files-container\">\n <div class=\"selected-files-list\">\n @for (file of selectedFilesArray(); track file; let i = $index) {\n <crispr-selected-file\n [color]=\"config().color === 'primary' ? 'accent' : 'primary'\"\n [fileName]=\"file.name\"\n [showProgress]=\"config().showUploadProgress\"\n [progress]=\"fileProgress && (fileProgress[i] | async)\">\n </crispr-selected-file>\n }\n </div>\n </div>\n }\n @if (config().hint && (control().valid || !control().touched)) {<mat-hint>{{config().hint}}</mat-hint>}\n </mat-form-field>\n @if ((selectedFiles())?.length > 0) {\n <div class=\"button-container\">\n <button\n mat-button\n (click)=\"resetFileInput()\"\n type=\"button\"\n [disabled]=\"(disabled$ | async) || (config().disableOnUpload && isUploaded)\"\n aria-label=\"Remove Selected File(s)\">\n {{config().clearFilesButtonText}}\n <mat-icon>delete</mat-icon>\n </button>\n @if (!!config().uploadFiles) {\n <button\n mat-raised-button\n type=\"button\"\n color=\"accent\"\n class=\"file-input-button\"\n [disabled]=\"(disabled$ | async) || (config().disableOnUpload && isUploaded)\"\n (click)=\"uploadFiles()\"\n [attr.aria-label]=\"config().uploadButtonText\">\n {{ config().uploadButtonText }}\n </button>\n }\n </div>\n }\n</crispr-field-container>\n", styles: [":host ::ng-deep .mat-mdc-form-field .mat-mdc-form-field-infix{padding-top:0;display:flex;justify-content:center}:host .drop-info{display:flex;flex-direction:column;align-items:center}:host .drop-info .drop-icon{font-size:36px}:host .drop-info .mat-h2{margin:0}:host .button-container{display:flex;justify-content:flex-end;margin-top:-16px}:host .button-container button{margin-left:8px}:host .selected-files-container{width:100%}:host [matInput]{position:absolute;max-height:0;visibility:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: FieldContainerComponent, selector: "crispr-field-container", inputs: ["config", "group", "inlineField"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.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: SelectedFileComponent, selector: "crispr-selected-file", inputs: ["fileName", "progress", "showProgress", "color"] }, { kind: "ngmodule", type: FormValidationHandlerModule }, { kind: "directive", type: i6.ControlErrorsDirective, selector: "[formControl], [formControlName]" }, { kind: "directive", type: i6.ControlErrorContainerDirective, selector: "[controlErrorContainer], [formGroup]" }, { kind: "directive", type: FileDropzoneDirective, selector: "[crisprFileDropzone]", inputs: ["crisprFileDropzone"], outputs: ["fileDrop"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
707
- }
708
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: FileUploadFieldComponent, decorators: [{
709
- type: Component,
710
- args: [{ selector: 'crispr-file-upload-field', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
711
- CommonModule,
712
- FieldContainerComponent,
713
- ReactiveFormsModule,
714
- MatIconModule,
715
- MatButtonModule,
716
- MatFormFieldModule,
717
- MatInputModule,
718
- SelectedFileComponent,
719
- FormValidationHandlerModule,
720
- FileDropzoneDirective,
721
- ], standalone: true, template: "<crispr-field-container\n [config]=\"config()\"\n [group]=\"group()\">\n <mat-form-field floatLabel=\"always\"\n [attr.data-testid]=\"config().controlName\"\n [color]=\"config().color\"\n appearance=\"outline\"\n [crisprFileDropzone]=\"!(disabled$ | async) && !(config().disableOnUpload && isUploaded)\"\n [formGroup]=\"group()\"\n (fileDrop)=\"filesChanged($event)\">\n\n <input [formControlName]=\"config().controlName\" matInput type=\"text\"/>\n <input\n #fileInput\n type=\"file\"\n style=\"display: none\"\n [accept]=\"config().acceptedTypes\"\n [multiple]=\"config().allowMultipleFiles\"\n (change)=\"filesChanged($event.target.files)\"/>\n <mat-label>{{config().label}}</mat-label>\n\n @if (!selectedFiles() || selectedFiles().length === 0) {\n <div class=\"drop-info\">\n <mat-icon class=\"drop-icon\" inline=\"true\">cloud_upload</mat-icon>\n <h2 class=\"mat-h2\">{{config().dropZoneText}}</h2>\n or\n <button\n mat-raised-button\n type=\"button\"\n color=\"primary\"\n [disabled]=\"(disabled$ | async) || config().disableOnUpload && isUploaded\"\n (click)=\"fileInput.click()\"\n [attr.aria-label]=\"config().controlName\">\n {{config().selectButtonText}}\n </button>\n </div>\n } @else {\n <div class=\"selected-files-container\">\n <div class=\"selected-files-list\">\n @for (file of selectedFilesArray(); track file; let i = $index) {\n <crispr-selected-file\n [color]=\"config().color === 'primary' ? 'accent' : 'primary'\"\n [fileName]=\"file.name\"\n [showProgress]=\"config().showUploadProgress\"\n [progress]=\"fileProgress && (fileProgress[i] | async)\">\n </crispr-selected-file>\n }\n </div>\n </div>\n }\n @if (config().hint && (control().valid || !control().touched)) {<mat-hint>{{config().hint}}</mat-hint>}\n </mat-form-field>\n @if ((selectedFiles())?.length > 0) {\n <div class=\"button-container\">\n <button\n mat-button\n (click)=\"resetFileInput()\"\n type=\"button\"\n [disabled]=\"(disabled$ | async) || (config().disableOnUpload && isUploaded)\"\n aria-label=\"Remove Selected File(s)\">\n {{config().clearFilesButtonText}}\n <mat-icon>delete</mat-icon>\n </button>\n @if (!!config().uploadFiles) {\n <button\n mat-raised-button\n type=\"button\"\n color=\"accent\"\n class=\"file-input-button\"\n [disabled]=\"(disabled$ | async) || (config().disableOnUpload && isUploaded)\"\n (click)=\"uploadFiles()\"\n [attr.aria-label]=\"config().uploadButtonText\">\n {{ config().uploadButtonText }}\n </button>\n }\n </div>\n }\n</crispr-field-container>\n", styles: [":host ::ng-deep .mat-mdc-form-field .mat-mdc-form-field-infix{padding-top:0;display:flex;justify-content:center}:host .drop-info{display:flex;flex-direction:column;align-items:center}:host .drop-info .drop-icon{font-size:36px}:host .drop-info .mat-h2{margin:0}:host .button-container{display:flex;justify-content:flex-end;margin-top:-16px}:host .button-container button{margin-left:8px}:host .selected-files-container{width:100%}:host [matInput]{position:absolute;max-height:0;visibility:hidden}\n"] }]
722
- }], ctorParameters: () => [{ type: i1$1.NgControl, decorators: [{
723
- type: Optional
724
- }, {
725
- type: Self
726
- }] }], propDecorators: { fileInputRef: [{
727
- type: ViewChild,
728
- args: ['fileInput']
729
- }] } });
730
-
731
- var index$3 = /*#__PURE__*/Object.freeze({
732
- __proto__: null,
733
- FileUploadFieldComponent: FileUploadFieldComponent
734
- });
735
-
736
- var index$2 = /*#__PURE__*/Object.freeze({
737
- __proto__: null,
738
- FieldContainerComponent: FieldContainerComponent,
739
- FileDropzoneDirective: FileDropzoneDirective,
740
- FileUploadFieldComponent: FileUploadFieldComponent,
741
- HeadingComponent: HeadingComponent,
742
- InfoComponent: InfoComponent,
743
- SelectedFileComponent: SelectedFileComponent
744
- });
745
-
746
- class CrisprDisplayFieldDirective {
747
- set value(value) {
748
- this._value = value;
749
- // This is needed to keep the group list from resetting control values to the initial input value
750
- this.updateComponentValue(value);
751
- }
752
- get value() {
753
- return this._value;
754
- }
755
- constructor(container, cdr) {
756
- this.container = container;
757
- this.cdr = cdr;
758
- }
759
- async ngOnInit() {
760
- if (this.component) {
761
- /**
762
- * create component and set values from config on its instance
763
- */
764
- const componentRef = this.container.createComponent(this.component);
765
- this.componentInstance = componentRef.instance;
766
- this.componentInstance.index = this.index;
767
- this.updateComponentValue(this.value);
768
- }
769
- }
770
- updateComponentValue(value) {
771
- if (!this.componentInstance)
772
- return;
773
- this.componentInstance.value = value;
774
- this.cdr.detectChanges();
775
- }
776
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprDisplayFieldDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
777
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.6", type: CrisprDisplayFieldDirective, isStandalone: true, selector: "[crisprDisplayField]", inputs: { group: "group", value: "value", component: "component", index: "index" }, ngImport: i0 }); }
778
- }
779
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprDisplayFieldDirective, decorators: [{
780
- type: Directive,
781
- args: [{
782
- selector: '[crisprDisplayField]',
783
- standalone: true,
784
- }]
785
- }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }], propDecorators: { group: [{
786
- type: Input
787
- }], value: [{
788
- type: Input
789
- }], component: [{
790
- type: Input
791
- }], index: [{
792
- type: Input
793
- }] } });
794
-
795
- const defaultConfig = {
796
- addButtonLabel: 'ADD ITEM',
797
- minListLength: 1,
798
- };
799
- class FormGroupListComponent extends CrisprControlComponent {
800
- constructor(cdr) {
801
- super();
802
- this.cdr = cdr;
803
- this.defaultConfig = defaultConfig;
804
- /**
805
- * By setting this to true when adding/removing items from array,
806
- * we can block original values from overwriting form values
807
- * */
808
- this.blockValue = false;
809
- this.selectedIndex = null;
810
- }
811
- ngOnInit() {
812
- super.ngOnInit();
813
- // TODO: this is required to ngFor of controls in template, must be a better way
814
- }
815
- setControlValue(values) {
816
- if (this.control()) {
817
- if (values?.length > 0) {
818
- // clear any existing values so that new values don't concatenate onto the old
819
- const currentValues = this.control().value;
820
- if (currentValues.length) {
821
- this.control().clear();
822
- }
823
- values.forEach((value) => this.addGroup(value));
824
- }
825
- else if (this.config().displayInitialItem) {
826
- this.addGroup();
827
- }
828
- // needed to ensure new array items render
829
- setTimeout(() => {
830
- this.cdr.detectChanges();
831
- });
832
- }
833
- }
834
- clickDelete(index) {
835
- this.blockValue = true;
836
- this.deleteGroup(index);
837
- }
838
- clickAdd() {
839
- this.blockValue = true;
840
- this.addGroup();
841
- }
842
- addGroup(value = null) {
843
- this.control().push(createControlForType(this.config().itemConfig, value));
844
- // needed to ensure new array items render
845
- setTimeout(() => {
846
- this.cdr.detectChanges();
847
- });
848
- }
849
- deleteGroup(index) {
850
- this.control().removeAt(index);
851
- }
852
- clickEditItem(index) {
853
- this.selectedIndex = index;
854
- }
855
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: FormGroupListComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
856
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: FormGroupListComponent, isStandalone: true, selector: "crispr-form-group-list", usesInheritance: true, ngImport: i0, template: "<crispr-field-container [config]=\"config()\" [group]=\"group()\" [formGroup]=\"group()\">\n\n <div [formArrayName]=\"config().controlName\">\n\n <!-- Don't add trackBy function, it confuses the state of the array -->\n @for (itemControl of control()?.controls; track itemControl; let i = $index; let last = $last) {\n @if (!config().displayItemComponent || i === selectedIndex || (last && selectedIndex ?? true)) {\n <!-- TODO: use content projection to allow custom item label component -->\n <div class=\"item-header\">\n <span class=\"mat-h2\"> {{ config().itemLabelBuilder ? config().itemLabelBuilder(i) : 'Item ' + (i + 1) }} </span>\n @if (i + 1 > config().minListLength) {\n <button mat-icon-button type=\"button\">\n <mat-icon (click)=\"clickDelete(i)\">delete</mat-icon>\n </button>\n }\n </div>\n <div [formGroup]=\"itemControl\">\n <!-- TODO: if chiplists didn't need to have labels mixed in with their values we could use [value]=\"control.value\" below -->\n @for (field of config().itemConfig.fields; track field) {\n <ng-container crisprField [value]=\"blockValue ? null : value && value[i] | initialControlValue : field\"\n [config]=\"field\" [group]=\"itemControl\">\n </ng-container>\n }\n </div>\n } @else {\n <div class=\"display-field-container\" crisprDisplayField [component]=\"config().displayItemComponent\"\n [value]=\"itemControl.value\" [index]=\"i\">\n <button mat-icon-button (click)=\"clickEditItem(i)\">\n <mat-icon>edit</mat-icon>\n </button>\n </div>\n }\n <ng-template #display>\n <div class=\"display-field-container\" crisprDisplayField [component]=\"config().displayItemComponent\"\n [value]=\"itemControl.value\" [index]=\"i\">\n <button mat-icon-button (click)=\"clickEditItem(i)\">\n <mat-icon>edit</mat-icon>\n </button>\n </div>\n </ng-template>\n }\n </div>\n <div class=\"group-footer\">\n <button type=\"button\" class=\"add\" mat-raised-button [color]=\"config().addButtonColor\" (click)=\"clickAdd()\">\n {{config().addItemLabel || config().addButtonLabel}}\n </button>\n </div>\n\n</crispr-field-container>", styles: [".item-header{display:flex;justify-content:space-between}.group-footer{display:flex;justify-content:flex-end}.group-footer button.add{margin-bottom:16px}.display-field-container{position:relative}.display-field-container button{position:absolute;top:0;right:0}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1$3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FieldContainerComponent, selector: "crispr-field-container", inputs: ["config", "group", "inlineField"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: CrisprFieldDirective, selector: "[crisprField]", inputs: ["config", "group", "value"] }, { kind: "directive", type: CrisprDisplayFieldDirective, selector: "[crisprDisplayField]", inputs: ["group", "value", "component", "index"] }, { kind: "ngmodule", type: CrisprPipesModule }, { kind: "ngmodule", type: FormValidationHandlerModule }, { kind: "directive", type: i6.ControlErrorContainerDirective, selector: "[controlErrorContainer], [formGroup]" }, { kind: "pipe", type: InitialControlValuePipe, name: "initialControlValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true }); }
857
- }
858
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: FormGroupListComponent, decorators: [{
859
- type: Component,
860
- args: [{ selector: 'crispr-form-group-list', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
861
- MatButtonModule,
862
- MatIconModule,
863
- FieldContainerComponent,
864
- ReactiveFormsModule,
865
- CrisprFieldDirective,
866
- CrisprDisplayFieldDirective,
867
- CrisprPipesModule,
868
- FormValidationHandlerModule
869
- ], standalone: true, template: "<crispr-field-container [config]=\"config()\" [group]=\"group()\" [formGroup]=\"group()\">\n\n <div [formArrayName]=\"config().controlName\">\n\n <!-- Don't add trackBy function, it confuses the state of the array -->\n @for (itemControl of control()?.controls; track itemControl; let i = $index; let last = $last) {\n @if (!config().displayItemComponent || i === selectedIndex || (last && selectedIndex ?? true)) {\n <!-- TODO: use content projection to allow custom item label component -->\n <div class=\"item-header\">\n <span class=\"mat-h2\"> {{ config().itemLabelBuilder ? config().itemLabelBuilder(i) : 'Item ' + (i + 1) }} </span>\n @if (i + 1 > config().minListLength) {\n <button mat-icon-button type=\"button\">\n <mat-icon (click)=\"clickDelete(i)\">delete</mat-icon>\n </button>\n }\n </div>\n <div [formGroup]=\"itemControl\">\n <!-- TODO: if chiplists didn't need to have labels mixed in with their values we could use [value]=\"control.value\" below -->\n @for (field of config().itemConfig.fields; track field) {\n <ng-container crisprField [value]=\"blockValue ? null : value && value[i] | initialControlValue : field\"\n [config]=\"field\" [group]=\"itemControl\">\n </ng-container>\n }\n </div>\n } @else {\n <div class=\"display-field-container\" crisprDisplayField [component]=\"config().displayItemComponent\"\n [value]=\"itemControl.value\" [index]=\"i\">\n <button mat-icon-button (click)=\"clickEditItem(i)\">\n <mat-icon>edit</mat-icon>\n </button>\n </div>\n }\n <ng-template #display>\n <div class=\"display-field-container\" crisprDisplayField [component]=\"config().displayItemComponent\"\n [value]=\"itemControl.value\" [index]=\"i\">\n <button mat-icon-button (click)=\"clickEditItem(i)\">\n <mat-icon>edit</mat-icon>\n </button>\n </div>\n </ng-template>\n }\n </div>\n <div class=\"group-footer\">\n <button type=\"button\" class=\"add\" mat-raised-button [color]=\"config().addButtonColor\" (click)=\"clickAdd()\">\n {{config().addItemLabel || config().addButtonLabel}}\n </button>\n </div>\n\n</crispr-field-container>", styles: [".item-header{display:flex;justify-content:space-between}.group-footer{display:flex;justify-content:flex-end}.group-footer button.add{margin-bottom:16px}.display-field-container{position:relative}.display-field-container button{position:absolute;top:0;right:0}\n"] }]
870
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
871
-
872
- var index$1 = /*#__PURE__*/Object.freeze({
873
- __proto__: null,
874
- FormGroupListComponent: FormGroupListComponent
875
- });
876
-
877
- class SubGroupComponent extends CrisprControlComponent {
878
- ngOnInit() {
879
- super.ngOnInit();
880
- }
881
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SubGroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
882
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SubGroupComponent, isStandalone: false, selector: "crispr-sub-group", usesInheritance: true, ngImport: i0, template: "<crispr-field-container [config]=\"config()\" [group]=\"group()\">\n @for (fieldConfig of config().fields; track fieldConfig) {\n <ng-container crisprField [value]=\"value | initialControlValue : fieldConfig\" [config]=\"fieldConfig\"\n [group]=\"control()\">\n </ng-container>\n }\n</crispr-field-container>", styles: [""], dependencies: [{ kind: "directive", type: CrisprFieldDirective, selector: "[crisprField]", inputs: ["config", "group", "value"] }, { kind: "component", type: FieldContainerComponent, selector: "crispr-field-container", inputs: ["config", "group", "inlineField"] }, { kind: "pipe", type: InitialControlValuePipe, name: "initialControlValue" }], preserveWhitespaces: true }); }
883
- }
884
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SubGroupComponent, decorators: [{
885
- type: Component,
886
- args: [{ selector: 'crispr-sub-group', standalone: false, template: "<crispr-field-container [config]=\"config()\" [group]=\"group()\">\n @for (fieldConfig of config().fields; track fieldConfig) {\n <ng-container crisprField [value]=\"value | initialControlValue : fieldConfig\" [config]=\"fieldConfig\"\n [group]=\"control()\">\n </ng-container>\n }\n</crispr-field-container>" }]
887
- }] });
888
-
889
- class SubGroupModule {
890
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SubGroupModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
891
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: SubGroupModule, declarations: [SubGroupComponent], imports: [CommonModule,
892
- CrisprFieldDirective,
893
- FieldContainerComponent,
894
- CrisprPipesModule,
895
- // TODO: Does this need to be here?
896
- FormValidationHandlerModule], exports: [SubGroupComponent] }); }
897
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SubGroupModule, imports: [CommonModule,
898
- FieldContainerComponent,
899
- CrisprPipesModule,
900
- // TODO: Does this need to be here?
901
- FormValidationHandlerModule] }); }
902
- }
903
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SubGroupModule, decorators: [{
904
- type: NgModule,
905
- args: [{
906
- imports: [
907
- CommonModule,
908
- CrisprFieldDirective,
909
- FieldContainerComponent,
910
- CrisprPipesModule,
911
- // TODO: Does this need to be here?
912
- FormValidationHandlerModule
913
- ],
914
- exports: [
915
- SubGroupComponent
916
- ],
917
- declarations: [
918
- SubGroupComponent
919
- ]
920
- }]
921
- }] });
922
-
923
- var index = /*#__PURE__*/Object.freeze({
924
- __proto__: null,
925
- SubGroupComponent: SubGroupComponent,
926
- SubGroupModule: SubGroupModule
927
- });
928
-
929
- class CrisprFormsModule {
930
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprFormsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
931
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: CrisprFormsModule, imports: [CommonModule,
932
- ReactiveFormsModule,
933
- FormValidationHandlerModule,
934
- FormGroupListComponent,
935
- FieldContainerComponent,
936
- CrisprFieldDirective,
937
- CrisprDisplayFieldDirective,
938
- SubGroupModule,
939
- CrisprPipesModule,
940
- CrisprFormComponent], exports: [CrisprFormComponent, FieldContainerComponent] }); }
941
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprFormsModule, imports: [CommonModule,
942
- ReactiveFormsModule,
943
- FormValidationHandlerModule,
944
- FormGroupListComponent,
945
- FieldContainerComponent,
946
- SubGroupModule,
947
- CrisprPipesModule,
948
- CrisprFormComponent] }); }
949
- }
950
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CrisprFormsModule, decorators: [{
951
- type: NgModule,
952
- args: [{
953
- imports: [
954
- CommonModule,
955
- ReactiveFormsModule,
956
- FormValidationHandlerModule,
957
- FormGroupListComponent,
958
- FieldContainerComponent,
959
- CrisprFieldDirective,
960
- CrisprDisplayFieldDirective,
961
- SubGroupModule,
962
- CrisprPipesModule,
963
- CrisprFormComponent,
964
- ],
965
- exports: [CrisprFormComponent, FieldContainerComponent],
966
- }]
967
- }] });
968
-
969
- /**
970
- * Generated bundle index. Do not edit.
971
- */
972
-
973
- export { AbstractAutocompleteComponent, ControlType, CrisprControlComponent, CrisprDisplayFieldComponent, CrisprFieldComponent, CrisprFormComponent, CrisprFormsModule, DEFAULT_EMPTY_OPTIONS_MESSAGE, FieldContainerComponent, FileDropzoneDirective, FileUploadFieldComponent, HeadingComponent, InfoComponent, SelectedFileComponent, allowedFileExtValidator, allowedFileType, buildFormGroupFromConfig, callOptionsIfFunction, convertBytesToMb, createControlForType, filterOptionsByLabel, isControlConfig, maxFileSizeValidator, observablifyOptions, valueIn };
1
+ export { A as AbstractAutocompleteComponent, d as ControlType, a as CrisprControlComponent, g as CrisprDisplayFieldComponent, C as CrisprFieldComponent, h as CrisprFormComponent, i as CrisprFormsModule, D as DEFAULT_EMPTY_OPTIONS_MESSAGE, F as FieldContainerComponent, f as FileDropzoneDirective, j as FileUploadFieldComponent, H as HeadingComponent, I as InfoComponent, S as SelectedFileComponent, k as allowedFileExtValidator, l as allowedFileType, b as buildFormGroupFromConfig, m as callOptionsIfFunction, e as convertBytesToMb, n as createControlForType, p as filterOptionsByLabel, q as isControlConfig, r as maxFileSizeValidator, o as observablifyOptions, v as valueIn } from './tft-crispr-forms-tft-crispr-forms-BFiZ8Nhn.mjs';
974
2
  //# sourceMappingURL=tft-crispr-forms.mjs.map