fleetcor-lwc 3.8.6 → 3.9.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.
package/README.md CHANGED
@@ -347,7 +347,6 @@ Add / update `lwc.config.json` file in your project
347
347
  show-dropdown-as-modal
348
348
  placeholder="City"
349
349
  error-message="Error! Empty field"
350
- required
351
350
  value="London"
352
351
  options="[{label:'London', value:'London'}, {label:'Leon', value:'Leon'}]"
353
352
  >
@@ -516,6 +515,59 @@ This component fully extends from `Input Text`
516
515
  | blur | event | object | Return common Event object |
517
516
  | change | event.detail | object | Return full data of component's state |
518
517
 
518
+ ### Input With Picklist
519
+
520
+ ```html
521
+ <flt-input-with-picklist
522
+ name="{picklist:'picklistName', input:'inputName'}"
523
+ required
524
+ label="{picklist:'picklistLabel', input:'inputLabel'}"
525
+ value="{picklist:'picklistValue', input:'inputValue'}"
526
+ show-dropdown-as-modal
527
+ placeholder="{picklist:'picklistPlaceholder', input:'inputPlaceholder'}"
528
+ onchange="{handleInputWithPicklist}"
529
+ min-value="100"
530
+ max-value="1000"
531
+ max-length="4000"
532
+ reg-exp="^([0-9]{1,1}||([1-9]{1,1}[0-9]{1,9}))$"
533
+ error-message="Error message Mounthly Sequrity"
534
+ options="[{label:'Label 1', value:'val_1'}, {label:'Label 2', value:'val_2'}]"
535
+ ></flt-input-with-picklist>
536
+ ...
537
+ ```
538
+
539
+ #### Input With Picklist variables
540
+
541
+ | @api variables | type | values | required | description |
542
+ | -------------- | ------ | ------ | -------- | ------------------------------------------------------------------ |
543
+ | name | object | | + | in format `{picklist:'value', input:'value'}` |
544
+ | label | object | | - | in format `{picklist:'value', input:'value'}` |
545
+ | value | object | | - | in format `{picklist:'value', input:'value'}` |
546
+ | placeholder | object | | - | in format `{picklist:'value', input:'value'}` |
547
+ | error-message | string | | - | |
548
+ | required | bool | | - | |
549
+ | disabled | bool | | - | |
550
+ | prefix | string | | - | |
551
+ | reg-exp | string | | - | |
552
+ | max-length | int | | - | |
553
+ | min-value | int | | - | |
554
+ | options | array | | + | Array of available items with `label` and `value` as unique string |
555
+ | max-value | int | | - | |
556
+
557
+ #### Input With Picklist methods
558
+
559
+ | @api | params | return type | description |
560
+ | -------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------------------------------- |
561
+ | validate | | void | Check component validation and show error message to user |
562
+ | isValid | | bool | Return `true` or `false` |
563
+ | getData | silent:bool | object | Return full data of component's state. If `silent` true - return value will be without any errors displaying for client |
564
+
565
+ #### Input With Picklist events
566
+
567
+ | name | handle | return | description |
568
+ | ------ | ------------ | ------ | ------------------------------------- |
569
+ | change | event.detail | object | Return full data of component's state |
570
+
519
571
  ## Interfaces
520
572
 
521
573
  #### ModalViewer
@@ -661,11 +713,17 @@ You can override them as you wish by global css variables as priority.
661
713
  --flt-picklist-dropdown-modal-header-bgc: #f3f4f6;
662
714
  --flt-input-phone-border-color-success: #59eb9c;
663
715
  --flt-input-phone-border-color-error: #ed123d;
716
+ --flt-input-with-picklist-border-color-success: #59eb9c;
717
+ --flt-input-with-picklist-border-color-error: #ed123d;
664
718
  }
