@crowdstrike/glide-core 0.8.0 → 0.9.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.d.ts +7 -3
- package/dist/button-group.button.d.ts +12 -16
- package/dist/button-group.button.js +1 -1
- package/dist/button-group.button.styles.js +76 -52
- package/dist/button-group.button.test.basics.d.ts +1 -1
- package/dist/button-group.button.test.basics.js +83 -147
- package/dist/button-group.button.test.events.js +8 -67
- package/dist/button-group.button.test.focus.js +13 -0
- package/dist/button-group.button.test.interactions.d.ts +1 -0
- package/dist/button-group.button.test.interactions.js +42 -0
- package/dist/button-group.d.ts +10 -10
- package/dist/button-group.js +1 -1
- package/dist/button-group.stories.d.ts +1 -5
- package/dist/button-group.styles.js +18 -6
- package/dist/button-group.test.basics.js +113 -234
- package/dist/button-group.test.events.js +210 -263
- package/dist/button-group.test.focus.d.ts +1 -0
- package/dist/button-group.test.focus.js +39 -0
- package/dist/button-group.test.interactions.d.ts +1 -0
- package/dist/button-group.test.interactions.js +91 -0
- package/dist/button.d.ts +3 -0
- package/dist/button.test.basics.js +1 -1
- package/dist/checkbox-group.d.ts +6 -2
- package/dist/checkbox-group.js +1 -1
- package/dist/checkbox-group.stories.d.ts +1 -1
- package/dist/checkbox-group.styles.js +1 -1
- package/dist/checkbox-group.test.basics.js +1 -1
- package/dist/checkbox-group.test.events.js +4 -4
- package/dist/checkbox-group.test.focus.js +4 -3
- package/dist/checkbox.d.ts +12 -5
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.stories.d.ts +1 -1
- package/dist/checkbox.styles.js +10 -0
- package/dist/checkbox.test.basics.js +15 -6
- package/dist/checkbox.test.events.js +16 -8
- package/dist/checkbox.test.focus.js +3 -3
- package/dist/checkbox.test.form.js +1 -0
- package/dist/checkbox.test.interactions.js +123 -0
- package/dist/drawer.d.ts +5 -5
- package/dist/drawer.js +1 -1
- package/dist/drawer.stories.d.ts +0 -1
- package/dist/dropdown.d.ts +9 -6
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.d.ts +6 -2
- package/dist/dropdown.option.js +1 -1
- package/dist/dropdown.option.styles.js +13 -0
- package/dist/dropdown.option.test.basics.js +6 -3
- package/dist/dropdown.option.test.events.js +1 -1
- package/dist/dropdown.option.test.focus.js +1 -1
- package/dist/dropdown.option.test.interactions.multiple.js +1 -54
- package/dist/dropdown.option.test.interactions.single.js +51 -9
- package/dist/dropdown.styles.js +20 -19
- package/dist/dropdown.test.basics.js +143 -2
- package/dist/dropdown.test.basics.multiple.js +5 -2
- package/dist/dropdown.test.events.filterable.js +74 -0
- package/dist/dropdown.test.events.js +49 -160
- package/dist/dropdown.test.events.multiple.js +265 -8
- package/dist/dropdown.test.events.single.js +199 -2
- package/dist/dropdown.test.focus.filterable.js +9 -5
- package/dist/dropdown.test.focus.js +1 -1
- package/dist/dropdown.test.focus.multiple.js +1 -1
- package/dist/dropdown.test.focus.single.js +1 -1
- package/dist/dropdown.test.interactions.filterable.js +68 -11
- package/dist/dropdown.test.interactions.js +94 -5
- package/dist/dropdown.test.interactions.multiple.js +202 -5
- package/dist/dropdown.test.interactions.single.js +68 -6
- package/dist/form-controls-layout.test.basics.js +1 -1
- package/dist/icon-button.d.ts +2 -0
- package/dist/icon-button.test.basics.js +1 -1
- package/dist/icons/checked.d.ts +1 -1
- package/dist/icons/checked.js +1 -1
- package/dist/icons/magnifying-glass.js +1 -1
- package/dist/input.d.ts +4 -9
- package/dist/input.js +1 -1
- package/dist/input.styles.js +7 -2
- package/dist/input.test.basics.js +19 -5
- package/dist/input.test.events.js +4 -4
- package/dist/input.test.focus.js +4 -4
- package/dist/input.test.translations.d.ts +1 -0
- package/dist/input.test.translations.js +38 -0
- package/dist/input.test.validity.js +133 -4
- package/dist/label.d.ts +1 -1
- package/dist/label.js +1 -1
- package/dist/label.styles.js +25 -13
- package/dist/label.test.basics.js +26 -24
- package/dist/library/expect-argument-error.js +1 -1
- package/dist/library/localize.d.ts +4 -1
- package/dist/menu.d.ts +3 -5
- package/dist/menu.js +1 -1
- package/dist/menu.options.test.basics.js +2 -2
- package/dist/menu.styles.js +1 -15
- package/dist/menu.test.basics.d.ts +1 -2
- package/dist/menu.test.basics.js +22 -6
- package/dist/menu.test.events.js +197 -7
- package/dist/menu.test.focus.d.ts +1 -0
- package/dist/menu.test.focus.js +13 -6
- package/dist/menu.test.interactions.js +214 -58
- package/dist/modal.icon-button.test.basics.js +1 -1
- package/dist/modal.js +1 -1
- package/dist/modal.stories.d.ts +1 -0
- package/dist/modal.styles.js +18 -13
- package/dist/modal.tertiary-icon.d.ts +0 -1
- package/dist/modal.tertiary-icon.js +1 -1
- package/dist/modal.tertiary-icon.test.basics.js +3 -3
- package/dist/modal.test.basics.js +1 -1
- package/dist/modal.test.events.js +10 -10
- package/dist/radio-group.d.ts +4 -3
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.stories.d.ts +1 -1
- package/dist/radio-group.styles.js +1 -1
- package/dist/radio-group.test.focus.js +3 -3
- package/dist/radio.d.ts +2 -2
- package/dist/radio.js +1 -1
- package/dist/radio.styles.js +33 -0
- package/dist/split-container.d.ts +1 -1
- package/dist/split-container.test.basics.js +4 -0
- package/dist/split-link.test.interactions.js +1 -1
- package/dist/status-indicator.d.ts +1 -1
- package/dist/styles/variables.css +1 -1
- package/dist/tab.d.ts +1 -1
- package/dist/tab.group.js +1 -1
- package/dist/tab.group.test.basics.js +1 -1
- package/dist/tab.group.test.interactions.js +198 -2
- package/dist/tab.js +1 -1
- package/dist/tab.panel.d.ts +1 -0
- package/dist/tab.panel.js +1 -1
- package/dist/tab.panel.styles.js +11 -1
- package/dist/tabs.stories.d.ts +1 -0
- package/dist/tag.d.ts +3 -6
- package/dist/tag.test.basics.js +2 -2
- package/dist/textarea.d.ts +4 -4
- package/dist/textarea.js +2 -2
- package/dist/textarea.stories.d.ts +3 -4
- package/dist/textarea.styles.js +14 -3
- package/dist/textarea.test.basics.js +80 -44
- package/dist/textarea.test.events.js +56 -41
- package/dist/textarea.test.translations.d.ts +1 -0
- package/dist/textarea.test.translations.js +34 -0
- package/dist/textarea.test.validity.js +104 -20
- package/dist/toasts.js +1 -1
- package/dist/toasts.styles.js +8 -1
- package/dist/toasts.test.basics.js +20 -0
- package/dist/toggle.d.ts +3 -3
- package/dist/toggle.js +1 -1
- package/dist/toggle.stories.d.ts +1 -1
- package/dist/toggle.test.focus.js +1 -1
- package/dist/toggle.test.interactions.d.ts +1 -0
- package/dist/{toggle.test.states.js → toggle.test.interactions.js} +26 -0
- package/dist/tooltip.d.ts +9 -7
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +90 -25
- package/dist/tooltip.test.basics.js +38 -3
- package/dist/tooltip.test.interactions.js +136 -34
- package/dist/translations/en.js +1 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/ja.js +1 -1
- package/dist/tree.d.ts +1 -2
- package/dist/tree.item.d.ts +1 -5
- package/dist/tree.item.icon-button.d.ts +1 -0
- package/dist/tree.item.icon-button.js +1 -1
- package/dist/tree.item.icon-button.test.basics.js +9 -0
- package/dist/tree.item.js +1 -1
- package/dist/tree.item.menu.d.ts +2 -1
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.item.menu.test.basics.js +15 -0
- package/dist/tree.item.styles.js +2 -0
- package/dist/tree.item.test.basics.d.ts +2 -1
- package/dist/tree.item.test.basics.js +46 -4
- package/dist/tree.js +1 -1
- package/dist/tree.test.basics.js +1 -1
- package/dist/tree.test.focus.js +91 -4
- package/package.json +3 -4
- package/dist/checkbox.test.states.js +0 -63
- package/dist/drawer.test.floating-components.d.ts +0 -1
- package/dist/drawer.test.floating-components.js +0 -52
- package/dist/library/set-containing-block.d.ts +0 -15
- package/dist/library/set-containing-block.js +0 -1
- package/dist/modal.test.floating-components.js +0 -63
- /package/dist/{checkbox.test.states.d.ts → button-group.button.test.focus.d.ts} +0 -0
- /package/dist/{modal.test.floating-components.d.ts → checkbox.test.interactions.d.ts} +0 -0
- /package/dist/{toggle.test.states.d.ts → dropdown.test.events.filterable.d.ts} +0 -0
package/dist/menu.d.ts
CHANGED
@@ -8,7 +8,7 @@ declare global {
|
|
8
8
|
/**
|
9
9
|
* @description A basic menu.
|
10
10
|
*
|
11
|
-
* @slot -
|
11
|
+
* @slot - `<glide-core-menu-options>`.
|
12
12
|
* @slot target - A focusable element against which Menu will be positioned. Opens and closes Menu when interacted with.
|
13
13
|
*/
|
14
14
|
export default class GlideCoreMenu extends LitElement {
|
@@ -18,15 +18,13 @@ export default class GlideCoreMenu extends LitElement {
|
|
18
18
|
get open(): boolean;
|
19
19
|
set open(isOpen: boolean);
|
20
20
|
placement: Placement;
|
21
|
-
containingBlock?: Element;
|
22
21
|
get size(): 'small' | 'large';
|
23
22
|
set size(size: 'small' | 'large');
|
24
23
|
connectedCallback(): void;
|
25
24
|
createRenderRoot(): ShadowRoot;
|
26
25
|
disconnectedCallback(): void;
|
27
26
|
firstUpdated(): void;
|
28
|
-
focus(): void;
|
27
|
+
focus(options?: FocusOptions): void;
|
28
|
+
private get isTargetDisabled();
|
29
29
|
render(): import("lit").TemplateResult<1>;
|
30
|
-
setContainingBlock(containingBlock: Element): void;
|
31
|
-
private isTargetDisabled;
|
32
30
|
}
|
package/dist/menu.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(e,t,i,o){var n,s=arguments.length,
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,i,o){var n,s=arguments.length,l=s<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,i,o);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(l=(s<3?n(l):s>3?n(t,i,l):n(t,i))||l);return s>3&&l&&Object.defineProperty(t,i,l),l};import{LitElement,html}from"lit";import{autoUpdate,computePosition,flip,offset}from"@floating-ui/dom";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{nanoid}from"nanoid";import GlideCoreMenuButton from"./menu.button.js";import GlideCoreMenuLink from"./menu.link.js";import GlideCoreMenuOptions from"./menu.options.js";import ow,{owSlot,owSlotType}from"./library/ow.js";import styles from"./menu.styles.js";let GlideCoreMenu=class GlideCoreMenu extends LitElement{constructor(){super(...arguments),this.placement="bottom-start",this.#e=createRef(),this.#t=createRef(),this.#i=!1,this.#o=!1,this.#n="large",this.#s=createRef(),this.#l=e=>{e.target&&e.target instanceof Node&&this.contains(e.target)||(this.open=!1,this.#a&&(this.#a.ariaActivedescendant=""))}}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}get open(){return this.#o}set open(e){this.#o=e,e&&!this.isTargetDisabled?this.#r():this.#c()}get size(){return this.#n}set size(e){this.#n=e,this.#a&&(this.#a.privateSize=e)}connectedCallback(){super.connectedCallback(),document.addEventListener("click",this.#l,{capture:!0})}createRenderRoot(){return this.#d=super.createRenderRoot(),this.#d}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("click",this.#l,{capture:!0})}firstUpdated(){ow(this.#a,ow.object.instanceOf(GlideCoreMenuOptions)),owSlot(this.#t.value),owSlot(this.#s.value),owSlotType(this.#t.value,[GlideCoreMenuOptions]),this.#t.value.popover="manual";const e=this.#h?.at(0);this.open&&e&&!this.isTargetDisabled&&(e.privateActive=!0,this.#r())}focus(e){this.#p&&"focus"in this.#p&&this.#p?.focus(e)}get isTargetDisabled(){const e=this.#p&&"disabled"in this.#p&&this.#p.disabled,t=this.#p&&"true"===this.#p.ariaDisabled;return Boolean(e)||Boolean(t)}render(){return html`<div class="component" @focusout="${this.#u}" ${ref(this.#e)}><slot class="target-slot" name="target" @click="${this.#m}" @keydown="${this.#f}" @slotchange="${this.#E}" ${ref(this.#s)}></slot><slot class="default-slot" @click="${this.#v}" @focusin="${this.#g}" @keydown="${this.#f}" @mouseover="${this.#w}" @slotchange="${this.#S}" ${ref(this.#t)}></slot></div>`}#C;#e;#t;#i;#o;#d;#n;#s;get#y(){return this.#h?.find((({privateActive:e})=>e))}#l;#c(){this.#C?.(),this.#a&&(this.#a.ariaActivedescendant=""),this.#p&&(this.#p.ariaExpanded="false"),this.#t.value?.hidePopover()}get#a(){const e=this.#t.value?.assignedElements().at(0);return e instanceof GlideCoreMenuOptions?e:null}#S(){ow(this.#a,ow.object.instanceOf(GlideCoreMenuOptions)),owSlot(this.#t.value),owSlotType(this.#t.value,[GlideCoreMenuOptions]);const e=this.#h?.at(0);e&&(e.privateActive=!0),this.#a.privateSize=this.size}#v(){this.open=!1}#g(e){(e.target instanceof GlideCoreMenuButton||e.target instanceof GlideCoreMenuLink)&&this.#y&&this.#a&&(e.target.privateActive=!0,this.#y.privateActive=!1,this.#a.ariaActivedescendant=e.target.id)}#w(e){if(e.target instanceof GlideCoreMenuLink||e.target instanceof GlideCoreMenuButton){if(this.#h)for(const t of this.#h)t.privateActive=t===e.target;this.#a&&(this.#a.ariaActivedescendant=e.target.id)}}#u(e){const t=e.relatedTarget instanceof HTMLElement&&this.#d?.contains(e.relatedTarget),i=e.relatedTarget instanceof GlideCoreMenuOptions,o=e.relatedTarget instanceof GlideCoreMenuButton||e.relatedTarget instanceof GlideCoreMenuLink;t||i||o||(this.open=!1)}#f(e){if(ow(this.#a,ow.object.instanceOf(GlideCoreMenuOptions)),[" ","Enter"].includes(e.key)&&this.open)return this.open=!1,this.focus(),this.#y?.dispatchEvent(new PointerEvent("click",{bubbles:!0})),void(this.#i=!0);if(["Escape"].includes(e.key)&&this.open)return this.open=!1,void this.focus();if([" ","ArrowUp","ArrowDown"].includes(e.key)&&!this.open&&this.#y)return e.preventDefault(),this.open=!0,void(this.#a.ariaActivedescendant=this.#y.id);if(this.open){ow(this.#h,ow.array),ow(this.#a,ow.object.instanceOf(GlideCoreMenuOptions)),ow(this.#y,ow.object.is((e=>e instanceof GlideCoreMenuButton||e instanceof GlideCoreMenuLink)));const t=this.#h.indexOf(this.#y);if("ArrowUp"===e.key&&!e.metaKey){e.preventDefault();const i=this.#h.at(t-1);return void(i&&0!==t&&(this.#y.privateActive=!1,this.#a.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowDown"===e.key&&!e.metaKey){e.preventDefault();const i=this.#h.at(t+1);return void(i&&(this.#y.privateActive=!1,this.#a.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowUp"===e.key&&e.metaKey||"Home"===e.key||"PageUp"===e.key){e.preventDefault();const t=this.#h.at(0);return void(t&&(this.#y.privateActive=!1,this.#a.ariaActivedescendant=t.id,t.privateActive=!0))}if("ArrowDown"===e.key&&e.metaKey||"End"===e.key||"PageDown"===e.key){e.preventDefault();const t=this.#h.at(-1);return void(t&&(this.#y.privateActive=!1,this.#a.ariaActivedescendant=t.id,t.privateActive=!0))}}}#E(){owSlot(this.#s.value),ow(this.#p,ow.object.instanceOf(Element)),ow(this.#a,ow.object.instanceOf(GlideCoreMenuOptions));new MutationObserver((e=>{e.some((e=>"disabled"===e.attributeName||"aria-disabled"===e.attributeName))&&(this.open&&!this.isTargetDisabled?this.#r():this.#c())})).observe(this.#p,{attributes:!0}),this.#p.ariaHasPopup="true",this.#p.id=nanoid(),this.#p.setAttribute("aria-controls",this.#a.id),this.#a.ariaLabelledby=this.#p.id,this.open&&!this.isTargetDisabled?this.#r():this.#c()}#m(){this.isTargetDisabled?this.#c():this.#i?this.#i=!1:this.#h&&this.#h.length>0&&(this.open=!this.open)}get#h(){let e=this.#t.value?.assignedElements()?.at(0)?.children;const t=e?.[0];if(t instanceof HTMLSlotElement&&(e=t.assignedElements()),e)return[...e].filter((e=>e instanceof GlideCoreMenuLink||e instanceof GlideCoreMenuButton))}#r(){this.#C?.(),this.#p&&this.#t.value&&(this.#C=autoUpdate(this.#p,this.#t.value,(()=>{(async()=>{if(this.#p&&this.#t.value){const{x:e,y:t,placement:i}=await computePosition(this.#p,this.#t.value,{placement:this.placement,middleware:[offset({mainAxis:Number.parseFloat(window.getComputedStyle(document.body).getPropertyValue("--glide-core-spacing-xxs"))*Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize)}),flip()]});this.#t.value.dataset.placement=i,Object.assign(this.#t.value.style,{left:`${e}px`,top:`${t}px`})}this.#t.value?.showPopover(),this.#a&&this.#y?.id&&(this.#a.ariaActivedescendant=this.#y.id),this.#p&&(this.#p.ariaExpanded="true")})()})))}get#p(){return this.#s.value?.assignedElements().at(0)}};__decorate([property({reflect:!0,type:Boolean})],GlideCoreMenu.prototype,"open",null),__decorate([property({reflect:!0})],GlideCoreMenu.prototype,"placement",void 0),__decorate([property({reflect:!0})],GlideCoreMenu.prototype,"size",null),GlideCoreMenu=__decorate([customElement("glide-core-menu")],GlideCoreMenu);export default GlideCoreMenu;
|
@@ -19,7 +19,7 @@ it('throws if it does not have a default slot', async () => {
|
|
19
19
|
spy();
|
20
20
|
}
|
21
21
|
}
|
22
|
-
expect(spy.
|
22
|
+
expect(spy.callCount).to.equal(1);
|
23
23
|
});
|
24
24
|
it('throws if the default slot is the incorrect type', async () => {
|
25
25
|
await expectArgumentError(() => {
|
@@ -40,5 +40,5 @@ it('does not throw if the default slot only contains whitespace', async () => {
|
|
40
40
|
spy();
|
41
41
|
}
|
42
42
|
}
|
43
|
-
expect(spy.
|
43
|
+
expect(spy.callCount).to.equal(0);
|
44
44
|
});
|
package/dist/menu.styles.js
CHANGED
@@ -20,25 +20,11 @@ import{css}from"lit";export default[css`
|
|
20
20
|
border-radius: var(--glide-core-spacing-xs);
|
21
21
|
box-shadow: var(--glide-core-shadow-lg);
|
22
22
|
box-sizing: border-box;
|
23
|
-
display: flex;
|
24
23
|
inline-size: max-content;
|
25
|
-
inset
|
26
|
-
inset-inline-start: 0;
|
24
|
+
inset: unset;
|
27
25
|
margin-block: 0;
|
28
26
|
min-inline-size: 9.375rem;
|
29
27
|
padding: var(--glide-core-spacing-xxxs);
|
30
28
|
position: absolute;
|
31
|
-
visibility: hidden;
|
32
|
-
|
33
|
-
/*
|
34
|
-
".container" is relative and many Menus may be stacked in a column.
|
35
|
-
This ensures the ".menu" of Menus earlier in the column aren't obscured
|
36
|
-
by the ".target-container" that come later.
|
37
|
-
*/
|
38
|
-
z-index: 1;
|
39
|
-
|
40
|
-
&.visible {
|
41
|
-
visibility: visible;
|
42
|
-
}
|
43
29
|
}
|
44
30
|
`];
|
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
import './menu.link.js';
|
1
|
+
export {};
|
package/dist/menu.test.basics.js
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
|
-
import './menu.button.js';
|
3
|
-
import './menu.link.js';
|
4
2
|
import { ArgumentError } from 'ow';
|
5
|
-
import { expect, fixture, html } from '@open-wc/testing';
|
3
|
+
import { aTimeout, expect, fixture, html } from '@open-wc/testing';
|
6
4
|
import GlideCoreMenu from './menu.js';
|
5
|
+
import GlideCoreMenuButton from './menu.button.js';
|
6
|
+
import GlideCoreMenuLink from './menu.link.js';
|
7
7
|
import GlideCoreMenuOptions from './menu.options.js';
|
8
8
|
import expectArgumentError from './library/expect-argument-error.js';
|
9
9
|
import sinon from 'sinon';
|
10
10
|
GlideCoreMenu.shadowRootOptions.mode = 'open';
|
11
|
+
GlideCoreMenuButton.shadowRootOptions.mode = 'open';
|
12
|
+
GlideCoreMenuLink.shadowRootOptions.mode = 'open';
|
11
13
|
it('registers', async () => {
|
12
14
|
expect(window.customElements.get('glide-core-menu')).to.equal(GlideCoreMenu);
|
13
15
|
});
|
@@ -38,6 +40,7 @@ it('is accessible', async () => {
|
|
38
40
|
const target = component.querySelector('button');
|
39
41
|
const options = component.querySelector('glide-core-menu-options');
|
40
42
|
expect(target?.getAttribute('aria-controls')).to.equal(options?.id);
|
43
|
+
expect(target?.getAttribute('aria-haspopup')).to.equal('true');
|
41
44
|
expect(options?.ariaLabelledby).to.equal(target?.id);
|
42
45
|
await expect(component).to.be.accessible();
|
43
46
|
});
|
@@ -49,11 +52,16 @@ it('can be opened', async () => {
|
|
49
52
|
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
50
53
|
</glide-core-menu-options>
|
51
54
|
</glide-core-menu>`);
|
55
|
+
// Wait for Floating UI.
|
56
|
+
await aTimeout(0);
|
52
57
|
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
58
|
+
const options = component.querySelector('glide-core-menu-options');
|
53
59
|
const target = component.querySelector('button');
|
60
|
+
const link = component.querySelector('glide-core-menu-link');
|
54
61
|
expect(component.open).to.be.true;
|
55
|
-
expect(defaultSlot?.checkVisibility(
|
62
|
+
expect(defaultSlot?.checkVisibility()).to.be.true;
|
56
63
|
expect(target?.ariaExpanded).to.equal('true');
|
64
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
|
57
65
|
});
|
58
66
|
it('can have a default slot', async () => {
|
59
67
|
const component = await fixture(html `<glide-core-menu>
|
@@ -92,6 +100,8 @@ it('activates the first menu link by default', async () => {
|
|
92
100
|
</glide-core-menu-options>
|
93
101
|
</glide-core-menu>
|
94
102
|
`);
|
103
|
+
// Wait for Floating UI.
|
104
|
+
await aTimeout(0);
|
95
105
|
const links = component.querySelectorAll('glide-core-menu-link');
|
96
106
|
const options = component.querySelector('glide-core-menu-options');
|
97
107
|
expect(links[0].privateActive).to.be.true;
|
@@ -109,6 +119,8 @@ it('activates the first menu button by default', async () => {
|
|
109
119
|
</glide-core-menu-options>
|
110
120
|
</glide-core-menu>
|
111
121
|
`);
|
122
|
+
// Wait for Floating UI.
|
123
|
+
await aTimeout(0);
|
112
124
|
const buttons = component.querySelectorAll('glide-core-menu-button');
|
113
125
|
const options = component.querySelector('glide-core-menu-options');
|
114
126
|
expect(buttons[0].privateActive).to.be.true;
|
@@ -123,10 +135,14 @@ it('is not opened when initially `open` and its target is `disabled`', async ()
|
|
123
135
|
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
124
136
|
</glide-core-menu-options>
|
125
137
|
</glide-core-menu>`);
|
138
|
+
// Wait for Floating UI.
|
139
|
+
await aTimeout(0);
|
126
140
|
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
127
141
|
const target = component.querySelector('button');
|
128
|
-
|
142
|
+
const options = component.querySelector('glide-core-menu-options');
|
143
|
+
expect(defaultSlot?.checkVisibility()).to.be.false;
|
129
144
|
expect(target?.ariaExpanded).to.equal('false');
|
145
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
130
146
|
});
|
131
147
|
it('throws if it does not have a default slot', async () => {
|
132
148
|
await expectArgumentError(() => {
|
@@ -157,7 +173,7 @@ it('throws if it does not have a "target" slot', async () => {
|
|
157
173
|
spy();
|
158
174
|
}
|
159
175
|
}
|
160
|
-
expect(spy.
|
176
|
+
expect(spy.callCount).to.equal(1);
|
161
177
|
});
|
162
178
|
it('sets accessibility attributes', async () => {
|
163
179
|
const component = await fixture(html `<glide-core-menu>
|
package/dist/menu.test.events.js
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
import './menu.js';
|
3
3
|
import './menu.link.js';
|
4
4
|
import './menu.options.js';
|
5
|
-
import { expect, fixture, html, oneEvent } from '@open-wc/testing';
|
6
|
-
|
5
|
+
import { aTimeout, assert, expect, fixture, html, oneEvent, } from '@open-wc/testing';
|
6
|
+
import { sendKeys } from '@web/test-runner-commands';
|
7
|
+
import sinon from 'sinon';
|
8
|
+
it('dispatches one link "click" event when a link is selected via click', async () => {
|
7
9
|
const component = await fixture(html `<glide-core-menu open>
|
8
10
|
<button slot="target">Target</button>
|
9
11
|
|
@@ -11,21 +13,209 @@ it('dispatches a "click" event when a link is clicked', async () => {
|
|
11
13
|
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
12
14
|
</glide-core-menu-options>
|
13
15
|
</glide-core-menu>`);
|
14
|
-
|
16
|
+
const spy = sinon.spy();
|
17
|
+
const link = component.querySelector('glide-core-menu-link');
|
18
|
+
assert(link);
|
19
|
+
link.addEventListener('click', spy);
|
20
|
+
setTimeout(() => link.click());
|
15
21
|
const event = await oneEvent(component, 'click');
|
16
22
|
expect(event instanceof PointerEvent).to.be.true;
|
17
23
|
expect(event.bubbles).to.be.true;
|
24
|
+
expect(event.target).to.equal(link);
|
25
|
+
expect(spy.callCount).to.equal(1);
|
18
26
|
});
|
19
|
-
it('dispatches
|
27
|
+
it('dispatches one button "click" event when a button is selected via click', async () => {
|
20
28
|
const component = await fixture(html `<glide-core-menu open>
|
21
29
|
<button slot="target">Target</button>
|
22
30
|
|
23
31
|
<glide-core-menu-options>
|
24
|
-
<glide-core-menu-button label="
|
32
|
+
<glide-core-menu-button label="Button"></glide-core-menu-button>
|
25
33
|
</glide-core-menu-options>
|
26
34
|
</glide-core-menu>`);
|
27
|
-
|
28
|
-
const
|
35
|
+
const spy = sinon.spy();
|
36
|
+
const button = component.querySelector('glide-core-menu-button');
|
37
|
+
assert(button);
|
38
|
+
button.addEventListener('click', spy);
|
39
|
+
setTimeout(() => button.click());
|
40
|
+
const event = await oneEvent(button, 'click');
|
41
|
+
expect(event instanceof PointerEvent).to.be.true;
|
42
|
+
expect(event.bubbles).to.be.true;
|
43
|
+
expect(event.target).to.equal(button);
|
44
|
+
expect(spy.callCount).to.equal(1);
|
45
|
+
});
|
46
|
+
it('dispatches one link "click" event when a link is selected via Space', async () => {
|
47
|
+
const component = await fixture(html `<glide-core-menu open>
|
48
|
+
<button slot="target">Target</button>
|
49
|
+
|
50
|
+
<glide-core-menu-options>
|
51
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
52
|
+
</glide-core-menu-options>
|
53
|
+
</glide-core-menu>`);
|
54
|
+
const spy = sinon.spy();
|
55
|
+
const link = component.querySelector('glide-core-menu-link');
|
56
|
+
assert(link);
|
57
|
+
link.addEventListener('click', spy);
|
58
|
+
component.focus();
|
59
|
+
sendKeys({ press: 'Space' });
|
60
|
+
const event = await oneEvent(link, 'click');
|
61
|
+
expect(event instanceof PointerEvent).to.be.true;
|
62
|
+
expect(event.bubbles).to.be.true;
|
63
|
+
expect(event.target).to.equal(link);
|
64
|
+
expect(spy.callCount).to.equal(1);
|
65
|
+
});
|
66
|
+
it('dispatches one button "click" event when a button is selected via Space', async () => {
|
67
|
+
const component = await fixture(html `<glide-core-menu open>
|
68
|
+
<button slot="target">Target</button>
|
69
|
+
|
70
|
+
<glide-core-menu-options>
|
71
|
+
<glide-core-menu-button label="Button"></glide-core-menu-button>
|
72
|
+
</glide-core-menu-options>
|
73
|
+
</glide-core-menu>`);
|
74
|
+
const spy = sinon.spy();
|
75
|
+
const button = component.querySelector('glide-core-menu-button');
|
76
|
+
assert(button);
|
77
|
+
button.addEventListener('click', spy);
|
78
|
+
component.focus();
|
79
|
+
sendKeys({ press: 'Space' });
|
80
|
+
const event = await oneEvent(button, 'click');
|
29
81
|
expect(event instanceof PointerEvent).to.be.true;
|
30
82
|
expect(event.bubbles).to.be.true;
|
83
|
+
expect(event.target).to.equal(button);
|
84
|
+
expect(spy.callCount).to.equal(1);
|
85
|
+
});
|
86
|
+
it('dispatches one link "click" event when a link is selected via Enter', async () => {
|
87
|
+
const component = await fixture(html `<glide-core-menu open>
|
88
|
+
<button slot="target">Target</button>
|
89
|
+
|
90
|
+
<glide-core-menu-options>
|
91
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
92
|
+
</glide-core-menu-options>
|
93
|
+
</glide-core-menu>`);
|
94
|
+
const spy = sinon.spy();
|
95
|
+
const link = component.querySelector('glide-core-menu-link');
|
96
|
+
assert(link);
|
97
|
+
link.addEventListener('click', spy);
|
98
|
+
component.focus();
|
99
|
+
sendKeys({ press: 'Enter' });
|
100
|
+
const event = await oneEvent(link, 'click');
|
101
|
+
expect(event instanceof PointerEvent).to.be.true;
|
102
|
+
expect(event.bubbles).to.be.true;
|
103
|
+
expect(event.target).to.equal(link);
|
104
|
+
expect(spy.callCount).to.equal(1);
|
105
|
+
});
|
106
|
+
it('dispatches one button "click" event when a button is selected via Enter', async () => {
|
107
|
+
const component = await fixture(html `<glide-core-menu open>
|
108
|
+
<button slot="target">Target</button>
|
109
|
+
|
110
|
+
<glide-core-menu-options>
|
111
|
+
<glide-core-menu-button label="Button"></glide-core-menu-button>
|
112
|
+
</glide-core-menu-options>
|
113
|
+
</glide-core-menu>`);
|
114
|
+
const spy = sinon.spy();
|
115
|
+
const button = component.querySelector('glide-core-menu-button');
|
116
|
+
assert(button);
|
117
|
+
button.addEventListener('click', spy);
|
118
|
+
component.focus();
|
119
|
+
sendKeys({ press: 'Enter' });
|
120
|
+
const event = await oneEvent(button, 'click');
|
121
|
+
expect(event instanceof PointerEvent).to.be.true;
|
122
|
+
expect(event.bubbles).to.be.true;
|
123
|
+
expect(event.target).to.equal(button);
|
124
|
+
expect(spy.callCount).to.equal(1);
|
125
|
+
});
|
126
|
+
it('does not dispatch a link "click" event when opened via click', async () => {
|
127
|
+
const component = await fixture(html `<glide-core-menu>
|
128
|
+
<button slot="target">Target</button>
|
129
|
+
|
130
|
+
<glide-core-menu-options>
|
131
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
132
|
+
</glide-core-menu-options>
|
133
|
+
</glide-core-menu>`);
|
134
|
+
const spy = sinon.spy();
|
135
|
+
const link = component.querySelector('glide-core-menu-link');
|
136
|
+
const target = component.querySelector('button');
|
137
|
+
link?.addEventListener('click', spy);
|
138
|
+
target?.click();
|
139
|
+
await aTimeout(0);
|
140
|
+
expect(spy.callCount).to.equal(0);
|
141
|
+
});
|
142
|
+
it('does not dispatch a button "click" event when opened via click', async () => {
|
143
|
+
const component = await fixture(html `<glide-core-menu>
|
144
|
+
<button slot="target">Target</button>
|
145
|
+
|
146
|
+
<glide-core-menu-options>
|
147
|
+
<glide-core-menu-button label="Button"></glide-core-menu-button>
|
148
|
+
</glide-core-menu-options>
|
149
|
+
</glide-core-menu>`);
|
150
|
+
const spy = sinon.spy();
|
151
|
+
const button = component.querySelector('glide-core-menu-button');
|
152
|
+
const target = component.querySelector('button');
|
153
|
+
button?.addEventListener('click', spy);
|
154
|
+
target?.click();
|
155
|
+
await aTimeout(0);
|
156
|
+
expect(spy.callCount).to.equal(0);
|
157
|
+
});
|
158
|
+
it('does not dispatch a link "click" event when opened via Space', async () => {
|
159
|
+
const component = await fixture(html `<glide-core-menu>
|
160
|
+
<button slot="target">Target</button>
|
161
|
+
|
162
|
+
<glide-core-menu-options>
|
163
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
164
|
+
</glide-core-menu-options>
|
165
|
+
</glide-core-menu>`);
|
166
|
+
const spy = sinon.spy();
|
167
|
+
const link = component.querySelector('glide-core-menu-link');
|
168
|
+
link?.addEventListener('click', spy);
|
169
|
+
component.focus();
|
170
|
+
sendKeys({ press: 'Space' });
|
171
|
+
await aTimeout(0);
|
172
|
+
expect(spy.callCount).to.equal(0);
|
173
|
+
});
|
174
|
+
it('does not dispatch a button "click" event when opened via Space', async () => {
|
175
|
+
const component = await fixture(html `<glide-core-menu>
|
176
|
+
<button slot="target">Target</button>
|
177
|
+
|
178
|
+
<glide-core-menu-options>
|
179
|
+
<glide-core-menu-button label="Link"></glide-core-menu-button>
|
180
|
+
</glide-core-menu-options>
|
181
|
+
</glide-core-menu>`);
|
182
|
+
const spy = sinon.spy();
|
183
|
+
const button = component.querySelector('glide-core-menu-button');
|
184
|
+
button?.addEventListener('click', spy);
|
185
|
+
component.focus();
|
186
|
+
sendKeys({ press: 'Space' });
|
187
|
+
await aTimeout(0);
|
188
|
+
expect(spy.callCount).to.equal(0);
|
189
|
+
});
|
190
|
+
it('does not dispatch a link "click" event when opened via Enter', async () => {
|
191
|
+
const component = await fixture(html `<glide-core-menu>
|
192
|
+
<button slot="target">Target</button>
|
193
|
+
|
194
|
+
<glide-core-menu-options>
|
195
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
196
|
+
</glide-core-menu-options>
|
197
|
+
</glide-core-menu>`);
|
198
|
+
const spy = sinon.spy();
|
199
|
+
const link = component.querySelector('glide-core-menu-link');
|
200
|
+
link?.addEventListener('click', spy);
|
201
|
+
component.focus();
|
202
|
+
sendKeys({ press: 'Enter' });
|
203
|
+
await aTimeout(0);
|
204
|
+
expect(spy.callCount).to.equal(0);
|
205
|
+
});
|
206
|
+
it('does not dispatch a button "click" event when opened via Enter', async () => {
|
207
|
+
const component = await fixture(html `<glide-core-menu>
|
208
|
+
<button slot="target">Target</button>
|
209
|
+
|
210
|
+
<glide-core-menu-options>
|
211
|
+
<glide-core-menu-button label="Link"></glide-core-menu-button>
|
212
|
+
</glide-core-menu-options>
|
213
|
+
</glide-core-menu>`);
|
214
|
+
const spy = sinon.spy();
|
215
|
+
const button = component.querySelector('glide-core-menu-button');
|
216
|
+
button?.addEventListener('click', spy);
|
217
|
+
component.focus();
|
218
|
+
sendKeys({ press: 'Enter' });
|
219
|
+
await aTimeout(0);
|
220
|
+
expect(spy.callCount).to.equal(0);
|
31
221
|
});
|
package/dist/menu.test.focus.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-expressions */
|
2
2
|
import './menu.link.js';
|
3
|
-
import
|
3
|
+
import './menu.options.js';
|
4
|
+
import { aTimeout, assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
|
4
5
|
import { sendKeys } from '@web/test-runner-commands';
|
5
6
|
import GlideCoreMenu from './menu.js';
|
6
|
-
import GlideCoreMenuOptions from './menu.options.js';
|
7
7
|
GlideCoreMenu.shadowRootOptions.mode = 'open';
|
8
8
|
it('focuses the target on `focus()`', async () => {
|
9
9
|
const component = await fixture(html `<glide-core-menu>
|
@@ -31,7 +31,7 @@ it('closes when it loses focus', async () => {
|
|
31
31
|
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
32
32
|
const options = component.querySelector('glide-core-menu-options');
|
33
33
|
expect(component.open).to.be.false;
|
34
|
-
expect(defaultSlot?.checkVisibility(
|
34
|
+
expect(defaultSlot?.checkVisibility()).be.false;
|
35
35
|
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
36
36
|
});
|
37
37
|
it('remains open when the options component is focused', async () => {
|
@@ -42,13 +42,14 @@ it('remains open when the options component is focused', async () => {
|
|
42
42
|
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
43
43
|
</glide-core-menu-options>
|
44
44
|
</glide-core-menu>`);
|
45
|
+
// Wait for Floating UI.
|
46
|
+
await aTimeout(0);
|
45
47
|
component.focus();
|
46
48
|
const options = component.querySelector('glide-core-menu-options');
|
47
|
-
assert(options instanceof GlideCoreMenuOptions);
|
48
|
-
options.focus();
|
49
49
|
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
50
|
+
options?.focus();
|
50
51
|
expect(component.open).to.be.true;
|
51
|
-
expect(defaultSlot?.checkVisibility(
|
52
|
+
expect(defaultSlot?.checkVisibility()).to.be.true;
|
52
53
|
});
|
53
54
|
it('remains open when an option is focused', async () => {
|
54
55
|
const component = await fixture(html `<glide-core-menu open>
|
@@ -58,11 +59,15 @@ it('remains open when an option is focused', async () => {
|
|
58
59
|
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
59
60
|
</glide-core-menu-options>
|
60
61
|
</glide-core-menu>`);
|
62
|
+
// Wait for Floating UI.
|
63
|
+
await aTimeout(0);
|
61
64
|
component.focus();
|
65
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
62
66
|
const option = component.querySelector('glide-core-menu-link');
|
63
67
|
assert(option);
|
64
68
|
option?.focus();
|
65
69
|
expect(component.open).to.be.true;
|
70
|
+
expect(defaultSlot?.checkVisibility()).to.be.true;
|
66
71
|
});
|
67
72
|
it('sets the focused option as active', async () => {
|
68
73
|
const component = await fixture(html `<glide-core-menu open>
|
@@ -73,6 +78,8 @@ it('sets the focused option as active', async () => {
|
|
73
78
|
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
74
79
|
</glide-core-menu-options>
|
75
80
|
</glide-core-menu>`);
|
81
|
+
// Wait for Floating UI.
|
82
|
+
await aTimeout(0);
|
76
83
|
component.focus();
|
77
84
|
const target = component.querySelector('glide-core-menu-button');
|
78
85
|
const link = component.querySelector('glide-core-menu-link');
|