fleetcor-lwc 3.6.3 → 3.8.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.
@@ -40,7 +40,7 @@ export default class InputText extends InputElement {
40
40
  'flt-input-text': true,
41
41
  'flt-input-text_disabled': this.disabled,
42
42
  'flt-input-text_active': this.value || this.focused || this.placeholderVisible,
43
- 'flt-input-text_error': this.touched && !this.isValid(),
43
+ 'flt-input-text_error': !this.focused && this.touched && !this.isValid(),
44
44
  'flt-input-text_success': this.value && this.isValid()
45
45
  })
46
46
  }
@@ -50,7 +50,7 @@ export default class InputText extends InputElement {
50
50
  if (this.disabled) return
51
51
  this.focused = true
52
52
  this.dispatchEvent(
53
- new CustomEvent('focus_happend', {
53
+ new CustomEvent('focus', {
54
54
  detail: null,
55
55
  cancelable: true,
56
56
  bubbles: true
@@ -66,7 +66,7 @@ export default class InputText extends InputElement {
66
66
  this.value = (event.target.value || '').trimEnd()
67
67
  event.target.value = this.value
68
68
  this.dispatchEvent(
69
- new CustomEvent('blur_happend', {
69
+ new CustomEvent('blur', {
70
70
  detail: null,
71
71
  cancelable: true,
72
72
  bubbles: true
@@ -5,7 +5,7 @@
5
5
  cursor: pointer;
6
6
 
7
7
  &__prefix {
8
- padding-right: 2px;
8
+ flex-shrink: 0;
9
9
  }
10
10
 
11
11
  &_disabled {
@@ -32,6 +32,8 @@
32
32
  &_activate {
33
33
  .flt-input-text__input-block {
34
34
  display: flex;
35
+ align-items: center;
36
+ gap: var(--flt-input-prefix-gap, 8px);
35
37
  height: 20px;
36
38
  opacity: 1;
37
39
  }
@@ -48,11 +50,11 @@
48
50
 
49
51
  &_error {
50
52
  .flt-input-text__wrapp {
51
- border-color: #ef4444;
53
+ border-color: var(--flt-input-border-color-error, #ed123d);
52
54
  }
53
55
 
54
56
  .flt-input-text__error {
55
- height: 16px;
57
+ line-height: 1.5;
56
58
  opacity: 1;
57
59
  }
58
60
  }
@@ -96,12 +98,10 @@
96
98
  }
97
99
 
98
100
  &__error {
99
- height: 0;
101
+ line-height: 0;
100
102
  opacity: 0;
101
- margin-top: 4px;
102
103
  font-size: 12px;
103
- line-height: 16px;
104
- color: #ef4444;
104
+ color: var(--flt-input-border-color-error, #ed123d);
105
105
  transition: all 0.3s;
106
106
  }
107
107
 
@@ -0,0 +1,135 @@
1
+ import { createElement } from 'lwc'
2
+ import Picklist from 'flt/picklist'
3
+
4
+ Object.defineProperty(window, 'matchMedia', {
5
+ writable: true,
6
+ value: jest.fn().mockImplementation((query) => ({
7
+ matches: false
8
+ // media: query,
9
+ // onchange: null,
10
+ // addListener: jest.fn(), // Deprecated
11
+ // removeListener: jest.fn(), // Deprecated
12
+ // addEventListener: jest.fn(),
13
+ // removeEventListener: jest.fn(),
14
+ // dispatchEvent: jest.fn()
15
+ }))
16
+ })
17
+
18
+ describe('flt-picklist', () => {
19
+ afterEach(() => {
20
+ while (document.body.firstChild) {
21
+ document.body.removeChild(document.body.firstChild)
22
+ }
23
+ })
24
+
25
+ it('base test', async () => {
26
+ const picklistEl = createElement('flt-picklist', { is: Picklist })
27
+ picklistEl.errorMessage = 'Error message'
28
+ picklistEl.required = true
29
+ picklistEl.options = [
30
+ {
31
+ label: 'Man',
32
+ value: 'man'
33
+ },
34
+ {
35
+ label: 'Woman',
36
+ value: 'woman'
37
+ }
38
+ ]
39
+ picklistEl.name = 'sex'
40
+ document.body.appendChild(picklistEl)
41
+ await expect(picklistEl.firstChild.classList).toContain('flt-picklist')
42
+ picklistEl.firstChild.focus()
43
+
44
+ return Promise.resolve().then(async () => {
45
+ const dropDownEl = picklistEl.querySelector('.flt-picklist__dropdown')
46
+ await expect(dropDownEl).toBeTruthy()
47
+ dropDownEl.querySelector('.flt-picklist__option').click()
48
+
49
+ return Promise.resolve().then(async () => {
50
+ const data = picklistEl.getData()
51
+ await expect(data.value).toBe('man')
52
+ })
53
+ })
54
+ })
55
+
56
+ it('disabled test', async () => {
57
+ const picklistEl = createElement('flt-picklist', { is: Picklist })
58
+ picklistEl.errorMessage = 'Error message'
59
+ picklistEl.required = true
60
+ picklistEl.disabled = true
61
+ picklistEl.options = [
62
+ {
63
+ label: 'Man',
64
+ value: 'man'
65
+ },
66
+ {
67
+ label: 'Woman',
68
+ value: 'woman'
69
+ }
70
+ ]
71
+ picklistEl.name = 'sex'
72
+ document.body.appendChild(picklistEl)
73
+ await expect(picklistEl.firstChild.classList).toContain('flt-picklist')
74
+ picklistEl.firstChild.focus()
75
+
76
+ return Promise.resolve().then(async () => {
77
+ const dropDownEl = picklistEl.querySelector('.flt-picklist__dropdown')
78
+ await expect(dropDownEl).toBeFalsy()
79
+ })
80
+ })
81
+
82
+ it('modal test', async () => {
83
+ const picklistEl = createElement('flt-picklist', { is: Picklist })
84
+ picklistEl.errorMessage = 'Error message'
85
+ picklistEl.placeholder = 'Sex'
86
+ picklistEl.required = true
87
+ picklistEl.showDropdownAsModal = true
88
+ picklistEl.options = [
89
+ {
90
+ label: 'Man',
91
+ value: 'man'
92
+ },
93
+ {
94
+ label: 'Woman',
95
+ value: 'woman'
96
+ }
97
+ ]
98
+ picklistEl.name = 'sex'
99
+ document.body.appendChild(picklistEl)
100
+ await expect(picklistEl.firstChild.classList).toContain('flt-picklist')
101
+ picklistEl.firstChild.focus()
102
+
103
+ return Promise.resolve().then(async () => {
104
+ const dropDownEl = picklistEl.querySelector('.flt-picklist__dropdown')
105
+ await expect(dropDownEl).toBeTruthy()
106
+ dropDownEl.querySelector('.flt-picklist__option').click()
107
+ picklistEl.firstChild.blur()
108
+
109
+ return Promise.resolve().then(async () => {
110
+ const data = picklistEl.getData()
111
+ await expect(data.value).toBe('man')
112
+ picklistEl.firstChild.focus()
113
+ return Promise.resolve().then(async () => {
114
+ await expect(picklistEl.firstChild.classList).toContain('flt-picklist_modal')
115
+ const modalEl = document.body.querySelector('flt-modal')
116
+ await expect(modalEl).toBeTruthy()
117
+ const closeButtonEl = modalEl.querySelector(
118
+ '.flt-picklist__modal-header-close-button'
119
+ )
120
+ const clickEvent = new MouseEvent('click', {
121
+ bubbles: true,
122
+ cancelable: true,
123
+ view: window
124
+ })
125
+
126
+ closeButtonEl.dispatchEvent(clickEvent)
127
+ return Promise.resolve().then(async () => {
128
+ const modalEl = picklistEl.querySelector('flt-modal')
129
+ await expect(modalEl).toBeFalsy()
130
+ })
131
+ })
132
+ })
133
+ })
134
+ })
135
+ })
@@ -0,0 +1,45 @@
1
+ <template lwc:render-mode="light">
2
+ <div class={computedStyles} tabindex="0" onfocus={handleShowView} onblur={handleHideView}>
3
+ <div class="flt-picklist__wrapp">
4
+ <div class="flt-picklist__wrapp-text">
5
+ <div class="flt-picklist__placeholder">{placeholder}</div>
6
+ <div class="flt-picklist__value" lwc:inner-html={displayLabel}></div>
7
+ </div>
8
+ <svg
9
+ width="24"
10
+ height="24"
11
+ viewBox="0 0 24 24"
12
+ fill="none"
13
+ class="flt-picklist__view-arrow">
14
+ <path
15
+ d="M19 9L12 16L5 9"
16
+ stroke-width="2"
17
+ stroke-linecap="round"
18
+ stroke-linejoin="round"
19
+ class="flt-picklist__view-arrow-path"></path>
20
+ </svg>
21
+ </div>
22
+ <div class="flt-picklist__dropdown-container">
23
+ <div lwc:if={showOptions} class="flt-picklist__dropdown">
24
+ <template for:each={optionsToDisplay} for:item="option">
25
+ <div
26
+ lwc:if={option.selected}
27
+ key={option.value}
28
+ onclick={handleChange}
29
+ data-value={option.value}
30
+ class="flt-picklist__option flt-picklist__option_selected"
31
+ lwc:inner-html={option.label}></div>
32
+ <div
33
+ lwc:else
34
+ onclick={handleChange}
35
+ key={option.value}
36
+ data-value={option.value}
37
+ class="flt-picklist__option"
38
+ lwc:inner-html={option.label}></div>
39
+ </template>
40
+ </div>
41
+ </div>
42
+
43
+ <div class={computedErrorMessage}>{errorMessage}</div>
44
+ </div>
45
+ </template>
@@ -0,0 +1,127 @@
1
+ import { api, setHooks } from 'lwc'
2
+ import { SelectElement } from 'fleetcor-lwc'
3
+ import './picklist.scss'
4
+ import picklistModal from './picklistModal.html'
5
+ import picklist from './picklist.html'
6
+
7
+ setHooks({
8
+ sanitizeHtmlContent(content) {
9
+ return content
10
+ }
11
+ })
12
+
13
+ export default class Picklist extends SelectElement {
14
+ error
15
+ showOptions
16
+ isDesktop
17
+
18
+ @api errorMessage
19
+ @api placeholder
20
+ @api prefix
21
+ @api showDropdownAsModal
22
+ @api modalDimentionStart = 1280
23
+
24
+ render() {
25
+ let result = picklist
26
+ if (this.showDropdownAsModal && !this.isDesktop) {
27
+ result = picklistModal
28
+ }
29
+ return result
30
+ }
31
+
32
+ @api validate() {
33
+ this.error = !this.isValid()
34
+ }
35
+
36
+ get displayLabel() {
37
+ return this.optionsToDisplay.find((item) => item.selected)?.label || ''
38
+ }
39
+
40
+ connectedCallback() {
41
+ if (this.showDropdownAsModal) {
42
+ this.handleResize()
43
+ window.addEventListener('resize', this.handleResize.bind(this))
44
+ }
45
+ }
46
+
47
+ disconnectedCallback() {
48
+ if (this.showDropdownAsModal) {
49
+ window.removeEventListener('resize', this.handleResize.bind(this))
50
+ }
51
+ }
52
+
53
+ handleResize() {
54
+ this.isDesktop = window.matchMedia(`(min-width: ${this.modalDimentionStart}px)`).matches
55
+ }
56
+
57
+ handleHideView(event) {
58
+ event.stopPropagation()
59
+ if (!this.disabled) {
60
+ this.showOptions = false
61
+ }
62
+ this.dispatchEvent(
63
+ new CustomEvent('blur', {
64
+ detail: null,
65
+ cancelable: true,
66
+ bubbles: true
67
+ })
68
+ )
69
+ }
70
+
71
+ handleCloseModal() {
72
+ this.querySelector('.flt-picklist').blur()
73
+ }
74
+
75
+ handleShowView(event) {
76
+ event.stopPropagation()
77
+ if (!this.disabled) {
78
+ this.showOptions = true
79
+ }
80
+ this.dispatchEvent(
81
+ new CustomEvent('focus', {
82
+ detail: null,
83
+ cancelable: true,
84
+ bubbles: true
85
+ })
86
+ )
87
+ }
88
+
89
+ handleChange(event) {
90
+ event.stopPropagation()
91
+ if (!this.disabled) {
92
+ this.value = event.currentTarget.dataset.value
93
+ this.dispatchEvent(
94
+ new CustomEvent('change', {
95
+ detail: this.getData()
96
+ })
97
+ )
98
+
99
+ this.querySelector('.flt-picklist').blur()
100
+ }
101
+ }
102
+
103
+ get computedStyles() {
104
+ return this.generateClassNameList({
105
+ 'flt-picklist': true,
106
+ 'flt-picklist_disabled': this.disabled,
107
+ 'flt-picklist_active': this.showOptions,
108
+ 'flt-picklist_selected': this.value,
109
+ 'flt-picklist_modal': this.showDropdownAsModal && this.showOptions && !this.isDesktop
110
+ })
111
+ }
112
+
113
+ get computedErrorMessage() {
114
+ return this.generateClassNameList({
115
+ 'flt-picklist__error-message': true,
116
+ 'flt-picklist__error-message_active': this.error
117
+ })
118
+ }
119
+
120
+ renderedCallback() {
121
+ super.renderedCallback()
122
+ this.setAttribute(
123
+ 'user-data-modal',
124
+ !!(this.showDropdownAsModal && this.showOptions && !this.isDesktop)
125
+ )
126
+ }
127
+ }
@@ -0,0 +1,186 @@
1
+ .flt-picklist {
2
+ outline: none;
3
+
4
+ &_active {
5
+ position: relative;
6
+ z-index: 10000;
7
+ .flt-picklist__view-arrow {
8
+ transform: scale(-1);
9
+ }
10
+ }
11
+
12
+ &_selected {
13
+ .flt-picklist__wrapp {
14
+ border-color: var(--flt-picklist-view-border-color-selected, #59eb9c);
15
+ }
16
+
17
+ .flt-picklist__placeholder {
18
+ font-size: var(--flt-picklist-placeholder-activate-fz, 12px);
19
+ line-height: var(--flt-picklist-placeholder-activate-lh, 16px);
20
+ }
21
+ }
22
+
23
+ &_disabled {
24
+ color: #d1d5db;
25
+
26
+ .flt-picklist__wrapp {
27
+ border-color: #d1d5db !important;
28
+ background: #f9fafb !important;
29
+ cursor: not-allowed;
30
+ }
31
+
32
+ .flt-picklist__view-arrow {
33
+ opacity: 0.25;
34
+ }
35
+ }
36
+
37
+ &_modal {
38
+ position: initial;
39
+ z-index: initial;
40
+
41
+ .flt-picklist__wrapp {
42
+ position: initial;
43
+ z-index: initial;
44
+ }
45
+ }
46
+
47
+ &__wrapp {
48
+ background-color: var(--flt-picklist-bgc, #ffffff);
49
+ border: var(--flt-picklist-border, 1px solid #6b7280);
50
+ border-radius: var(--flt-picklist-border-radius, 12px);
51
+ overflow: hidden;
52
+ height: var(--flt-picklist-wrapper-height, 44px);
53
+ display: flex;
54
+ justify-content: space-between;
55
+ gap: 12px;
56
+ align-items: center;
57
+ padding: var(--flt-picklist-wrapper-padding, 0 16px);
58
+ transition: all 0.3s;
59
+ cursor: pointer;
60
+ position: relative;
61
+ z-index: 1;
62
+ }
63
+
64
+ &__error-message {
65
+ color: var(--flt-picklist-error-color, #ed123d);
66
+ opacity: 0;
67
+ line-height: 0;
68
+ transition: all 0.3s;
69
+ font-size: var(--flt-picklist-error-fz, 12px);
70
+
71
+ &_active {
72
+ opacity: 1;
73
+ line-height: 1.5;
74
+ }
75
+ }
76
+
77
+ &__placeholder {
78
+ transition: all 0.3s;
79
+ color: var(--flt-picklist-placeholder-color, #111827);
80
+ font-size: var(--flt-picklist-placeholder-fz, 16px);
81
+ line-height: var(--flt-picklist-placeholder-lh, 20px);
82
+ }
83
+
84
+ &__view-arrow-path {
85
+ stroke: var(--flt-picklist-view-arrow-path-stroke, #4c4c4c);
86
+ }
87
+
88
+ &__view-arrow {
89
+ transition: all 0.3s;
90
+ flex-shrink: 0;
91
+ }
92
+
93
+ &__dropdown-container {
94
+ position: relative;
95
+ }
96
+
97
+ &__dropdown {
98
+ position: absolute;
99
+ width: 100%;
100
+ top: -20px;
101
+ left: 0;
102
+ max-height: 240px;
103
+ border: var(--flt-picklist-dropdown-border, none);
104
+ overflow: auto;
105
+ background: var(--flt-picklist-dropdown-bgc, #ffffff);
106
+ box-shadow: 0px 30px 40px rgba(33, 46, 53, 0.3);
107
+ cursor: pointer;
108
+ border-bottom-left-radius: var(--flt-picklist-border-radius, 12px);
109
+ border-bottom-right-radius: var(--flt-picklist-border-radius, 12px);
110
+ animation: fadeIn 0.3s ease-in-out;
111
+ }
112
+
113
+ &__option {
114
+ display: block;
115
+ padding: var(--flt-picklist-option-padding, 12px 16px);
116
+ color: var(--flt-picklist-option-color, #4c4c4c);
117
+ user-select: none;
118
+ box-sizing: border-box;
119
+ border-bottom: 1px solid var(--flt-picklist-dropdown-option-border-bottom-color, #eeeeee);
120
+ position: relative;
121
+ line-height: 18px;
122
+
123
+ &:hover,
124
+ &_selected {
125
+ color: var(--flt-picklist-option-selected-color, #4c4c4c);
126
+ background: var(--flt-picklist-dropdown-option-bgc, #f2d400);
127
+ }
128
+
129
+ &:first-child {
130
+ padding: var(--flt-picklist-option-first-child-padding, 32px 16px 12px);
131
+ }
132
+
133
+ &:last-child {
134
+ border-bottom: none;
135
+ border-bottom-left-radius: var(--flt-picklist-border-radius, 12px);
136
+ border-bottom-right-radius: var(--flt-picklist-border-radius, 12px);
137
+ }
138
+ }
139
+
140
+ &__modal {
141
+ background-color: #fff;
142
+ overflow: hidden;
143
+ border-radius: var(--flt-picklist-border-radius, 12px);
144
+ width: 80vw;
145
+
146
+ .flt-picklist__dropdown {
147
+ position: relative;
148
+ top: initial;
149
+ left: initial;
150
+ animation: initial;
151
+ max-height: 80vh;
152
+ }
153
+
154
+ .flt-picklist__option {
155
+ &:first-child {
156
+ padding: var(--flt-picklist-option-padding, 12px 16px);
157
+ }
158
+ }
159
+ }
160
+
161
+ &__modal-header-close-button {
162
+ padding: 4px;
163
+ width: 16px;
164
+ height: 16px;
165
+ }
166
+
167
+ &__modal-header {
168
+ display: flex;
169
+ justify-content: space-between;
170
+ align-items: center;
171
+ font-weight: 700;
172
+ padding: 12px 16px;
173
+ background-color: var(--flt-picklist-dropdown-modal-header-bgc, #f3f4f6);
174
+ border-top-left-radius: var(--flt-picklist-border-radius, 12px);
175
+ border-top-right-radius: var(--flt-picklist-border-radius, 12px);
176
+ }
177
+ }
178
+
179
+ @keyframes fadeIn {
180
+ 0% {
181
+ opacity: 0;
182
+ }
183
+ 100% {
184
+ opacity: 100%;
185
+ }
186
+ }
@@ -0,0 +1,68 @@
1
+ <template lwc:render-mode="light">
2
+ <div class={computedStyles} tabindex="0" onfocus={handleShowView} onblur={handleHideView}>
3
+ <div class="flt-picklist__wrapp">
4
+ <div class="flt-picklist__wrapp-text">
5
+ <div class="flt-picklist__placeholder">{placeholder}</div>
6
+ <div class="flt-picklist__value" lwc:inner-html={displayLabel}></div>
7
+ </div>
8
+ <svg
9
+ width="24"
10
+ height="24"
11
+ viewBox="0 0 24 24"
12
+ fill="none"
13
+ class="flt-picklist__view-arrow">
14
+ <path
15
+ d="M19 9L12 16L5 9"
16
+ stroke-width="2"
17
+ stroke-linecap="round"
18
+ stroke-linejoin="round"
19
+ class="flt-picklist__view-arrow-path"></path>
20
+ </svg>
21
+ </div>
22
+ <div class="flt-picklist__dropdown-container">
23
+ <flt-modal lwc:if={showOptions} deactive-glass>
24
+ <div class="flt-picklist__modal">
25
+ <div class="flt-picklist__modal-header">
26
+ <div class="flt-picklist__modal-header-placeholder">{placeholder}:</div>
27
+ <svg
28
+ onclick={handleCloseModal}
29
+ class="flt-picklist__modal-header-close-button"
30
+ x="0px"
31
+ y="0px"
32
+ width="32px"
33
+ height="32px"
34
+ viewBox="0 0 612 612"
35
+ style="enable-background: new 0 0 612 612"
36
+ xml:space="preserve">
37
+ <polygon
38
+ points="612,36.004 576.521,0.603 306,270.608 35.478,0.603 0,36.004 270.522,306.011 0,575.997 35.478,611.397 306,341.411 576.521,611.397 612,575.997 341.459,306.011 "
39
+ data-original="#000000"
40
+ class="active-path"
41
+ data-old_color="#000000"
42
+ fill="#111827"></polygon>
43
+ </svg>
44
+ </div>
45
+ <div class="flt-picklist__dropdown">
46
+ <template for:each={optionsToDisplay} for:item="option">
47
+ <div
48
+ lwc:if={option.selected}
49
+ key={option.value}
50
+ onclick={handleChange}
51
+ data-value={option.value}
52
+ class="flt-picklist__option flt-picklist__option_selected"
53
+ lwc:inner-html={option.label}></div>
54
+ <div
55
+ lwc:else
56
+ onclick={handleChange}
57
+ key={option.value}
58
+ data-value={option.value}
59
+ class="flt-picklist__option"
60
+ lwc:inner-html={option.label}></div>
61
+ </template>
62
+ </div>
63
+ </div>
64
+ </flt-modal>
65
+ </div>
66
+ <div class={computedErrorMessage}>{errorMessage}</div>
67
+ </div>
68
+ </template>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetcor-lwc",
3
- "version": "3.6.3",
3
+ "version": "3.8.0",
4
4
  "description": "LWC framework by Fleetcor",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,6 +32,8 @@
32
32
  "flt/icon",
33
33
  "flt/inputText",
34
34
  "flt/inputEmail",
35
+ "flt/inputPhone",
36
+ "flt/picklist",
35
37
  "flt/modal",
36
38
  "flt/radioGroup",
37
39
  "flt/radioGroupIcon",
@@ -76,7 +78,6 @@
76
78
  "terser-webpack-plugin": "^5.3.16",
77
79
  "webpack": "^5.105.2",
78
80
  "webpack-cli": "^6.0.1",
79
- "webpack-dev-server": "^5.2.3",
80
- "imask": "^7.6.1"
81
+ "webpack-dev-server": "^5.2.3"
81
82
  }
82
83
  }