665
719
  ```
666
720
 
667
721
  ## Release Notes:
668
722
 
723
+ - v.3.9.0
724
+
725
+ - Added new component `flt-input-with-picklist`
726
+
669
727
  - v.3.8.6
670
728
 
671
729
  - Bug fix visiability of `flt-input-phone`
@@ -37,7 +37,6 @@
37
37
  flex-shrink: 0;
38
38
  position: relative;
39
39
  z-index: 1;
40
- width: 76px;
41
40
  }
42
41
 
43
42
  &__error {
@@ -46,6 +45,9 @@
46
45
  line-height: 0;
47
46
  color: var(--flt-input-phone-border-color-error, #ed123d);
48
47
  transition: all 0.3s;
48
+ &:empty {
49
+ display: none;
50
+ }
49
51
  }
50
52
 
51
53
  .flt-input-text__wrapp {
@@ -103,6 +103,9 @@
103
103
  font-size: 12px;
104
104
  color: var(--flt-input-border-color-error, #ed123d);
105
105
  transition: all 0.3s;
106
+ &:empty {
107
+ display: none;
108
+ }
106
109
  }
107
110
 
108
111
  input {
@@ -0,0 +1,227 @@
1
+ import { createElement, setHooks } from 'lwc'
2
+ import InputWithPicklist from 'flt/inputWithPicklist'
3
+
4
+ setHooks({
5
+ sanitizeHtmlContent(content) {
6
+ return content
7
+ }
8
+ })
9
+
10
+ Object.defineProperty(window, 'matchMedia', {
11
+ writable: true,
12
+ value: jest.fn().mockImplementation((query) => ({
13
+ matches: false
14
+ // media: query,
15
+ // onchange: null,
16
+ // addListener: jest.fn(), // Deprecated
17
+ // removeListener: jest.fn(), // Deprecated
18
+ // addEventListener: jest.fn(),
19
+ // removeEventListener: jest.fn(),
20
+ // dispatchEvent: jest.fn()
21
+ }))
22
+ })
23
+
24
+ describe('flt-input-with-picklist', () => {
25
+ afterEach(() => {
26
+ while (document.body.firstChild) {
27
+ document.body.removeChild(document.body.firstChild)
28
+ }
29
+ })
30
+
31
+ it('flt-input-with-picklist base', async () => {
32
+ const inputWithPicklistEl = createElement('flt-input-phone', { is: InputWithPicklist })
33
+
34
+ inputWithPicklistEl.name = {
35
+ picklist: 'currency',
36
+ input: 'price'
37
+ }
38
+ inputWithPicklistEl.required = true
39
+ inputWithPicklistEl.label = {
40
+ picklist: 'Currency',
41
+ input: 'Price'
42
+ }
43
+ inputWithPicklistEl.value = {
44
+ picklist: 'eur',
45
+ input: '100'
46
+ }
47
+ inputWithPicklistEl.showDropdownAsModal
48
+ inputWithPicklistEl.placeholder = {
49
+ picklist: 'Currency',
50
+ input: 'Price'
51
+ }
52
+ inputWithPicklistEl.minValue = '100'
53
+ inputWithPicklistEl.maxValue = '1000'
54
+ inputWithPicklistEl.maxLength = '4000'
55
+ inputWithPicklistEl.regExp = '^([0-9]{1,1}||([1-9]{1,1}[0-9]{1,9}))$'
56
+ inputWithPicklistEl.errorMessage = 'Error message Mounthly Sequrity'
57
+ inputWithPicklistEl.options = [
58
+ { label: 'Euro', value: 'eur' },
59
+ { label: 'Dollar', value: 'usd' }
60
+ ]
61
+
62
+ document.body.appendChild(inputWithPicklistEl)
63
+ await expect(inputWithPicklistEl.firstChild.classList).toContain(
64
+ 'flt-input-with-picklist_success'
65
+ )
66
+
67
+ const picklistEl = inputWithPicklistEl.querySelector('flt-picklist')
68
+ picklistEl.firstChild.focus()
69
+ return Promise.resolve().then(async () => {
70
+ const dropDownEl = picklistEl.querySelector('.flt-picklist__dropdown')
71
+ await expect(dropDownEl).toBeTruthy()
72
+ const options = dropDownEl.querySelectorAll('.flt-picklist__option')
73
+ options[options.length - 1].click()
74
+ inputWithPicklistEl.dispatchEvent(new CustomEvent('change'))
75
+ return Promise.resolve().then(async () => {
76
+ const data = inputWithPicklistEl.getData()
77
+ await expect(data.value.picklist).toBe('usd')
78
+ const inputEl = inputWithPicklistEl.querySelector('input')
79
+ inputEl.focus()
80
+ inputEl.value = '120'
81
+ inputEl.dispatchEvent(new CustomEvent('input'))
82
+ return Promise.resolve().then(async () => {
83
+ await expect(inputWithPicklistEl.getData().isValid).toBeTruthy()
84
+ await expect(inputWithPicklistEl.getData().value.input).toBe('120')
85
+ })
86
+ })
87
+ })
88
+ })
89
+
90
+ it('flt-input-with-picklist disabled', async () => {
91
+ const inputWithPicklistEl = createElement('flt-input-phone', { is: InputWithPicklist })
92
+
93
+ inputWithPicklistEl.name = {
94
+ picklist: 'currency',
95
+ input: 'price'
96
+ }
97
+ inputWithPicklistEl.required = true
98
+ inputWithPicklistEl.disabled = true
99
+ inputWithPicklistEl.label = {
100
+ picklist: 'Currency',
101
+ input: 'Price'
102
+ }
103
+ inputWithPicklistEl.value = {
104
+ picklist: 'eur',
105
+ input: '100'
106
+ }
107
+ inputWithPicklistEl.showDropdownAsModal
108
+ inputWithPicklistEl.placeholder = {
109
+ picklist: 'Currency',
110
+ input: 'Price'
111
+ }
112
+ inputWithPicklistEl.minValue = '100'
113
+ inputWithPicklistEl.maxValue = '1000'
114
+ inputWithPicklistEl.maxLength = '40'
115
+ inputWithPicklistEl.regExp = '^([0-9]{1,1}||([1-9]{1,1}[0-9]{1,9}))$'
116
+ inputWithPicklistEl.errorMessage = 'Error message Mounthly Sequrity'
117
+ inputWithPicklistEl.options = [
118
+ { label: 'Euro', value: 'eur' },
119
+ { label: 'Dollar', value: 'usd' }
120
+ ]
121
+
122
+ document.body.appendChild(inputWithPicklistEl)
123
+ await expect(inputWithPicklistEl.firstChild.classList).toContain(
124
+ 'flt-input-with-picklist_disabled'
125
+ )
126
+
127
+ const picklistEl = inputWithPicklistEl.querySelector('flt-picklist')
128
+ return Promise.resolve().then(async () => {
129
+ inputWithPicklistEl.dispatchEvent(new CustomEvent('change'))
130
+ return Promise.resolve().then(async () => {
131
+ const data = inputWithPicklistEl.getData()
132
+ await expect(data.value.picklist).toBe('eur')
133
+ })
134
+ })
135
+ })
136
+
137
+ it('flt-input-with-picklist with empty value', async () => {
138
+ const inputWithPicklistEl = createElement('flt-input-phone', { is: InputWithPicklist })
139
+
140
+ inputWithPicklistEl.name = {
141
+ picklist: 'currency',
142
+ input: 'price'
143
+ }
144
+ inputWithPicklistEl.required = true
145
+ inputWithPicklistEl.label = {
146
+ picklist: 'Currency',
147
+ input: 'Price'
148
+ }
149
+
150
+ inputWithPicklistEl.showDropdownAsModal
151
+ inputWithPicklistEl.placeholder = {
152
+ picklist: 'Currency',
153
+ input: 'Price'
154
+ }
155
+ inputWithPicklistEl.minValue = '100'
156
+ inputWithPicklistEl.maxValue = '1000'
157
+ inputWithPicklistEl.maxLength = '4000'
158
+ inputWithPicklistEl.regExp = '^([0-9]{1,1}||([1-9]{1,1}[0-9]{1,9}))$'
159
+ inputWithPicklistEl.errorMessage = 'Error message Mounthly Sequrity'
160
+ inputWithPicklistEl.options = [
161
+ { label: 'Euro', value: 'eur' },
162
+ { label: 'Dollar', value: 'usd' }
163
+ ]
164
+
165
+ document.body.appendChild(inputWithPicklistEl)
166
+ await expect(inputWithPicklistEl.firstChild.classList).not.toContain(
167
+ 'flt-input-with-picklist_success'
168
+ )
169
+
170
+ inputWithPicklistEl.validate()
171
+ })
172
+
173
+ it('flt-input-with-picklist with incorrect value', async () => {
174
+ const inputWithPicklistEl = createElement('flt-input-phone', { is: InputWithPicklist })
175
+
176
+ inputWithPicklistEl.name = {
177
+ picklist: 'currency',
178
+ input: 'price'
179
+ }
180
+ inputWithPicklistEl.required = true
181
+ inputWithPicklistEl.label = {
182
+ picklist: 'Currency',
183
+ input: 'Price'
184
+ }
185
+
186
+ inputWithPicklistEl.value = {
187
+ picklist: 'eurInccorect',
188
+ input: ''
189
+ }
190
+
191
+ inputWithPicklistEl.showDropdownAsModal
192
+ inputWithPicklistEl.placeholder = {
193
+ picklist: 'Currency',
194
+ input: 'Price'
195
+ }
196
+ inputWithPicklistEl.minValue = '100'
197
+ inputWithPicklistEl.maxValue = '1000'
198
+ inputWithPicklistEl.maxLength = '5'
199
+ inputWithPicklistEl.regExp = '^([0-9]{1,1}||([1-9]{1,1}[0-9]{1,9}))$'
200
+ inputWithPicklistEl.errorMessage = 'Error message Mounthly Sequrity'
201
+ inputWithPicklistEl.options = [
202
+ { label: 'Euro', value: 'eur' },
203
+ { label: 'Dollar', value: 'usd' }
204
+ ]
205
+
206
+ document.body.appendChild(inputWithPicklistEl)
207
+ await expect(inputWithPicklistEl.firstChild.classList).not.toContain(
208
+ 'flt-input-with-picklist_success'
209
+ )
210
+
211
+ inputWithPicklistEl.validate()
212
+ inputWithPicklistEl.value = {
213
+ picklist: 'usd',
214
+ input: 'incorrectRegexp'
215
+ }
216
+
217
+ return Promise.resolve().then(async () => {
218
+ inputWithPicklistEl.validate()
219
+
220
+ inputWithPicklistEl.value = {
221
+ picklist: 'usd',
222
+ input: '32512512'
223
+ }
224
+ inputWithPicklistEl.validate()
225
+ })
226
+ })
227
+ })
@@ -0,0 +1,37 @@
1
+ <template lwc:render-mode="light">
2
+ <div class={inputStyle}>
3
+ <div class="flt-input-with-picklist__block">
4
+ <flt-picklist
5
+ class="flt-input-with-picklist__code"
6
+ placeholder={placeholder.picklist}
7
+ value={value.picklist}
8
+ label={label.picklist}
9
+ options={options}
10
+ disabled={disabled}
11
+ required={required}
12
+ onfocus={handleFocus}
13
+ onblur={handleBlur}
14
+ show-dropdown-as-modal={showDropdownAsModal}
15
+ modal-dimention-start={modalDimentionStart}
16
+ onchange={handleChanged}
17
+ name="picklist"></flt-picklist>
18
+ <flt-input-text
19
+ class="flt-input-with-picklist__input"
20
+ prefix={inputPrefix}
21
+ label={label.input}
22
+ value={value.input}
23
+ required={required}
24
+ disabled={disabled}
25
+ min-value={minValue}
26
+ max-value={maxValue}
27
+ max-length={maxLength}
28
+ reg-exp={regExp}
29
+ onfocus={handleFocus}
30
+ onchange={handleChanged}
31
+ onblur={handleBlur}
32
+ placeholder={placeholder.input}
33
+ name="input"></flt-input-text>
34
+ </div>
35
+ <div class="flt-input-with-picklist__error">{errorMessage}</div>
36
+ </div>
37
+ </template>
@@ -0,0 +1,148 @@
1
+ import { api } from 'lwc'
2
+ import { UserDataValidator } from 'fleetcor-lwc'
3
+ import './inputWithPicklist.scss'
4
+
5
+ export default class InputWithPicklist extends UserDataValidator {
6
+ @api picklistRight
7
+ @api errorMessage
8
+ @api placeholder
9
+ @api disabled
10
+ @api required
11
+ @api minValue
12
+ @api maxValue
13
+ @api maxLength
14
+ @api regExp
15
+ @api options
16
+ @api inputPrefix
17
+ @api showDropdownAsModal
18
+ @api modalDimentionStart = 1280
19
+ @api name = {
20
+ picklist: null,
21
+ input: null
22
+ }
23
+ @api value = {
24
+ picklist: null,
25
+ input: ''
26
+ }
27
+ @api label = {
28
+ picklist: '',
29
+ input: ''
30
+ }
31
+
32
+ touched
33
+ focused
34
+
35
+ @api validate() {
36
+ if (this.disabled) return
37
+ this.touched = true
38
+ this.error = !this.isValid()
39
+ }
40
+
41
+ @api isValid() {
42
+ let result = true
43
+ if (this.required) {
44
+ if (
45
+ this.regExp &&
46
+ this.value.input &&
47
+ !new RegExp(this.regExp).test(this.value.input)
48
+ ) {
49
+ result = false
50
+ } else if (!this.value.input) {
51
+ result = false
52
+ }
53
+
54
+ if (!this.value.picklist) {
55
+ result = false
56
+ }
57
+ }
58
+
59
+ if (
60
+ result &&
61
+ this.maxLength &&
62
+ this.value.input &&
63
+ this.value.input.length > parseInt(this.maxLength)
64
+ ) {
65
+ result = false
66
+ }
67
+
68
+ if (result && this.minValue) {
69
+ const numberValue = parseInt(this.value.input)
70
+ result = false
71
+ if (!isNaN(numberValue) && numberValue >= parseInt(this.minValue)) {
72
+ result = true
73
+ }
74
+ }
75
+
76
+ if (result && this.maxValue) {
77
+ const numberValue = parseInt(this.value.input)
78
+ result = false
79
+ if (!isNaN(numberValue) && numberValue <= parseInt(this.maxValue)) {
80
+ result = true
81
+ }
82
+ }
83
+
84
+ return result
85
+ }
86
+
87
+ @api getData(silent) {
88
+ return {
89
+ ...super.getData(silent),
90
+ modalDimentionStart: this.modalDimentionStart,
91
+ errorMessage: this.errorMessage,
92
+ placeholder: this.placeholder,
93
+ picklistRight: this.picklistRight,
94
+ maxValue: this.maxValue,
95
+ minValue: this.minValue,
96
+ regExp: this.regExp,
97
+ inputPrefix: this.inputPrefix,
98
+ showDropdownAsModal: this.showDropdownAsModal
99
+ }
100
+ }
101
+
102
+ handleFocus() {
103
+ this.focused = true
104
+ this.touched = true
105
+ }
106
+
107
+ handleBlur() {
108
+ this.focused = false
109
+ }
110
+
111
+ connectedCallback() {
112
+ if (this.value.picklist) {
113
+ const foundedOption = this.options.find((opt) => opt.value == this.value.picklist)
114
+ if (!foundedOption) {
115
+ console.log(
116
+ 'Warning:',
117
+ `Option value "${this.value.picklist}" no available in picklist options`
118
+ )
119
+ this.value = {
120
+ input: this.value.input,
121
+ picklist: ''
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ get inputStyle() {
128
+ return this.generateClassNameList({
129
+ 'flt-input-with-picklist': true,
130
+ 'flt-input-with-picklist_right': this.picklistRight,
131
+ 'flt-input-with-picklist_disabled': this.disabled,
132
+ 'flt-input-with-picklist_active': this.focused,
133
+ 'flt-input-with-picklist_error': !this.focused && this.touched && !this.isValid(),
134
+ 'flt-input-with-picklist_success': this.isValid()
135
+ })
136
+ }
137
+
138
+ handleChanged(event) {
139
+ if (!this.disabled) {
140
+ this.value = { ...this.value, [event.detail.name]: event.detail.value }
141
+ this.dispatchEvent(
142
+ new CustomEvent('change', {
143
+ detail: this.getData()
144
+ })
145
+ )
146
+ }
147
+ }
148
+ }
@@ -0,0 +1,109 @@
1
+ .flt-input-with-picklist {
2
+ --flt-picklist-view-border-color-selected: #6b7280;
3
+ --flt-input-border-color-success: #6b7280;
4
+ --flt-input-border-color-error: #6b7280;
5
+
6
+ &_error {
7
+ .flt-input-with-picklist__error {
8
+ line-height: 1.5;
9
+ opacity: 1;
10
+ }
11
+ .flt-picklist__wrapp,
12
+ .flt-input-text__wrapp {
13
+ border-color: var(--flt-input-with-picklist-border-color-error, #ed123d);
14
+ }
15
+ }
16
+
17
+ &_success {
18
+ .flt-picklist__wrapp,
19
+ .flt-input-text__wrapp {
20
+ border-color: var(--flt-input-with-picklist-border-color-success, #59eb9c);
21
+ }
22
+ }
23
+
24
+ &_right {
25
+ .flt-input-with-picklist__block {
26
+ flex-direction: row-reverse;
27
+ }
28
+
29
+ .flt-input-text__wrapp {
30
+ border-bottom-right-radius: 0;
31
+ border-top-right-radius: 0;
32
+ border-right: 0;
33
+ }
34
+
35
+ .flt-picklist__wrapp {
36
+ border-bottom-left-radius: 0;
37
+ border-top-left-radius: 0;
38
+ border-left: 0;
39
+ padding-left: 0;
40
+ }
41
+ }
42
+
43
+ &__block {
44
+ display: flex;
45
+ align-items: start;
46
+ background-color: #ffffff;
47
+ position: relative;
48
+ }
49
+
50
+ &__input {
51
+ flex-grow: 1;
52
+ position: relative;
53
+ z-index: 2;
54
+ }
55
+
56
+ &__code {
57
+ flex-shrink: 0;
58
+ position: relative;
59
+ z-index: 1;
60
+ }
61
+
62
+ &__error {
63
+ opacity: 0;
64
+ font-size: 12px;
65
+ line-height: 0;
66
+ color: var(--flt-input-with-picklist-border-color-error, #ed123d);
67
+ transition: all 0.3s;
68
+
69
+ &:empty {
70
+ display: none;
71
+ }
72
+ }
73
+
74
+ &:not(.flt-input-with-picklist_right) {
75
+ .flt-input-text__wrapp {
76
+ border-bottom-left-radius: 0;
77
+ border-top-left-radius: 0;
78
+ border-left: 0;
79
+ }
80
+
81
+ .flt-picklist__wrapp {
82
+ border-bottom-right-radius: 0;
83
+ border-top-right-radius: 0;
84
+ border-right: 0;
85
+ padding-right: 0;
86
+ }
87
+ }
88
+
89
+ .flt-picklist__dropdown-container,
90
+ .flt-input-with-picklist__code,
91
+ .flt-picklist_active {
92
+ position: initial;
93
+ }
94
+
95
+ .flt-picklist__dropdown {
96
+ top: 32px;
97
+ }
98
+
99
+ .flt-modal {
100
+ .flt-picklist__dropdown {
101
+ top: initial;
102
+ }
103
+ }
104
+
105
+ [user-data-modal='true'] + .flt-input-with-picklist__input {
106
+ position: initial;
107
+ z-index: initial;
108
+ }
109
+ }
@@ -7,6 +7,9 @@
7
7
  .flt-picklist__view-arrow {
8
8
  transform: scale(-1);
9
9
  }
10
+ .flt-picklist__wrapp {
11
+ position: relative;
12
+ }
10
13
  }
11
14
 
12
15
  &_selected {
@@ -57,7 +60,6 @@
57
60
  padding: var(--flt-picklist-wrapper-padding, 0 16px);
58
61
  transition: all 0.3s;
59
62
  cursor: pointer;
60
- position: relative;
61
63
  z-index: 1;
62
64
  }
63
65
 
@@ -72,6 +74,10 @@
72
74
  opacity: 1;
73
75
  line-height: 1.5;
74
76
  }
77
+
78
+ &:empty {
79
+ display: none;
80
+ }
75
81
  }
76
82
 
77
83
  &__placeholder {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetcor-lwc",
3
- "version": "3.8.6",
3
+ "version": "3.9.0",
4
4
  "description": "LWC framework by Fleetcor",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,6 +33,7 @@
33
33
  "flt/inputText",
34
34
  "flt/inputEmail",
35
35
  "flt/inputPhone",
36
+ "flt/inputWithPicklist",
36
37
  "flt/picklist",
37
38
  "flt/modal",
38
39
  "flt/radioGroup",