@crowdstrike/glide-core 0.6.1 → 0.6.3

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.
Files changed (59) hide show
  1. package/dist/button.styles.js +1 -1
  2. package/dist/checkbox-group.d.ts +1 -0
  3. package/dist/checkbox-group.js +1 -1
  4. package/dist/checkbox-group.styles.js +1 -1
  5. package/dist/checkbox.d.ts +1 -0
  6. package/dist/checkbox.js +1 -1
  7. package/dist/checkbox.styles.js +3 -0
  8. package/dist/dropdown.d.ts +1 -0
  9. package/dist/dropdown.js +1 -1
  10. package/dist/dropdown.styles.js +1 -1
  11. package/dist/dropdown.test.events.multiple.js +62 -0
  12. package/dist/dropdown.test.events.single.d.ts +1 -0
  13. package/dist/dropdown.test.events.single.js +47 -0
  14. package/dist/form-controls-layout.d.ts +23 -0
  15. package/dist/form-controls-layout.js +1 -0
  16. package/dist/form-controls-layout.stories.d.ts +10 -0
  17. package/dist/form-controls-layout.styles.d.ts +2 -0
  18. package/dist/form-controls-layout.styles.js +7 -0
  19. package/dist/form-controls-layout.test.basics.d.ts +2 -0
  20. package/dist/form-controls-layout.test.basics.js +74 -0
  21. package/dist/form-controls-layout.test.interactions.d.ts +2 -0
  22. package/dist/form-controls-layout.test.interactions.js +26 -0
  23. package/dist/input.d.ts +1 -0
  24. package/dist/input.js +1 -1
  25. package/dist/input.test.basics.js +6 -0
  26. package/dist/label.d.ts +3 -0
  27. package/dist/label.js +1 -1
  28. package/dist/label.styles.js +24 -3
  29. package/dist/label.test.basics.js +9 -5
  30. package/dist/library/ow.d.ts +2 -2
  31. package/dist/menu.js +1 -1
  32. package/dist/menu.test.basics.js +3 -10
  33. package/dist/menu.test.events.d.ts +2 -0
  34. package/dist/menu.test.events.js +30 -0
  35. package/dist/menu.test.interactions.js +129 -36
  36. package/dist/modal.js +1 -1
  37. package/dist/modal.tertiary-icon.js +1 -1
  38. package/dist/radio-group.d.ts +1 -0
  39. package/dist/radio-group.js +1 -1
  40. package/dist/radio-group.styles.js +1 -1
  41. package/dist/split-container.styles.js +1 -1
  42. package/dist/styles/variables.css +1 -1
  43. package/dist/textarea.d.ts +1 -0
  44. package/dist/textarea.js +2 -2
  45. package/dist/textarea.styles.js +1 -1
  46. package/dist/toasts.d.ts +1 -1
  47. package/dist/toasts.js +1 -1
  48. package/dist/toggle.d.ts +1 -0
  49. package/dist/toggle.js +1 -1
  50. package/dist/tooltip.d.ts +1 -1
  51. package/dist/tooltip.js +1 -1
  52. package/dist/tooltip.styles.js +3 -0
  53. package/dist/tooltip.test.interactions.js +22 -0
  54. package/dist/tree.item.d.ts +0 -3
  55. package/dist/tree.item.js +1 -1
  56. package/dist/tree.item.menu.d.ts +2 -0
  57. package/dist/tree.item.menu.js +1 -1
  58. package/dist/tree.item.menu.test.basics.js +17 -0
  59. package/package.json +2 -2
package/dist/label.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(t,e,o,l){var i,r=arguments.length,s=r<3?e:null===l?l=Object.getOwnPropertyDescriptor(e,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,o,l);else for(var a=t.length-1;a>=0;a--)(i=t[a])&&(s=(r<3?i(s):r>3?i(e,o,s):i(e,o))||s);return r>3&&s&&Object.defineProperty(e,o,s),s};import"./tooltip.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,state}from"lit/decorators.js";import{owSlot}from"./library/ow.js";import styles from"./label.styles.js";import{svg}from"lit";const infoCircleIcon=svg`<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"><path d="M12 16L12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="8" r="1" fill="currentColor">`;let GlideCoreLabel=class GlideCoreLabel extends LitElement{constructor(){super(...arguments),this.disabled=!1,this.error=!1,this.hide=!1,this.orientation="horizontal",this.required=!1,this.hasDescriptionSlot=!1,this.hasSummarySlot=!1,this.hasTooltipSlot=!1,this.#t=createRef(),this.#e=createRef(),this.#o=createRef(),this.#l=new LocalizeController(this),this.#i=createRef(),this.#r=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#e.value),owSlot(this.#t.value)}render(){return html`<div class="${classMap({component:!0,horizontal:"horizontal"===this.orientation,vertical:"vertical"===this.orientation,"hidden-label":this.hide})}"><div class="${classMap({"tooltip-and-label":!0,hidden:this.hide})}" part="tooltip-and-label-container"><div class="tooltip-and-label"><glide-core-tooltip class="${classMap({tooltip:!0,vertical:"vertical"===this.orientation,visible:this.hasTooltipSlot})}" placement="${"vertical"===this.orientation?"right":"bottom"}"><span class="tooltip-target" slot="target" tabindex="0"><svg aria-label="${this.#l.term("moreInformation")}" width="16" height="16" viewBox="0 0 24 24" fill="none">${infoCircleIcon}</svg></span><slot class="${classMap({tooltip:!0,visible:this.hasTooltipSlot})}" name="tooltip" @slotchange="${this.#s}" ${ref(this.#r)}></slot></glide-core-tooltip><div class="${classMap({label:!0,disabled:this.disabled})}" data-test="label"><slot @slotchange="${this.#a}" ${ref(this.#e)}></slot>${this.required?html`<span aria-hidden="true" class="required-symbol">*</span>`:""}</div></div></div><div class="control-and-summary"><slot class="${classMap({control:!0,error:this.error,disabled:this.disabled,vertical:"vertical"===this.orientation,summaryless:!this.hasSummarySlot,"hidden-label":this.hide})}" name="control" @slotchange="${this.#n}" ${ref(this.#t)}></slot><slot class="${classMap({summary:!0,error:this.error})}" name="summary" @slotchange="${this.#c}" ${ref(this.#i)}></slot></div><slot class="${classMap({description:!0,visible:this.hasDescriptionSlot,error:this.error,tooltip:this.hasTooltipSlot})}" id="description" name="description" @slotchange="${this.#d}" ${ref(this.#o)}></slot></div>`}#t;#e;#o;#l;#i;#r;#n(){owSlot(this.#t.value)}#a(){owSlot(this.#e.value)}#d(){const t=this.#o.value?.assignedNodes({flatten:!0});this.hasDescriptionSlot=Boolean(t&&t.length>0)}#c(){const t=this.#i.value?.assignedNodes({flatten:!0});this.hasSummarySlot=Boolean(t&&t.length>0)}#s(){const t=this.#r.value?.assignedNodes({flatten:!0});this.hasTooltipSlot=Boolean(t&&t.length>0)}};__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"disabled",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"error",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"hide",void 0),__decorate([property({reflect:!0})],GlideCoreLabel.prototype,"orientation",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"required",void 0),__decorate([state()],GlideCoreLabel.prototype,"hasDescriptionSlot",void 0),__decorate([state()],GlideCoreLabel.prototype,"hasSummarySlot",void 0),__decorate([state()],GlideCoreLabel.prototype,"hasTooltipSlot",void 0),GlideCoreLabel=__decorate([customElement("glide-core-label")],GlideCoreLabel);export default GlideCoreLabel;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,l){var i,s=arguments.length,r=s<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,o,l);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(r=(s<3?i(r):s>3?i(t,o,r):i(t,o))||r);return s>3&&r&&Object.defineProperty(t,o,r),r};import"./tooltip.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,state}from"lit/decorators.js";import ow,{owSlot}from"./library/ow.js";import styles from"./label.styles.js";import{svg}from"lit";const infoCircleIcon=svg`<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"><path d="M12 16L12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="8" r="1" fill="currentColor">`;let GlideCoreLabel=class GlideCoreLabel extends LitElement{constructor(){super(...arguments),this.disabled=!1,this.error=!1,this.hide=!1,this.orientation="horizontal",this.required=!1,this.hasDescriptionSlot=!1,this.hasSummarySlot=!1,this.hasTooltipSlot=!1,this.isLabelTooltip=!1,this.label="",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=createRef(),this.#i=new LocalizeController(this),this.#s=createRef(),this.#r=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){owSlot(this.#t.value),owSlot(this.#e.value)}render(){return html`<div class="${classMap({component:!0,horizontal:"horizontal"===this.orientation,vertical:"vertical"===this.orientation,left:"left"===this.split,middle:"middle"===this.split,"hidden-label":this.hide})}"><div class="${classMap({"tooltips-and-label":!0,hidden:this.hide,left:"left"===this.split,middle:"middle"===this.split})}" part="tooltips-and-label"><glide-core-tooltip class="${classMap({"optional-tooltip":!0,vertical:"vertical"===this.orientation,visible:this.hasTooltipSlot})}" placement="${"vertical"===this.orientation?"right":"bottom"}"><span class="optional-tooltip-target" slot="target" tabindex="0"><svg aria-label="${this.#i.term("moreInformation")}" width="16" height="16" viewBox="0 0 24 24" fill="none">${infoCircleIcon}</svg></span><slot name="tooltip" @slotchange="${this.#a}" ${ref(this.#r)}></slot></glide-core-tooltip><glide-core-tooltip class="label-overflow-tooltip" placement="right" ?disabled="${!this.isLabelTooltip}"><div class="${classMap({label:!0,disabled:this.disabled})}" data-test="label" slot="target" ${ref(this.#l)}><slot @slotchange="${this.#n}" ${ref(this.#t)}></slot>${this.required?html`<span aria-hidden="true" class="required-symbol">*</span>`:""}</div><div aria-hidden="true">${this.label}</div></glide-core-tooltip></div><div class="control-and-summary"><slot class="${classMap({control:!0,error:this.error,disabled:this.disabled,vertical:"vertical"===this.orientation,summaryless:!this.hasSummarySlot,"hidden-label":this.hide})}" name="control" @slotchange="${this.#d}" ${ref(this.#e)}></slot><slot class="${classMap({summary:!0,error:this.error})}" name="summary" @slotchange="${this.#c}" ${ref(this.#s)}></slot></div><slot class="${classMap({description:!0,visible:this.hasDescriptionSlot,error:this.error,tooltip:this.hasTooltipSlot})}" id="description" name="description" @slotchange="${this.#h}" ${ref(this.#o)}></slot></div>`}#e;#t;#o;#l;#i;#s;#r;#d(){owSlot(this.#e.value)}#n(){owSlot(this.#t.value);const e=this.#t.value?.assignedElements().at(0),t=this.#l.value;ow(e,ow.object.instanceOf(Element)),ow(t,ow.object.instanceOf(HTMLElement)),e.textContent&&(this.label=e.textContent);new ResizeObserver((()=>{this.isLabelTooltip=e.getBoundingClientRect().width>t.getBoundingClientRect().width})).observe(t)}#h(){const e=this.#o.value?.assignedNodes({flatten:!0});this.hasDescriptionSlot=Boolean(e&&e.length>0)}#c(){const e=this.#s.value?.assignedNodes({flatten:!0});this.hasSummarySlot=Boolean(e&&e.length>0)}#a(){const e=this.#r.value?.assignedNodes({flatten:!0});this.hasTooltipSlot=Boolean(e&&e.length>0)}};__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"disabled",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"error",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"hide",void 0),__decorate([property({reflect:!0})],GlideCoreLabel.prototype,"orientation",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreLabel.prototype,"required",void 0),__decorate([property()],GlideCoreLabel.prototype,"split",void 0),__decorate([state()],GlideCoreLabel.prototype,"hasDescriptionSlot",void 0),__decorate([state()],GlideCoreLabel.prototype,"hasSummarySlot",void 0),__decorate([state()],GlideCoreLabel.prototype,"hasTooltipSlot",void 0),__decorate([state()],GlideCoreLabel.prototype,"isLabelTooltip",void 0),__decorate([state()],GlideCoreLabel.prototype,"label",void 0),GlideCoreLabel=__decorate([customElement("glide-core-label")],GlideCoreLabel);export default GlideCoreLabel;
@@ -17,23 +17,35 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
17
17
  flex-direction: column;
18
18
  }
