@crowdstrike/glide-core 0.29.2 → 0.30.1
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/dist/accordion.js +240 -1
- package/dist/accordion.styles.js +13 -7
- package/dist/button-group.button.js +143 -1
- package/dist/button-group.button.styles.js +43 -15
- package/dist/button-group.js +249 -1
- package/dist/button-group.styles.js +10 -5
- package/dist/button.js +206 -1
- package/dist/button.styles.js +12 -7
- package/dist/checkbox-group.js +479 -14
- package/dist/checkbox-group.styles.js +5 -2
- package/dist/checkbox.js +519 -32
- package/dist/checkbox.styles.js +10 -5
- package/dist/drawer.js +168 -1
- package/dist/drawer.styles.js +5 -2
- package/dist/dropdown.js +2423 -123
- package/dist/dropdown.option.js +536 -1
- package/dist/dropdown.option.styles.js +5 -2
- package/dist/dropdown.styles.js +15 -8
- package/dist/form-controls-layout.js +102 -1
- package/dist/form-controls-layout.styles.js +5 -2
- package/dist/icon-button.js +139 -1
- package/dist/icon-button.styles.js +19 -7
- package/dist/icons/checked.js +28 -1
- package/dist/icons/chevron.js +21 -1
- package/dist/icons/magnifying-glass.js +23 -1
- package/dist/icons/pencil.js +21 -1
- package/dist/icons/severity-critical.js +20 -1
- package/dist/icons/severity-informational.js +20 -1
- package/dist/icons/severity-medium.js +20 -1
- package/dist/icons/x.js +21 -1
- package/dist/inline-alert.js +118 -1
- package/dist/inline-alert.styles.js +5 -2
- package/dist/input.d.ts +8 -2
- package/dist/input.js +505 -41
- package/dist/input.styles.js +25 -4
- package/dist/label.js +303 -1
- package/dist/label.styles.js +11 -5
- package/dist/library/assert-slot.js +136 -1
- package/dist/library/expect-unhandled-rejection.js +14 -1
- package/dist/library/expect-window-error.js +26 -1
- package/dist/library/final.js +18 -1
- package/dist/library/form-control.js +1 -1
- package/dist/library/localize.js +10 -1
- package/dist/library/mouse.js +35 -1
- package/dist/library/on-resize.js +24 -1
- package/dist/library/required.js +35 -1
- package/dist/library/shadow-root-mode.js +4 -1
- package/dist/library/unique-id.js +3 -1
- package/dist/link.js +92 -1
- package/dist/link.styles.js +10 -5
- package/dist/menu.d.ts +3 -2
- package/dist/menu.js +1259 -1
- package/dist/menu.styles.js +35 -19
- package/dist/modal.d.ts +4 -0
- package/dist/modal.icon-button.js +60 -1
- package/dist/modal.icon-button.styles.js +5 -2
- package/dist/modal.js +473 -1
- package/dist/modal.styles.js +71 -22
- package/dist/option.d.ts +74 -0
- package/dist/option.js +498 -0
- package/dist/option.styles.js +140 -0
- package/dist/{menu.options.d.ts → options.d.ts} +5 -6
- package/dist/options.js +130 -0
- package/dist/options.styles.js +21 -0
- package/dist/popover.js +620 -1
- package/dist/popover.styles.js +11 -5
- package/dist/radio-group.js +624 -17
- package/dist/radio-group.radio.js +211 -1
- package/dist/radio-group.radio.styles.js +9 -4
- package/dist/radio-group.styles.js +5 -2
- package/dist/slider.js +1040 -61
- package/dist/slider.styles.js +9 -4
- package/dist/spinner.js +60 -1
- package/dist/spinner.styles.js +5 -2
- package/dist/split-button.js +116 -1
- package/dist/split-button.primary-button.js +100 -1
- package/dist/split-button.primary-button.styles.js +13 -6
- package/dist/split-button.primary-link.js +102 -1
- package/dist/split-button.secondary-button.d.ts +2 -3
- package/dist/split-button.secondary-button.js +121 -1
- package/dist/split-button.secondary-button.styles.js +12 -7
- package/dist/split-button.styles.js +9 -4
- package/dist/styles/focus-outline.js +9 -3
- package/dist/styles/fonts.css +6 -1
- package/dist/styles/opacity-and-scale-animation.js +6 -3
- package/dist/styles/skeleton.js +6 -3
- package/dist/styles/variables.css +410 -1
- package/dist/styles/visually-hidden.js +6 -3
- package/dist/tab.group.js +386 -1
- package/dist/tab.group.styles.js +5 -2
- package/dist/tab.js +133 -1
- package/dist/tab.panel.js +93 -1
- package/dist/tab.panel.styles.js +11 -5
- package/dist/tab.styles.js +9 -4
- package/dist/tag.js +207 -1
- package/dist/tag.styles.js +10 -5
- package/dist/textarea.js +353 -19
- package/dist/textarea.styles.js +23 -4
- package/dist/toast.js +130 -1
- package/dist/toast.toasts.js +248 -25
- package/dist/toast.toasts.styles.js +9 -4
- package/dist/toggle.js +178 -1
- package/dist/toggle.styles.js +25 -5
- package/dist/tooltip.container.js +130 -1
- package/dist/tooltip.container.styles.js +5 -2
- package/dist/tooltip.js +484 -1
- package/dist/tooltip.styles.js +21 -5
- package/dist/translations/en.js +36 -1
- package/dist/translations/fr.js +37 -1
- package/dist/translations/ja.js +37 -1
- package/package.json +8 -12
- package/dist/menu.button.d.ts +0 -42
- package/dist/menu.button.js +0 -1
- package/dist/menu.button.styles.js +0 -32
- package/dist/menu.link.d.ts +0 -44
- package/dist/menu.link.js +0 -1
- package/dist/menu.link.styles.js +0 -35
- package/dist/menu.options.js +0 -1
- package/dist/menu.options.styles.d.ts +0 -2
- package/dist/menu.options.styles.js +0 -20
- /package/dist/{menu.button.styles.d.ts → option.styles.d.ts} +0 -0
- /package/dist/{menu.link.styles.d.ts → options.styles.d.ts} +0 -0
package/dist/input.js
CHANGED
@@ -1,19 +1,185 @@
|
|
1
|
-
var __decorate
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
6
|
+
};
|
7
|
+
import './icon-button.js';
|
8
|
+
import './label.js';
|
9
|
+
import { html, LitElement, nothing } from 'lit';
|
10
|
+
import { classMap } from 'lit/directives/class-map.js';
|
11
|
+
import { createRef, ref } from 'lit/directives/ref.js';
|
12
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
13
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
14
|
+
import { styleMap } from 'lit/directives/style-map.js';
|
15
|
+
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
16
|
+
import { when } from 'lit/directives/when.js';
|
17
|
+
import packageJson from '../package.json' with { type: 'json' };
|
18
|
+
import { LocalizeController } from './library/localize.js';
|
19
|
+
import magnifyingGlassIcon from './icons/magnifying-glass.js';
|
20
|
+
import styles from './input.styles.js';
|
21
|
+
import xIcon from './icons/x.js';
|
22
|
+
import shadowRootMode from './library/shadow-root-mode.js';
|
23
|
+
import final from './library/final.js';
|
24
|
+
import required from './library/required.js';
|
25
|
+
/**
|
26
|
+
* @attr {string} label
|
27
|
+
* @attr {string} [aria-controls]
|
28
|
+
* @attr {'true'|'false'|null} [aria-expanded=null]
|
29
|
+
* @attr {'true'|'false'|null} [aria-haspopup=null]
|
30
|
+
* @attr {'on'|'off'|'none'|'sentences'|'words'|'characters'} [autocapitalize='on']
|
31
|
+
* @attr {'on'|'off'} [autocomplete='on']
|
32
|
+
* @attr {boolean} [clearable=false]
|
33
|
+
* @attr {boolean} [disabled=false]
|
34
|
+
* @attr {boolean} [hide-label=false]
|
35
|
+
* @attr {number} [maxlength]
|
36
|
+
* @attr {string} [name='']
|
37
|
+
* @attr {'horizontal'|'vertical'} [orientation='horizontal']
|
38
|
+
* @attr {boolean} [password-toggle=false] - For 'password' type, whether to show a button to toggle the password's visibility
|
39
|
+
* @attr {string} [pattern='']
|
40
|
+
* @attr {string} [placeholder]
|
41
|
+
* @attr {boolean} [readonly=false]
|
42
|
+
* @attr {boolean} [required=false]
|
43
|
+
* @attr {boolean} [spellcheck=false]
|
44
|
+
* @attr {string} [tooltip]
|
45
|
+
* @attr {'color'|'date'|'email'|'number'|'password'|'search'|'tel'|'text'|'time'|'url'} [type='text']
|
46
|
+
* @attr {string} [value='']
|
47
|
+
*
|
48
|
+
* @readonly
|
49
|
+
* @attr {string} [version]
|
50
|
+
*
|
51
|
+
* @slot {Element | string} [description] - Additional information or context
|
52
|
+
* @slot {Element} [prefix-icon] - An icon before the input field
|
53
|
+
* @slot {Element} [suffix-icon] - An icon after the input field
|
54
|
+
*
|
55
|
+
* @fires {Event} change
|
56
|
+
* @fires {Event} input
|
57
|
+
* @fires {Event} invalid
|
58
|
+
*
|
59
|
+
* @readonly
|
60
|
+
* @prop {HTMLFormElement | null} form
|
61
|
+
*
|
62
|
+
* @readonly
|
63
|
+
* @prop {ValidityState} validity
|
64
|
+
*
|
65
|
+
* @method checkValidity
|
66
|
+
* @returns boolean
|
67
|
+
*
|
68
|
+
* @method formAssociatedCallback
|
69
|
+
* @method formResetCallback
|
70
|
+
*
|
71
|
+
* @method reportValidity
|
72
|
+
* @returns boolean
|
73
|
+
*
|
74
|
+
* @method resetValidityFeedback
|
75
|
+
*
|
76
|
+
* @method setCustomValidity
|
77
|
+
* @param {string} message
|
78
|
+
*
|
79
|
+
* @method setValidity
|
80
|
+
* @param {ValidityStateFlags} [flags]
|
81
|
+
* @param {string} [message]
|
82
|
+
*/
|
83
|
+
let Input = class Input extends LitElement {
|
84
|
+
static { this.formAssociated = true; }
|
85
|
+
static { this.shadowRootOptions = {
|
86
|
+
...LitElement.shadowRootOptions,
|
87
|
+
mode: shadowRootMode,
|
88
|
+
delegatesFocus: true,
|
89
|
+
}; }
|
90
|
+
static { this.styles = styles; }
|
91
|
+
get form() {
|
92
|
+
return this.#internals.form;
|
93
|
+
}
|
94
|
+
get validity() {
|
95
|
+
if (this.pattern && this.pattern.length > 0) {
|
96
|
+
// A validation message is required but unused because we disable native validation
|
97
|
+
// feedback. And an empty string isn't allowed. Thus a single space.
|
98
|
+
this.#internals.setValidity({
|
99
|
+
customError: Boolean(this.validityMessage),
|
100
|
+
// Empty values do not trigger a pattern mismatch error to align
|
101
|
+
// with native behavior¹.
|
102
|
+
//
|
103
|
+
// When checking pattern validity like the native input element, we
|
104
|
+
// need to ensure it matches the entire string, not just a portion of it¹.
|
105
|
+
//
|
106
|
+
// The regex we use internally matches native's according to the documentation².
|
107
|
+
//
|
108
|
+
// 1: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern#constraint_validation
|
109
|
+
// 2: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern#overview
|
110
|
+
patternMismatch: Boolean(this.value &&
|
111
|
+
!new RegExp(`^(?:${this.pattern})$`, 'v').test(this.value)),
|
112
|
+
valueMissing: Boolean(this.required && !this.value),
|
113
|
+
}, ' ', this.#inputElementRef.value);
|
114
|
+
return this.#internals.validity;
|
115
|
+
}
|
116
|
+
if (!this.pattern && this.#internals.validity.patternMismatch) {
|
117
|
+
this.#internals.setValidity({});
|
118
|
+
return this.#internals.validity;
|
119
|
+
}
|
120
|
+
if (this.required && !this.value && !this.disabled) {
|
121
|
+
// A validation message is required but unused because we disable native validation
|
122
|
+
// feedback. And an empty string isn't allowed. Thus a single space.
|
123
|
+
this.#internals.setValidity({ customError: Boolean(this.validityMessage), valueMissing: true }, ' ', this.#inputElementRef.value);
|
124
|
+
return this.#internals.validity;
|
125
|
+
}
|
126
|
+
if (this.required && this.#internals.validity.valueMissing && this.value) {
|
127
|
+
this.#internals.setValidity({});
|
128
|
+
return this.#internals.validity;
|
129
|
+
}
|
130
|
+
if (!this.required &&
|
131
|
+
this.#internals.validity.valueMissing &&
|
132
|
+
!this.value) {
|
133
|
+
this.#internals.setValidity({});
|
134
|
+
return this.#internals.validity;
|
135
|
+
}
|
136
|
+
return this.#internals.validity;
|
137
|
+
}
|
138
|
+
checkValidity() {
|
139
|
+
this.isCheckingValidity = true;
|
140
|
+
const isValid = this.#internals.checkValidity();
|
141
|
+
this.isCheckingValidity = false;
|
142
|
+
return isValid;
|
143
|
+
}
|
144
|
+
disconnectedCallback() {
|
145
|
+
super.disconnectedCallback();
|
146
|
+
this.form?.removeEventListener('formdata', this.#onFormdata);
|
147
|
+
}
|
148
|
+
formAssociatedCallback() {
|
149
|
+
this.form?.addEventListener('formdata', this.#onFormdata);
|
150
|
+
}
|
151
|
+
formResetCallback() {
|
152
|
+
this.value = this.getAttribute('value') ?? '';
|
153
|
+
}
|
154
|
+
render() {
|
155
|
+
return html `
|
2
156
|
<glide-core-private-label
|
3
|
-
class=${classMap({
|
157
|
+
class=${classMap({
|
158
|
+
left: this.privateSplit === 'left',
|
159
|
+
middle: this.privateSplit === 'middle',
|
160
|
+
})}
|
4
161
|
label=${ifDefined(this.label)}
|
5
162
|
orientation=${this.orientation}
|
6
|
-
split=${ifDefined(this.privateSplit??
|
163
|
+
split=${ifDefined(this.privateSplit ?? undefined)}
|
7
164
|
tooltip=${ifDefined(this.tooltip)}
|
8
165
|
?disabled=${this.disabled}
|
9
|
-
?error=${this.#
|
166
|
+
?error=${this.#isShowValidationFeedback ||
|
167
|
+
this.#isMaxCharacterCountExceeded}
|
10
168
|
?hide=${this.hideLabel}
|
11
169
|
?required=${this.required}
|
12
170
|
>
|
13
171
|
<label for="input"> ${this.label} </label>
|
14
172
|
|
15
173
|
<div
|
16
|
-
class=${classMap({
|
174
|
+
class=${classMap({
|
175
|
+
'input-container': true,
|
176
|
+
focused: this.hasFocus,
|
177
|
+
empty: this.value === '',
|
178
|
+
disabled: this.disabled,
|
179
|
+
readonly: this.readonly && !this.disabled,
|
180
|
+
error: this.#isShowValidationFeedback ||
|
181
|
+
this.#isMaxCharacterCountExceeded,
|
182
|
+
})}
|
17
183
|
slot="control"
|
18
184
|
>
|
19
185
|
<slot name="prefix-icon">
|
@@ -24,55 +190,76 @@ var __decorate=this&&this.__decorate||function(t,e,i,s){var a,o=arguments.length
|
|
24
190
|
</slot>
|
25
191
|
|
26
192
|
<input
|
193
|
+
aria-controls=${ifDefined(this.ariaControls)}
|
27
194
|
aria-describedby="meta"
|
28
|
-
aria-
|
195
|
+
aria-expanded=${ifDefined(this.ariaExpanded ?? undefined)}
|
196
|
+
aria-haspopup=${ifDefined(this.ariaHasPopup ?? undefined)}
|
197
|
+
aria-invalid=${this.#isShowValidationFeedback ||
|
198
|
+
this.#isMaxCharacterCountExceeded}
|
199
|
+
autocapitalize=${this.autocapitalize}
|
200
|
+
autocomplete=${this.autocomplete}
|
29
201
|
class="input"
|
30
202
|
data-test="input"
|
31
203
|
id="input"
|
32
|
-
type=${"password"===this.type&&this.passwordVisible?"text":this.type}
|
33
|
-
.value=${this.value}
|
34
204
|
placeholder=${ifDefined(this.placeholder)}
|
35
|
-
autocapitalize=${this.autocapitalize}
|
36
|
-
autocomplete=${this.autocomplete}
|
37
205
|
spellcheck=${this.spellcheck}
|
206
|
+
type=${this.type === 'password' && this.passwordVisible
|
207
|
+
? 'text'
|
208
|
+
: this.type}
|
209
|
+
.value=${this.value}
|
38
210
|
?required=${this.required}
|
39
211
|
?readonly=${this.readonly}
|
40
212
|
?disabled=${this.disabled}
|
41
|
-
@focus=${this.#
|
42
|
-
@blur=${this.#
|
43
|
-
@change=${this.#
|
44
|
-
@input=${this.#
|
45
|
-
@keydown=${this.#
|
46
|
-
${ref(this.#
|
213
|
+
@focus=${this.#onInputFocus}
|
214
|
+
@blur=${this.#onInputBlur}
|
215
|
+
@change=${this.#onInputChange}
|
216
|
+
@input=${this.#onInputInput}
|
217
|
+
@keydown=${this.#onInputKeydown}
|
218
|
+
${ref(this.#inputElementRef)}
|
47
219
|
/>
|
48
220
|
|
49
|
-
${this.#
|
221
|
+
${this.#hasClearButton
|
222
|
+
? html `
|
50
223
|
<glide-core-icon-button
|
51
224
|
variant="tertiary"
|
52
|
-
class=${classMap({
|
225
|
+
class=${classMap({
|
226
|
+
'clear-icon-button': true,
|
227
|
+
'clear-icon-button--visible': this.#isClearButtonVisible,
|
228
|
+
})}
|
53
229
|
data-test="clear-button"
|
54
|
-
label=${this.#
|
55
|
-
|
230
|
+
label=${this.#localize.term('clearEntry',
|
231
|
+
// `this.label` is always defined because it's a required attribute.
|
232
|
+
//
|
233
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
234
|
+
this.label)}
|
235
|
+
@click=${this.#onClearButtonClick}
|
56
236
|
>
|
57
237
|
${xIcon}
|
58
238
|
</glide-core-icon-button>
|
59
|
-
|
60
|
-
|
239
|
+
`
|
240
|
+
: nothing}
|
241
|
+
${this.type === 'password' && this.passwordToggle && !this.disabled
|
242
|
+
? html `
|
61
243
|
<glide-core-icon-button
|
62
244
|
variant="tertiary"
|
63
245
|
class="password-toggle"
|
64
246
|
data-test="password-toggle"
|
65
|
-
label=${this.passwordVisible
|
247
|
+
label=${this.passwordVisible
|
248
|
+
? 'Hide password'
|
249
|
+
: 'Show password'}
|
66
250
|
aria-controls="input"
|
67
|
-
aria-expanded=${this.passwordVisible?
|
68
|
-
@click=${this.#
|
251
|
+
aria-expanded=${this.passwordVisible ? 'true' : 'false'}
|
252
|
+
@click=${this.#onPasswordToggle}
|
69
253
|
>
|
70
|
-
${this.passwordVisible?icons.eyeWithSlash:icons.eye}
|
254
|
+
${this.passwordVisible ? icons.eyeWithSlash : icons.eye}
|
71
255
|
</glide-core-icon-button>
|
72
|
-
|
256
|
+
`
|
257
|
+
: nothing}
|
73
258
|
|
74
259
|
<div class="suffix-icon">
|
75
|
-
${
|
260
|
+
${this.type === 'search'
|
261
|
+
? magnifyingGlassIcon
|
262
|
+
: html `
|
76
263
|
<slot name="suffix-icon">
|
77
264
|
<!--
|
78
265
|
An icon after the input field
|
@@ -85,7 +272,10 @@ var __decorate=this&&this.__decorate||function(t,e,i,s){var a,o=arguments.length
|
|
85
272
|
|
86
273
|
<div class="meta" id="meta" slot="description">
|
87
274
|
<slot
|
88
|
-
class=${classMap({
|
275
|
+
class=${classMap({
|
276
|
+
description: true,
|
277
|
+
hidden: Boolean(this.#isShowValidationFeedback && this.validityMessage),
|
278
|
+
})}
|
89
279
|
name="description"
|
90
280
|
>
|
91
281
|
<!--
|
@@ -94,12 +284,16 @@ var __decorate=this&&this.__decorate||function(t,e,i,s){var a,o=arguments.length
|
|
94
284
|
-->
|
95
285
|
</slot>
|
96
286
|
|
97
|
-
${when(this.#
|
287
|
+
${when(this.#isShowValidationFeedback && this.validityMessage, () => html `<span class="validity-message" data-test="validity-message"
|
98
288
|
>${unsafeHTML(this.validityMessage)}</span
|
99
|
-
>`)
|
100
|
-
${this.maxlength
|
289
|
+
>`)}
|
290
|
+
${this.maxlength
|
291
|
+
? html `
|
101
292
|
<div
|
102
|
-
class=${classMap({
|
293
|
+
class=${classMap({
|
294
|
+
'character-count': true,
|
295
|
+
error: this.#isMaxCharacterCountExceeded,
|
296
|
+
})}
|
103
297
|
data-test="character-count-container"
|
104
298
|
>
|
105
299
|
<!--
|
@@ -108,19 +302,284 @@ var __decorate=this&&this.__decorate||function(t,e,i,s){var a,o=arguments.length
|
|
108
302
|
more accesible, verbose description below.
|
109
303
|
-->
|
110
304
|
<span aria-hidden="true" data-test="character-count-text">
|
111
|
-
${this.#
|
305
|
+
${this.#localize.term('displayedCharacterCount', this.#valueCharacterCount, this.maxlength)}
|
112
306
|
</span>
|
113
307
|
|
114
308
|
<span class="hidden" data-test="character-count-announcement">
|
115
|
-
${this.#
|
309
|
+
${this.#localize.term('announcedCharacterCount', this.#valueCharacterCount, this.maxlength)}
|
116
310
|
</span>
|
117
311
|
</div>
|
118
|
-
|
312
|
+
`
|
313
|
+
: nothing}
|
119
314
|
</div>
|
120
315
|
</glide-core-private-label>
|
121
|
-
|
316
|
+
`;
|
317
|
+
}
|
318
|
+
reportValidity() {
|
319
|
+
this.isReportValidityOrSubmit = true;
|
320
|
+
const isValid = this.#internals.reportValidity();
|
321
|
+
// Ensures that getters referencing `this.validity.valid` are updated.
|
322
|
+
this.requestUpdate();
|
323
|
+
return isValid;
|
324
|
+
}
|
325
|
+
resetValidityFeedback() {
|
326
|
+
this.isReportValidityOrSubmit = false;
|
327
|
+
}
|
328
|
+
setCustomValidity(message) {
|
329
|
+
this.validityMessage = message;
|
330
|
+
if (message === '') {
|
331
|
+
this.#internals.setValidity({ customError: false }, '', this.#inputElementRef.value);
|
332
|
+
}
|
333
|
+
else {
|
334
|
+
// A validation message is required but unused because we disable native validation
|
335
|
+
// feedback. And an empty string isn't allowed. Thus a single space.
|
336
|
+
this.#internals.setValidity({
|
337
|
+
customError: true,
|
338
|
+
patternMismatch: this.#internals.validity.patternMismatch,
|
339
|
+
valueMissing: this.#internals.validity.valueMissing,
|
340
|
+
}, ' ', this.#inputElementRef.value);
|
341
|
+
}
|
342
|
+
}
|
343
|
+
setValidity(flags, message) {
|
344
|
+
this.validityMessage = message;
|
345
|
+
// A validation message is required but unused because we disable native validation
|
346
|
+
// feedback. And an empty string isn't allowed. Thus a single space.
|
347
|
+
this.#internals.setValidity(flags, ' ', this.#inputElementRef.value);
|
348
|
+
}
|
349
|
+
constructor() {
|
350
|
+
super();
|
351
|
+
this.ariaExpanded = null;
|
352
|
+
this.ariaHasPopup = null;
|
353
|
+
this.autocapitalize = 'on';
|
354
|
+
this.autocomplete = 'on';
|
355
|
+
this.clearable = false;
|
356
|
+
this.disabled = false;
|
357
|
+
this.hideLabel = false;
|
358
|
+
this.name = '';
|
359
|
+
this.orientation = 'horizontal';
|
360
|
+
/** For 'password' type, whether to show a button to toggle the password's visibility */
|
361
|
+
this.passwordToggle = false;
|
362
|
+
this.pattern = '';
|
363
|
+
this.readonly = false;
|
364
|
+
this.required = false;
|
365
|
+
// It's typed by TypeScript as a boolean. But we treat it as a string throughout.
|
366
|
+
this.spellcheck = false;
|
367
|
+
this.type = 'text';
|
368
|
+
// Intentionally not reflected to match native.
|
369
|
+
this.value = '';
|
370
|
+
this.version = packageJson.version;
|
371
|
+
this.hasFocus = false;
|
372
|
+
this.isBlurring = false;
|
373
|
+
this.isCheckingValidity = false;
|
374
|
+
this.isReportValidityOrSubmit = false;
|
375
|
+
this.passwordVisible = false;
|
376
|
+
this.#inputElementRef = createRef();
|
377
|
+
this.#localize = new LocalizeController(this);
|
378
|
+
this.#onFormdata = ({ formData }) => {
|
379
|
+
if (this.name && this.value && !this.disabled) {
|
380
|
+
formData.append(this.name, this.value);
|
381
|
+
}
|
382
|
+
};
|
383
|
+
this.#internals = this.attachInternals();
|
384
|
+
// Event handlers on the host aren't great because consumers can remove them.
|
385
|
+
// Unfortunately, the host is the only thing on which this event is dispatched
|
386
|
+
// because it's the host that is form-associated.
|
387
|
+
this.addEventListener('invalid', (event) => {
|
388
|
+
event?.preventDefault(); // Canceled so a native validation message isn't shown.
|
389
|
+
// We only want to focus the input if the "invalid" event resulted from either:
|
390
|
+
//
|
391
|
+
// 1. A form submission.
|
392
|
+
// 2. A call of `reportValidity()` that did not result from the input's "blur"
|
393
|
+
// event.
|
394
|
+
if (this.isCheckingValidity || this.isBlurring) {
|
395
|
+
return;
|
396
|
+
}
|
397
|
+
this.isReportValidityOrSubmit = true;
|
398
|
+
const isFirstInvalidFormElement = this.form?.querySelector(':invalid') === this;
|
399
|
+
if (isFirstInvalidFormElement) {
|
400
|
+
// - `this.#internals.delegatesFocus` is preferred because it's declarative. But
|
401
|
+
// it's limited to focusing the first focusable element. That doesn't work for
|
402
|
+
// us because our first focusable element is the tooltip when it's present.
|
403
|
+
//
|
404
|
+
// - Canceling this event means the input won't get focus, even if we were to use
|
405
|
+
// `this.#internals.delegatesFocus`.
|
406
|
+
//
|
407
|
+
// - The browser will ignore this if Input isn't the first invalid form control.
|
408
|
+
//
|
409
|
+
// TODO
|
410
|
+
// Try passing `focusVisible` after browsers support it. It may prevent the issue
|
411
|
+
// where the input itself has a focus outline after this call.
|
412
|
+
//
|
413
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#focusvisible
|
414
|
+
this.focus();
|
415
|
+
}
|
416
|
+
});
|
417
|
+
}
|
418
|
+
#inputElementRef;
|
419
|
+
#internals;
|
420
|
+
#localize;
|
421
|
+
get #hasClearButton() {
|
422
|
+
return this.clearable && !this.disabled && !this.readonly;
|
423
|
+
}
|
424
|
+
get #isClearButtonVisible() {
|
425
|
+
return this.#hasClearButton && this.value.length > 0;
|
426
|
+
}
|
427
|
+
get #valueCharacterCount() {
|
428
|
+
return this.value.length;
|
429
|
+
}
|
430
|
+
#onFormdata;
|
431
|
+
get #isMaxCharacterCountExceeded() {
|
432
|
+
return Boolean(!this.disabled &&
|
433
|
+
!this.readonly &&
|
434
|
+
this.maxlength &&
|
435
|
+
this.#valueCharacterCount > this.maxlength);
|
436
|
+
}
|
437
|
+
get #isShowValidationFeedback() {
|
438
|
+
return (!this.disabled && !this.validity?.valid && this.isReportValidityOrSubmit);
|
439
|
+
}
|
440
|
+
#onClearButtonClick(event) {
|
441
|
+
this.value = '';
|
442
|
+
this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
443
|
+
this.#inputElementRef.value?.focus();
|
444
|
+
event.stopPropagation();
|
445
|
+
}
|
446
|
+
#onInputBlur() {
|
447
|
+
this.isBlurring = true;
|
448
|
+
this.reportValidity();
|
449
|
+
this.isBlurring = false;
|
450
|
+
this.hasFocus = false;
|
451
|
+
}
|
452
|
+
#onInputChange() {
|
453
|
+
if (this.#inputElementRef.value?.value) {
|
454
|
+
this.value = this.#inputElementRef.value?.value;
|
455
|
+
}
|
456
|
+
// Unlike "input" events, "change" events aren't composed. So we have to
|
457
|
+
// manually dispatch them.
|
458
|
+
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
459
|
+
}
|
460
|
+
#onInputFocus() {
|
461
|
+
this.hasFocus = true;
|
462
|
+
}
|
463
|
+
#onInputInput() {
|
464
|
+
if (this.#inputElementRef.value) {
|
465
|
+
this.value = this.#inputElementRef.value.value;
|
466
|
+
}
|
467
|
+
}
|
468
|
+
#onInputKeydown(event) {
|
469
|
+
if (event.key === 'Enter') {
|
470
|
+
this.form?.requestSubmit();
|
471
|
+
}
|
472
|
+
}
|
473
|
+
#onPasswordToggle() {
|
474
|
+
this.passwordVisible = !this.passwordVisible;
|
475
|
+
}
|
476
|
+
};
|
477
|
+
__decorate([
|
478
|
+
property({ reflect: true }),
|
479
|
+
required
|
480
|
+
], Input.prototype, "label", void 0);
|
481
|
+
__decorate([
|
482
|
+
property({ attribute: 'aria-controls', reflect: true })
|
483
|
+
], Input.prototype, "ariaControls", void 0);
|
484
|
+
__decorate([
|
485
|
+
property({ attribute: 'aria-expanded', reflect: true })
|
486
|
+
], Input.prototype, "ariaExpanded", void 0);
|
487
|
+
__decorate([
|
488
|
+
property({ attribute: 'aria-haspopup', reflect: true })
|
489
|
+
], Input.prototype, "ariaHasPopup", void 0);
|
490
|
+
__decorate([
|
491
|
+
property({ reflect: true, useDefault: true })
|
492
|
+
], Input.prototype, "autocapitalize", void 0);
|
493
|
+
__decorate([
|
494
|
+
property({ reflect: true, useDefault: true })
|
495
|
+
], Input.prototype, "autocomplete", void 0);
|
496
|
+
__decorate([
|
497
|
+
property({ reflect: true, type: Boolean })
|
498
|
+
], Input.prototype, "clearable", void 0);
|
499
|
+
__decorate([
|
500
|
+
property({ reflect: true, type: Boolean })
|
501
|
+
], Input.prototype, "disabled", void 0);
|
502
|
+
__decorate([
|
503
|
+
property({ attribute: 'hide-label', reflect: true, type: Boolean })
|
504
|
+
], Input.prototype, "hideLabel", void 0);
|
505
|
+
__decorate([
|
506
|
+
property({
|
507
|
+
type: Number,
|
508
|
+
converter(value) {
|
509
|
+
return value && Number.parseInt(value, 10);
|
510
|
+
},
|
511
|
+
reflect: true,
|
512
|
+
})
|
513
|
+
], Input.prototype, "maxlength", void 0);
|
514
|
+
__decorate([
|
515
|
+
property({ reflect: true, useDefault: true })
|
516
|
+
], Input.prototype, "name", void 0);
|
517
|
+
__decorate([
|
518
|
+
property({ reflect: true, useDefault: true })
|
519
|
+
], Input.prototype, "orientation", void 0);
|
520
|
+
__decorate([
|
521
|
+
property({ attribute: 'password-toggle', reflect: true, type: Boolean })
|
522
|
+
], Input.prototype, "passwordToggle", void 0);
|
523
|
+
__decorate([
|
524
|
+
property({ reflect: true })
|
525
|
+
], Input.prototype, "placeholder", void 0);
|
526
|
+
__decorate([
|
527
|
+
property({ reflect: true, useDefault: true })
|
528
|
+
], Input.prototype, "pattern", void 0);
|
529
|
+
__decorate([
|
530
|
+
property()
|
531
|
+
], Input.prototype, "privateSplit", void 0);
|
532
|
+
__decorate([
|
533
|
+
property({ reflect: true, type: Boolean })
|
534
|
+
], Input.prototype, "readonly", void 0);
|
535
|
+
__decorate([
|
536
|
+
property({ reflect: true, type: Boolean })
|
537
|
+
], Input.prototype, "required", void 0);
|
538
|
+
__decorate([
|
539
|
+
property({ reflect: true, type: Boolean, useDefault: true })
|
540
|
+
], Input.prototype, "spellcheck", void 0);
|
541
|
+
__decorate([
|
542
|
+
property({ reflect: true })
|
543
|
+
], Input.prototype, "tooltip", void 0);
|
544
|
+
__decorate([
|
545
|
+
property({ reflect: true, useDefault: true })
|
546
|
+
], Input.prototype, "type", void 0);
|
547
|
+
__decorate([
|
548
|
+
property()
|
549
|
+
], Input.prototype, "value", void 0);
|
550
|
+
__decorate([
|
551
|
+
property({ reflect: true })
|
552
|
+
], Input.prototype, "version", void 0);
|
553
|
+
__decorate([
|
554
|
+
state()
|
555
|
+
], Input.prototype, "hasFocus", void 0);
|
556
|
+
__decorate([
|
557
|
+
state()
|
558
|
+
], Input.prototype, "isBlurring", void 0);
|
559
|
+
__decorate([
|
560
|
+
state()
|
561
|
+
], Input.prototype, "isCheckingValidity", void 0);
|
562
|
+
__decorate([
|
563
|
+
state()
|
564
|
+
], Input.prototype, "isReportValidityOrSubmit", void 0);
|
565
|
+
__decorate([
|
566
|
+
state()
|
567
|
+
], Input.prototype, "passwordVisible", void 0);
|
568
|
+
__decorate([
|
569
|
+
state()
|
570
|
+
], Input.prototype, "validityMessage", void 0);
|
571
|
+
Input = __decorate([
|
572
|
+
customElement('glide-core-input'),
|
573
|
+
final
|
574
|
+
], Input);
|
575
|
+
export default Input;
|
576
|
+
const icons = {
|
577
|
+
eye: html `<svg
|
122
578
|
aria-hidden="true"
|
123
|
-
style=${styleMap({
|
579
|
+
style=${styleMap({
|
580
|
+
height: '1rem',
|
581
|
+
width: '1rem',
|
582
|
+
})}
|
124
583
|
fill="none"
|
125
584
|
viewBox="0 0 24 24"
|
126
585
|
stroke-width="1.5"
|
@@ -136,9 +595,13 @@ var __decorate=this&&this.__decorate||function(t,e,i,s){var a,o=arguments.length
|
|
136
595
|
stroke-linejoin="round"
|
137
596
|
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
|
138
597
|
/>
|
139
|
-
</svg>`,
|
598
|
+
</svg>`,
|
599
|
+
eyeWithSlash: html `<svg
|
140
600
|
aria-hidden="true"
|
141
|
-
style=${styleMap({
|
601
|
+
style=${styleMap({
|
602
|
+
height: '1rem',
|
603
|
+
width: '1rem',
|
604
|
+
})}
|
142
605
|
fill="none"
|
143
606
|
viewBox="0 0 24 24"
|
144
607
|
stroke-width="1.5"
|
@@ -149,4 +612,5 @@ var __decorate=this&&this.__decorate||function(t,e,i,s){var a,o=arguments.length
|
|
149
612
|
stroke-linejoin="round"
|
150
613
|
d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"
|
151
614
|
/>
|
152
|
-
</svg
|
615
|
+
</svg>`,
|
616
|
+
};
|