@crowdstrike/glide-core 0.9.6 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -53
- package/dist/accordion.d.ts +10 -10
- package/dist/accordion.js +1 -1
- package/dist/accordion.stories.d.ts +0 -1
- package/dist/accordion.styles.js +36 -38
- package/dist/accordion.test.basics.js +13 -95
- package/dist/accordion.test.events.js +21 -33
- package/dist/accordion.test.focus.d.ts +1 -0
- package/dist/accordion.test.focus.js +11 -0
- package/dist/accordion.test.interactions.d.ts +1 -0
- package/dist/accordion.test.interactions.js +75 -0
- package/dist/button-group.button.d.ts +2 -4
- package/dist/button-group.button.js +1 -1
- package/dist/button-group.button.styles.js +6 -14
- package/dist/button-group.button.test.basics.js +8 -17
- package/dist/button-group.button.test.interactions.js +4 -4
- package/dist/button-group.d.ts +0 -2
- package/dist/button-group.test.basics.js +10 -10
- package/dist/button-group.test.events.js +2 -2
- package/dist/button-group.test.interactions.js +1 -1
- package/dist/button.d.ts +7 -10
- package/dist/button.js +1 -1
- package/dist/button.styles.js +4 -7
- package/dist/button.test.basics.js +10 -26
- package/dist/button.test.events.js +9 -9
- package/dist/checkbox-group.d.ts +3 -4
- package/dist/checkbox-group.js +1 -1
- package/dist/checkbox-group.styles.js +13 -1
- package/dist/checkbox-group.test.basics.js +8 -12
- package/dist/checkbox-group.test.focus.js +7 -7
- package/dist/checkbox-group.test.interactions.d.ts +1 -0
- package/dist/checkbox-group.test.interactions.js +82 -0
- package/dist/checkbox.d.ts +5 -4
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.styles.js +35 -15
- package/dist/checkbox.test.basics.js +6 -15
- package/dist/checkbox.test.events.js +9 -0
- package/dist/checkbox.test.focus.js +4 -2
- package/dist/checkbox.test.interactions.js +11 -11
- package/dist/drawer.d.ts +2 -5
- package/dist/drawer.js +1 -1
- package/dist/drawer.test.accessibility.js +8 -8
- package/dist/drawer.test.basics.js +16 -16
- package/dist/drawer.test.closing.js +18 -16
- package/dist/drawer.test.events.js +13 -24
- package/dist/drawer.test.methods.js +22 -22
- package/dist/dropdown.d.ts +7 -5
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.d.ts +2 -3
- package/dist/dropdown.option.js +1 -1
- package/dist/dropdown.option.styles.js +31 -19
- package/dist/dropdown.option.test.basics.js +4 -4
- package/dist/dropdown.option.test.events.js +9 -1
- package/dist/dropdown.option.test.interactions.single.js +2 -2
- package/dist/dropdown.styles.js +39 -3
- package/dist/dropdown.test.basics.d.ts +1 -1
- package/dist/dropdown.test.basics.js +27 -14
- package/dist/dropdown.test.basics.multiple.js +65 -32
- package/dist/dropdown.test.basics.single.js +49 -0
- package/dist/dropdown.test.events.filterable.js +13 -2
- package/dist/dropdown.test.focus.filterable.js +12 -3
- package/dist/dropdown.test.focus.js +18 -2
- package/dist/dropdown.test.form.multiple.js +3 -2
- package/dist/dropdown.test.interactions.filterable.js +141 -45
- package/dist/dropdown.test.interactions.js +24 -0
- package/dist/dropdown.test.interactions.multiple.js +87 -30
- package/dist/dropdown.test.interactions.single.js +40 -4
- package/dist/form-controls-layout.d.ts +0 -2
- package/dist/icon-button.d.ts +2 -4
- package/dist/icon-button.js +1 -1
- package/dist/icon-button.test.basics.js +14 -82
- package/dist/icon-button.test.focus.d.ts +1 -0
- package/dist/icon-button.test.focus.js +13 -0
- package/dist/input.d.ts +4 -5
- package/dist/input.js +1 -1
- package/dist/input.styles.js +4 -4
- package/dist/input.test.basics.js +0 -52
- package/dist/input.test.events.js +27 -27
- package/dist/input.test.focus.js +27 -26
- package/dist/input.test.form.js +6 -6
- package/dist/input.test.validity.js +130 -130
- package/dist/label.d.ts +1 -3
- package/dist/label.js +1 -1
- package/dist/label.styles.js +5 -6
- package/dist/label.test.basics.js +4 -4
- package/dist/library/ow.js +1 -1
- package/dist/menu.button.d.ts +0 -2
- package/dist/menu.button.test.basics.js +3 -3
- package/dist/menu.d.ts +1 -4
- package/dist/menu.js +1 -1
- package/dist/menu.link.d.ts +1 -2
- package/dist/menu.link.js +1 -1
- package/dist/menu.options.d.ts +0 -2
- package/dist/menu.test.events.js +6 -6
- package/dist/menu.test.focus.js +5 -18
- package/dist/menu.test.interactions.js +48 -24
- package/dist/modal.d.ts +6 -17
- package/dist/modal.icon-button.d.ts +0 -2
- package/dist/modal.icon-button.test.basics.js +3 -3
- package/dist/modal.js +1 -1
- package/dist/modal.styles.js +13 -19
- package/dist/modal.tertiary-icon.d.ts +0 -3
- package/dist/modal.tertiary-icon.test.basics.js +3 -3
- package/dist/modal.test.basics.js +9 -5
- package/dist/modal.test.close.js +2 -2
- package/dist/modal.test.events.js +2 -2
- package/dist/radio-group.d.ts +0 -3
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.test.basics.js +61 -61
- package/dist/radio-group.test.events.js +13 -13
- package/dist/radio-group.test.focus.js +1 -1
- package/dist/radio-group.test.form.js +2 -2
- package/dist/radio-group.test.validity.js +12 -12
- package/dist/radio.d.ts +0 -3
- package/dist/radio.styles.js +4 -12
- package/dist/split-button.d.ts +8 -11
- package/dist/split-button.js +1 -1
- package/dist/split-button.primary-button.d.ts +21 -0
- package/dist/split-button.primary-button.js +1 -0
- package/dist/split-button.primary-button.styles.js +96 -0
- package/dist/split-button.primary-button.test.basics.d.ts +1 -0
- package/dist/split-button.primary-button.test.basics.js +31 -0
- package/dist/split-button.primary-button.test.focus.d.ts +1 -0
- package/dist/split-button.primary-button.test.focus.js +14 -0
- package/dist/split-button.primary-link.d.ts +19 -0
- package/dist/split-button.primary-link.js +1 -0
- package/dist/split-button.primary-link.test.basics.d.ts +1 -0
- package/dist/split-button.primary-link.test.basics.js +30 -0
- package/dist/split-button.primary-link.test.focus.d.ts +1 -0
- package/dist/split-button.primary-link.test.focus.js +15 -0
- package/dist/split-button.secondary-button.d.ts +25 -0
- package/dist/split-button.secondary-button.js +1 -0
- package/dist/split-button.secondary-button.styles.js +103 -0
- package/dist/split-button.secondary-button.test.basics.d.ts +1 -0
- package/dist/split-button.secondary-button.test.basics.js +58 -0
- package/dist/split-button.secondary-button.test.focus.d.ts +1 -0
- package/dist/split-button.secondary-button.test.focus.js +14 -0
- package/dist/split-button.secondary-button.test.interactions.d.ts +2 -0
- package/dist/split-button.secondary-button.test.interactions.js +30 -0
- package/dist/split-button.stories.d.ts +4 -3
- package/dist/split-button.styles.js +1 -94
- package/dist/split-button.test.basics.d.ts +2 -1
- package/dist/split-button.test.basics.js +67 -80
- package/dist/split-button.test.interactions.d.ts +4 -0
- package/dist/split-button.test.interactions.js +51 -0
- package/dist/styles/opacity-and-scale-animation.js +2 -6
- package/dist/styles/variables.css +1 -1
- package/dist/tab.d.ts +2 -11
- package/dist/tab.group.d.ts +3 -5
- package/dist/tab.group.js +1 -1
- package/dist/tab.group.styles.js +18 -15
- package/dist/tab.group.test.basics.js +49 -34
- package/dist/tab.group.test.interactions.js +17 -14
- package/dist/tab.panel.d.ts +0 -3
- package/dist/tab.test.basics.js +6 -5
- package/dist/tag.d.ts +5 -4
- package/dist/tag.js +1 -1
- package/dist/tag.styles.js +47 -38
- package/dist/tag.test.basics.js +18 -110
- package/dist/tag.test.events.js +12 -8
- package/dist/tag.test.focus.js +2 -3
- package/dist/tag.test.interactions.d.ts +1 -0
- package/dist/tag.test.interactions.js +36 -0
- package/dist/textarea.d.ts +2 -3
- package/dist/textarea.js +2 -2
- package/dist/textarea.test.basics.js +8 -8
- package/dist/textarea.test.events.js +55 -55
- package/dist/textarea.test.form.js +9 -9
- package/dist/textarea.test.validity.js +167 -135
- package/dist/toasts.d.ts +1 -5
- package/dist/toasts.test.basics.js +2 -1
- package/dist/toasts.toast.d.ts +1 -4
- package/dist/toasts.toast.js +1 -1
- package/dist/toasts.toast.styles.js +12 -0
- package/dist/toggle.d.ts +0 -2
- package/dist/toggle.styles.js +1 -5
- package/dist/toggle.test.basics.js +2 -2
- package/dist/toggle.test.interactions.js +7 -7
- package/dist/tooltip.d.ts +2 -1
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +37 -13
- package/dist/tooltip.test.basics.d.ts +1 -1
- package/dist/tooltip.test.basics.js +19 -19
- package/dist/tree.d.ts +0 -2
- package/dist/tree.item.d.ts +5 -7
- package/dist/tree.item.icon-button.d.ts +1 -4
- package/dist/tree.item.js +1 -1
- package/dist/tree.item.menu.d.ts +1 -2
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.item.menu.test.basics.js +31 -10
- package/dist/tree.item.styles.js +7 -9
- package/dist/tree.item.test.basics.js +43 -31
- package/dist/tree.test.basics.js +29 -29
- package/dist/tree.test.focus.js +77 -74
- package/package.json +12 -14
- package/dist/split-container.d.ts +0 -31
- package/dist/split-container.js +0 -1
- package/dist/split-container.styles.js +0 -132
- package/dist/split-container.test.basics.d.ts +0 -3
- package/dist/split-container.test.basics.js +0 -445
- package/dist/split-container.test.interactions.d.ts +0 -1
- package/dist/split-container.test.interactions.js +0 -20
- package/dist/split-link.d.ts +0 -25
- package/dist/split-link.js +0 -1
- package/dist/split-link.test.basics.d.ts +0 -1
- package/dist/split-link.test.basics.js +0 -93
- package/dist/split-link.test.interactions.d.ts +0 -1
- package/dist/split-link.test.interactions.js +0 -20
- package/dist/status-indicator.d.ts +0 -30
- package/dist/status-indicator.js +0 -1
- package/dist/status-indicator.stories.d.ts +0 -5
- package/dist/status-indicator.styles.js +0 -58
- package/dist/status-indicator.test.basics.d.ts +0 -1
- package/dist/status-indicator.test.basics.js +0 -102
- /package/dist/{split-container.styles.d.ts → split-button.primary-button.styles.d.ts} +0 -0
- /package/dist/{status-indicator.styles.d.ts → split-button.secondary-button.styles.d.ts} +0 -0
@@ -13,9 +13,9 @@ it('has defaults', async () => {
|
|
13
13
|
<input id="input" slot="control" />
|
14
14
|
</glide-core-private-label>`);
|
15
15
|
expect(component.getAttribute('error')).to.equal(null);
|
16
|
-
expect(component.error).to.
|
16
|
+
expect(component.error).to.be.false;
|
17
17
|
expect(component.getAttribute('hide')).to.equal(null);
|
18
|
-
expect(component.hide).to.
|
18
|
+
expect(component.hide).to.be.false;
|
19
19
|
expect(component.getAttribute('orientation')).to.equal('horizontal');
|
20
20
|
expect(component.orientation).to.equal('horizontal');
|
21
21
|
expect(component.hasAttribute('required')).to.be.false;
|
@@ -68,7 +68,7 @@ it('can be required', async () => {
|
|
68
68
|
<input id="input" slot="control" />
|
69
69
|
</glide-core-private-label>`);
|
70
70
|
expect(component.hasAttribute('required')).to.be.true;
|
71
|
-
expect(component.required).to.
|
71
|
+
expect(component.required).to.be.true;
|
72
72
|
const label = component.shadowRoot?.querySelector('[data-test="label"]');
|
73
73
|
expect(label?.textContent?.includes('*')).to.be.true;
|
74
74
|
});
|
@@ -78,7 +78,7 @@ it('can have an `error`', async () => {
|
|
78
78
|
<input id="input" slot="control" />
|
79
79
|
</glide-core-private-label>`);
|
80
80
|
expect(component.hasAttribute('error')).to.be.true;
|
81
|
-
expect(component.error).to.
|
81
|
+
expect(component.error).to.be.true;
|
82
82
|
});
|
83
83
|
it('places the tooltip on the bottom when horizontal', async () => {
|
84
84
|
const component = await fixture(html `<glide-core-private-label>
|
package/dist/library/ow.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
import ow,{}from"ow";const isDevelopment=window.location.host.startsWith("localhost")||window.location.host.startsWith("127.0.0.1");export function owSlot(e){isDevelopment&&(ow(e,ow.object.is((e=>e instanceof HTMLSlotElement))),ow(e.assignedNodes().length,ow.number.is((e=>e>0)).message(e.name?`Expected a "${e.name}" slot.`:"Expected a default slot.")))}export function owSlotType(e,o=[]){if(isDevelopment&&(ow(e,ow.object.is((e=>e instanceof HTMLSlotElement))),0!==e.assignedNodes().length&&o.length>0)){const t=e.assignedNodes({flatten:!0}).filter((e=>!!(e instanceof Text&&o.includes(Text))||!(e instanceof Text)));ow(t.length,ow.number.is((e=>e>0)).message(`Expected a slotted
|
1
|
+
import ow,{}from"ow";const isDevelopment=window.location.host.startsWith("localhost")||window.location.host.startsWith("127.0.0.1");export function owSlot(e){isDevelopment&&(ow(e,ow.object.is((e=>e instanceof HTMLSlotElement))),ow(e.assignedNodes().length,ow.number.is((e=>e>0)).message(e.name?`Expected a "${e.name}" slot.`:"Expected a default slot.")))}export function owSlotType(e,o=[]){if(isDevelopment&&(ow(e,ow.object.is((e=>e instanceof HTMLSlotElement))),0!==e.assignedNodes().length&&o.length>0)){const t=e.assignedNodes({flatten:!0}).filter((e=>!!(e instanceof Text&&o.includes(Text))||!(e instanceof Text)));ow(t.length,ow.number.is((e=>e>0)).message(`Expected a slotted element that extends ${o.map((({name:e})=>e)).join(" or ")}.`));for(const e of t){const t=`Expected slotted element to extend ${o.map((({name:e})=>e)).join(" or ")}. Extends ${e.constructor.name} instead.`,n=o.some((o=>e instanceof o));ow(n,ow.boolean.true.message(t))}}}const shim=new Proxy((()=>{}),{get:()=>shim,apply:()=>shim}),owOrShim=isDevelopment?ow:shim;export default owOrShim;
|
package/dist/menu.button.d.ts
CHANGED
@@ -11,11 +11,11 @@ it('has defaults', async () => {
|
|
11
11
|
// typechecked, which means supplying required attributes up front.
|
12
12
|
const component = await fixture(html `<glide-core-menu-button label="Label"></glide-core-menu-button>`);
|
13
13
|
// Not reflected. So no attribute assertions are necessary.
|
14
|
-
expect(component.privateActive).to.
|
14
|
+
expect(component.privateActive).to.be.false;
|
15
15
|
});
|
16
16
|
it('can have a label', async () => {
|
17
|
-
const
|
18
|
-
expect(
|
17
|
+
const component = await fixture(html `<glide-core-menu-button label="Label"></glide-core-menu-button>`);
|
18
|
+
expect(component.shadowRoot?.textContent?.trim()).to.equal('Label');
|
19
19
|
});
|
20
20
|
it('can have an icon', async () => {
|
21
21
|
const component = await fixture(html `<glide-core-menu-button label="Label">
|
package/dist/menu.d.ts
CHANGED
@@ -6,9 +6,7 @@ declare global {
|
|
6
6
|
}
|
7
7
|
}
|
8
8
|
/**
|
9
|
-
* @
|
10
|
-
*
|
11
|
-
* @slot - `<glide-core-menu-options>`.
|
9
|
+
* @slot - One of `<glide-core-menu-options>`.
|
12
10
|
* @slot target - A focusable element against which Menu will be positioned. Opens and closes Menu when interacted with.
|
13
11
|
*/
|
14
12
|
export default class GlideCoreMenu extends LitElement {
|
@@ -24,7 +22,6 @@ export default class GlideCoreMenu extends LitElement {
|
|
24
22
|
createRenderRoot(): ShadowRoot;
|
25
23
|
disconnectedCallback(): void;
|
26
24
|
firstUpdated(): void;
|
27
|
-
focus(options?: FocusOptions): void;
|
28
25
|
private get isTargetDisabled();
|
29
26
|
render(): import("lit").TemplateResult<1>;
|
30
27
|
}
|
package/dist/menu.js
CHANGED
@@ -1 +1 @@
|
|
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.#
|
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=!1,this.#s="large",this.#l=createRef(),this.#a=()=>{this.#n?this.#n=!1:(this.open=!1,this.#r&&(this.#r.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.#c():this.#h()}get size(){return this.#s}set size(e){this.#s=e,this.#r&&(this.#r.privateSize=e)}connectedCallback(){super.connectedCallback(),document.addEventListener("click",this.#a,{capture:!0})}createRenderRoot(){return this.#d=super.createRenderRoot(),this.#d}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("click",this.#a,{capture:!0})}firstUpdated(){ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),owSlot(this.#t.value),owSlot(this.#l.value),owSlotType(this.#t.value,[GlideCoreMenuOptions]),this.#t.value.popover="manual";const e=this.#p?.at(0);this.open&&e&&!this.isTargetDisabled&&(e.privateActive=!0,this.#c()),this.#l.value.addEventListener("mouseup",(()=>{this.#n=!0}))}get isTargetDisabled(){const e=this.#u&&"disabled"in this.#u&&this.#u.disabled,t=this.#u&&"true"===this.#u.ariaDisabled;return Boolean(e)||Boolean(t)}render(){return html`<div class="component" @focusout="${this.#m}" ${ref(this.#e)}><slot class="target-slot" name="target" @click="${this.#f}" @keydown="${this.#E}" @slotchange="${this.#v}" ${ref(this.#l)}></slot><slot class="default-slot" @click="${this.#g}" @focusin="${this.#S}" @keydown="${this.#E}" @mouseover="${this.#w}" @slotchange="${this.#C}" ${ref(this.#t)}></slot></div>`}#y;#e;#t;#i;#o;#n;#d;#s;#l;get#R(){return this.#p?.find((({privateActive:e})=>e))}#a;#k(e){this.#u&&"focus"in this.#u&&this.#u?.focus(e)}#h(){this.#y?.(),this.#r&&(this.#r.ariaActivedescendant=""),this.#u&&(this.#u.ariaExpanded="false"),this.#t.value?.hidePopover()}get#r(){const e=this.#t.value?.assignedElements().at(0);return e instanceof GlideCoreMenuOptions?e:null}#C(){ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),owSlot(this.#t.value),owSlotType(this.#t.value,[GlideCoreMenuOptions]);const e=this.#p?.at(0);e&&(e.privateActive=!0),this.#r.privateSize=this.size}#g(){this.open=!1}#S(e){(e.target instanceof GlideCoreMenuButton||e.target instanceof GlideCoreMenuLink)&&this.#R&&this.#r&&(this.#R.privateActive=!1,e.target.privateActive=!0,this.#r.ariaActivedescendant=e.target.id)}#w(e){if(e.target instanceof GlideCoreMenuLink||e.target instanceof GlideCoreMenuButton){if(this.#p)for(const t of this.#p)t.privateActive=t===e.target;this.#r&&(this.#r.ariaActivedescendant=e.target.id)}}#m(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)}#E(e){if(ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),[" ","Enter"].includes(e.key)&&this.open)return this.open=!1,this.#k(),this.#R?.click(),void(this.#i=!0);if(["Escape"].includes(e.key)&&this.open)return this.open=!1,void this.#k();if(["ArrowUp","ArrowDown"].includes(e.key)&&!this.open&&this.#R)return e.preventDefault(),this.open=!0,void(this.#r.ariaActivedescendant=this.#R.id);if(this.open){ow(this.#p,ow.array),ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),ow(this.#R,ow.object.is((e=>e instanceof GlideCoreMenuButton||e instanceof GlideCoreMenuLink)));const t=this.#p.indexOf(this.#R);if("ArrowUp"===e.key&&!e.metaKey){e.preventDefault();const i=this.#p.at(t-1);return void(i&&0!==t&&(this.#R.privateActive=!1,this.#r.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowDown"===e.key&&!e.metaKey){e.preventDefault();const i=this.#p.at(t+1);return void(i&&(this.#R.privateActive=!1,this.#r.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowUp"===e.key&&e.metaKey||"Home"===e.key||"PageUp"===e.key){e.preventDefault();const t=this.#p.at(0);return void(t&&(this.#R.privateActive=!1,this.#r.ariaActivedescendant=t.id,t.privateActive=!0))}if("ArrowDown"===e.key&&e.metaKey||"End"===e.key||"PageDown"===e.key){e.preventDefault();const t=this.#p.at(-1);return void(t&&(this.#R.privateActive=!1,this.#r.ariaActivedescendant=t.id,t.privateActive=!0))}}}#v(){owSlot(this.#l.value),ow(this.#u,ow.object.instanceOf(Element)),ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions));new MutationObserver((()=>{this.open&&!this.isTargetDisabled?this.#c():this.#h()})).observe(this.#u,{attributes:!0,attributeFilter:["aria-disabled","disabled"]}),this.#u.ariaHasPopup="true",this.#u.id=nanoid(),this.#u.setAttribute("aria-controls",this.#r.id),this.#r.ariaLabelledby=this.#u.id,this.open&&!this.isTargetDisabled?this.#c():this.#h()}#f(){this.isTargetDisabled?this.#h():this.#i?this.#i=!1:this.#p&&this.#p.length>0&&(this.open=!this.open)}get#p(){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))}#c(){this.#y?.(),this.#u&&this.#t.value&&(this.#y=autoUpdate(this.#u,this.#t.value,(()=>{(async()=>{if(this.#u&&this.#t.value){const{x:e,y:t,placement:i}=await computePosition(this.#u,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.#r&&this.#R?.id&&(this.#r.ariaActivedescendant=this.#R.id),this.#u&&(this.#u.ariaExpanded="true")})()})))}get#u(){return this.#l.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;
|
package/dist/menu.link.d.ts
CHANGED
@@ -5,8 +5,6 @@ declare global {
|
|
5
5
|
}
|
6
6
|
}
|
7
7
|
/**
|
8
|
-
* @description A link for use within a <glide-core-menu>.
|
9
|
-
*
|
10
8
|
* @slot icon - An icon.
|
11
9
|
*/
|
12
10
|
export default class GlideCoreMenuLink extends LitElement {
|
@@ -16,6 +14,7 @@ export default class GlideCoreMenuLink extends LitElement {
|
|
16
14
|
label?: string;
|
17
15
|
url?: string;
|
18
16
|
privateActive: boolean;
|
17
|
+
click(): void;
|
19
18
|
connectedCallback(): void;
|
20
19
|
render(): import("lit").TemplateResult<1>;
|
21
20
|
}
|
package/dist/menu.link.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(e,t,i,o){var r,n=arguments.length,l=n<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 s=e.length-1;s>=0;s--)(r=e[s])&&(l=(n<3?r(l):n>3?r(t,i,l):r(t,i))||l);return n>3&&l&&Object.defineProperty(t,i,l),l};import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{nanoid}from"nanoid";import styles from"./menu.link.styles.js";let GlideCoreMenuLink=class GlideCoreMenuLink extends LitElement{constructor(){super(...arguments),this.privateActive=!1,this.#e=nanoid()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}connectedCallback(){super.connectedCallback(),this.id=this.#
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,i,o){var r,n=arguments.length,l=n<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 s=e.length-1;s>=0;s--)(r=e[s])&&(l=(n<3?r(l):n>3?r(t,i,l):r(t,i))||l);return n>3&&l&&Object.defineProperty(t,i,l),l};import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{nanoid}from"nanoid";import styles from"./menu.link.styles.js";let GlideCoreMenuLink=class GlideCoreMenuLink extends LitElement{constructor(){super(...arguments),this.privateActive=!1,this.#e=createRef(),this.#t=nanoid()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}click(){this.#e.value?.click()}connectedCallback(){super.connectedCallback(),this.id=this.#t,this.role="menuitem",this.tabIndex=-1}render(){return html`<a class="${classMap({component:!0,active:this.privateActive})}" data-test="component" href="${ifDefined(this.url)}" ${ref(this.#e)}><slot name="icon"></slot>${this.label}</a>`}#e;#t};__decorate([property({reflect:!0})],GlideCoreMenuLink.prototype,"label",void 0),__decorate([property({reflect:!0})],GlideCoreMenuLink.prototype,"url",void 0),__decorate([property({type:Boolean})],GlideCoreMenuLink.prototype,"privateActive",void 0),GlideCoreMenuLink=__decorate([customElement("glide-core-menu-link")],GlideCoreMenuLink);export default GlideCoreMenuLink;
|
package/dist/menu.options.d.ts
CHANGED
package/dist/menu.test.events.js
CHANGED
@@ -55,8 +55,8 @@ it('dispatches one link "click" event when a link is selected via Space', async
|
|
55
55
|
const link = component.querySelector('glide-core-menu-link');
|
56
56
|
assert(link);
|
57
57
|
link.addEventListener('click', spy);
|
58
|
-
component.focus();
|
59
|
-
sendKeys({ press: '
|
58
|
+
component.querySelector('button')?.focus();
|
59
|
+
sendKeys({ press: ' ' });
|
60
60
|
const event = await oneEvent(link, 'click');
|
61
61
|
expect(event instanceof PointerEvent).to.be.true;
|
62
62
|
expect(event.bubbles).to.be.true;
|
@@ -75,8 +75,8 @@ it('dispatches one button "click" event when a button is selected via Space', as
|
|
75
75
|
const button = component.querySelector('glide-core-menu-button');
|
76
76
|
assert(button);
|
77
77
|
button.addEventListener('click', spy);
|
78
|
-
component.focus();
|
79
|
-
sendKeys({ press: '
|
78
|
+
component.querySelector('button')?.focus();
|
79
|
+
sendKeys({ press: ' ' });
|
80
80
|
const event = await oneEvent(button, 'click');
|
81
81
|
expect(event instanceof PointerEvent).to.be.true;
|
82
82
|
expect(event.bubbles).to.be.true;
|
@@ -95,7 +95,7 @@ it('dispatches one link "click" event when a link is selected via Enter', async
|
|
95
95
|
const link = component.querySelector('glide-core-menu-link');
|
96
96
|
assert(link);
|
97
97
|
link.addEventListener('click', spy);
|
98
|
-
component.focus();
|
98
|
+
component.querySelector('button')?.focus();
|
99
99
|
sendKeys({ press: 'Enter' });
|
100
100
|
const event = await oneEvent(link, 'click');
|
101
101
|
expect(event instanceof PointerEvent).to.be.true;
|
@@ -115,7 +115,7 @@ it('dispatches one button "click" event when a button is selected via Enter', as
|
|
115
115
|
const button = component.querySelector('glide-core-menu-button');
|
116
116
|
assert(button);
|
117
117
|
button.addEventListener('click', spy);
|
118
|
-
component.focus();
|
118
|
+
component.querySelector('button')?.focus();
|
119
119
|
sendKeys({ press: 'Enter' });
|
120
120
|
const event = await oneEvent(button, 'click');
|
121
121
|
expect(event instanceof PointerEvent).to.be.true;
|
package/dist/menu.test.focus.js
CHANGED
@@ -5,19 +5,6 @@ import { aTimeout, assert, elementUpdated, expect, fixture, html, } from '@open-
|
|
5
5
|
import { sendKeys } from '@web/test-runner-commands';
|
6
6
|
import GlideCoreMenu from './menu.js';
|
7
7
|
GlideCoreMenu.shadowRootOptions.mode = 'open';
|
8
|
-
it('focuses the target on `focus()`', async () => {
|
9
|
-
const component = await fixture(html `<glide-core-menu>
|
10
|
-
<button slot="target">Target</button>
|
11
|
-
|
12
|
-
<glide-core-menu-options>
|
13
|
-
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
14
|
-
</glide-core-menu-options>
|
15
|
-
</glide-core-menu>`);
|
16
|
-
component.focus();
|
17
|
-
const target = component.querySelector('button');
|
18
|
-
assert(target);
|
19
|
-
expect(document.activeElement).to.equal(target);
|
20
|
-
});
|
21
8
|
it('closes when it loses focus', async () => {
|
22
9
|
const component = await fixture(html `<glide-core-menu open>
|
23
10
|
<button slot="target">Target</button>
|
@@ -26,7 +13,7 @@ it('closes when it loses focus', async () => {
|
|
26
13
|
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
27
14
|
</glide-core-menu-options>
|
28
15
|
</glide-core-menu>`);
|
29
|
-
component.focus();
|
16
|
+
component.querySelector('button')?.focus();
|
30
17
|
await sendKeys({ press: 'Tab' });
|
31
18
|
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
32
19
|
const options = component.querySelector('glide-core-menu-options');
|
@@ -44,7 +31,7 @@ it('remains open when the options component is focused', async () => {
|
|
44
31
|
</glide-core-menu>`);
|
45
32
|
// Wait for Floating UI.
|
46
33
|
await aTimeout(0);
|
47
|
-
component.focus();
|
34
|
+
component.querySelector('button')?.focus();
|
48
35
|
const options = component.querySelector('glide-core-menu-options');
|
49
36
|
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
50
37
|
options?.focus();
|
@@ -61,7 +48,7 @@ it('remains open when an option is focused', async () => {
|
|
61
48
|
</glide-core-menu>`);
|
62
49
|
// Wait for Floating UI.
|
63
50
|
await aTimeout(0);
|
64
|
-
component.focus();
|
51
|
+
component.querySelector('button')?.focus();
|
65
52
|
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
66
53
|
const option = component.querySelector('glide-core-menu-link');
|
67
54
|
assert(option);
|
@@ -80,7 +67,7 @@ it('sets an inactive option as active when focused', async () => {
|
|
80
67
|
</glide-core-menu>`);
|
81
68
|
// Wait for Floating UI.
|
82
69
|
await aTimeout(0);
|
83
|
-
component.focus();
|
70
|
+
component.querySelector('button')?.focus();
|
84
71
|
const button = component.querySelector('glide-core-menu-button');
|
85
72
|
const link = component.querySelector('glide-core-menu-link');
|
86
73
|
const options = component.querySelector('glide-core-menu-options');
|
@@ -103,7 +90,7 @@ it('sets an already active option as active when focused', async () => {
|
|
103
90
|
</glide-core-menu>`);
|
104
91
|
// Wait for Floating UI.
|
105
92
|
await aTimeout(0);
|
106
|
-
component.focus();
|
93
|
+
component.querySelector('button')?.focus();
|
107
94
|
const button = component.querySelector('glide-core-menu-button');
|
108
95
|
const link = component.querySelector('glide-core-menu-link');
|
109
96
|
const options = component.querySelector('glide-core-menu-options');
|
@@ -11,6 +11,7 @@ import { LitElement } from 'lit';
|
|
11
11
|
import { aTimeout, assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
|
12
12
|
import { customElement } from 'lit/decorators.js';
|
13
13
|
import { sendKeys } from '@web/test-runner-commands';
|
14
|
+
import { sendMouse } from '@web/test-runner-commands';
|
14
15
|
import GlideCoreMenu from './menu.js';
|
15
16
|
let GlideCoreNestedSlot = class GlideCoreNestedSlot extends LitElement {
|
16
17
|
static { this.shadowRootOptions = {
|
@@ -30,8 +31,27 @@ let GlideCoreNestedSlot = class GlideCoreNestedSlot extends LitElement {
|
|
30
31
|
GlideCoreNestedSlot = __decorate([
|
31
32
|
customElement('glide-core-nested-slot')
|
32
33
|
], GlideCoreNestedSlot);
|
34
|
+
let GlideCoreMenuInAnotherComponent = class GlideCoreMenuInAnotherComponent extends LitElement {
|
35
|
+
static { this.shadowRootOptions = {
|
36
|
+
...LitElement.shadowRootOptions,
|
37
|
+
mode: 'closed',
|
38
|
+
}; }
|
39
|
+
render() {
|
40
|
+
return html `<glide-core-menu open>
|
41
|
+
<button slot="target">Target</button>
|
42
|
+
|
43
|
+
<glide-core-menu-options>
|
44
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
45
|
+
</glide-core-menu-options>
|
46
|
+
</glide-core-menu>`;
|
47
|
+
}
|
48
|
+
};
|
49
|
+
GlideCoreMenuInAnotherComponent = __decorate([
|
50
|
+
customElement('glide-core-menu-in-another-component')
|
51
|
+
], GlideCoreMenuInAnotherComponent);
|
33
52
|
GlideCoreMenu.shadowRootOptions.mode = 'open';
|
34
53
|
GlideCoreNestedSlot.shadowRootOptions.mode = 'open';
|
54
|
+
GlideCoreMenuInAnotherComponent.shadowRootOptions.mode = 'open';
|
35
55
|
it('opens on click', async () => {
|
36
56
|
const component = await fixture(html `<glide-core-menu>
|
37
57
|
<button slot="target">Target</button>
|
@@ -377,19 +397,23 @@ it('sets `privateSize` on the options component when `size` is changed programma
|
|
377
397
|
const options = component.querySelector('glide-core-menu-options');
|
378
398
|
expect(options?.privateSize).to.equal('small');
|
379
399
|
});
|
380
|
-
it('closes when clicked', async () => {
|
381
|
-
const component = await fixture(html `<glide-core-menu
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
400
|
+
it('closes when its target clicked', async () => {
|
401
|
+
const component = await fixture(html `<glide-core-menu-in-another-component></glide-core-menu-in-another-component>`);
|
402
|
+
// Wait for it to open.
|
403
|
+
await aTimeout(0);
|
404
|
+
const target = component.shadowRoot?.querySelector('button');
|
405
|
+
assert(target);
|
406
|
+
const { x, y } = target.getBoundingClientRect();
|
407
|
+
// Calling `click()` won't do because Menu relies on a "mouseup" event to
|
408
|
+
// decide if it should close.
|
409
|
+
await sendMouse({
|
410
|
+
type: 'click',
|
411
|
+
position: [Math.ceil(x), Math.ceil(y)],
|
412
|
+
});
|
413
|
+
const menu = component.shadowRoot?.querySelector('glide-core-menu');
|
414
|
+
const defaultSlot = menu?.shadowRoot?.querySelector('slot:not([name])');
|
415
|
+
const options = menu?.querySelector('glide-core-menu-options');
|
416
|
+
expect(menu?.open).to.be.false;
|
393
417
|
expect(defaultSlot?.checkVisibility()).to.be.false;
|
394
418
|
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
395
419
|
expect(target?.ariaExpanded).to.equal('false');
|
@@ -422,7 +446,7 @@ it('closes on Escape', async () => {
|
|
422
446
|
</glide-core-menu>`);
|
423
447
|
// Wait for it to open
|
424
448
|
await aTimeout(0);
|
425
|
-
component.focus();
|
449
|
+
component.querySelector('button')?.focus();
|
426
450
|
await sendKeys({ press: 'Escape' });
|
427
451
|
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
428
452
|
const options = component.querySelector('glide-core-menu-options');
|
@@ -457,7 +481,7 @@ it('closes when an option is selected via Enter', async () => {
|
|
457
481
|
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
458
482
|
</glide-core-menu-options>
|
459
483
|
</glide-core-menu>`);
|
460
|
-
component.focus();
|
484
|
+
component.querySelector('button')?.focus();
|
461
485
|
component
|
462
486
|
.querySelector('glide-core-menu-link')
|
463
487
|
?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
@@ -478,7 +502,7 @@ it('closes when an option is selected via Space', async () => {
|
|
478
502
|
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
479
503
|
</glide-core-menu-options>
|
480
504
|
</glide-core-menu>`);
|
481
|
-
component.focus();
|
505
|
+
component.querySelector('button')?.focus();
|
482
506
|
await sendKeys({ press: ' ' });
|
483
507
|
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
484
508
|
const options = component.querySelector('glide-core-menu-options');
|
@@ -617,7 +641,7 @@ it('activates the next option on ArrowDown', async () => {
|
|
617
641
|
`);
|
618
642
|
// Wait for Floating UI.
|
619
643
|
await aTimeout(0);
|
620
|
-
component.focus();
|
644
|
+
component.querySelector('button')?.focus();
|
621
645
|
const links = component.querySelectorAll('glide-core-menu-link');
|
622
646
|
const options = component.querySelector('glide-core-menu-options');
|
623
647
|
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
@@ -640,7 +664,7 @@ it('activates the previous option on ArrowUp', async () => {
|
|
640
664
|
`);
|
641
665
|
// Wait for Floating UI.
|
642
666
|
await aTimeout(0);
|
643
|
-
component.focus();
|
667
|
+
component.querySelector('button')?.focus();
|
644
668
|
const links = component.querySelectorAll('glide-core-menu-link');
|
645
669
|
const options = component.querySelector('glide-core-menu-options');
|
646
670
|
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
@@ -662,7 +686,7 @@ it('activates the first option on Home', async () => {
|
|
662
686
|
`);
|
663
687
|
// Wait for Floating UI.
|
664
688
|
await aTimeout(0);
|
665
|
-
component.focus();
|
689
|
+
component.querySelector('button')?.focus();
|
666
690
|
const links = component.querySelectorAll('glide-core-menu-link');
|
667
691
|
const options = component.querySelector('glide-core-menu-options');
|
668
692
|
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
@@ -684,7 +708,7 @@ it('activates the first option on PageUp', async () => {
|
|
684
708
|
`);
|
685
709
|
// Wait for Floating UI.
|
686
710
|
await aTimeout(0);
|
687
|
-
component.focus();
|
711
|
+
component.querySelector('button')?.focus();
|
688
712
|
const links = component.querySelectorAll('glide-core-menu-link');
|
689
713
|
const options = component.querySelector('glide-core-menu-options');
|
690
714
|
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
@@ -706,7 +730,7 @@ it('activates the first option on Meta + ArrowUp', async () => {
|
|
706
730
|
`);
|
707
731
|
// Wait for Floating UI.
|
708
732
|
await aTimeout(0);
|
709
|
-
component.focus();
|
733
|
+
component.querySelector('button')?.focus();
|
710
734
|
const links = component.querySelectorAll('glide-core-menu-link');
|
711
735
|
const options = component.querySelector('glide-core-menu-options');
|
712
736
|
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
@@ -730,7 +754,7 @@ it('activates the last option on End', async () => {
|
|
730
754
|
`);
|
731
755
|
// Wait for Floating UI.
|
732
756
|
await aTimeout(0);
|
733
|
-
component.focus();
|
757
|
+
component.querySelector('button')?.focus();
|
734
758
|
await sendKeys({ press: 'End' });
|
735
759
|
const links = component.querySelectorAll('glide-core-menu-link');
|
736
760
|
const options = component.querySelector('glide-core-menu-options');
|
@@ -752,7 +776,7 @@ it('activates the last option on PageDown', async () => {
|
|
752
776
|
component.querySelector('button')?.click();
|
753
777
|
// Wait for Floating UI.
|
754
778
|
await aTimeout(0);
|
755
|
-
component.focus();
|
779
|
+
component.querySelector('button')?.focus();
|
756
780
|
const links = component.querySelectorAll('glide-core-menu-link');
|
757
781
|
const options = component.querySelector('glide-core-menu-options');
|
758
782
|
links[0].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
@@ -774,7 +798,7 @@ it('activates the last option on Meta + ArrowDown', async () => {
|
|
774
798
|
`);
|
775
799
|
// Wait for Floating UI.
|
776
800
|
await aTimeout(0);
|
777
|
-
component.focus();
|
801
|
+
component.querySelector('button')?.focus();
|
778
802
|
const links = component.querySelectorAll('glide-core-menu-link');
|
779
803
|
const options = component.querySelector('glide-core-menu-options');
|
780
804
|
links[0].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
package/dist/modal.d.ts
CHANGED
@@ -6,31 +6,20 @@ declare global {
|
|
6
6
|
}
|
7
7
|
}
|
8
8
|
/**
|
9
|
-
* @
|
10
|
-
*
|
11
|
-
* @event close - Emitted when the Modal closes.
|
9
|
+
* @event close - `(event: "close", listener: (event: Event)) => void) => void`
|
12
10
|
*
|
13
11
|
* @slot - The content of the modal.
|
14
|
-
*
|
15
|
-
* @slot
|
16
|
-
*
|
17
|
-
*
|
18
|
-
* @slot primary - A slot for rendering a primary action button. Normally a "Continue", "Next", or "Submit" action.
|
19
|
-
*
|
20
|
-
* @slot secondary - A slot for rendering a secondary action button. Normally a "Cancel" action.
|
21
|
-
*
|
22
|
-
* @slot tertiary - A slot for rendering an icon+tooltip for additional information,
|
23
|
-
* or a tertiary action button.
|
12
|
+
* @slot header-actions - One or more of `<glide-core-modal-icon-button>`.
|
13
|
+
* @slot primary - One of `<glide-core-button>`.
|
14
|
+
* @slot secondary - One of `<glide-core-button>`.
|
15
|
+
* @slot tertiary - One or more of `<glide-core-button>` or `<glide-core-modal-tertiary-icon>`.
|
24
16
|
*/
|
25
17
|
export default class GlideCoreModal extends LitElement {
|
26
18
|
#private;
|
27
19
|
static shadowRootOptions: ShadowRootInit;
|
28
20
|
static styles: import("lit").CSSResult[];
|
29
|
-
/** The title text for the Modal. */
|
30
21
|
label: string;
|
31
|
-
|
32
|
-
showBackButton: boolean;
|
33
|
-
/** Fixed-size options for the Modal. */
|
22
|
+
backButton: boolean;
|
34
23
|
size?: 'small' | 'medium' | 'large' | 'xlarge';
|
35
24
|
close(): void;
|
36
25
|
connectedCallback(): void;
|
@@ -6,8 +6,6 @@ declare global {
|
|
6
6
|
}
|
7
7
|
}
|
8
8
|
/**
|
9
|
-
* @description A Modal Icon Button. Should be used only in the "header-actions" slot of a Modal.
|
10
|
-
*
|
11
9
|
* @slot - The content of the button. Should only be an icon. The icon should also leverage the
|
12
10
|
* "label" attribute for accessibility so that it is read to screenreaders.
|
13
11
|
*
|
@@ -18,19 +18,19 @@ it('renders and sets default attributes', async () => {
|
|
18
18
|
expect(component).to.be.ok;
|
19
19
|
const buttonElement = component.shadowRoot?.querySelector('glide-core-icon-button');
|
20
20
|
expect(buttonElement).to.be.not.null;
|
21
|
-
expect(buttonElement).to.
|
21
|
+
expect(buttonElement?.getAttribute('variant')).to.equal('tertiary');
|
22
22
|
});
|
23
23
|
it('adds an accessible label when given', async () => {
|
24
24
|
const component = await fixture(html `<glide-core-modal-icon-button label="test-label"
|
25
25
|
>Test</glide-core-modal-icon-button
|
26
26
|
>`);
|
27
27
|
const buttonElement = component.shadowRoot?.querySelector('glide-core-icon-button');
|
28
|
-
expect(buttonElement).to.
|
28
|
+
expect(buttonElement?.getAttribute('label')).to.equal('test-label');
|
29
29
|
});
|
30
30
|
it('does not add an acceessible label when not given', async () => {
|
31
31
|
const component = await fixture(html `<glide-core-modal-icon-button>Test</glide-core-modal-icon-button>`);
|
32
32
|
const buttonElement = component.shadowRoot?.querySelector('glide-core-icon-button');
|
33
|
-
expect(buttonElement).to.
|
33
|
+
expect(buttonElement?.getAttribute('label')).to.equal('');
|
34
34
|
});
|
35
35
|
it('throws if it does not have a default slot', async () => {
|
36
36
|
const spy = sinon.spy();
|
package/dist/modal.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var __decorate=this&&this.__decorate||function(e,t,o,l){var n,r=arguments.length,i=r<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,l);else for(var s=e.length-1;s>=0;s--)(n=e[s])&&(i=(r<3?n(i):r>3?n(t,o,i):n(t,o))||i);return r>3&&i&&Object.defineProperty(t,o,i),i};import"./modal.icon-button.js";import{LitElement,html}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}from"lit/decorators.js";import{when}from"lit/directives/when.js";import GlideCoreButton from"./button.js";import GlideCoreModalIconButton from"./modal.icon-button.js";import GlideCoreModalTertiaryIcon from"./modal.tertiary-icon.js";import ow,{owSlot,owSlotType}from"./library/ow.js";import styles from"./modal.styles.js";const globalStylesheet=new CSSStyleSheet;globalStylesheet.insertRule("\n @supports (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n scrollbar-gutter: stable !important;\n overflow: hidden !important;\n }\n }\n"),globalStylesheet.insertRule("\n @supports not (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n padding-right: var(--glide-scroll-size, 0.9375rem) !important;\n overflow: hidden !important;\n }\n }\n");let GlideCoreModal=class GlideCoreModal extends LitElement{constructor(){super(...arguments),this.label="",this.
|
1
|
+
var __decorate=this&&this.__decorate||function(e,t,o,l){var n,r=arguments.length,i=r<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,l);else for(var s=e.length-1;s>=0;s--)(n=e[s])&&(i=(r<3?n(i):r>3?n(t,o,i):n(t,o))||i);return r>3&&i&&Object.defineProperty(t,o,i),i};import"./modal.icon-button.js";import{LitElement,html}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}from"lit/decorators.js";import{when}from"lit/directives/when.js";import GlideCoreButton from"./button.js";import GlideCoreModalIconButton from"./modal.icon-button.js";import GlideCoreModalTertiaryIcon from"./modal.tertiary-icon.js";import ow,{owSlot,owSlotType}from"./library/ow.js";import styles from"./modal.styles.js";const globalStylesheet=new CSSStyleSheet;globalStylesheet.insertRule("\n @supports (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n scrollbar-gutter: stable !important;\n overflow: hidden !important;\n }\n }\n"),globalStylesheet.insertRule("\n @supports not (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n padding-right: var(--glide-scroll-size, 0.9375rem) !important;\n overflow: hidden !important;\n }\n }\n");let GlideCoreModal=class GlideCoreModal extends LitElement{constructor(){super(...arguments),this.label="",this.backButton=!1,this.size="medium",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=createRef(),this.#n=createRef(),this.#r=createRef(),this.#i=new LocalizeController(this)}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}close(){this.#e.value?.open&&(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}connectedCallback(){super.connectedCallback();document.adoptedStyleSheets.includes(globalStylesheet)||document.adoptedStyleSheets.push(globalStylesheet)}disconnectedCallback(){super.disconnectedCallback(),document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),document.adoptedStyleSheets=document.adoptedStyleSheets.filter((e=>e!==globalStylesheet))}firstUpdated(){owSlot(this.#t.value),owSlotType(this.#r.value,[GlideCoreModalIconButton]),owSlotType(this.#o.value,[GlideCoreButton]),owSlotType(this.#l.value,[GlideCoreButton]),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}render(){return html`<dialog class="${classMap({component:!0,small:"small"===this.size,medium:"medium"===this.size,large:"large"===this.size,xlarge:"xlarge"===this.size})}" tabindex="-1" @keydown="${this.#s}" @mousedown="${this.#a}" ${ref(this.#e)}><header class="header"><h2 class="label" data-test="heading" id="heading">${when(this.backButton,(()=>html`<glide-core-modal-icon-button class="icon-button" data-test="back-button" @click="${this.#c}"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("dismiss")}</title><path d="M12 18C11.4477 18 11 18.4477 11 19C11 19.5523 11.4477 20 12 20V18ZM20 14.5C20 16.433 18.433 18 16.5 18V20C19.5376 20 22 17.5376 22 14.5H20ZM16.5 11C18.433 11 20 12.567 20 14.5H22C22 11.4624 19.5376 9 16.5 9V11ZM16.5 18H12V20H16.5V18ZM16.5 9H3V11H16.5V9Z" fill="currentColor"/><path d="M7 6L3 10L7 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button>`))} ${this.label}</h2><div class="header-actions" role="toolbar"><slot name="header-actions" @slotchange="${this.#d}" ${ref(this.#r)}></slot><glide-core-modal-icon-button class="icon-button" data-test="close-button" @click="${this.#c}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("close")}</title><path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button></div></header><article aria-labelledby="heading" class="body" role="region" tabindex="0"><slot @slotchange="${this.#m}" ${ref(this.#t)}></slot></article><footer class="footer"><menu class="menu"><li class="flex align-center"><slot name="tertiary" @slotchange="${this.#u}" ${ref(this.#n)}></slot></li><li><menu class="actions"><li><slot name="secondary" @slotchange="${this.#h}" ${ref(this.#l)}></slot></li><li><slot name="primary" @slotchange="${this.#f}" ${ref(this.#o)}></slot></li></menu></li></menu></footer></dialog>`}showModal(){if(!this.#e.value?.open){if(document.documentElement.classList.add("private-glide-core-modal-lock-scroll"),!window.CSS.supports("scrollbar-gutter","stable")){const e=Math.abs(window.innerWidth-document.documentElement.clientWidth);document.documentElement.style.setProperty("--glide-scroll-size",`${e}px`)}this.#e.value?.showModal(),this.#e.value?.focus()}}#e;#t;#o;#l;#n;#r;#i;#c(){document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close()}#m(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlot(this.#t.value)}#f(){owSlotType(this.#o.value,[GlideCoreButton])}#h(){owSlotType(this.#l.value,[GlideCoreButton])}#u(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}#d(){owSlotType(this.#r.value,[GlideCoreModalIconButton])}#s(e){"Escape"===e.key&&(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}#a(e){if(e.target!==this.#e.value)return;const t=this.#e.value?.getBoundingClientRect();if(t){t.top<=e.clientY&&e.clientY<=t.top+t.height&&t.left<=e.clientX&&e.clientX<=t.left+t.width||(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}}};__decorate([property({reflect:!0})],GlideCoreModal.prototype,"label",void 0),__decorate([property({attribute:"back-button",type:Boolean,reflect:!0})],GlideCoreModal.prototype,"backButton",void 0),__decorate([property({reflect:!0})],GlideCoreModal.prototype,"size",void 0),GlideCoreModal=__decorate([customElement("glide-core-modal")],GlideCoreModal);export default GlideCoreModal;
|
package/dist/modal.styles.js
CHANGED
@@ -24,22 +24,6 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
24
24
|
}
|
25
25
|
}
|
26
26
|
|
27
|
-
@media (prefers-reduced-motion) {
|
28
|
-
/**
|
29
|
-
':host' is targeted here to increase specificity so that
|
30
|
-
we don't need to use '!important' to turn off the animation.
|
31
|
-
*/
|
32
|
-
:host .component {
|
33
|
-
&[open] {
|
34
|
-
animation: none;
|
35
|
-
}
|
36
|
-
|
37
|
-
&::backdrop {
|
38
|
-
animation: none;
|
39
|
-
}
|
40
|
-
}
|
41
|
-
}
|
42
|
-
|
43
27
|
.component {
|
44
28
|
backdrop-filter: blur(100px);
|
45
29
|
background-color: var(--glide-core-surface-modal);
|
@@ -54,8 +38,11 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
54
38
|
padding: 1.25rem;
|
55
39
|
|
56
40
|
&[open] {
|
57
|
-
animation: modal-open 250ms;
|
58
41
|
opacity: 1;
|
42
|
+
|
43
|
+
@media (prefers-reduced-motion: no-preference) {
|
44
|
+
animation: modal-open 250ms;
|
45
|
+
}
|
59
46
|
}
|
60
47
|
|
61
48
|
&:focus {
|
@@ -63,18 +50,21 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
63
50
|
}
|
64
51
|
|
65
52
|
&::backdrop {
|
66
|
-
animation: backdrop-fade-in 250ms;
|
67
|
-
|
68
53
|
/* prefix required for Safari */
|
69
54
|
/* stylelint-disable-next-line property-no-vendor-prefix */
|
70
55
|
-webkit-backdrop-filter: blur(3px);
|
71
56
|
backdrop-filter: blur(3px);
|
72
57
|
background-color: rgba(0 0 0 / 40%);
|
58
|
+
|
59
|
+
@media (prefers-reduced-motion: no-preference) {
|
60
|
+
animation: backdrop-fade-in 250ms;
|
61
|
+
}
|
73
62
|
}
|
74
63
|
|
75
64
|
::slotted([slot='tertiary']) {
|
76
65
|
--size: 1rem;
|
77
66
|
|
67
|
+
display: contents;
|
78
68
|
size: 1rem;
|
79
69
|
}
|
80
70
|
}
|
@@ -123,6 +113,10 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
|
|
123
113
|
line-height: 1;
|
124
114
|
}
|
125
115
|
|
116
|
+
.icon-button {
|
117
|
+
display: contents;
|
118
|
+
}
|
119
|
+
|
126
120
|
.body {
|
127
121
|
line-height: 1;
|
128
122
|
overflow: auto;
|
@@ -6,9 +6,6 @@ declare global {
|
|
6
6
|
}
|
7
7
|
}
|
8
8
|
/**
|
9
|
-
* @description A Modal tertiary icon wrapper. Provides opinionated styling and accessibility for icons in Modals.
|
10
|
-
* Should be used only in the "tertiary" slot of a Modal.
|
11
|
-
*
|
12
9
|
* @slot - The icon to be rendered.
|
13
10
|
*/
|
14
11
|
export default class GlideCoreModalTertiaryIcon extends LitElement {
|