19
19
 
20
+ &.left {
21
+ grid-template-columns: calc(100% / 3) 1fr;
22
+ }
23
+
24
+ &.middle {
25
+ grid-template-columns: 1fr 1fr;
26
+ }
27
+
20
28
  &.hidden-label {
21
29
  display: flex;
22
30
  flex-direction: column;
23
31
  }
24
32
  }
25
33
 
26
- .tooltip-and-label {
34
+ .tooltips-and-label {
27
35
  align-items: center;
28
36
  column-gap: var(--glide-core-spacing-xs);
29
37
  display: flex;
38
+ justify-content: flex-end;
39
+
40
+ /* Prevent it from growing larger than its column percentage when a child of Form Controls Layout. */
41
+ min-inline-size: 0;
30
42
 
31
43
  &.hidden {
32
44
  ${visuallyHidden};
33
45
  }
34
46
  }
35
47
 
36
- glide-core-tooltip {
48
+ .optional-tooltip {
37
49
  display: none;
38
50
 
39
51
  &.vertical {
@@ -49,7 +61,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
49
61
  }
50
62
  }
51
63
 
52
- .tooltip-target {
64
+ .optional-tooltip-target {
53
65
  background-color: transparent;
54
66
  border: none;
55
67
  border-radius: 0.0625rem;
@@ -78,7 +90,12 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
78
90
  font-variant: var(--glide-core-heading-xxxs-font-variant);
79
91
  font-weight: var(--glide-core-heading-xxxs-font-weight);
80
92
  line-height: 100%;
93
+ margin-inline-start: auto;
94
+ overflow: hidden;
95
+ text-align: end;
96
+ text-overflow: ellipsis;
81
97
  user-select: none;
98
+ white-space: nowrap;
82
99
 
83
100
  &.disabled ::slotted(*) {
84
101
  cursor: not-allowed;
@@ -93,6 +110,10 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
93
110
  }
94
111
  }
95
112
 
113
+ .label-overflow-tooltip {
114
+ inline-size: 100%;
115
+ }
116
+
96
117
  .required-symbol {
97
118
  color: var(--glide-core-status-error);
98
119
  }
@@ -1,5 +1,5 @@
1
1
  import { ArgumentError } from 'ow';
2
- import { expect, fixture, html } from '@open-wc/testing';
2
+ import { expect, fixture, html, waitUntil } from '@open-wc/testing';
3
3
  import GlideCoreLabel from './label.js';
4
4
  import sinon from 'sinon';
5
5
  GlideCoreLabel.shadowRootOptions.mode = 'open';
@@ -102,9 +102,7 @@ it('places the tooltip on the right when vertical', async () => {
102
102
  it('throws if it does not have a default slot', async () => {
103
103
  const spy = sinon.spy();
104
104
  try {
105
- await fixture(html `<glide-core-label orientation="vertical"
106
- ><input slot="control"
107
- /></glide-core-label>`);
105
+ await fixture(html `<glide-core-label><input slot="control" /></glide-core-label>`);
108
106
  }
109
107
  catch (error) {
110
108
  if (error instanceof ArgumentError) {
@@ -115,8 +113,9 @@ it('throws if it does not have a default slot', async () => {
115
113
  });
116
114
  it('throws if it does not have a "control" slot', async () => {
117
115
  const spy = sinon.spy();
116
+ const stub = sinon.stub(console, 'error');
118
117
  try {
119
- await fixture(html `<glide-core-label orientation="vertical">
118
+ await fixture(html `<glide-core-label>
120
119
  <label>Label</label>
121
120
  </glide-core-label>`);
122
121
  }
@@ -126,4 +125,9 @@ it('throws if it does not have a "control" slot', async () => {
126
125
  }
127
126
  }
128
127
  expect(spy.called).to.be.true;
128
+ // It's not clear to me why the error logged by Ow shows up in the console
129
+ // here and not in the above test or elsewhere. A bug in Web Test Runner?
130
+ // Something I don't understand about Lit's lifecycle?
131
+ await waitUntil(() => stub.called);
132
+ stub.restore();
129
133
  });
@@ -4,13 +4,13 @@ import { type Ow } from 'ow';
4
4
  *
5
5
  * @param slot - The slot to assert against.
6
6
  */
7
- export declare function owSlot(slot?: HTMLSlotElement): void;
7
+ export declare function owSlot(slot?: HTMLSlotElement): asserts slot is HTMLSlotElement;
8
8
  /**
9
9
  * @description Asserts that slotted nodes are a certain type.
10
10
  *
11
11
  * @param slot - The slot to assert against.
12
12
  * @param slotted - An array of constructors. Slotted nodes must extend one of them.
13
13
  */
14
- export declare function owSlotType(slot?: HTMLSlotElement, slotted?: (typeof Element | typeof Text)[]): void;
14
+ export declare function owSlotType(slot?: HTMLSlotElement, slotted?: (typeof Element | typeof Text)[]): asserts slot is HTMLSlotElement;
15
15
  declare const owOrShim: Ow;
16
16
  export default owOrShim;
package/dist/menu.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(t,e,i,o){var n,s=arguments.length,a=s<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,i,o);else for(var l=t.length-1;l>=0;l--)(n=t[l])&&(a=(s<3?n(a):s>3?n(e,i,a):n(e,i))||a);return s>3&&a&&Object.defineProperty(e,i,a),a};import{LitElement,html}from"lit";import{autoUpdate,computePosition,flip,offset,platform}from"@floating-ui/dom";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{nanoid}from"nanoid";import{offsetParent}from"composed-offset-position";import{owSlot,owSlotType}from"./library/ow.js";import GlideCoreMenuButton from"./menu.button.js";import GlideCoreMenuLink from"./menu.link.js";import GlideCoreMenuOptions from"./menu.options.js";import styles from"./menu.styles.js";let GlideCoreMenu=class GlideCoreMenu extends LitElement{constructor(){super(...arguments),this.placement="bottom-start",this.isTargetDisabled=!1,this.#t=createRef(),this.#e=createRef(),this.#i=!1,this.#o=!1,this.#n="large",this.#s=createRef(),this.#a=t=>{t.target&&this.contains(t.target)||(this.open=!1,this.#l&&(this.#l.ariaActivedescendant=""))}}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}get open(){return this.#o}set open(t){this.#o=t,t&&!this.isTargetDisabled&&this.#l?(this.#r(),this.#l.ariaActivedescendant=this.#c?.id??""):this.#l&&(this.#p?.(),this.#l.ariaActivedescendant=""),this.#h&&(this.#h.ariaExpanded=t&&!this.isTargetDisabled?"true":"false")}get size(){return this.#n}set size(t){this.#n=t,this.#l&&(this.#l.privateSize=t)}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(){owSlot(this.#e.value),owSlot(this.#s.value),owSlotType(this.#e.value,[GlideCoreMenuOptions]);const t=this.#m?.at(0);this.open&&t&&this.#l&&(this.#r(),t.privateActive=!0,this.#l.ariaActivedescendant=t.id)}focus(){this.#h&&"focus"in this.#h&&this.#h?.focus()}render(){return html`<div class="component" @focusout="${this.#f}" ${ref(this.#t)}><slot class="target-slot" name="target" @click="${this.#u}" @keydown="${this.#E}" @slotchange="${this.#g}" ${ref(this.#s)}></slot><slot class="${classMap({"default-slot":!0,visible:this.open&&!this.isTargetDisabled})}" @click="${this.#v}" @focusin="${this.#S}" @keydown="${this.#E}" @mouseover="${this.#y}" @slotchange="${this.#C}" ${ref(this.#e)}></slot></div>`}setContainingBlock(t){this.containingBlock=t}#p;#t;#e;#i;#o;#d;#n;#s;get#c(){return this.#m?.find((({privateActive:t})=>t))}get#l(){const t=this.#e.value?.assignedElements().at(0);return t||null}#a;#C(){owSlot(this.#e.value),owSlotType(this.#e.value,[GlideCoreMenuOptions]);const t=this.#m?.at(0);t&&(t.privateActive=!0),this.#l&&(this.#l.privateSize=this.size)}#v(){this.open=!1,this.#l&&(this.#l.ariaActivedescendant="")}#S(t){(t.target instanceof GlideCoreMenuButton||t.target instanceof GlideCoreMenuLink)&&this.#c&&this.#l&&(this.#c.privateActive=!1,t.target.privateActive=!0,this.#l.ariaActivedescendant=t.target.id)}#y(t){if(t.target instanceof GlideCoreMenuLink||t.target instanceof GlideCoreMenuButton){if(this.#m)for(const e of this.#m)e.privateActive=e===t.target;this.#l&&(this.#l.ariaActivedescendant=t.target.id)}}#f(t){const e=t.relatedTarget instanceof HTMLElement&&this.#d?.contains(t.relatedTarget),i=t.relatedTarget instanceof HTMLElement&&this.contains(t.relatedTarget);e||i||(this.open=!1)}#E(t){if([" ","Enter","Escape"].includes(t.key)&&this.open&&this.#l)return this.open=!1,this.#l.ariaActivedescendant="",this.focus(),void(this.#i=!0);if([" ","ArrowUp","ArrowDown"].includes(t.key)&&!this.open&&this.#c&&this.#l)return t.preventDefault(),this.open=!0,void(this.#l.ariaActivedescendant=this.#c.id);if(this.open&&this.#c&&this.#m){const e=this.#m.indexOf(this.#c);if("ArrowUp"===t.key&&!t.metaKey){t.preventDefault();const i=this.#m?.at(e-1);return void(i&&0!==e&&this.#l&&(this.#c.privateActive=!1,this.#l.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowDown"===t.key&&!t.metaKey&&this.#l){t.preventDefault();const i=this.#m?.at(e+1);return void(i&&(this.#c.privateActive=!1,this.#l.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowUp"===t.key&&t.metaKey||"Home"===t.key||"PageUp"===t.key){t.preventDefault();const e=this.#m?.at(0);return void(e&&this.#l&&(this.#c.privateActive=!1,this.#l.ariaActivedescendant=e.id,e.privateActive=!0))}if("ArrowDown"===t.key&&t.metaKey||"End"===t.key||"PageDown"===t.key){t.preventDefault();const e=this.#m?.at(-1);return void(e&&this.#l&&(this.#c.privateActive=!1,this.#l.ariaActivedescendant=e.id,e.privateActive=!0))}}}#g(){owSlot(this.#s.value);const t=this.#h&&"disabled"in this.#h&&this.#h.disabled,e=this.#h&&"true"===this.#h.ariaDisabled;this.isTargetDisabled=Boolean(t)||Boolean(e),this.#h&&this.#l&&(this.#h.ariaHasPopup="true",this.#h.ariaExpanded=this.open&&!this.isTargetDisabled?"true":"false",this.#h.id=nanoid(),this.#h.setAttribute("aria-controls",this.#l.id),this.#l.ariaLabelledby=this.#h.id)}#u(){this.isTargetDisabled||this.#i?this.#i=!1:(this.#h instanceof HTMLElement&&(this.#h.ariaExpanded=this.open?"true":"false"),this.open=!this.open,this.open&&this.#c&&this.#l?this.#l.ariaActivedescendant=this.#c.id:!this.open&&this.#l&&(this.#l.ariaActivedescendant="",this.focus()))}get#m(){const t=this.#e.value?.assignedElements()?.at(0)?.children;if(t)return[...t].filter((t=>t instanceof GlideCoreMenuLink||t instanceof GlideCoreMenuButton))}#r(){this.#h&&this.#e.value&&(this.#p=autoUpdate(this.#h,this.#e.value,(()=>{(async()=>{if(this.#h&&this.#e.value){const{x:t,y:e,placement:i}=await computePosition(this.#h,this.#e.value,{platform:{...platform,getOffsetParent:t=>this.containingBlock??platform.getOffsetParent(t,offsetParent)},placement:this.placement,middleware:[offset({mainAxis:16*Number.parseFloat(window.getComputedStyle(document.body).getPropertyValue("--glide-core-spacing-xxs"))}),flip()]});this.#e.value.dataset.placement=i,Object.assign(this.#e.value.style,{left:`${t}px`,top:`${e}px`})}})()})))}get#h(){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([state()],GlideCoreMenu.prototype,"containingBlock",void 0),__decorate([property({reflect:!0})],GlideCoreMenu.prototype,"size",null),__decorate([state()],GlideCoreMenu.prototype,"isTargetDisabled",void 0),GlideCoreMenu=__decorate([customElement("glide-core-menu")],GlideCoreMenu);export default GlideCoreMenu;
1
+ var __decorate=this&&this.__decorate||function(e,t,i,o){var n,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--)(n=e[l])&&(a=(s<3?n(a):s>3?n(t,i,a):n(t,i))||a);return s>3&&a&&Object.defineProperty(t,i,a),a};import{LitElement,html}from"lit";import{autoUpdate,computePosition,flip,offset,platform}from"@floating-ui/dom";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{nanoid}from"nanoid";import{offsetParent}from"composed-offset-position";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.isTargetDisabled=!1,this.#e=createRef(),this.#t=createRef(),this.#i=!1,this.#o=!1,this.#n="large",this.#s=createRef(),this.#a=e=>{e.target&&e.target instanceof Node&&this.contains(e.target)||(this.open=!1,this.#l&&(this.#l.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.#l?(this.#r(),this.#l.ariaActivedescendant=this.#c?.id??""):this.#l&&(this.#p?.(),this.#l.ariaActivedescendant=""),this.#d&&(this.#d.ariaExpanded=e&&!this.isTargetDisabled?"true":"false")}get size(){return this.#n}set size(e){this.#n=e,this.#l&&(this.#l.privateSize=e)}connectedCallback(){super.connectedCallback(),document.addEventListener("click",this.#a,{capture:!0})}createRenderRoot(){return this.#h=super.createRenderRoot(),this.#h}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("click",this.#a,{capture:!0})}firstUpdated(){ow(this.#l,ow.object.instanceOf(GlideCoreMenuOptions)),owSlot(this.#t.value),owSlot(this.#s.value),owSlotType(this.#t.value,[GlideCoreMenuOptions]);const e=this.#m?.at(0);this.open&&e&&(this.#r(),e.privateActive=!0,this.#l.ariaActivedescendant=e.id)}focus(){this.#d&&"focus"in this.#d&&this.#d?.focus()}render(){return html`<div class="component" @focusout="${this.#f}" ${ref(this.#e)}><slot class="target-slot" name="target" @click="${this.#u}" @keydown="${this.#E}" @slotchange="${this.#g}" ${ref(this.#s)}></slot><slot class="${classMap({"default-slot":!0,visible:this.open})}" @click="${this.#v}" @focusin="${this.#C}" @keydown="${this.#E}" @mouseover="${this.#w}" @slotchange="${this.#S}" ${ref(this.#t)}></slot></div>`}setContainingBlock(e){this.containingBlock=e}#p;#e;#t;#i;#o;#h;#n;#s;get#c(){return this.#m?.find((({privateActive:e})=>e))}get#l(){const e=this.#t.value?.assignedElements().at(0);return e||null}#a;#S(){ow(this.#l,ow.object.instanceOf(GlideCoreMenuOptions)),owSlot(this.#t.value),owSlotType(this.#t.value,[GlideCoreMenuOptions]);const e=this.#m?.at(0);e&&(e.privateActive=!0),this.#l.privateSize=this.size}#v(){this.open=!1,this.#l&&(this.#l.ariaActivedescendant="")}#C(e){(e.target instanceof GlideCoreMenuButton||e.target instanceof GlideCoreMenuLink)&&this.#c&&this.#l&&(e.target.privateActive=!0,this.#c.privateActive=!1,this.#l.ariaActivedescendant=e.target.id)}#w(e){if(e.target instanceof GlideCoreMenuLink||e.target instanceof GlideCoreMenuButton){if(this.#m)for(const t of this.#m)t.privateActive=t===e.target;this.#l&&(this.#l.ariaActivedescendant=e.target.id)}}#f(e){const t=e.relatedTarget instanceof HTMLElement&&this.#h?.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.#l,ow.object.instanceOf(GlideCoreMenuOptions)),[" ","Enter","Escape"].includes(e.key)&&this.open)return this.open=!1,this.#l.ariaActivedescendant="",this.focus(),void(this.#i=!0);if([" ","ArrowUp","ArrowDown"].includes(e.key)&&!this.open&&this.#c)return e.preventDefault(),this.open=!0,void(this.#l.ariaActivedescendant=this.#c.id);if(this.open){ow(this.#m,ow.array),ow(this.#l,ow.object.instanceOf(GlideCoreMenuOptions)),ow(this.#c,ow.object.is((e=>e instanceof GlideCoreMenuButton||e instanceof GlideCoreMenuLink)));const t=this.#m.indexOf(this.#c);if("ArrowUp"===e.key&&!e.metaKey){e.preventDefault();const i=this.#m.at(t-1);return void(i&&0!==t&&(this.#c.privateActive=!1,this.#l.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowDown"===e.key&&!e.metaKey){e.preventDefault();const i=this.#m.at(t+1);return void(i&&(this.#c.privateActive=!1,this.#l.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowUp"===e.key&&e.metaKey||"Home"===e.key||"PageUp"===e.key){e.preventDefault();const t=this.#m.at(0);return void(t&&(this.#c.privateActive=!1,this.#l.ariaActivedescendant=t.id,t.privateActive=!0))}if("ArrowDown"===e.key&&e.metaKey||"End"===e.key||"PageDown"===e.key){e.preventDefault();const t=this.#m.at(-1);return void(t&&(this.#c.privateActive=!1,this.#l.ariaActivedescendant=t.id,t.privateActive=!0))}}}#g(){owSlot(this.#s.value),ow(this.#d,ow.object.instanceOf(Element)),ow(this.#l,ow.object.instanceOf(GlideCoreMenuOptions)),this.#y(),this.isTargetDisabled&&(this.open=!1);new MutationObserver((e=>{e.some((e=>"disabled"===e.attributeName||"aria-disabled"===e.attributeName))&&(this.#y(),this.isTargetDisabled&&(this.open=!1))})).observe(this.#d,{attributes:!0}),this.#d.ariaHasPopup="true",this.#d.ariaExpanded=this.open?"true":"false",this.#d.id=nanoid(),this.#d.setAttribute("aria-controls",this.#l.id),this.#l.ariaLabelledby=this.#d.id}#u(){this.isTargetDisabled||this.#i?this.#i=!1:(this.#d instanceof HTMLElement&&(this.#d.ariaExpanded=this.open?"true":"false"),this.#m&&this.#m.length>0&&(this.open=!this.open),this.open&&this.#c&&this.#l?this.#l.ariaActivedescendant=this.#c.id:!this.open&&this.#l&&(this.#l.ariaActivedescendant="",this.focus()))}get#m(){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))}#y(){const e=this.#d&&"disabled"in this.#d&&this.#d.disabled,t=this.#d&&"true"===this.#d.ariaDisabled;this.isTargetDisabled=Boolean(e)||Boolean(t)}#r(){this.#d&&this.#t.value&&(this.#p=autoUpdate(this.#d,this.#t.value,(()=>{(async()=>{if(this.#d&&this.#t.value){const{x:e,y:t,placement:i}=await computePosition(this.#d,this.#t.value,{platform:{...platform,getOffsetParent:e=>this.containingBlock??platform.getOffsetParent(e,offsetParent)},placement:this.placement,middleware:[offset({mainAxis:16*Number.parseFloat(window.getComputedStyle(document.body).getPropertyValue("--glide-core-spacing-xxs"))}),flip()]});this.#t.value.dataset.placement=i,Object.assign(this.#t.value.style,{left:`${e}px`,top:`${t}px`})}})()})))}get#d(){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([state()],GlideCoreMenu.prototype,"containingBlock",void 0),__decorate([property({reflect:!0})],GlideCoreMenu.prototype,"size",null),__decorate([state()],GlideCoreMenu.prototype,"isTargetDisabled",void 0),GlideCoreMenu=__decorate([customElement("glide-core-menu")],GlideCoreMenu);export default GlideCoreMenu;
@@ -128,18 +128,11 @@ it('is not opened when initially `open` and its target is `disabled`', async ()
128
128
  expect(target?.ariaExpanded).to.equal('false');
129
129
  });
130
130
  it('throws if it does not have a default slot', async () => {
131
- const spy = sinon.spy();
132
- try {
133
- await fixture(html `<glide-core-menu
131
+ await expectArgumentError(() => {
132
+ return fixture(html `<glide-core-menu
134
133
  ><button slot="target">Target</button></glide-core-menu
135
134
  >`);
136
- }
137
- catch (error) {
138
- if (error instanceof ArgumentError) {
139
- spy();
140
- }
141
- }
142
- expect(spy.called).to.be.true;
135
+ });
143
136
  });
144
137
  it('throws if the default slot is the incorrect type', async () => {
145
138
  await expectArgumentError(() => {
@@ -0,0 +1,2 @@
1
+ import './menu.link.js';
2
+ import './menu.options.js';
@@ -0,0 +1,30 @@
1
+ import './menu.link.js';
2
+ import './menu.options.js';
3
+ import { expect, fixture, html, oneEvent } from '@open-wc/testing';
4
+ import GlideCoreMenu from './menu.js';
5
+ it('dispatches a "click" event when a link is clicked', async () => {
6
+ const component = await fixture(html `<glide-core-menu open>
7
+ <button slot="target">Target</button>
8
+
9
+ <glide-core-menu-options>
10
+ <glide-core-menu-link label="Link"></glide-core-menu-link>
11
+ </glide-core-menu-options>
12
+ </glide-core-menu>`);
13
+ setTimeout(() => document.querySelector('glide-core-menu-link')?.click());
14
+ const event = await oneEvent(component, 'click');
15
+ expect(event instanceof PointerEvent).to.be.true;
16
+ expect(event.bubbles).to.be.true;
17
+ });
18
+ it('dispatches a "click" event when a button is clicked', async () => {
19
+ const component = await fixture(html `<glide-core-menu open>
20
+ <button slot="target">Target</button>
21
+
22
+ <glide-core-menu-options>
23
+ <glide-core-menu-button label="Link"></glide-core-menu-button>
24
+ </glide-core-menu-options>
25
+ </glide-core-menu>`);
26
+ setTimeout(() => document.querySelector('glide-core-menu-button')?.click());
27
+ const event = await oneEvent(component, 'click');
28
+ expect(event instanceof PointerEvent).to.be.true;
29
+ expect(event.bubbles).to.be.true;
30
+ });
@@ -1,10 +1,37 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
1
7
  import './menu.link.js';
2
8
  import './menu.options.js';
3
- import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
9
+ import { LitElement } from 'lit';
10
+ import { assert, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
11
+ import { customElement } from 'lit/decorators.js';
4
12
  import { sendKeys } from '@web/test-runner-commands';
5
13
  import GlideCoreMenu from './menu.js';
14
+ let GlideCoreNestedSlot = class GlideCoreNestedSlot extends LitElement {
15
+ static { this.shadowRootOptions = {
16
+ ...LitElement.shadowRootOptions,
17
+ mode: 'closed',
18
+ }; }
19
+ render() {
20
+ return html `<glide-core-menu open>
21
+ <button slot="target">Target</button>
22
+
23
+ <glide-core-menu-options>
24
+ <slot></slot>
25
+ </glide-core-menu-options>
26
+ </glide-core-menu>`;
27
+ }
28
+ };
29
+ GlideCoreNestedSlot = __decorate([
30
+ customElement('glide-core-nested-slot')
31
+ ], GlideCoreNestedSlot);
6
32
  GlideCoreMenu.shadowRootOptions.mode = 'open';
7
- it('opens when clicked', async () => {
33
+ GlideCoreNestedSlot.shadowRootOptions.mode = 'open';
34
+ it('opens on click', async () => {
8
35
  const component = await fixture(html `<glide-core-menu>
9
36
  <button slot="target">Target</button>
10
37
 
@@ -20,7 +47,21 @@ it('opens when clicked', async () => {
20
47
  expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
21
48
  expect(target?.ariaExpanded).to.equal('true');
22
49
  });
23
- it('does not open when clicked when its target is `disabled`', async () => {
50
+ it('does not open on click when there are no options', async () => {
51
+ const component = await fixture(html `<glide-core-menu>
52
+ <button slot="target">Target</button>
53
+ <glide-core-menu-options> </glide-core-menu-options>
54
+ </glide-core-menu>`);
55
+ component.querySelector('button')?.click();
56
+ const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
57
+ const options = component.querySelector('glide-core-menu-options');
58
+ const target = component.querySelector('button');
59
+ expect(component.open).to.be.false;
60
+ expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.not.ok;
61
+ expect(options?.getAttribute('aria-activedescendant')).to.equal('');
62
+ expect(target?.ariaExpanded).to.equal('false');
63
+ });
64
+ it('does not open when `disabled` is set on its target', async () => {
24
65
  const component = await fixture(html `<glide-core-menu>
25
66
  <button slot="target" disabled>Target</button>
26
67
 
@@ -37,7 +78,27 @@ it('does not open when clicked when its target is `disabled`', async () => {
37
78
  expect(options?.getAttribute('aria-activedescendant')).to.equal('');
38
79
  expect(target?.ariaExpanded).to.equal('false');
39
80
  });
40
- it('does not open when clicked when its target is `aria-disabled`', async () => {
81
+ it('does not open when `disabled` is set programmatically on its target', async () => {
82
+ const component = await fixture(html `<glide-core-menu>
83
+ <button slot="target">Target</button>
84
+
85
+ <glide-core-menu-options>
86
+ <glide-core-menu-link label="Link"></glide-core-menu-link>
87
+ </glide-core-menu-options>
88
+ </glide-core-menu>`);
89
+ const target = component.querySelector('button');
90
+ assert(target);
91
+ target.click();
92
+ target.disabled = true;
93
+ await elementUpdated(component);
94
+ const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
95
+ const options = component.querySelector('glide-core-menu-options');
96
+ expect(component.open).to.be.false;
97
+ expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
98
+ expect(options?.getAttribute('aria-activedescendant')).to.equal('');
99
+ expect(target?.ariaExpanded).to.equal('false');
100
+ });
101
+ it('does not open when `aria-disabled` is set on its target', async () => {
41
102
  const component = await fixture(html `<glide-core-menu>
42
103
  <button aria-disabled="true" slot="target">Target</button>
43
104
 
@@ -45,7 +106,28 @@ it('does not open when clicked when its target is `aria-disabled`', async () =>
45
106
  <glide-core-menu-link label="Link"></glide-core-menu-link>
46
107
  </glide-core-menu-options>
47
108
  </glide-core-menu>`);
48
- component.querySelector('button')?.click();
109
+ const target = component.querySelector('button');
110
+ target?.click();
111
+ const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
112
+ const options = component.querySelector('glide-core-menu-options');
113
+ expect(component.open).to.be.false;
114
+ expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
115
+ expect(options?.getAttribute('aria-activedescendant')).to.equal('');
116
+ expect(target?.ariaExpanded).to.equal('false');
117
+ });
118
+ it('does not open when `aria-disabled` is set programmatically on its target', async () => {
119
+ const component = await fixture(html `<glide-core-menu>
120
+ <button slot="target">Target</button>
121
+
122
+ <glide-core-menu-options>
123
+ <glide-core-menu-link label="Link"></glide-core-menu-link>
124
+ </glide-core-menu-options>
125
+ </glide-core-menu>`);
126
+ const button = component.querySelector('button');
127
+ assert(button);
128
+ button?.click();
129
+ button.ariaDisabled = 'true';
130
+ await elementUpdated(component);
49
131
  const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
50
132
  const options = component.querySelector('glide-core-menu-options');
51
133
  const target = component.querySelector('button');
@@ -130,44 +212,24 @@ it('opens on Space', async () => {
130
212
  expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
131
213
  expect(target?.ariaExpanded).to.equal('true');
132
214
  });
133
- it('opens when opened programmatically', async () => {
215
+ it('does not open on Space when there are no options', async () => {
134
216
  const component = await fixture(html `<glide-core-menu>
135
217
  <button slot="target">Target</button>
136
-
137
- <glide-core-menu-options>
138
- <glide-core-menu-link label="Link"></glide-core-menu-link>
139
- </glide-core-menu-options>
140
- </glide-core-menu>`);
141
- component.open = true;
142
- await elementUpdated(component);
143
- const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
144
- const options = component.querySelector('glide-core-menu-options');
145
- const target = component.querySelector('button');
146
- const link = component.querySelector('glide-core-menu-link');
147
- expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
148
- expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
149
- expect(target?.ariaExpanded).to.equal('true');
150
- });
151
- it('does not open when opened programmatically and its target is `disabled`', async () => {
152
- const component = await fixture(html `<glide-core-menu>
153
- <button slot="target" disabled>Target</button>
154
-
155
- <glide-core-menu-options>
156
- <glide-core-menu-link label="Link"></glide-core-menu-link>
157
- </glide-core-menu-options>
218
+ <glide-core-menu-options> </glide-core-menu-options>
158
219
  </glide-core-menu>`);
159
- component.open = true;
160
- await elementUpdated(component);
220
+ component.querySelector('button')?.focus();
221
+ await sendKeys({ press: ' ' });
161
222
  const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
162
223
  const options = component.querySelector('glide-core-menu-options');
163
224
  const target = component.querySelector('button');
164
- expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
225
+ expect(component.open).to.be.false;
226
+ expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.not.ok;
165
227
  expect(options?.getAttribute('aria-activedescendant')).to.equal('');
166
228
  expect(target?.ariaExpanded).to.equal('false');
167
229
  });
168
- it('does not open when opened programmatically and its target is `aria-disabled`', async () => {
230
+ it('opens when opened programmatically', async () => {
169
231
  const component = await fixture(html `<glide-core-menu>
170
- <button aria-disabled="true" slot="target">Target</button>
232
+ <button slot="target">Target</button>
171
233
 
172
234
  <glide-core-menu-options>
173
235
  <glide-core-menu-link label="Link"></glide-core-menu-link>
@@ -178,9 +240,10 @@ it('does not open when opened programmatically and its target is `aria-disabled`
178
240
  const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
179
241
  const options = component.querySelector('glide-core-menu-options');
180
242
  const target = component.querySelector('button');
181
- expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
182
- expect(options?.getAttribute('aria-activedescendant')).to.equal('');
183
- expect(target?.ariaExpanded).to.equal('false');
243
+ const link = component.querySelector('glide-core-menu-link');
244
+ expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
245
+ expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
246
+ expect(target?.ariaExpanded).to.equal('true');
184
247
  });
185
248
  // See the `document` click listener comment in `menu.ts` for an explanation.
186
249
  it('opens when opened programmatically via the click handler of another element', async () => {
@@ -387,6 +450,21 @@ it('activates a menu link on "mouseover"', async () => {
387
450
  expect(links[1].privateActive).to.be.true;
388
451
  expect(options?.getAttribute('aria-activedescendant')).to.equal(links[1].id);
389
452
  });
453
+ it('activates a menu link on "mouseover" when the link is in a nested slot', async () => {
454
+ const component = await fixture(html `
455
+ <glide-core-nested-slot>
456
+ <glide-core-menu-link label="One"></glide-core-menu-link>
457
+ <glide-core-menu-link label="Two"></glide-core-menu-link>
458
+ </glide-core-nested-slot>
459
+ `);
460
+ const links = component.querySelectorAll('glide-core-menu-link');
461
+ const options = component.shadowRoot?.querySelector('glide-core-menu-options');
462
+ links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
463
+ await elementUpdated(component);
464
+ expect(links[0].privateActive).to.be.false;
465
+ expect(links[1].privateActive).to.be.true;
466
+ expect(options?.getAttribute('aria-activedescendant')).to.equal(links[1].id);
467
+ });
390
468
  it('activates a menu button on "mouseover"', async () => {
391
469
  const component = await fixture(html `
392
470
  <glide-core-menu open>
@@ -406,6 +484,21 @@ it('activates a menu button on "mouseover"', async () => {
406
484
  expect(buttons[1].privateActive).to.be.true;
407
485
  expect(options?.getAttribute('aria-activedescendant')).equal(buttons[1].id);
408
486
  });
487
+ it('activates a menu button on "mouseover" when the button is in a nested slot', async () => {
488
+ const component = await fixture(html `
489
+ <glide-core-nested-slot>
490
+ <glide-core-menu-button label="One"></glide-core-menu-button>
491
+ <glide-core-menu-button label="Two"></glide-core-menu-button>
492
+ </glide-core-nested-slot>
493
+ `);
494
+ const links = component.querySelectorAll('glide-core-menu-button');
495
+ const options = component.shadowRoot?.querySelector('glide-core-menu-options');
496
+ links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
497
+ await elementUpdated(component);
498
+ expect(links[0].privateActive).to.be.false;
499
+ expect(links[1].privateActive).to.be.true;
500
+ expect(options?.getAttribute('aria-activedescendant')).to.equal(links[1].id);
501
+ });
409
502
  it('activates the next option on ArrowDown', async () => {
410
503
  const component = await fixture(html `
411
504
  <glide-core-menu>
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{owSlot,owSlotType}from"./library/ow.js";import{setContainingBlock}from"./library/set-containing-block.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 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.showBackButton=!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.showBackButton,(()=>html`<glide-core-modal-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 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.#h}" ${ref(this.#n)}></slot></li><li><menu class="actions"><li><slot name="secondary" @slotchange="${this.#u}" ${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(){owSlot(this.#t.value);const e=this.#t.value.assignedElements();setContainingBlock({elements:e,containingBlock:this.#e.value})}#f(){owSlotType(this.#o.value,[GlideCoreButton])}#u(){owSlotType(this.#l.value,[GlideCoreButton])}#h(){owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton]);const e=this.#n.value.assignedElements().filter((e=>e instanceof GlideCoreModalTertiaryIcon));for(const t of e)t.setContainingBlock(this.#e.value)}#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:"show-back-button",type:Boolean,reflect:!0})],GlideCoreModal.prototype,"showBackButton",void 0),__decorate([property({reflect:!0})],GlideCoreModal.prototype,"size",void 0),GlideCoreModal=__decorate([customElement("glide-core-modal")],GlideCoreModal);export default GlideCoreModal;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,l){var n,i=arguments.length,r=i<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,o,l);else for(var s=e.length-1;s>=0;s--)(n=e[s])&&(r=(i<3?n(r):i>3?n(t,o,r):n(t,o))||r);return i>3&&r&&Object.defineProperty(t,o,r),r};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{setContainingBlock}from"./library/set-containing-block.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.showBackButton=!1,this.size="medium",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=createRef(),this.#n=createRef(),this.#i=createRef(),this.#r=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.#i.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.showBackButton,(()=>html`<glide-core-modal-icon-button data-test="back-button" @click="${this.#c}"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><title>${this.#r.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.#i)}></slot><glide-core-modal-icon-button data-test="close-button" @click="${this.#c}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><title>${this.#r.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.#h}" ${ref(this.#n)}></slot></li><li><menu class="actions"><li><slot name="secondary" @slotchange="${this.#u}" ${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;#i;#r;#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);const e=this.#t.value.assignedElements();setContainingBlock({elements:e,containingBlock:this.#e.value})}#f(){owSlotType(this.#o.value,[GlideCoreButton])}#u(){owSlotType(this.#l.value,[GlideCoreButton])}#h(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton]);const e=this.#n.value.assignedElements().filter((e=>e instanceof GlideCoreModalTertiaryIcon));for(const t of e)t.setContainingBlock(this.#e.value)}#d(){owSlotType(this.#i.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:"show-back-button",type:Boolean,reflect:!0})],GlideCoreModal.prototype,"showBackButton",void 0),__decorate([property({reflect:!0})],GlideCoreModal.prototype,"size",void 0),GlideCoreModal=__decorate([customElement("glide-core-modal")],GlideCoreModal);export default GlideCoreModal;
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,l){var r,i=arguments.length,a=i<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,o,l);else for(var n=e.length-1;n>=0;n--)(r=e[n])&&(a=(i<3?r(a):i>3?r(t,o,a):r(t,o))||a);return i>3&&a&&Object.defineProperty(t,o,a),a};import"./tooltip.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{owSlot}from"./library/ow.js";import GlideCoreTooltip from"./tooltip.js";let GlideCoreModalTertiaryIcon=class GlideCoreModalTertiaryIcon extends LitElement{constructor(){super(...arguments),this.tooltipPlacement="bottom",this.#e=createRef(),this.#t=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}firstUpdated(){owSlot(this.#e.value)}render(){return html`<glide-core-tooltip placement="${this.tooltipPlacement}" ${ref(this.#t)}>${this.label} <span tabindex="0" aria-label="${ifDefined(this.label)}" slot="target"><slot @slotchange="${this.#o}" ${ref(this.#e)}></slot></span></glide-core-tooltip>`}setContainingBlock(e){this.#t.value.containingBlock=e}#e;#t;#o(){owSlot(this.#e.value)}};__decorate([property()],GlideCoreModalTertiaryIcon.prototype,"label",void 0),__decorate([property({attribute:"tooltip-placement"})],GlideCoreModalTertiaryIcon.prototype,"tooltipPlacement",void 0),GlideCoreModalTertiaryIcon=__decorate([customElement("glide-core-modal-tertiary-icon")],GlideCoreModalTertiaryIcon);export default GlideCoreModalTertiaryIcon;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,l){var i,r=arguments.length,a=r<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,o,l);else for(var n=e.length-1;n>=0;n--)(i=e[n])&&(a=(r<3?i(a):r>3?i(t,o,a):i(t,o))||a);return r>3&&a&&Object.defineProperty(t,o,a),a};import"./tooltip.js";import{LitElement,html}from"lit";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import GlideCoreTooltip from"./tooltip.js";import ow,{owSlot}from"./library/ow.js";let GlideCoreModalTertiaryIcon=class GlideCoreModalTertiaryIcon extends LitElement{constructor(){super(...arguments),this.tooltipPlacement="bottom",this.#e=createRef(),this.#t=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}firstUpdated(){owSlot(this.#e.value)}render(){return html`<glide-core-tooltip placement="${this.tooltipPlacement}" ${ref(this.#t)}>${this.label} <span tabindex="0" aria-label="${ifDefined(this.label)}" slot="target"><slot @slotchange="${this.#o}" ${ref(this.#e)}></slot></span></glide-core-tooltip>`}setContainingBlock(e){ow(this.#t.value,ow.object.instanceOf(GlideCoreTooltip)),this.#t.value.containingBlock=e}#e;#t;#o(){owSlot(this.#e.value)}};__decorate([property()],GlideCoreModalTertiaryIcon.prototype,"label",void 0),__decorate([property({attribute:"tooltip-placement"})],GlideCoreModalTertiaryIcon.prototype,"tooltipPlacement",void 0),GlideCoreModalTertiaryIcon=__decorate([customElement("glide-core-modal-tertiary-icon")],GlideCoreModalTertiaryIcon);export default GlideCoreModalTertiaryIcon;
@@ -27,6 +27,7 @@ export default class GlideCoreRadioGroup extends LitElement {
27
27
  label: string;
28
28
  hideLabel: boolean;
29
29
  name: string;
30
+ privateSplit?: 'left' | 'middle';
30
31
  required: boolean;
31
32
  value: string;
32
33
  checkValidity(): boolean;
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,i,t,o){var s,a=arguments.length,d=a<3?i:null===o?o=Object.getOwnPropertyDescriptor(i,t):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)d=Reflect.decorate(e,i,t,o);else for(var l=e.length-1;l>=0;l--)(s=e[l])&&(d=(a<3?s(d):a>3?s(i,t,d):s(i,t))||d);return a>3&&d&&Object.defineProperty(i,t,d),d};import"./label.js";import"./tooltip.js";import{LitElement,html}from"lit";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{owSlot,owSlotType}from"./library/ow.js";import GlideCoreRadio from"./radio.js";import styles from"./radio-group.styles.js";let GlideCoreRadioGroup=class GlideCoreRadioGroup extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}checkValidity(){return this.isCheckingValidity=!0,this.#e.checkValidity()}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i),this.#t=void 0}firstUpdated(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#t=this.#s.find((e=>e.checked)),this.#a()}focus(e){let i=this.#s.find((e=>e.checked));i||(i=this.#s.find((e=>0===e.tabIndex))),i?.focus(e)}get form(){return this.#e.form}get validity(){return this.#e.validity}get willValidate(){return this.#e.willValidate}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){if(this.#t&&this.contains(this.#t))for(const e of this.#s)this.#d(e===this.#t,e)}render(){return html`<div class="component" @click="${this.#l}" @keydown="${this.#r}" ${ref(this.#n)}><glide-core-label orientation="horizontal" ?disabled="${this.disabled}" ?error="${this.#h}" ?hide="${this.hideLabel}" ?required="${this.required}"><label id="label" data-test="label">${this.label}</label><div class="${classMap({"radio-container":!0,vertical:!0,invalid:this.#h})}" role="radiogroup" slot="control" aria-labelledby="label description"><slot ${ref(this.#o)} @slotchange="${this.#c}"></slot></div><slot name="tooltip" slot="tooltip"></slot><slot id="description" name="description" slot="description"></slot></glide-core-label></div>`}reportValidity(){return this.#e.reportValidity()}updated(e){this.hasUpdated&&(e.has("value")||e.has("required"))&&(this.#p(),this.#f(!this.#e.validity.valid),this.requestUpdate())}willUpdate(e){if(this.hasUpdated){if(e.has("required")&&this.#u(),e.has("disabled")){for(const e of this.#s)this.#R(this.disabled,e);!this.disabled&&this.#m()}if(e.has("value"))for(const e of this.#s)e.checked=e.value===this.value}}constructor(){super(),this.description="",this.disabled=!1,this.label="",this.hideLabel=!1,this.name="",this.required=!1,this.value="",this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#n=createRef(),this.#o=createRef(),this.#t=void 0,this.#i=({formData:e})=>{this.name&&this.value.length>0&&!this.disabled&&e.append(this.name,this.value)},this.#e=this.attachInternals(),this.addEventListener("invalid",this.#b)}#n;#o;#t;#e;#v;#i;#a(){const e=this.#s.find((e=>e.checked));this.value=e?.value??this.#t?.value??"",this.#v=e??this.#t,this.required&&this.#u();for(const e of this.#s)this.disabled?this.#R(this.disabled,e):this.#R(e.disabled,e);!this.disabled&&this.#m()}get#h(){const e=!this.disabled&&!this.validity.valid&&this.isReportValidityOrSubmit;return this.#f(e),e}#l(e){if(this.disabled)return;if(e.target instanceof GlideCoreRadio&&e.target.disabled&&this.#v&&!this.#v.disabled)return void this.#v?.focus();const i=e.target;if(i instanceof GlideCoreRadio&&i&&!i.disabled){this.#d(!0,i);for(const e of this.#s)e!==i&&this.#d(!1,e)}}#c(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#a()}#b(e){e.preventDefault(),this.isCheckingValidity||(this.isReportValidityOrSubmit=!0,this.focus())}#r(e){if(!(this.disabled||e.target instanceof GlideCoreRadio&&e.target?.disabled)&&e.target instanceof GlideCoreRadio){const i=e.target;switch(e.key){case"ArrowUp":case"ArrowLeft":{e.preventDefault();let t=i.previousElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(-1);e&&(t=e)}else t=t.previousElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#d(!1,i),this.#d(!0,t));break}case"ArrowDown":case"ArrowRight":{e.preventDefault();let t=i.nextElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(0);e&&(t=e)}else t=t.nextElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#d(!1,i),this.#d(!0,t));break}case" ":if(e.preventDefault(),!i.disabled&&!i.checked){this.#d(!0,i);for(const e of this.#s)e!==i&&this.#d(!1,e)}}}}#p(){const e=this.#s.find((e=>e.checked));this.required&&!e?this.#e.setValidity({valueMissing:!0}," ",this.#n.value):this.#e.setValidity({})}get#s(){return this.#o.value?.assignedElements().filter((e=>e instanceof GlideCoreRadio))??[]}#d(e,i){i.checked=e,i.tabIndex=e?0:-1,e&&(this.#v=i,this.value=i.value,i.focus(),i.dispatchEvent(new Event("change",{bubbles:!0})),i.dispatchEvent(new Event("input",{bubbles:!0})))}#R(e,i){i.disabled=e,e&&(i.tabIndex=-1)}#f(e){for(const i of this.#s)i.invalid=e}#m(){if(this.disabled||this.#s.every((e=>e.disabled)))return;let e=null;const i=this.#s.find((e=>!e.disabled&&e.checked));if(i)e=i;else{const i=this.#s.find((e=>!e.disabled));i&&(e=i)}if(e)for(const i of this.#s)i.tabIndex=i===e?0:-1}#u(){for(const e of this.#s)e.required=this.required}};__decorate([property()],GlideCoreRadioGroup.prototype,"description",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"disabled",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"label",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreRadioGroup.prototype,"hideLabel",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"name",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"required",void 0),__decorate([property({reflect:!0})],GlideCoreRadioGroup.prototype,"value",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isReportValidityOrSubmit",void 0),GlideCoreRadioGroup=__decorate([customElement("glide-core-radio-group")],GlideCoreRadioGroup);export default GlideCoreRadioGroup;
1
+ var __decorate=this&&this.__decorate||function(e,i,t,o){var s,d=arguments.length,a=d<3?i:null===o?o=Object.getOwnPropertyDescriptor(i,t):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,i,t,o);else for(var r=e.length-1;r>=0;r--)(s=e[r])&&(a=(d<3?s(a):d>3?s(i,t,a):s(i,t))||a);return d>3&&a&&Object.defineProperty(i,t,a),a};import"./label.js";import"./tooltip.js";import{LitElement,html}from"lit";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{owSlot,owSlotType}from"./library/ow.js";import GlideCoreRadio from"./radio.js";import styles from"./radio-group.styles.js";let GlideCoreRadioGroup=class GlideCoreRadioGroup extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}checkValidity(){return this.isCheckingValidity=!0,this.#e.checkValidity()}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i),this.#t=void 0}firstUpdated(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#t=this.#s.find((e=>e.checked)),this.#d()}focus(e){let i=this.#s.find((e=>e.checked));i||(i=this.#s.find((e=>0===e.tabIndex))),i?.focus(e)}get form(){return this.#e.form}get validity(){return this.#e.validity}get willValidate(){return this.#e.willValidate}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){if(this.#t&&this.contains(this.#t))for(const e of this.#s)this.#a(e===this.#t,e)}render(){return html`<div class="component" @click="${this.#r}" @keydown="${this.#l}" ${ref(this.#n)}><glide-core-label orientation="horizontal" split="${ifDefined(this.privateSplit??void 0)}" ?disabled="${this.disabled}" ?error="${this.#h}" ?hide="${this.hideLabel}" ?required="${this.required}"><label id="label" data-test="label">${this.label}</label><div class="${classMap({"radio-container":!0,vertical:!0,invalid:this.#h})}" role="radiogroup" slot="control" aria-labelledby="label description"><slot ${ref(this.#o)} @slotchange="${this.#c}"></slot></div><slot name="tooltip" slot="tooltip"></slot><slot id="description" name="description" slot="description"></slot></glide-core-label></div>`}reportValidity(){return this.#e.reportValidity()}updated(e){this.hasUpdated&&(e.has("value")||e.has("required"))&&(this.#p(),this.#f(!this.#e.validity.valid),this.requestUpdate())}willUpdate(e){if(this.hasUpdated){if(e.has("required")&&this.#u(),e.has("disabled")){for(const e of this.#s)this.#R(this.disabled,e);!this.disabled&&this.#m()}if(e.has("value"))for(const e of this.#s)e.checked=e.value===this.value}}constructor(){super(),this.description="",this.disabled=!1,this.label="",this.hideLabel=!1,this.name="",this.required=!1,this.value="",this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#n=createRef(),this.#o=createRef(),this.#t=void 0,this.#i=({formData:e})=>{this.name&&this.value.length>0&&!this.disabled&&e.append(this.name,this.value)},this.#e=this.attachInternals(),this.addEventListener("invalid",this.#b)}#n;#o;#t;#e;#v;#i;#d(){const e=this.#s.find((e=>e.checked));this.value=e?.value??this.#t?.value??"",this.#v=e??this.#t,this.required&&this.#u();for(const e of this.#s)this.disabled?this.#R(this.disabled,e):this.#R(e.disabled,e);!this.disabled&&this.#m()}get#h(){const e=!this.disabled&&!this.validity.valid&&this.isReportValidityOrSubmit;return this.#f(e),e}#r(e){if(this.disabled)return;if(e.target instanceof GlideCoreRadio&&e.target.disabled&&this.#v&&!this.#v.disabled)return void this.#v?.focus();const i=e.target;if(i instanceof GlideCoreRadio&&i&&!i.disabled){this.#a(!0,i);for(const e of this.#s)e!==i&&this.#a(!1,e)}}#c(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#d()}#b(e){e.preventDefault(),this.isCheckingValidity||(this.isReportValidityOrSubmit=!0,this.focus())}#l(e){if(!(this.disabled||e.target instanceof GlideCoreRadio&&e.target?.disabled)&&e.target instanceof GlideCoreRadio){const i=e.target;switch(e.key){case"ArrowUp":case"ArrowLeft":{e.preventDefault();let t=i.previousElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(-1);e&&(t=e)}else t=t.previousElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#a(!1,i),this.#a(!0,t));break}case"ArrowDown":case"ArrowRight":{e.preventDefault();let t=i.nextElementSibling;for(;(!t||t instanceof GlideCoreRadio&&t.disabled||!(t instanceof GlideCoreRadio))&&t!==i;)if(null===t){const e=this.#s.at(0);e&&(t=e)}else t=t.nextElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#a(!1,i),this.#a(!0,t));break}case" ":if(e.preventDefault(),!i.disabled&&!i.checked){this.#a(!0,i);for(const e of this.#s)e!==i&&this.#a(!1,e)}}}}#p(){const e=this.#s.find((e=>e.checked));this.required&&!e?this.#e.setValidity({valueMissing:!0}," ",this.#n.value):this.#e.setValidity({})}get#s(){return this.#o.value?.assignedElements().filter((e=>e instanceof GlideCoreRadio))??[]}#a(e,i){i.checked=e,i.tabIndex=e?0:-1,e&&(this.#v=i,this.value=i.value,i.focus(),i.dispatchEvent(new Event("change",{bubbles:!0})),i.dispatchEvent(new Event("input",{bubbles:!0})))}#R(e,i){i.disabled=e,e&&(i.tabIndex=-1)}#f(e){for(const i of this.#s)i.invalid=e}#m(){if(this.disabled||this.#s.every((e=>e.disabled)))return;let e=null;const i=this.#s.find((e=>!e.disabled&&e.checked));if(i)e=i;else{const i=this.#s.find((e=>!e.disabled));i&&(e=i)}if(e)for(const i of this.#s)i.tabIndex=i===e?0:-1}#u(){for(const e of this.#s)e.required=this.required}};__decorate([property()],GlideCoreRadioGroup.prototype,"description",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"disabled",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"label",void 0),__decorate([property({attribute:"hide-label",type:Boolean})],GlideCoreRadioGroup.prototype,"hideLabel",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"name",void 0),__decorate([property()],GlideCoreRadioGroup.prototype,"privateSplit",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreRadioGroup.prototype,"required",void 0),__decorate([property({reflect:!0})],GlideCoreRadioGroup.prototype,"value",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isReportValidityOrSubmit",void 0),GlideCoreRadioGroup=__decorate([customElement("glide-core-radio-group")],GlideCoreRadioGroup);export default GlideCoreRadioGroup;
@@ -30,7 +30,7 @@ import{css}from"lit";export default[css`
30
30
  }
31
31
  }
32
32
 
33
- glide-core-label::part(tooltip-and-label-container) {
33
+ glide-core-label::part(tooltips-and-label) {
34
34
  align-items: flex-start;
35
35
  }
36
36
  `];
@@ -1,7 +1,7 @@
1
1
  import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
2
2
  .component {
3
3
  display: inline-flex;
4
- gap: 0;
4
+ position: relative;
5
5
 
6
6
  & .divider {
7
7
  inline-size: 1px;