@crowdstrike/glide-core 0.9.1 → 0.9.2
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.styles.js +2 -4
- package/dist/button-group.button.styles.js +3 -8
- package/dist/button-group.styles.js +2 -2
- package/dist/button.d.ts +1 -0
- package/dist/button.js +1 -1
- package/dist/button.styles.js +2 -4
- package/dist/button.test.events.js +86 -10
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.styles.js +43 -6
- package/dist/checkbox.test.form.js +16 -0
- package/dist/checkbox.test.interactions.js +8 -0
- package/dist/drawer.js +1 -1
- package/dist/dropdown.d.ts +4 -2
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.js +1 -1
- package/dist/dropdown.option.styles.js +1 -0
- package/dist/dropdown.styles.js +47 -26
- package/dist/dropdown.test.focus.filterable.js +20 -0
- package/dist/dropdown.test.focus.js +1 -0
- package/dist/dropdown.test.form.js +23 -112
- package/dist/dropdown.test.interactions.filterable.js +121 -17
- package/dist/dropdown.test.interactions.multiple.js +15 -22
- package/dist/dropdown.test.interactions.single.js +44 -22
- package/dist/icon-button.styles.js +2 -4
- package/dist/icons/checked.d.ts +5 -0
- package/dist/icons/checked.js +1 -1
- package/dist/input.d.ts +1 -1
- package/dist/input.js +1 -1
- package/dist/input.stories.d.ts +0 -4
- package/dist/input.styles.d.ts +1 -1
- package/dist/input.styles.js +93 -93
- package/dist/input.test.basics.js +45 -45
- package/dist/input.test.form.js +17 -0
- package/dist/label.styles.js +6 -11
- package/dist/library/localize.test.js +45 -0
- package/dist/menu.button.styles.js +1 -0
- package/dist/menu.js +1 -1
- package/dist/menu.link.styles.js +1 -0
- package/dist/menu.styles.js +3 -1
- package/dist/menu.test.events.js +1 -97
- package/dist/menu.test.focus.js +26 -3
- package/dist/menu.test.interactions.js +3 -0
- package/dist/modal.d.ts +0 -7
- package/dist/modal.icon-button.test.basics.js +9 -9
- package/dist/modal.styles.js +2 -4
- package/dist/modal.tertiary-icon.test.basics.js +14 -14
- package/dist/modal.test.accessibility.js +16 -27
- package/dist/modal.test.basics.js +64 -68
- package/dist/modal.test.close.js +12 -16
- package/dist/modal.test.events.js +32 -44
- package/dist/modal.test.lock-scroll.js +15 -25
- package/dist/modal.test.methods.js +8 -12
- package/dist/modal.test.scrollbars.js +2 -4
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.test.basics.js +3 -3
- package/dist/radio-group.test.events.js +6 -6
- package/dist/radio-group.test.form.js +19 -0
- package/dist/radio.styles.js +2 -6
- package/dist/split-button.styles.js +2 -4
- package/dist/split-container.styles.js +2 -4
- package/dist/styles/focus-outline.d.ts +1 -1
- package/dist/styles/focus-outline.js +7 -1
- package/dist/styles/menu-opening-animation.d.ts +2 -0
- package/dist/styles/menu-opening-animation.js +26 -0
- package/dist/styles/variables.css +1 -1
- package/dist/styles/visually-hidden.d.ts +1 -1
- package/dist/styles/visually-hidden.js +14 -1
- package/dist/tab.group.d.ts +6 -6
- package/dist/tab.group.js +1 -1
- package/dist/tab.group.styles.js +46 -5
- package/dist/tab.group.test.basics.js +9 -2
- package/dist/tab.group.test.interactions.js +70 -93
- package/dist/tab.js +1 -1
- package/dist/tab.panel.styles.js +3 -9
- package/dist/tab.styles.js +6 -13
- package/dist/tab.test.basics.js +15 -17
- package/dist/tag.js +1 -1
- package/dist/tag.styles.js +2 -4
- package/dist/tag.test.basics.js +28 -27
- package/dist/tag.test.events.js +3 -3
- package/dist/tag.test.focus.js +4 -4
- package/dist/textarea.d.ts +1 -1
- package/dist/textarea.stories.d.ts +0 -4
- package/dist/textarea.styles.d.ts +1 -1
- package/dist/textarea.styles.js +63 -67
- package/dist/textarea.test.basics.js +52 -52
- package/dist/toasts.d.ts +5 -0
- package/dist/toasts.styles.js +1 -1
- package/dist/toggle.styles.js +2 -1
- package/dist/toggle.test.interactions.js +11 -0
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +22 -18
- package/dist/tooltip.test.interactions.js +6 -6
- package/dist/translations/en.js +1 -1
- package/dist/translations/fr.d.ts +3 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/ja.d.ts +3 -1
- package/dist/translations/ja.js +1 -1
- package/dist/tree.item.styles.js +11 -3
- package/dist/tree.item.test.basics.js +0 -30
- package/package.json +1 -1
- package/dist/button.test.form.d.ts +0 -1
- package/dist/button.test.form.js +0 -50
- package/dist/input.test.translations.js +0 -38
- package/dist/tag.test.translations.d.ts +0 -1
- package/dist/tag.test.translations.js +0 -25
- package/dist/textarea.test.translations.d.ts +0 -1
- package/dist/textarea.test.translations.js +0 -34
- /package/dist/{input.test.translations.d.ts → library/localize.test.d.ts} +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
2
|
import { ArgumentError } from 'ow';
|
3
|
-
import { aTimeout, assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
|
3
|
+
import { aTimeout, assert, elementUpdated, expect, fixture, html, oneEvent, } from '@open-wc/testing';
|
4
4
|
import { sendKeys } from '@web/test-runner-commands';
|
5
5
|
import GlideCoreDropdown from './dropdown.js';
|
6
6
|
import GlideCoreDropdownOption from './dropdown.option.js';
|
@@ -97,6 +97,35 @@ it('selects an option on Space', async () => {
|
|
97
97
|
await sendKeys({ press: ' ' });
|
98
98
|
expect(option?.selected).to.be.true;
|
99
99
|
});
|
100
|
+
it('selects an option when its icon is clicked', async () => {
|
101
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
102
|
+
<glide-core-dropdown-option label="One" value="one">
|
103
|
+
<svg
|
104
|
+
slot="icon"
|
105
|
+
fill="none"
|
106
|
+
viewBox="0 0 24 24"
|
107
|
+
stroke-width="1.5"
|
108
|
+
stroke="currentColor"
|
109
|
+
style="height: 1rem; width: 1rem;"
|
110
|
+
>
|
111
|
+
<path
|
112
|
+
stroke-linecap="round"
|
113
|
+
stroke-linejoin="round"
|
114
|
+
d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15"
|
115
|
+
/>
|
116
|
+
</svg>
|
117
|
+
</glide-core-dropdown-option>
|
118
|
+
</glide-core-dropdown>`);
|
119
|
+
// Wait for it to open.
|
120
|
+
await aTimeout(0);
|
121
|
+
const option = component.querySelector('glide-core-dropdown-option');
|
122
|
+
option?.shadowRoot
|
123
|
+
?.querySelector('[data-test="icon-slot"]')
|
124
|
+
?.assignedElements()
|
125
|
+
?.at(0)
|
126
|
+
?.dispatchEvent(new Event('click', { bubbles: true }));
|
127
|
+
expect(option?.selected).to.be.true;
|
128
|
+
});
|
100
129
|
it('does not deselect options on Space', async () => {
|
101
130
|
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
|
102
131
|
<glide-core-dropdown-option
|
@@ -490,8 +519,8 @@ it('hides Select All', async () => {
|
|
490
519
|
const selectAll = component.shadowRoot?.querySelector('[data-test="select-all"]');
|
491
520
|
expect(selectAll?.checkVisibility()).to.not.be.ok;
|
492
521
|
});
|
493
|
-
it('
|
494
|
-
|
522
|
+
it('cannot be tabbed to when `disabled`', async () => {
|
523
|
+
await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" disabled>
|
495
524
|
<glide-core-dropdown-option
|
496
525
|
label="One"
|
497
526
|
value="one"
|
@@ -502,28 +531,21 @@ it('does not select an option on Enter when the option is not focused', async ()
|
|
502
531
|
value="two"
|
503
532
|
></glide-core-dropdown-option>
|
504
533
|
</glide-core-dropdown>`);
|
505
|
-
// Wait for it to open.
|
506
|
-
await aTimeout(0);
|
507
|
-
const option = component.querySelector('glide-core-dropdown-option');
|
508
|
-
option?.focus();
|
509
534
|
await sendKeys({ down: 'Tab' });
|
510
|
-
|
511
|
-
await sendKeys({ up: 'Tab' });
|
512
|
-
await sendKeys({ press: 'Enter' });
|
513
|
-
expect(option?.selected).to.be.false;
|
535
|
+
expect(document.activeElement).to.equal(document.body);
|
514
536
|
});
|
515
|
-
it('
|
516
|
-
await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder"
|
517
|
-
<glide-core-dropdown-option
|
518
|
-
label="One"
|
519
|
-
value="one"
|
520
|
-
></glide-core-dropdown-option>
|
521
|
-
|
537
|
+
it('clicks the button when `click()` is called', async () => {
|
538
|
+
const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
|
522
539
|
<glide-core-dropdown-option
|
523
|
-
label="
|
524
|
-
value="
|
540
|
+
label="Label"
|
541
|
+
value="value"
|
525
542
|
></glide-core-dropdown-option>
|
526
543
|
</glide-core-dropdown>`);
|
527
|
-
|
528
|
-
|
544
|
+
const button = component.shadowRoot?.querySelector('[data-test="button"]');
|
545
|
+
assert(button);
|
546
|
+
setTimeout(() => {
|
547
|
+
component.click();
|
548
|
+
});
|
549
|
+
const event = await oneEvent(button, 'click');
|
550
|
+
expect(event instanceof PointerEvent).to.be.true;
|
529
551
|
});
|
@@ -1,4 +1,6 @@
|
|
1
1
|
import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
|
2
|
+
${focusOutline(".component:focus-visible")}
|
3
|
+
`,css`
|
2
4
|
:host {
|
3
5
|
/* Contains elements with "padding" and "width". Inline by default. */
|
4
6
|
display: inline-flex;
|
@@ -24,10 +26,6 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
24
26
|
outline: none;
|
25
27
|
}
|
26
28
|
|
27
|
-
&:focus-visible {
|
28
|
-
${focusOutline};
|
29
|
-
}
|
30
|
-
|
31
29
|
&:disabled {
|
32
30
|
cursor: not-allowed;
|
33
31
|
opacity: 1;
|
package/dist/icons/checked.d.ts
CHANGED
@@ -1,2 +1,7 @@
|
|
1
|
+
/**
|
2
|
+
* The class="check" on the path below is used as a CSS selector
|
3
|
+
* in checkbox.styles.ts. Please be cautious when making changes
|
4
|
+
* here as to not break the Checkbox selectors.
|
5
|
+
*/
|
1
6
|
declare const _default: import("lit").TemplateResult<1>;
|
2
7
|
export default _default;
|
package/dist/icons/checked.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
import{html}from"lit";export default html`<svg fill="none" viewBox="0 0 24 24" style="height: var(--size, 0.875rem); width: var(--size, 0.875rem);"><path d="M20 6L9 17L4 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
1
|
+
import{html}from"lit";export default html`<svg aria-hidden="true" fill="none" viewBox="0 0 24 24" style="height: var(--size, 0.875rem); width: var(--size, 0.875rem);"><path class="check" d="M20 6L9 17L4 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
package/dist/input.d.ts
CHANGED
@@ -24,7 +24,7 @@ export default class GlideCoreInput extends LitElement {
|
|
24
24
|
#private;
|
25
25
|
static formAssociated: boolean;
|
26
26
|
static shadowRootOptions: ShadowRootInit;
|
27
|
-
static styles: import("lit").CSSResult;
|
27
|
+
static styles: import("lit").CSSResult[];
|
28
28
|
type: SupportedTypes;
|
29
29
|
name?: string;
|
30
30
|
value: string;
|
package/dist/input.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(e,t,i,o){var r,s=arguments.length,a=s<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,o);else for(var l=e.length-1;l>=0;l--)(r=e[l])&&(a=(s<3?r(a):s>3?r(t,i,a):r(t,i))||a);return s>3&&a&&Object.defineProperty(t,i,a),a};import"./icon-button.js";import"./label.js";import{LitElement,html,nothing}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import magnifyingGlassIcon from"./icons/magnifying-glass.js";import ow from"./library/ow.js";import styles from"./input.styles.js";export const SUPPORTED_TYPES=["email","number","password","search","tel","text","url"];let GlideCoreInput=class GlideCoreInput extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed",delegatesFocus:!0}}static{this.styles=styles}get form(){return this.#e.form}get validity(){return!this.required||this.value||this.disabled?this.#t?this.#e.setValidity({tooLong:!0}," ",this.#i.value):this.#e.setValidity({}):this.#e.setValidity({valueMissing:!0}," ",this.#i.value),this.#e.validity}get willValidate(){return this.#e.willValidate}blur(){this.#i.value?.blur()}checkValidity(){this.isCheckingValidity=!0;const e=this.#e.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#o)}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#o)}formResetCallback(){this.value=this.getAttribute("value")??""}get hasClearIcon(){return this.clearable&&!this.disabled&&!this.readonly}get isClearIconVisible(){return this.hasClearIcon&&this.value.length>0}render(){return html`<glide-core-private-label class="${classMap({left:"left"===this.privateSplit,middle:"middle"===this.privateSplit})}" orientation="${this.orientation}" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?error="${this.#r||this.#t}" ?hide="${this.hideLabel}" ?required="${this.required}"><slot name="tooltip" slot="tooltip"></slot><label for="input">${this.label}</label><div class="${classMap({"input-container":!0,focused:this.hasFocus,empty:""===this.value,disabled:this.disabled,readonly:this.readonly&&!this.disabled,error:this.#r||this.#t})}" slot="control"><slot name="prefix"></slot><input aria-describedby="meta" aria-invalid="${this.#r||this.#t}" id="input" type="${"password"===this.type&&this.passwordVisible?"text":this.type}" .value="${this.value}" placeholder="${ifDefined(this.placeholder)}" autocapitalize="${ifDefined(this.autocapitalize)}" spellcheck="${this.spellcheck}" ?required="${this.required}" ?readonly="${this.readonly}" ?disabled="${this.disabled}" @focus="${this.#s}" @blur="${this.#a}" @change="${this.#l}" @input="${this.#n}" ${ref(this.#i)}> ${this.hasClearIcon?html`<glide-core-icon-button variant="tertiary" class="${classMap({"clear-icon-button":!0,"clear-icon-button--visible":this.isClearIconVisible})}" data-test="clear-button" label="${this.#
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,i,o){var r,s=arguments.length,a=s<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,o);else for(var l=e.length-1;l>=0;l--)(r=e[l])&&(a=(s<3?r(a):s>3?r(t,i,a):r(t,i))||a);return s>3&&a&&Object.defineProperty(t,i,a),a};import"./icon-button.js";import"./label.js";import{LitElement,html,nothing}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import magnifyingGlassIcon from"./icons/magnifying-glass.js";import ow from"./library/ow.js";import styles from"./input.styles.js";export const SUPPORTED_TYPES=["email","number","password","search","tel","text","url"];let GlideCoreInput=class GlideCoreInput extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed",delegatesFocus:!0}}static{this.styles=styles}get form(){return this.#e.form}get validity(){return!this.required||this.value||this.disabled?this.#t?this.#e.setValidity({tooLong:!0}," ",this.#i.value):this.#e.setValidity({}):this.#e.setValidity({valueMissing:!0}," ",this.#i.value),this.#e.validity}get willValidate(){return this.#e.willValidate}blur(){this.#i.value?.blur()}checkValidity(){this.isCheckingValidity=!0;const e=this.#e.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#o)}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#o)}formResetCallback(){this.value=this.getAttribute("value")??""}get hasClearIcon(){return this.clearable&&!this.disabled&&!this.readonly}get isClearIconVisible(){return this.hasClearIcon&&this.value.length>0}render(){return html`<glide-core-private-label class="${classMap({left:"left"===this.privateSplit,middle:"middle"===this.privateSplit})}" orientation="${this.orientation}" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?error="${this.#r||this.#t}" ?hide="${this.hideLabel}" ?required="${this.required}"><slot name="tooltip" slot="tooltip"></slot><label for="input">${this.label}</label><div class="${classMap({"input-container":!0,focused:this.hasFocus,empty:""===this.value,disabled:this.disabled,readonly:this.readonly&&!this.disabled,error:this.#r||this.#t})}" slot="control"><slot name="prefix"></slot><input aria-describedby="meta" aria-invalid="${this.#r||this.#t}" id="input" type="${"password"===this.type&&this.passwordVisible?"text":this.type}" .value="${this.value}" placeholder="${ifDefined(this.placeholder)}" autocapitalize="${ifDefined(this.autocapitalize)}" spellcheck="${this.spellcheck}" ?required="${this.required}" ?readonly="${this.readonly}" ?disabled="${this.disabled}" @focus="${this.#s}" @blur="${this.#a}" @change="${this.#l}" @input="${this.#n}" @keydown="${this.#d}" ${ref(this.#i)}> ${this.hasClearIcon?html`<glide-core-icon-button variant="tertiary" class="${classMap({"clear-icon-button":!0,"clear-icon-button--visible":this.isClearIconVisible})}" data-test="clear-button" label="${this.#h.term("clearEntry",this.label)}" @click="${this.#p}"><svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M6 6L18 18" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-icon-button>`:nothing} ${"password"===this.type&&this.passwordToggle&&!this.disabled?html`<glide-core-icon-button variant="tertiary" class="password-toggle" data-test="password-toggle" label="${this.passwordVisible?"Hide password":"Show password"}" aria-controls="input" aria-expanded="${this.passwordVisible?"true":"false"}" @click="${this.#c}">${this.passwordVisible?html`<svg aria-hidden="true" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" 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"/></svg>`:html`<svg aria-hidden="true" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"/><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/></svg>`}</glide-core-icon-button>`:nothing}<div class="suffix">${"search"===this.type?magnifyingGlassIcon:html`<slot name="suffix"></slot>`}</div></div><div class="meta" id="meta" slot="description"><slot class="description" name="description"></slot>${this.maxlength?html`<div class="${classMap({"character-count":!0,error:this.#t})}" data-test="character-count-container"><span aria-hidden="true" data-test="character-count-text">${this.#h.term("displayedCharacterCount",this.#u,this.maxlength)} </span><span class="hidden" data-test="character-count-announcement">${this.#h.term("announcedCharacterCount",this.#u,this.maxlength)}</span></div>`:nothing}</div></glide-core-private-label>`}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#e.reportValidity();return this.requestUpdate(),e}constructor(){super(),this.type="text",this.value="",this.hideLabel=!1,this.orientation="horizontal",this.clearable=!1,this.spellcheck=!1,this.autocapitalize="on",this.passwordToggle=!1,this.required=!1,this.readonly=!1,this.disabled=!1,this.hasFocus=!1,this.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.passwordVisible=!1,this.#i=createRef(),this.#h=new LocalizeController(this),this.#o=({formData:e})=>{this.name&&this.value&&!this.disabled&&e.append(this.name,this.value)},this.#e=this.attachInternals(),this.addEventListener("invalid",(e=>{if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}))}#i;#e;#h;get#u(){return this.value.length}#o;get#t(){return Boolean(!this.disabled&&!this.readonly&&this.maxlength&&this.#u>this.maxlength)}get#r(){return!this.disabled&&!this.validity?.valid&&this.isReportValidityOrSubmit}#a(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1,this.hasFocus=!1}#l(e){ow(this.#i.value,ow.object.instanceOf(HTMLInputElement)),this.value=this.#i.value?.value,this.dispatchEvent(new Event(e.type,e))}#p(e){this.value="",this.dispatchEvent(new Event("clear",{bubbles:!0})),this.#i.value?.focus(),e.stopPropagation()}#s(){this.hasFocus=!0}#n(){ow(this.#i.value,ow.object.instanceOf(HTMLInputElement)),this.value=this.#i.value.value}#d(e){"Enter"===e.key&&this.form?.requestSubmit()}#c(){this.passwordVisible=!this.passwordVisible}};__decorate([property()],GlideCoreInput.prototype,"type",void 0),__decorate([property({reflect:!0})],GlideCoreInput.prototype,"name",void 0),__decorate([property()],GlideCoreInput.prototype,"value",void 0),__decorate([property()],GlideCoreInput.prototype,"label",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreInput.prototype,"hideLabel",void 0),__decorate([property({reflect:!0})],GlideCoreInput.prototype,"orientation",void 0),__decorate([property()],GlideCoreInput.prototype,"placeholder",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"clearable",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreInput.prototype,"spellcheck",void 0),__decorate([property()],GlideCoreInput.prototype,"autocapitalize",void 0),__decorate([property({attribute:"password-toggle",type:Boolean})],GlideCoreInput.prototype,"passwordToggle",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreInput.prototype,"required",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"readonly",void 0),__decorate([property({type:Boolean})],GlideCoreInput.prototype,"disabled",void 0),__decorate([property()],GlideCoreInput.prototype,"privateSplit",void 0),__decorate([property({type:Number,converter:e=>e&&Number.parseInt(e,10)})],GlideCoreInput.prototype,"maxlength",void 0),__decorate([state()],GlideCoreInput.prototype,"hasFocus",void 0),__decorate([state()],GlideCoreInput.prototype,"isBlurring",void 0),__decorate([state()],GlideCoreInput.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreInput.prototype,"isReportValidityOrSubmit",void 0),__decorate([state()],GlideCoreInput.prototype,"passwordVisible",void 0),GlideCoreInput=__decorate([customElement("glide-core-input")],GlideCoreInput);export default GlideCoreInput;
|
package/dist/input.stories.d.ts
CHANGED
@@ -6,10 +6,6 @@ export default meta;
|
|
6
6
|
export declare const Default: StoryObj;
|
7
7
|
export declare const Password: StoryObj;
|
8
8
|
export declare const WithError: StoryObj;
|
9
|
-
export declare const Description: StoryObj;
|
10
|
-
export declare const Readonly: StoryObj;
|
11
|
-
export declare const Disabled: StoryObj;
|
12
|
-
export declare const Placeholder: StoryObj;
|
13
9
|
export declare const Clearable: StoryObj;
|
14
10
|
export declare const SuffixIcon: StoryObj;
|
15
11
|
export declare const PrefixIcon: StoryObj;
|
package/dist/input.styles.d.ts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
declare const _default: import("lit").CSSResult;
|
1
|
+
declare const _default: import("lit").CSSResult[];
|
2
2
|
export default _default;
|
package/dist/input.styles.js
CHANGED
@@ -1,115 +1,115 @@
|
|
1
|
-
import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";export default
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
display: block;
|
12
|
-
}
|
1
|
+
import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
|
2
|
+
${visuallyHidden(".character-count .hidden")}
|
3
|
+
`,css`
|
4
|
+
.meta {
|
5
|
+
column-gap: var(--glide-core-spacing-xs);
|
6
|
+
display: flex;
|
7
|
+
font-size: 0.75rem;
|
8
|
+
grid-column: 2;
|
9
|
+
justify-content: space-between;
|
10
|
+
}
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
font-weight: var(--glide-core-font-weight-bold);
|
12
|
+
.description {
|
13
|
+
display: block;
|
17
14
|
}
|
18
15
|
|
19
|
-
.
|
20
|
-
|
16
|
+
.character-count {
|
17
|
+
&.error {
|
18
|
+
font-weight: var(--glide-core-font-weight-bold);
|
19
|
+
}
|
21
20
|
}
|
22
|
-
}
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
.search-icon {
|
23
|
+
align-items: center;
|
24
|
+
display: flex;
|
25
|
+
}
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
27
|
+
.input-container {
|
28
|
+
align-items: center;
|
29
|
+
background-color: var(--glide-core-surface-base-lighter);
|
30
|
+
block-size: 2.125rem;
|
31
|
+
border: 1px solid var(--glide-core-border-base);
|
32
|
+
border-radius: var(--glide-core-spacing-xs);
|
33
|
+
box-sizing: border-box;
|
34
|
+
color: var(--glide-core-text-body-1);
|
35
|
+
display: flex;
|
36
|
+
gap: var(--glide-core-spacing-xxs);
|
37
|
+
line-height: var(--glide-core-body-xs-line-height);
|
38
|
+
padding-inline: var(--glide-core-spacing-sm);
|
41
39
|
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
&.focused,
|
41
|
+
&:hover {
|
42
|
+
border-color: var(--glide-core-border-focus);
|
43
|
+
transition: border-color 200ms ease-in-out;
|
44
|
+
}
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
}
|
46
|
+
&.error {
|
47
|
+
border-color: var(--glide-core-status-error);
|
48
|
+
}
|
50
49
|
|
51
|
-
|
50
|
+
/* We had to resort to a class selector because there may be a bug in Chrome and Safari
|
52
51
|
* with ":read-only"
|
53
52
|
* https://bugs.chromium.org/p/chromium/issues/detail?id=1519649
|
54
53
|
*/
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
&.readonly {
|
55
|
+
border: 1px solid transparent;
|
56
|
+
padding-inline-start: 0;
|
57
|
+
}
|
59
58
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
59
|
+
&.disabled {
|
60
|
+
background-color: var(--glide-core-surface-disabled);
|
61
|
+
border-color: var(--glide-core-border-base-light);
|
62
|
+
color: var(--glide-core-text-tertiary-disabled);
|
63
|
+
}
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
65
|
+
input {
|
66
|
+
background-color: transparent;
|
67
|
+
border: none;
|
68
|
+
color: inherit;
|
69
|
+
cursor: inherit;
|
70
|
+
font-family: var(--glide-core-font-sans);
|
71
|
+
font-size: var(--glide-core-body-sm-font-size);
|
72
|
+
font-weight: var(--glide-core-body-xs-font-weight);
|
73
|
+
inline-size: 100%;
|
74
|
+
min-inline-size: 0;
|
75
|
+
outline: none;
|
76
|
+
padding: 0;
|
77
|
+
|
78
|
+
&::-webkit-search-decoration,
|
79
|
+
&::-webkit-search-cancel-button,
|
80
|
+
&::-webkit-search-results-button,
|
81
|
+
&::-webkit-search-results-decoration {
|
82
|
+
appearance: none;
|
83
|
+
}
|
84
|
+
}
|
77
85
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
&::-webkit-search-results-decoration {
|
82
|
-
appearance: none;
|
86
|
+
.suffix {
|
87
|
+
align-items: center;
|
88
|
+
display: flex;
|
83
89
|
}
|
84
90
|
}
|
85
91
|
|
86
|
-
.
|
92
|
+
.clear-icon-button,
|
93
|
+
.password-toggle,
|
94
|
+
::slotted([slot='suffix']) {
|
87
95
|
align-items: center;
|
88
|
-
|
96
|
+
background: none;
|
97
|
+
border: none;
|
98
|
+
color: var(--glide-core-icon-default);
|
99
|
+
display: inline-flex;
|
100
|
+
justify-content: center;
|
101
|
+
padding: 0;
|
89
102
|
}
|
90
|
-
}
|
91
|
-
|
92
|
-
.clear-icon-button,
|
93
|
-
.password-toggle,
|
94
|
-
::slotted([slot='suffix']) {
|
95
|
-
align-items: center;
|
96
|
-
background: none;
|
97
|
-
border: none;
|
98
|
-
color: var(--glide-core-icon-default);
|
99
|
-
display: inline-flex;
|
100
|
-
justify-content: center;
|
101
|
-
padding: 0;
|
102
|
-
}
|
103
103
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
104
|
+
.clear-icon-button,
|
105
|
+
.password-toggle,
|
106
|
+
.search-icon,
|
107
|
+
::slotted([slot='prefix']),
|
108
|
+
::slotted([slot='suffix']) {
|
109
|
+
display: flex;
|
110
|
+
}
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
112
|
+
.empty .clear-icon-button {
|
113
|
+
visibility: hidden;
|
114
|
+
}
|
115
|
+
`];
|
@@ -7,43 +7,43 @@ it('registers', async () => {
|
|
7
7
|
expect(window.customElements.get('glide-core-input')).to.equal(GlideCoreInput);
|
8
8
|
});
|
9
9
|
it('is accessible', async () => {
|
10
|
-
const
|
10
|
+
const component = await fixture(html `
|
11
11
|
<glide-core-input label="Test" value="lorem"></glide-core-input>
|
12
12
|
`);
|
13
|
-
await expect(
|
13
|
+
await expect(component).to.be.accessible();
|
14
14
|
});
|
15
15
|
it('accepts and contains "value" attribute', async () => {
|
16
|
-
const
|
16
|
+
const component = await fixture(html `
|
17
17
|
<glide-core-input label="Test" value="lorem"></glide-core-input>
|
18
18
|
`);
|
19
|
-
expect(
|
19
|
+
expect(component.value).to.equal('lorem');
|
20
20
|
});
|
21
21
|
it('accepts disable attribute and disables the underlying input', async () => {
|
22
|
-
const
|
22
|
+
const component = await fixture(html `
|
23
23
|
<glide-core-input label="Test" disabled></glide-core-input>
|
24
24
|
`);
|
25
|
-
const inputElement =
|
25
|
+
const inputElement = component.shadowRoot?.querySelector('input');
|
26
26
|
expect(inputElement).to.exist;
|
27
27
|
expect(inputElement?.hasAttribute('disabled')).to.be.true;
|
28
28
|
});
|
29
29
|
it('accepts readonly attribute and applies readonly to the underlying input', async () => {
|
30
|
-
const
|
30
|
+
const component = await fixture(html `
|
31
31
|
<glide-core-input label="Test" readonly></glide-core-input>
|
32
32
|
`);
|
33
|
-
const inputElement =
|
33
|
+
const inputElement = component.shadowRoot?.querySelector('input');
|
34
34
|
expect(inputElement).to.exist;
|
35
35
|
expect(inputElement?.hasAttribute('readonly')).to.be.true;
|
36
36
|
});
|
37
37
|
it('accepts a type attribute', async () => {
|
38
|
-
const
|
38
|
+
const component = await fixture(html `
|
39
39
|
<glide-core-input label="Test" type="number"></glide-core-input>
|
40
40
|
`);
|
41
|
-
const inputElement =
|
41
|
+
const inputElement = component.shadowRoot?.querySelector('input');
|
42
42
|
expect(inputElement).to.exist;
|
43
43
|
expect(inputElement?.getAttribute('type')).to.equal('number');
|
44
44
|
});
|
45
45
|
it('changes to type text when password is revealed', async () => {
|
46
|
-
const
|
46
|
+
const component = await fixture(html `
|
47
47
|
<glide-core-input
|
48
48
|
label="Test"
|
49
49
|
value="password123"
|
@@ -51,89 +51,89 @@ it('changes to type text when password is revealed', async () => {
|
|
51
51
|
password-toggle
|
52
52
|
></glide-core-input>
|
53
53
|
`);
|
54
|
-
const inputElement =
|
54
|
+
const inputElement = component.shadowRoot?.querySelector('input');
|
55
55
|
expect(inputElement).to.exist;
|
56
56
|
expect(inputElement?.getAttribute('type')).to.equal('password');
|
57
|
-
const passwordToggle =
|
57
|
+
const passwordToggle = component.shadowRoot?.querySelector('[data-test="password-toggle"]');
|
58
58
|
passwordToggle?.click();
|
59
|
-
await
|
59
|
+
await component.updateComplete;
|
60
60
|
expect(inputElement?.getAttribute('type')).to.equal('text');
|
61
61
|
});
|
62
62
|
it('shows search icon with type search', async () => {
|
63
|
-
const
|
63
|
+
const component = await fixture(html `
|
64
64
|
<glide-core-input label="Test" type="search"></glide-core-input>
|
65
65
|
`);
|
66
|
-
const inputElement =
|
66
|
+
const inputElement = component.shadowRoot?.querySelector('input');
|
67
67
|
expect(inputElement).to.exist;
|
68
68
|
expect(inputElement?.getAttribute('type')).to.equal('search');
|
69
|
-
const searchIcon =
|
69
|
+
const searchIcon = component.shadowRoot?.querySelector('[data-test="search-icon"]');
|
70
70
|
expect(searchIcon).to.exist;
|
71
71
|
});
|
72
72
|
it('when using "focus() on input", the native input is focused', async () => {
|
73
|
-
const
|
73
|
+
const component = await fixture(html `
|
74
74
|
<glide-core-input label="Test"></glide-core-input>
|
75
75
|
`);
|
76
|
-
const inputElement =
|
77
|
-
|
78
|
-
expect(document.activeElement).to.equal(
|
79
|
-
expect(
|
76
|
+
const inputElement = component.shadowRoot?.querySelector('input');
|
77
|
+
component.focus();
|
78
|
+
expect(document.activeElement).to.equal(component);
|
79
|
+
expect(component.shadowRoot?.activeElement).to.equal(inputElement);
|
80
80
|
});
|
81
81
|
it('emits input events when text is changed and reports a value through the event target', async () => {
|
82
|
-
const
|
82
|
+
const component = await fixture(html `
|
83
83
|
<glide-core-input label="Test"></glide-core-input>
|
84
84
|
`);
|
85
85
|
let inputEventCaught = false;
|
86
86
|
let value = '';
|
87
|
-
|
87
|
+
component.addEventListener('input', (event) => {
|
88
88
|
inputEventCaught = true;
|
89
89
|
if (event.target instanceof GlideCoreInput) {
|
90
90
|
value = event.target.value;
|
91
91
|
}
|
92
92
|
});
|
93
|
-
|
93
|
+
component.focus();
|
94
94
|
await sendKeys({ type: 'testing' });
|
95
|
-
|
95
|
+
component.blur();
|
96
96
|
expect(inputEventCaught).to.be.true;
|
97
97
|
expect(value).to.be.equal('testing');
|
98
98
|
});
|
99
99
|
it('clearable attribute allows for a button which can clear input', async () => {
|
100
|
-
const
|
100
|
+
const component = await fixture(html `
|
101
101
|
<glide-core-input label="Test" clearable></glide-core-input>
|
102
102
|
`);
|
103
|
-
const clearButton =
|
104
|
-
|
103
|
+
const clearButton = component.shadowRoot?.querySelector('[data-test="clear-button"]');
|
104
|
+
component.focus();
|
105
105
|
await sendKeys({ type: 'testing' });
|
106
|
-
expect(
|
106
|
+
expect(component.value).to.be.equal('testing');
|
107
107
|
clearButton?.click();
|
108
|
-
expect(
|
108
|
+
expect(component.value).to.be.equal('');
|
109
109
|
});
|
110
110
|
it('label correctly displays when provided as an attribute', async () => {
|
111
|
-
const
|
111
|
+
const component = await fixture(html `
|
112
112
|
<glide-core-input label="Test label"></glide-core-input>
|
113
113
|
`);
|
114
|
-
const labelElement =
|
114
|
+
const labelElement = component?.shadowRoot?.querySelector('label');
|
115
115
|
const labelText = labelElement?.textContent?.trim();
|
116
116
|
expect(labelText).to.be.equal('Test label');
|
117
117
|
});
|
118
118
|
it('displays a max character and current character count if maxlength is provided', async () => {
|
119
|
-
const
|
119
|
+
const component = await fixture(html `
|
120
120
|
<glide-core-input label="Test label" maxlength="5"></glide-core-input>
|
121
121
|
`);
|
122
|
-
const maxCharacterCountText =
|
122
|
+
const maxCharacterCountText = component.shadowRoot?.querySelector('[data-test="character-count-text"]');
|
123
123
|
expect(maxCharacterCountText?.textContent?.trim()).to.equal('0/5');
|
124
124
|
});
|
125
125
|
it('displays visually hidden character count text for screenreaders', async () => {
|
126
|
-
const
|
126
|
+
const component = await fixture(html `
|
127
127
|
<glide-core-input label="Test label" maxlength="5"></glide-core-input>
|
128
128
|
`);
|
129
|
-
const maxCharacterCountAnnouncement =
|
129
|
+
const maxCharacterCountAnnouncement = component.shadowRoot?.querySelector('[data-test="character-count-announcement"]');
|
130
130
|
expect(maxCharacterCountAnnouncement?.textContent?.trim()).to.equal('Character count 0 of 5');
|
131
131
|
});
|
132
132
|
it('does not render a character count when attribute `maxlength` is set less than than zero', async () => {
|
133
|
-
const
|
133
|
+
const component = await fixture(html `
|
134
134
|
<glide-core-input label="Test label" maxlength="0"></glide-core-input>
|
135
135
|
`);
|
136
|
-
const container =
|
136
|
+
const container = component.shadowRoot?.querySelector('[data-test="character-count-container"]');
|
137
137
|
expect(container).to.be.null;
|
138
138
|
});
|
139
139
|
it('supports a "tooltip" slot', async () => {
|
@@ -146,25 +146,25 @@ it('supports a "tooltip" slot', async () => {
|
|
146
146
|
expect(assignedElements?.at(0)?.textContent).to.equal('Tooltip');
|
147
147
|
});
|
148
148
|
it('supports a "description" slot', async () => {
|
149
|
-
const
|
149
|
+
const component = await fixture(html `
|
150
150
|
<glide-core-input label="Test">
|
151
151
|
<div slot="description">Description</div>
|
152
152
|
</glide-core-input>
|
153
153
|
`);
|
154
|
-
const assignedElements =
|
154
|
+
const assignedElements = component.shadowRoot
|
155
155
|
?.querySelector('slot[name="description"]')
|
156
156
|
?.assignedElements();
|
157
157
|
expect(assignedElements?.at(0)?.textContent).to.equal('Description');
|
158
158
|
});
|
159
159
|
it('supports a "prefix" icon slot', async () => {
|
160
|
-
const
|
160
|
+
const component = await fixture(html `
|
161
161
|
<glide-core-input label="Test">
|
162
162
|
<div slot="prefix">
|
163
163
|
<span data-svg></span>
|
164
164
|
</div>
|
165
165
|
</glide-core-input>
|
166
166
|
`);
|
167
|
-
const assignedElements =
|
167
|
+
const assignedElements = component.shadowRoot
|
168
168
|
?.querySelector('slot[name="prefix"]')
|
169
169
|
?.assignedElements();
|
170
170
|
const slottedSvg = assignedElements
|
@@ -173,14 +173,14 @@ it('supports a "prefix" icon slot', async () => {
|
|
173
173
|
expect(slottedSvg).to.exist;
|
174
174
|
});
|
175
175
|
it('supports a "suffix" icon slot', async () => {
|
176
|
-
const
|
176
|
+
const component = await fixture(html `
|
177
177
|
<glide-core-input label="Test">
|
178
178
|
<div slot="suffix">
|
179
179
|
<span data-svg></span>
|
180
180
|
</div>
|
181
181
|
</glide-core-input>
|
182
182
|
`);
|
183
|
-
const assignedElements =
|
183
|
+
const assignedElements = component.shadowRoot
|
184
184
|
?.querySelector('slot[name="suffix"]')
|
185
185
|
?.assignedElements();
|
186
186
|
const slottedSvg = assignedElements
|