@crowdstrike/glide-core 0.11.0 → 0.12.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.
Files changed (39) hide show
  1. package/dist/checkbox-group.d.ts +3 -0
  2. package/dist/checkbox-group.js +43 -1
  3. package/dist/checkbox-group.styles.js +12 -0
  4. package/dist/checkbox-group.test.validity.js +69 -0
  5. package/dist/checkbox.d.ts +3 -1
  6. package/dist/checkbox.js +135 -1
  7. package/dist/checkbox.styles.js +12 -0
  8. package/dist/checkbox.test.validity.js +77 -1
  9. package/dist/dropdown.d.ts +3 -0
  10. package/dist/dropdown.js +195 -1
  11. package/dist/dropdown.styles.js +18 -6
  12. package/dist/dropdown.test.events.single.js +19 -0
  13. package/dist/dropdown.test.interactions.js +0 -18
  14. package/dist/dropdown.test.interactions.multiple.js +8 -10
  15. package/dist/dropdown.test.interactions.single.js +18 -0
  16. package/dist/dropdown.test.validity.js +172 -1
  17. package/dist/input.d.ts +4 -0
  18. package/dist/input.js +155 -1
  19. package/dist/input.styles.js +8 -0
  20. package/dist/input.test.validity.js +140 -62
  21. package/dist/menu.d.ts +2 -0
  22. package/dist/menu.js +1 -1
  23. package/dist/menu.test.basics.d.ts +1 -1
  24. package/dist/menu.test.basics.js +12 -27
  25. package/dist/menu.test.interactions.js +90 -0
  26. package/dist/radio-group.d.ts +3 -0
  27. package/dist/radio-group.js +45 -1
  28. package/dist/radio-group.styles.js +12 -0
  29. package/dist/radio-group.test.validity.js +82 -0
  30. package/dist/styles/variables.css +1 -1
  31. package/dist/tag.styles.js +1 -1
  32. package/dist/textarea.d.ts +3 -0
  33. package/dist/textarea.js +58 -2
  34. package/dist/textarea.styles.js +8 -0
  35. package/dist/textarea.test.events.js +0 -114
  36. package/dist/textarea.test.validity.js +64 -72
  37. package/dist/tooltip.d.ts +2 -1
  38. package/dist/tooltip.js +1 -1
  39. package/package.json +1 -1
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=!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;
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 offset(){return this.#c??Number.parseFloat(window.getComputedStyle(document.body).getPropertyValue("--glide-core-spacing-xxs"))*Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize)}set offset(e){this.#c=e}get open(){return this.#o}set open(e){this.#o=e,e&&!this.isTargetDisabled?this.#h():this.#p()}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.#m?.at(0);this.open&&e&&!this.isTargetDisabled&&(e.privateActive=!0,this.#h()),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.#f}" ${ref(this.#e)}><slot class="target-slot" name="target" @click="${this.#E}" @keydown="${this.#v}" @slotchange="${this.#g}" ${ref(this.#l)}></slot><slot class="default-slot" @click="${this.#S}" @focusin="${this.#w}" @keydown="${this.#v}" @mouseover="${this.#C}" @slotchange="${this.#y}" ${ref(this.#t)}></slot></div>`}#R;#e;#t;#i;#o;#n;#c;#d;#s;#l;get#k(){return this.#m?.find((({privateActive:e})=>e))}#a;#O(e){this.#u&&"focus"in this.#u&&this.#u?.focus(e)}#p(){this.#R?.(),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}#y(){ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),owSlot(this.#t.value),owSlotType(this.#t.value,[GlideCoreMenuOptions]);const e=this.#m?.at(0);e&&(e.privateActive=!0),this.#r.privateSize=this.size}#S(){this.open=!1}#w(e){(e.target instanceof GlideCoreMenuButton||e.target instanceof GlideCoreMenuLink)&&this.#k&&this.#r&&(this.#k.privateActive=!1,e.target.privateActive=!0,this.#r.ariaActivedescendant=e.target.id)}#C(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.#r&&(this.#r.ariaActivedescendant=e.target.id)}}#f(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)}#v(e){ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions));const t=this.#u instanceof HTMLSpanElement||this.#u instanceof HTMLDivElement;if([" ","Enter"].includes(e.key)&&this.open)return" "===e.key&&t&&e.preventDefault(),this.open=!1,this.#O(),this.#k?.click(),void(this.#i=!0);if([" ","Enter"].includes(e.key)&&t)return e.preventDefault(),void(this.open=!0);if(["Escape"].includes(e.key)&&this.open)return this.open=!1,void this.#O();if(["ArrowUp","ArrowDown"].includes(e.key)&&!this.open&&this.#k)return e.preventDefault(),this.open=!0,void(this.#r.ariaActivedescendant=this.#k.id);if(this.open){ow(this.#m,ow.array),ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),ow(this.#k,ow.object.is((e=>e instanceof GlideCoreMenuButton||e instanceof GlideCoreMenuLink)));const t=this.#m.indexOf(this.#k);if("ArrowUp"===e.key&&!e.metaKey){e.preventDefault();const i=this.#m.at(t-1);return void(i&&0!==t&&(this.#k.privateActive=!1,this.#r.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.#k.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.#m.at(0);return void(t&&(this.#k.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.#m.at(-1);return void(t&&(this.#k.privateActive=!1,this.#r.ariaActivedescendant=t.id,t.privateActive=!0))}}}#g(){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.#h():this.#p()})).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.#u instanceof HTMLSpanElement||this.#u instanceof HTMLDivElement)&&this.#u instanceof HTMLElement&&(this.#u.tabIndex=0),this.open&&!this.isTargetDisabled?this.#h():this.#p()}#E(){this.isTargetDisabled?this.#p():this.#i?this.#i=!1:this.#m&&this.#m.length>0&&(this.open=!this.open)}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))}#h(){this.#R?.(),this.#u&&this.#t.value&&(this.#R=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(this.offset),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.#k?.id&&(this.#r.ariaActivedescendant=this.#k.id),this.#u&&(this.#u.ariaExpanded="true")})()})))}get#u(){return this.#l.value?.assignedElements().at(0)}};__decorate([property({reflect:!0,type:Number})],GlideCoreMenu.prototype,"offset",null),__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;
@@ -1 +1 @@
1
- export {};
1
+ import './menu.options.js';
@@ -1,10 +1,10 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-expressions */
2
+ import './menu.options.js';
2
3
  import { ArgumentError } from 'ow';
3
4
  import { aTimeout, expect, fixture, html } from '@open-wc/testing';
4
5
  import GlideCoreMenu from './menu.js';
5
6
  import GlideCoreMenuButton from './menu.button.js';
6
7
  import GlideCoreMenuLink from './menu.link.js';
7
- import GlideCoreMenuOptions from './menu.options.js';
8
8
  import expectArgumentError from './library/expect-argument-error.js';
9
9
  import sinon from 'sinon';
10
10
  GlideCoreMenu.shadowRootOptions.mode = 'open';
@@ -63,32 +63,6 @@ it('can be opened', async () => {
63
63
  expect(target?.ariaExpanded).to.equal('true');
64
64
  expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
65
65
  });
66
- it('can have a default slot', async () => {
67
- const component = await fixture(html `<glide-core-menu>
68
- <button slot="target">Target</button>
69
-
70
- <glide-core-menu-options>
71
- <glide-core-menu-link label="Link"></glide-core-menu-link>
72
- </glide-core-menu-options>
73
- </glide-core-menu>`);
74
- const assignedElements = component.shadowRoot
75
- ?.querySelectorAll('slot')[1]
76
- .assignedElements();
77
- expect(assignedElements?.at(0) instanceof GlideCoreMenuOptions).to.be.true;
78
- });
79
- it('can have a target slot', async () => {
80
- const component = await fixture(html `<glide-core-menu>
81
- <button slot="target">Target</button>
82
-
83
- <glide-core-menu-options>
84
- <glide-core-menu-link label="Link"></glide-core-menu-link>
85
- </glide-core-menu-options>
86
- </glide-core-menu>`);
87
- const assignedElements = component.shadowRoot
88
- ?.querySelector('slot[name="target"]')
89
- ?.assignedElements();
90
- expect(assignedElements?.at(0)?.textContent).to.equal('Target');
91
- });
92
66
  it('activates the first menu link by default', async () => {
93
67
  const component = await fixture(html `
94
68
  <glide-core-menu open>
@@ -144,6 +118,17 @@ it('is not opened when initially `open` and its target is `disabled`', async ()
144
118
  expect(target?.ariaExpanded).to.equal('false');
145
119
  expect(options?.getAttribute('aria-activedescendant')).to.equal('');
146
120
  });
121
+ it('adds `tabIndex` to its target when it is a `<span>`', async () => {
122
+ const component = await fixture(html `<glide-core-menu>
123
+ <span slot="target">Target</span>
124
+
125
+ <glide-core-menu-options>
126
+ <glide-core-menu-link label="Link"></glide-core-menu-link>
127
+ </glide-core-menu-options>
128
+ </glide-core-menu>`);
129
+ const target = component.querySelector('span');
130
+ expect(target?.tabIndex).to.equal(0);
131
+ });
147
132
  it('throws if it does not have a default slot', async () => {
148
133
  await expectArgumentError(() => {
149
134
  return fixture(html `<glide-core-menu
@@ -269,6 +269,25 @@ it('opens on Enter', async () => {
269
269
  expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
270
270
  expect(target?.ariaExpanded).to.equal('true');
271
271
  });
272
+ it('opens on Enter when its target is a `<span>`', async () => {
273
+ const component = await fixture(html `<glide-core-menu>
274
+ <span slot="target">Target</span>
275
+
276
+ <glide-core-menu-options>
277
+ <glide-core-menu-link label="Link"></glide-core-menu-link>
278
+ </glide-core-menu-options>
279
+ </glide-core-menu>`);
280
+ component.querySelector('span')?.focus();
281
+ await sendKeys({ press: 'Enter' });
282
+ const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
283
+ const options = component.querySelector('glide-core-menu-options');
284
+ const target = component.querySelector('span');
285
+ const link = component.querySelector('glide-core-menu-link');
286
+ expect(component.open).to.be.true;
287
+ expect(defaultSlot?.checkVisibility()).to.be.true;
288
+ expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
289
+ expect(target?.ariaExpanded).to.equal('true');
290
+ });
272
291
  it('opens on ArrowUp', async () => {
273
292
  const component = await fixture(html `<glide-core-menu>
274
293
  <button slot="target">Target</button>
@@ -326,6 +345,25 @@ it('opens on Space', async () => {
326
345
  expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
327
346
  expect(target?.ariaExpanded).to.equal('true');
328
347
  });
348
+ it('opens on Space when its target is a `<span>`', async () => {
349
+ const component = await fixture(html `<glide-core-menu>
350
+ <span slot="target">Target</span>
351
+
352
+ <glide-core-menu-options>
353
+ <glide-core-menu-link label="Link"></glide-core-menu-link>
354
+ </glide-core-menu-options>
355
+ </glide-core-menu>`);
356
+ component.querySelector('span')?.focus();
357
+ await sendKeys({ press: ' ' });
358
+ const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
359
+ const options = component.querySelector('glide-core-menu-options');
360
+ const target = component.querySelector('span');
361
+ const link = component.querySelector('glide-core-menu-link');
362
+ expect(component.open).to.be.true;
363
+ expect(defaultSlot?.checkVisibility()).to.be.true;
364
+ expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
365
+ expect(target?.ariaExpanded).to.equal('true');
366
+ });
329
367
  it('does not open on Space when there are no options', async () => {
330
368
  const component = await fixture(html `<glide-core-menu>
331
369
  <button slot="target">Target</button>
@@ -494,6 +532,27 @@ it('closes when an option is selected via Enter', async () => {
494
532
  expect(options?.getAttribute('aria-activedescendant')).to.equal('');
495
533
  expect(target?.ariaExpanded).to.equal('false');
496
534
  });
535
+ it('closes when an option is selected via Enter and its target is a `<span>', async () => {
536
+ const component = await fixture(html `<glide-core-menu open>
537
+ <span slot="target">Target</span>
538
+
539
+ <glide-core-menu-options>
540
+ <glide-core-menu-link label="Link"></glide-core-menu-link>
541
+ </glide-core-menu-options>
542
+ </glide-core-menu>`);
543
+ component.querySelector('span')?.focus();
544
+ component
545
+ .querySelector('glide-core-menu-link')
546
+ ?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
547
+ await sendKeys({ press: 'Enter' });
548
+ const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
549
+ const options = component.querySelector('glide-core-menu-options');
550
+ const target = component.querySelector('span');
551
+ expect(component.open).to.be.false;
552
+ expect(defaultSlot?.checkVisibility()).to.be.false;
553
+ expect(options?.getAttribute('aria-activedescendant')).to.equal('');
554
+ expect(target?.ariaExpanded).to.equal('false');
555
+ });
497
556
  it('closes when an option is selected via Space', async () => {
498
557
  const component = await fixture(html `<glide-core-menu open>
499
558
  <button slot="target">Target</button>
@@ -512,6 +571,24 @@ it('closes when an option is selected via Space', async () => {
512
571
  expect(options?.getAttribute('aria-activedescendant')).to.equal('');
513
572
  expect(target?.ariaExpanded).to.equal('false');
514
573
  });
574
+ it('closes when an option is selected via Space and its target is a `<span>`', async () => {
575
+ const component = await fixture(html `<glide-core-menu open>
576
+ <span slot="target">Target</span>
577
+
578
+ <glide-core-menu-options>
579
+ <glide-core-menu-link label="Link"></glide-core-menu-link>
580
+ </glide-core-menu-options>
581
+ </glide-core-menu>`);
582
+ component.querySelector('span')?.focus();
583
+ await sendKeys({ press: ' ' });
584
+ const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
585
+ const options = component.querySelector('glide-core-menu-options');
586
+ const target = component.querySelector('span');
587
+ expect(component.open).to.be.false;
588
+ expect(defaultSlot?.checkVisibility()).to.be.false;
589
+ expect(options?.getAttribute('aria-activedescendant')).to.equal('');
590
+ expect(target?.ariaExpanded).to.equal('false');
591
+ });
515
592
  it('activates the first menu link by default', async () => {
516
593
  const component = await fixture(html `
517
594
  <glide-core-menu open>
@@ -939,3 +1016,16 @@ it('does not wrap on ArrowDown', async () => {
939
1016
  await sendKeys({ up: 'Meta' });
940
1017
  expect(options[1].privateActive).to.be.true;
941
1018
  });
1019
+ it('has `set offset()` coverage', async () => {
1020
+ const component = await fixture(html `
1021
+ <glide-core-menu>
1022
+ <button slot="target">Target</button>
1023
+
1024
+ <glide-core-menu-options>
1025
+ <glide-core-menu-link label="One"></glide-core-menu-link>
1026
+ <glide-core-menu-link label="Two"></glide-core-menu-link>
1027
+ </glide-core-menu-options>
1028
+ </glide-core-menu>
1029
+ `);
1030
+ component.offset = 10;
1031
+ });
@@ -39,10 +39,13 @@ export default class GlideCoreRadioGroup extends LitElement {
39
39
  formResetCallback(): void;
40
40
  render(): import("lit").TemplateResult<1>;
41
41
  reportValidity(): boolean;
42
+ setCustomValidity(message: string): void;
43
+ setValidity(flags?: ValidityStateFlags, message?: string): void;
42
44
  updated(changedProperties: PropertyValueMap<GlideCoreRadioGroup>): void;
43
45
  willUpdate(changedProperties: PropertyValueMap<GlideCoreRadioGroup>): void;
44
46
  constructor();
45
47
  private isBlurring;
46
48
  private isCheckingValidity;
47
49
  private isReportValidityOrSubmit;
50
+ private validityMessage?;
48
51
  }
@@ -1 +1,45 @@
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 r=e.length-1;r>=0;r--)(s=e[r])&&(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{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(){this.isCheckingValidity=!0;const e=this.#e.checkValidity();return this.isCheckingValidity=!1,e}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.#r}" @keydown="${this.#l}" ${ref(this.#n)}><glide-core-private-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" @blur="${this.#c}"><slot ${ref(this.#o)} @slotchange="${this.#p}"></slot></div><slot name="tooltip" slot="tooltip"></slot><slot id="description" name="description" slot="description"></slot></glide-core-private-label></div>`}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#e.reportValidity();return this.requestUpdate(),e}updated(e){this.hasUpdated&&(e.has("value")||e.has("required"))&&(this.#f(),this.#u(!this.#e.validity.valid),this.requestUpdate())}willUpdate(e){if(this.hasUpdated){if(e.has("required")&&this.#R(),e.has("disabled")){for(const e of this.#s)this.#m(this.disabled,e);!this.disabled&&this.#b()}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.isBlurring=!1,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.#v)}#n;#o;#t;#e;#C;#i;#a(){const e=this.#s.find((e=>e.checked));this.value=e?.value??this.#t?.value??"",this.#C=e??this.#t,this.required&&this.#R();for(const e of this.#s)this.disabled?this.#m(this.disabled,e):this.#m(e.disabled,e),e.addEventListener("blur",this.#y.bind(this));!this.disabled&&this.#b()}get#h(){const e=!this.disabled&&!this.validity.valid&&this.isReportValidityOrSubmit;return this.#u(e),e}#c(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1}#r(e){if(this.disabled)return;if(e.target instanceof GlideCoreRadio&&e.target.disabled&&this.#C&&!this.#C.disabled)return void this.#C?.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)}}#p(){owSlot(this.#o.value),owSlotType(this.#o.value,[GlideCoreRadio]),this.#a()}#v(e){if(e.preventDefault(),!this.isCheckingValidity){if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&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"Enter":this.form?.requestSubmit();break;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)}}}}#y(e){const i=e.relatedTarget;i&&i instanceof GlideCoreRadio&&this.#s.includes(i)||this.#c()}#f(){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.#C=i,this.value=i.value,i.focus(),i.dispatchEvent(new Event("change",{bubbles:!0})),i.dispatchEvent(new Event("input",{bubbles:!0})))}#m(e,i){i.disabled=e,e&&(i.tabIndex=-1)}#u(e){for(const i of this.#s)i.invalid=e}#b(){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}#R(){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({reflect:!0})],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,"isBlurring",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,s){var o,a=arguments.length,d=a<3?i:null===s?s=Object.getOwnPropertyDescriptor(i,t):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)d=Reflect.decorate(e,i,t,s);else for(var r=e.length-1;r>=0;r--)(o=e[r])&&(d=(a<3?o(d):a>3?o(i,t,d):o(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{ifDefined}from"lit/directives/if-defined.js";import{owSlot,owSlotType}from"./library/ow.js";import{unsafeHTML}from"lit/directives/unsafe-html.js";import{when}from"lit/directives/when.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(){this.isCheckingValidity=!0;const e=this.#e.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i),this.#t=void 0}firstUpdated(){owSlot(this.#s.value),owSlotType(this.#s.value,[GlideCoreRadio]),this.#t=this.#o.find((e=>e.checked)),this.#a()}focus(e){let i=this.#o.find((e=>e.checked));i||(i=this.#o.find((e=>0===e.tabIndex))),i?.focus(e)}get form(){return this.#e.form}get validity(){const e=this.#o.some((({checked:e})=>e));return!this.required||e||this.value||this.disabled?this.required&&this.#e.validity.valueMissing&&(e||this.value)?(this.#e.setValidity({}),this.#e.validity):this.#e.validity:(this.#e.setValidity({customError:Boolean(this.validityMessage),valueMissing:!0}," ",this.#d.value),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.#o)this.#r(e===this.#t,e)}render(){return html`
2
+ <div
3
+ class="component"
4
+ @click=${this.#l}
5
+ @keydown=${this.#n}
6
+ ${ref(this.#d)}
7
+ >
8
+ <glide-core-private-label
9
+ orientation="horizontal"
10
+ split=${ifDefined(this.privateSplit??void 0)}
11
+ ?disabled=${this.disabled}
12
+ ?error=${this.#h}
13
+ ?hide=${this.hideLabel}
14
+ ?required=${this.required}
15
+ >
16
+ <label id="label" data-test="label"> ${this.label} </label>
17
+
18
+ <div
19
+ class=${classMap({"radio-container":!0,vertical:!0,invalid:this.#h})}
20
+ role="radiogroup"
21
+ slot="control"
22
+ aria-labelledby="label description"
23
+ @blur=${this.#c}
24
+ >
25
+ <slot
26
+ ${ref(this.#s)}
27
+ @slotchange=${this.#p}
28
+ ></slot>
29
+ </div>
30
+
31
+ <slot name="tooltip" slot="tooltip"></slot>
32
+
33
+ <div id="description" slot="description">
34
+ <slot
35
+ class=${classMap({description:!0,hidden:Boolean(this.#h&&this.validityMessage)})}
36
+ name="description"
37
+ ></slot>
38
+
39
+ ${when(this.#h&&this.validityMessage,(()=>html`<span class="validity-message" data-test="validity-message"
40
+ >${unsafeHTML(this.validityMessage)}</span
41
+ >`))}
42
+ </div>
43
+ </glide-core-private-label>
44
+ </div>
45
+ `}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#e.reportValidity();return this.requestUpdate(),e}setCustomValidity(e){this.validityMessage=e,""===e?this.#e.setValidity({customError:!1},"",this.#d.value):this.#e.setValidity({customError:!0,valueMissing:this.#e.validity.valueMissing}," ",this.#d.value)}setValidity(e,i){this.validityMessage=i,this.#e.setValidity(e," ",this.#d.value)}updated(e){this.hasUpdated&&(e.has("value")||e.has("required"))&&(this.#u(),this.#f(!this.#e.validity.valid),this.requestUpdate())}willUpdate(e){if(this.hasUpdated){if(e.has("required")&&this.#m(),e.has("disabled")){for(const e of this.#o)this.#v(this.disabled,e);!this.disabled&&this.#R()}if(e.has("value"))for(const e of this.#o)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.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#d=createRef(),this.#s=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)}#d;#s;#t;#e;#y;#i;#a(){const e=this.#o.find((e=>e.checked));this.value=e?.value??this.#t?.value??"",this.#y=e??this.#t,this.required&&this.#m();for(const e of this.#o)this.disabled?this.#v(this.disabled,e):this.#v(e.disabled,e),e.addEventListener("blur",this.#C.bind(this));!this.disabled&&this.#R()}get#h(){const e=!this.disabled&&!this.validity.valid&&this.isReportValidityOrSubmit;return this.#f(e),e}#c(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1}#l(e){if(this.disabled)return;if(e.target instanceof GlideCoreRadio&&e.target.disabled&&this.#y&&!this.#y.disabled)return void this.#y?.focus();const i=e.target;if(i instanceof GlideCoreRadio&&i&&!i.disabled){this.#r(!0,i);for(const e of this.#o)e!==i&&this.#r(!1,e)}}#p(){owSlot(this.#s.value),owSlotType(this.#s.value,[GlideCoreRadio]),this.#a()}#b(e){if(e.preventDefault(),!this.isCheckingValidity){if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}}#n(e){if(!(this.disabled||e.target instanceof GlideCoreRadio&&e.target?.disabled)&&e.target instanceof GlideCoreRadio){const i=e.target;switch(e.key){case"Enter":this.form?.requestSubmit();break;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.#o.at(-1);e&&(t=e)}else t=t.previousElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#r(!1,i),this.#r(!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.#o.at(0);e&&(t=e)}else t=t.nextElementSibling;t&&t instanceof GlideCoreRadio&&!t.disabled&&t!==i&&(this.#r(!1,i),this.#r(!0,t));break}case" ":if(e.preventDefault(),!i.disabled&&!i.checked){this.#r(!0,i);for(const e of this.#o)e!==i&&this.#r(!1,e)}}}}#C(e){const i=e.relatedTarget;i&&i instanceof GlideCoreRadio&&this.#o.includes(i)||this.#c()}#u(){const e=this.#o.find((e=>e.checked));this.required&&!e?this.#e.setValidity({valueMissing:!0}," ",this.#d.value):this.#e.setValidity({})}get#o(){return this.#s.value?.assignedElements().filter((e=>e instanceof GlideCoreRadio))??[]}#r(e,i){i.checked=e,i.tabIndex=e?0:-1,e&&(this.#y=i,this.value=i.value,i.focus(),i.dispatchEvent(new Event("change",{bubbles:!0})),i.dispatchEvent(new Event("input",{bubbles:!0})))}#v(e,i){i.disabled=e,e&&(i.tabIndex=-1)}#f(e){for(const i of this.#o)i.invalid=e}#R(){if(this.disabled||this.#o.every((e=>e.disabled)))return;let e=null;const i=this.#o.find((e=>!e.disabled&&e.checked));if(i)e=i;else{const i=this.#o.find((e=>!e.disabled));i&&(e=i)}if(e)for(const i of this.#o)i.tabIndex=i===e?0:-1}#m(){for(const e of this.#o)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({reflect:!0})],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,"isBlurring",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"isReportValidityOrSubmit",void 0),__decorate([state()],GlideCoreRadioGroup.prototype,"validityMessage",void 0),GlideCoreRadioGroup=__decorate([customElement("glide-core-radio-group")],GlideCoreRadioGroup);export default GlideCoreRadioGroup;
@@ -33,4 +33,16 @@ import{css}from"lit";export default[css`
33
33
  glide-core-private-label::part(tooltips-and-label) {
34
34
  align-items: flex-start;
35
35
  }
36
+
37
+ .description {
38
+ display: block;
39
+
40
+ &.hidden {
41
+ display: none;
42
+ }
43
+ }
44
+
45
+ .validity-message {
46
+ display: block;
47
+ }
36
48
  `];
@@ -227,3 +227,85 @@ it('sets radios as valid initially when required', async () => {
227
227
  expect(radios[1]?.invalid).to.be.false;
228
228
  expect(radios[1]?.ariaInvalid).to.equal('false');
229
229
  });
230
+ it('is valid after `value` is set and `required`', async () => {
231
+ const component = await fixture(html `<glide-core-radio-group label="label" name="name" required>
232
+ <glide-core-radio value="value-1" label="One"></glide-core-radio>
233
+ </glide-core-radio-group>`);
234
+ expect(component.validity?.valid).to.be.false;
235
+ expect(component.validity?.valueMissing).to.be.true;
236
+ expect(component.checkValidity()).to.be.false;
237
+ expect(component.reportValidity()).to.be.false;
238
+ component.value = 'value-1';
239
+ expect(component.validity?.valid).to.be.true;
240
+ expect(component.validity?.valueMissing).to.be.false;
241
+ expect(component.checkValidity()).to.be.true;
242
+ expect(component.reportValidity()).to.be.true;
243
+ });
244
+ it('sets the validity message with `setCustomValidity()`', async () => {
245
+ const component = await fixture(html `<glide-core-radio-group label="label" name="name">
246
+ <glide-core-radio value="value-1" label="One"></glide-core-radio>
247
+ </glide-core-radio-group>`);
248
+ component.setCustomValidity('validity message');
249
+ expect(component.validity?.valid).to.be.false;
250
+ expect(component.validity?.customError).to.be.true;
251
+ expect(component.checkValidity()).to.be.false;
252
+ await elementUpdated(component);
253
+ // Like native, the validity message shouldn't display until `reportValidity()` is called.
254
+ expect(component.shadowRoot?.querySelector('[data-test="validity-message"]')
255
+ ?.textContent).to.be.undefined;
256
+ expect(component.reportValidity()).to.be.false;
257
+ await elementUpdated(component);
258
+ expect(component.shadowRoot?.querySelector('[data-test="validity-message"]')
259
+ ?.textContent).to.equal('validity message');
260
+ });
261
+ it('removes a validity message with an empty argument to `setCustomValidity()`', async () => {
262
+ const component = await fixture(html `<glide-core-radio-group label="label" name="name">
263
+ <glide-core-radio value="value-1" label="One"></glide-core-radio>
264
+ </glide-core-radio-group>`);
265
+ component.setCustomValidity('validity message');
266
+ component.reportValidity();
267
+ await elementUpdated(component);
268
+ component.setCustomValidity('');
269
+ await elementUpdated(component);
270
+ expect(component.shadowRoot?.querySelector('[data-test="validity-message"]')
271
+ ?.textContent).to.be.undefined;
272
+ });
273
+ it('is invalid when `setValidity()` is called', async () => {
274
+ const component = await fixture(html `<glide-core-radio-group label="label" name="name">
275
+ <glide-core-radio value="value-1" label="One"></glide-core-radio>
276
+ </glide-core-radio-group>`);
277
+ component.setValidity({ customError: true }, 'validity message');
278
+ expect(component.validity.valid).to.be.false;
279
+ await elementUpdated(component);
280
+ // Like native, the validity message shouldn't display until `reportValidity()` is called.
281
+ expect(component.shadowRoot?.querySelector('[data-test="validity-message"]')
282
+ ?.textContent).to.be.undefined;
283
+ expect(component.validity?.customError).to.be.true;
284
+ component.reportValidity();
285
+ await elementUpdated(component);
286
+ expect(component.shadowRoot?.querySelector('[data-test="validity-message"]')
287
+ ?.textContent).to.equal('validity message');
288
+ });
289
+ it('is valid when `setValidity()` is called', async () => {
290
+ const component = await fixture(html `<glide-core-radio-group label="label" name="name">
291
+ <glide-core-radio value="value-1" label="One"></glide-core-radio>
292
+ </glide-core-radio-group>`);
293
+ component.setValidity({ customError: true }, 'validity message');
294
+ component.setValidity({});
295
+ await elementUpdated(component);
296
+ expect(component.validity.valid).to.be.true;
297
+ expect(component.validity.customError).to.be.false;
298
+ expect(component.reportValidity()).to.be.true;
299
+ await elementUpdated(component);
300
+ expect(component.shadowRoot?.querySelector('[data-test="validity-message"]')
301
+ ?.textContent).to.be.undefined;
302
+ });
303
+ it('retains existing validity state when `setCustomValidity()` is called', async () => {
304
+ const component = await fixture(html `<glide-core-radio-group label="label" name="name" required>
305
+ <glide-core-radio value="value-1" label="One"></glide-core-radio>
306
+ </glide-core-radio-group>`);
307
+ component.setCustomValidity('validity message');
308
+ expect(component.validity?.valid).to.be.false;
309
+ expect(component.validity?.customError).to.be.true;
310
+ expect(component.validity?.valueMissing).to.be.true;
311
+ });
@@ -1 +1 @@
1
- :root,:host{color-scheme:normal;--glide-core-border-radius-lg: .75rem;--glide-core-border-radius-md: .5rem;--glide-core-border-radius-none: 0rem;--glide-core-border-radius-round: 7.5rem;--glide-core-border-radius-sm: .25rem;--glide-core-border-radius-xs: .125rem;--glide-core-border-width-lg: .25rem;--glide-core-border-width-md: .125rem;--glide-core-border-width-none: 0rem;--glide-core-border-width-sm: .0625rem;--glide-core-page-size-details-panel: 27.375rem;--glide-core-page-size-height: 46.875rem;--glide-core-page-size-width: 83.3125rem;--glide-core-spacing-lg: 1.5rem;--glide-core-spacing-md: 1rem;--glide-core-spacing-sm: .75rem;--glide-core-spacing-xl: 2rem;--glide-core-spacing-xs: .5rem;--glide-core-spacing-xxl: 3rem;--glide-core-spacing-xxs: .25rem;--glide-core-spacing-xxxl: 4rem;--glide-core-spacing-xxxs: .125rem;--glide-core-spacing-zero: 0rem}:root,:host,.theme-light{color-scheme:light;--glide-core-border-action: #0073e6;--glide-core-border-action-disabled: #d7e7ff;--glide-core-border-action-hover: #eef5ff;--glide-core-border-base: #c9c9c9;--glide-core-border-base-dark: #6d6d6d;--glide-core-border-base-darker: #424242;--glide-core-border-base-light: #e3e3e3;--glide-core-border-base-lighter: #f0f0f0;--glide-core-border-base-lightest: #ffffff;--glide-core-border-base-transparent: #0000001a;--glide-core-border-disabled: #8a8a8a;--glide-core-border-focus: #0073e6;--glide-core-border-focus-light: #eef5ff;--glide-core-border-primary: #054fb9;--glide-core-border-primary-hover: #0461cf;--glide-core-icon-active: #0073e6;--glide-core-icon-default: #212121;--glide-core-icon-default2: #212121;--glide-core-icon-display: #212121;--glide-core-icon-display-light: #6d6d6d;--glide-core-icon-hover: #8babf1;--glide-core-icon-primary: #054fb9;--glide-core-icon-primary-hover: #0461cf;--glide-core-icon-secondary-disabled: #d7e7ff;--glide-core-icon-selected: #ffffff;--glide-core-icon-selected-disabled: #eef5ff;--glide-core-icon-selected2: #ffffff;--glide-core-icon-tertiary-disabled: #8a8a8a;--glide-core-status-error: #db2d24;--glide-core-status-expired: #ff3b30;--glide-core-status-failed: #ff3b30;--glide-core-status-in-progress: #ffcc00;--glide-core-status-queued: #5ac8fa;--glide-core-status-scheduled: #af52de;--glide-core-status-success: #34c759;--glide-core-status-unknown: #6d6d6d;--glide-core-status-warning-critical: #ff3b30;--glide-core-status-warning-high: #ff9500;--glide-core-status-warning-informational: #0073e6;--glide-core-status-warning-low: #607d8b;--glide-core-status-warning-medium: #ffcc00;--glide-core-surface-active: #ffffff;--glide-core-surface-attention: #fffbeb;--glide-core-surface-base: #f0f0f0;--glide-core-surface-base-dark: #212121;--glide-core-surface-base-gray: #0000001a;--glide-core-surface-base-gray-dark: #00000066;--glide-core-surface-base-gray-light: #00000012;--glide-core-surface-base-gray-lighter: #00000008;--glide-core-surface-base-light: #ffffff8c;--glide-core-surface-base-lighter: #ffffffbf;--glide-core-surface-base-lightest: #ffffffcc;--glide-core-surface-base-xlightest: #ffffffe5;--glide-core-surface-disabled: #f0f0f0;--glide-core-surface-dot-step: #8babf1;--glide-core-surface-error: #fff0ef;--glide-core-surface-focus: #0073e6;--glide-core-surface-hover: #d7e7ff;--glide-core-surface-informational: #eef5ff;--glide-core-surface-modal: #ffffff;--glide-core-surface-page: #ffffff;--glide-core-surface-primary: #0073e6;--glide-core-surface-primary-disabled: #1d7afc26;--glide-core-surface-secondary: #eef5ff;--glide-core-surface-secondary-disabled: #eef5ff;--glide-core-surface-selected: #0073e6;--glide-core-surface-selected-disabled: #8a8a8a;--glide-core-surface-selected-hover: #054fb9;--glide-core-surface-success: #f1fdf4;--glide-core-surface-table-row-hover: #1d7afc26;--glide-core-surface-unselected-disabled: #e3e3e3;--glide-core-surface-warning: #fff6e9;--glide-core-surface-white-1percent: #ffffff03;--glide-core-text-body-1: #212121;--glide-core-text-body-2: #212121;--glide-core-text-body-light: #424242;--glide-core-text-body-lighter: #8a8a8a;--glide-core-text-disabled: #f0f0f0;--glide-core-text-header-1: #424242;--glide-core-text-header-2: #6d6d6d;--glide-core-text-link: #0461cf;--glide-core-text-link-dark-surface: #8babf1;--glide-core-text-link-table: #0461cf;--glide-core-text-placeholder: #6d6d6d;--glide-core-text-primary: #054fb9;--glide-core-text-primary-hover: #0461cf;--glide-core-text-secondary: #0073e6;--glide-core-text-secondary-disabled: #d7e7ff;--glide-core-text-selected: #ffffff;--glide-core-text-selected-2: #ffffff;--glide-core-text-tertiary: #212121;--glide-core-text-tertiary-disabled: #8a8a8a}:host,.theme-dark{color-scheme:dark;--glide-core-border-action: #0073e6;--glide-core-border-action-disabled: #eef5ff;--glide-core-border-action-hover: #eef5ff;--glide-core-border-base: #6d6d6d;--glide-core-border-base-dark: #c9c9c9;--glide-core-border-base-darker: #e3e3e3;--glide-core-border-base-light: #212121;--glide-core-border-base-lighter: #212121;--glide-core-border-base-lightest: #424242;--glide-core-border-base-transparent: #0000001a;--glide-core-border-disabled: #8a8a8a;--glide-core-border-focus: #0073e6;--glide-core-border-focus-light: #eef5ff;--glide-core-border-primary: #ffffff;--glide-core-border-primary-hover: #0461cf;--glide-core-icon-active: #0073e6;--glide-core-icon-default: #ffffff;--glide-core-icon-default2: #212121;--glide-core-icon-display: #ffffff;--glide-core-icon-display-light: #d7e7ff;--glide-core-icon-hover: #eef5ff;--glide-core-icon-primary: #ffffff;--glide-core-icon-primary-hover: #d7e7ff;--glide-core-icon-secondary-disabled: #d7e7ff;--glide-core-icon-selected: #ffffff;--glide-core-icon-selected-disabled: #eef5ff;--glide-core-icon-selected2: #424242;--glide-core-icon-tertiary-disabled: #6d6d6d;--glide-core-status-error: #ff3b30;--glide-core-status-expired: #ff3b30;--glide-core-status-failed: #ff3b30;--glide-core-status-in-progress: #ffcc00;--glide-core-status-queued: #5ac8fa;--glide-core-status-scheduled: #af52de;--glide-core-status-success: #34c759;--glide-core-status-unknown: #6d6d6d;--glide-core-status-warning-critical: #ff3b30;--glide-core-status-warning-high: #ff9500;--glide-core-status-warning-informational: #0073e6;--glide-core-status-warning-low: #607d8b;--glide-core-status-warning-medium: #ffcc00;--glide-core-surface-active: #ffffff;--glide-core-surface-attention: #fffbeb;--glide-core-surface-base: #424242;--glide-core-surface-base-dark: #f0f0f0;--glide-core-surface-base-gray: #00000066;--glide-core-surface-base-gray-dark: #ffffff8c;--glide-core-surface-base-gray-light: #00000066;--glide-core-surface-base-gray-lighter: #ffffff1a;--glide-core-surface-base-light: #0000008c;--glide-core-surface-base-lighter: #000000bf;--glide-core-surface-base-lightest: #000000cc;--glide-core-surface-base-xlightest: #000000e5;--glide-core-surface-disabled: #424242;--glide-core-surface-dot-step: #8babf1;--glide-core-surface-error: #fff0ef;--glide-core-surface-focus: #0073e6;--glide-core-surface-hover: #0461cf;--glide-core-surface-informational: #eef5ff;--glide-core-surface-modal: #151515;--glide-core-surface-page: #212121;--glide-core-surface-primary: #0073e6;--glide-core-surface-primary-disabled: #6d6d6d;--glide-core-surface-secondary: #f0f0f0;--glide-core-surface-secondary-disabled: #f0f0f0;--glide-core-surface-selected: #0073e6;--glide-core-surface-selected-disabled: #8a8a8a;--glide-core-surface-selected-hover: #054fb9;--glide-core-surface-success: #f1fdf4;--glide-core-surface-table-row-hover: #1d7afc26;--glide-core-surface-unselected-disabled: #e3e3e3;--glide-core-surface-warning: #fff6e9;--glide-core-surface-white-1percent: #000000e5;--glide-core-text-body-1: #ffffff;--glide-core-text-body-2: #212121;--glide-core-text-body-light: #ffffff;--glide-core-text-body-lighter: #8a8a8a;--glide-core-text-disabled: #f0f0f0;--glide-core-text-header-1: #ffffff;--glide-core-text-header-2: #d7e7ff;--glide-core-text-link: #8babf1;--glide-core-text-link-dark-surface: #8babf1;--glide-core-text-link-table: #d0e8f2;--glide-core-text-placeholder: #c9c9c9;--glide-core-text-primary: #ffffff;--glide-core-text-primary-hover: #d7e7ff;--glide-core-text-secondary: #8babf1;--glide-core-text-secondary-disabled: #d7e7ff;--glide-core-text-selected: #ffffff;--glide-core-text-selected-2: #424242;--glide-core-text-tertiary: #ffffff;--glide-core-text-tertiary-disabled: #6d6d6d}:root{--glide-core-body-md-font-family: var(--glide-core-font-sans);--glide-core-body-md-font-size: 1rem;--glide-core-body-md-font-style: normal;--glide-core-body-md-font-weight: 400;--glide-core-body-md-line-height: normal;--glide-core-body-sm-font-family: var(--glide-core-font-sans);--glide-core-body-sm-font-size: .875rem;--glide-core-body-sm-font-variant: normal;--glide-core-body-sm-font-weight: 400;--glide-core-body-sm-line-height: 1.3;--glide-core-body-xs-font-family: var(--glide-core-font-sans);--glide-core-body-xs-font-size: .75rem;--glide-core-body-xs-font-variant: normal;--glide-core-body-xs-font-weight: 400;--glide-core-body-xs-line-height: 1.3;--glide-core-color-dark-blue: #054fb9;--glide-core-color-white: #ffffff;--glide-core-font-sans: "Nunito";--glide-core-font-weight-bold: 700;--glide-core-font-weight-semi-bold: 600;--glide-core-glow-sm: 0px 0px 2px 0px #2c97eee5;--glide-core-heading-xs-font-size: 1.25rem;--glide-core-heading-xs-font-weight: var(--glide-core-font-weight-semi-bold);--glide-core-heading-xxs-font-family: var(--glide-core-font-sans);--glide-core-heading-xxs-font-size: 1rem;--glide-core-heading-xxs-font-style: normal;--glide-core-heading-xxs-font-variant: normal;--glide-core-heading-xxs-font-weight: var(--glide-core-font-weight-bold);--glide-core-heading-xxxs-font-family: var(--glide-core-font-sans);--glide-core-heading-xxxs-font-size: .875rem;--glide-core-heading-xxxs-font-style: normal;--glide-core-heading-xxxs-font-variant: normal;--glide-core-heading-xxxs-font-weight: var(--glide-core-font-weight-bold);--glide-core-heading-xxxs-line-height: 1.7;--glide-core-shadow-lg: 0px 4px 14px 0px #00000040;--glide-core-shadow-sm: 0px 2.275px 8.342px 0px rgba(181, 181, 181, .25);--glide-core-shadow-xl: 0px 4px 60px 0px #adadad}
1
+ :root,:host{color-scheme:normal;--glide-core-border-radius-lg: .75rem;--glide-core-border-radius-md: .5rem;--glide-core-border-radius-none: 0rem;--glide-core-border-radius-round: 7.5rem;--glide-core-border-radius-sm: .25rem;--glide-core-border-radius-xs: .125rem;--glide-core-border-width-lg: .25rem;--glide-core-border-width-md: .125rem;--glide-core-border-width-none: 0rem;--glide-core-border-width-sm: .0625rem;--glide-core-number-14: .875rem;--glide-core-number-16: 1rem;--glide-core-page-size-details-panel: 27.375rem;--glide-core-page-size-height: 46.875rem;--glide-core-page-size-width: 83.3125rem;--glide-core-spacing-lg: 1.5rem;--glide-core-spacing-md: 1rem;--glide-core-spacing-sm: .75rem;--glide-core-spacing-xl: 2rem;--glide-core-spacing-xs: .5rem;--glide-core-spacing-xxl: 3rem;--glide-core-spacing-xxs: .25rem;--glide-core-spacing-xxxl: 4rem;--glide-core-spacing-xxxs: .125rem;--glide-core-spacing-zero: 0rem}:root,:host,.theme-light{color-scheme:light;--glide-core-border-action: #0073e6;--glide-core-border-action-disabled: #d7e7ff;--glide-core-border-action-hover: #eef5ff;--glide-core-border-base: #c9c9c9;--glide-core-border-base-dark: #6d6d6d;--glide-core-border-base-darker: #424242;--glide-core-border-base-light: #e3e3e3;--glide-core-border-base-lighter: #f0f0f0;--glide-core-border-base-lightest: #ffffff;--glide-core-border-base-transparent: #0000001a;--glide-core-border-disabled: #8a8a8a;--glide-core-border-focus: #0073e6;--glide-core-border-focus-light: #eef5ff;--glide-core-border-primary: #054fb9;--glide-core-border-primary-hover: #0461cf;--glide-core-generic-border-active: #6d6d6d;--glide-core-icon-active: #0073e6;--glide-core-icon-default: #212121;--glide-core-icon-default2: #212121;--glide-core-icon-display: #212121;--glide-core-icon-display-light: #6d6d6d;--glide-core-icon-hover: #8babf1;--glide-core-icon-primary: #054fb9;--glide-core-icon-primary-hover: #0461cf;--glide-core-icon-secondary-disabled: #d7e7ff;--glide-core-icon-selected: #ffffff;--glide-core-icon-selected-disabled: #eef5ff;--glide-core-icon-selected2: #ffffff;--glide-core-icon-tertiary-disabled: #8a8a8a;--glide-core-status-error: #db2d24;--glide-core-status-expired: #ff3b30;--glide-core-status-failed: #ff3b30;--glide-core-status-in-progress: #ffcc00;--glide-core-status-queued: #5ac8fa;--glide-core-status-scheduled: #af52de;--glide-core-status-success: #34c759;--glide-core-status-unknown: #6d6d6d;--glide-core-status-warning-critical: #ff3b30;--glide-core-status-warning-high: #ff9500;--glide-core-status-warning-informational: #0073e6;--glide-core-status-warning-low: #607d8b;--glide-core-status-warning-medium: #ffcc00;--glide-core-surface-active: #ffffff;--glide-core-surface-attention: #fffbeb;--glide-core-surface-base: #f0f0f0;--glide-core-surface-base-dark: #212121;--glide-core-surface-base-gray: #0000001a;--glide-core-surface-base-gray-dark: #00000066;--glide-core-surface-base-gray-light: #00000012;--glide-core-surface-base-gray-lighter: #00000008;--glide-core-surface-base-light: #ffffff8c;--glide-core-surface-base-lighter: #ffffffbf;--glide-core-surface-base-lightest: #ffffffcc;--glide-core-surface-base-xlightest: #ffffffe5;--glide-core-surface-disabled: #f0f0f0;--glide-core-surface-dot-step: #8babf1;--glide-core-surface-error: #fff0ef;--glide-core-surface-focus: #0073e6;--glide-core-surface-hover: #d7e7ff;--glide-core-surface-informational: #eef5ff;--glide-core-surface-modal: #ffffff;--glide-core-surface-page: #ffffff;--glide-core-surface-primary: #0073e6;--glide-core-surface-primary-disabled: #d7e7ff;--glide-core-surface-secondary: #eef5ff;--glide-core-surface-secondary-disabled: #eef5ff;--glide-core-surface-selected: #0073e6;--glide-core-surface-selected-disabled: #8a8a8a;--glide-core-surface-selected-hover: #054fb9;--glide-core-surface-success: #f1fdf4;--glide-core-surface-table-row-hover: #1d7afc26;--glide-core-surface-tag-default: #00000012;--glide-core-surface-unselected-disabled: #e3e3e3;--glide-core-surface-warning: #fff6e9;--glide-core-surface-white-1percent: #ffffff03;--glide-core-text-body-1: #212121;--glide-core-text-body-2: #212121;--glide-core-text-body-light: #424242;--glide-core-text-body-lighter: #8a8a8a;--glide-core-text-disabled: #f0f0f0;--glide-core-text-header-1: #424242;--glide-core-text-header-2: #6d6d6d;--glide-core-text-link: #0461cf;--glide-core-text-link-dark-surface: #8babf1;--glide-core-text-link-table: #0461cf;--glide-core-text-placeholder: #6d6d6d;--glide-core-text-primary: #054fb9;--glide-core-text-primary-hover: #0461cf;--glide-core-text-secondary: #0073e6;--glide-core-text-secondary-disabled: #d7e7ff;--glide-core-text-selected: #ffffff;--glide-core-text-selected-2: #ffffff;--glide-core-text-tertiary: #212121;--glide-core-text-tertiary-disabled: #8a8a8a}:host,.theme-dark{color-scheme:dark;--glide-core-border-action: #0073e6;--glide-core-border-action-disabled: #eef5ff;--glide-core-border-action-hover: #eef5ff;--glide-core-border-base: #6d6d6d;--glide-core-border-base-dark: #c9c9c9;--glide-core-border-base-darker: #e3e3e3;--glide-core-border-base-light: #212121;--glide-core-border-base-lighter: #212121;--glide-core-border-base-lightest: #424242;--glide-core-border-base-transparent: #0000001a;--glide-core-border-disabled: #8a8a8a;--glide-core-border-focus: #0073e6;--glide-core-border-focus-light: #eef5ff;--glide-core-border-primary: #ffffff;--glide-core-border-primary-hover: #0461cf;--glide-core-generic-border-active: #6d6d6d;--glide-core-icon-active: #0073e6;--glide-core-icon-default: #ffffff;--glide-core-icon-default2: #212121;--glide-core-icon-display: #ffffff;--glide-core-icon-display-light: #d7e7ff;--glide-core-icon-hover: #eef5ff;--glide-core-icon-primary: #ffffff;--glide-core-icon-primary-hover: #d7e7ff;--glide-core-icon-secondary-disabled: #d7e7ff;--glide-core-icon-selected: #ffffff;--glide-core-icon-selected-disabled: #eef5ff;--glide-core-icon-selected2: #424242;--glide-core-icon-tertiary-disabled: #6d6d6d;--glide-core-status-error: #ff3b30;--glide-core-status-expired: #ff3b30;--glide-core-status-failed: #ff3b30;--glide-core-status-in-progress: #ffcc00;--glide-core-status-queued: #5ac8fa;--glide-core-status-scheduled: #af52de;--glide-core-status-success: #34c759;--glide-core-status-unknown: #6d6d6d;--glide-core-status-warning-critical: #ff3b30;--glide-core-status-warning-high: #ff9500;--glide-core-status-warning-informational: #0073e6;--glide-core-status-warning-low: #607d8b;--glide-core-status-warning-medium: #ffcc00;--glide-core-surface-active: #ffffff;--glide-core-surface-attention: #fffbeb;--glide-core-surface-base: #424242;--glide-core-surface-base-dark: #f0f0f0;--glide-core-surface-base-gray: #00000066;--glide-core-surface-base-gray-dark: #ffffff8c;--glide-core-surface-base-gray-light: #00000066;--glide-core-surface-base-gray-lighter: #ffffff1a;--glide-core-surface-base-light: #0000008c;--glide-core-surface-base-lighter: #000000bf;--glide-core-surface-base-lightest: #000000cc;--glide-core-surface-base-xlightest: #000000e5;--glide-core-surface-disabled: #424242;--glide-core-surface-dot-step: #8babf1;--glide-core-surface-error: #fff0ef;--glide-core-surface-focus: #0073e6;--glide-core-surface-hover: #0461cf;--glide-core-surface-informational: #eef5ff;--glide-core-surface-modal: #151515;--glide-core-surface-page: #212121;--glide-core-surface-primary: #0073e6;--glide-core-surface-primary-disabled: #6d6d6d;--glide-core-surface-secondary: #f0f0f0;--glide-core-surface-secondary-disabled: #f0f0f0;--glide-core-surface-selected: #0073e6;--glide-core-surface-selected-disabled: #8a8a8a;--glide-core-surface-selected-hover: #054fb9;--glide-core-surface-success: #f1fdf4;--glide-core-surface-table-row-hover: #1d7afc26;--glide-core-surface-tag-default: #ffffff1a;--glide-core-surface-unselected-disabled: #e3e3e3;--glide-core-surface-warning: #fff6e9;--glide-core-surface-white-1percent: #000000e5;--glide-core-text-body-1: #ffffff;--glide-core-text-body-2: #212121;--glide-core-text-body-light: #ffffff;--glide-core-text-body-lighter: #8a8a8a;--glide-core-text-disabled: #f0f0f0;--glide-core-text-header-1: #ffffff;--glide-core-text-header-2: #d7e7ff;--glide-core-text-link: #8babf1;--glide-core-text-link-dark-surface: #8babf1;--glide-core-text-link-table: #d0e8f2;--glide-core-text-placeholder: #c9c9c9;--glide-core-text-primary: #ffffff;--glide-core-text-primary-hover: #d7e7ff;--glide-core-text-secondary: #8babf1;--glide-core-text-secondary-disabled: #d7e7ff;--glide-core-text-selected: #ffffff;--glide-core-text-selected-2: #424242;--glide-core-text-tertiary: #ffffff;--glide-core-text-tertiary-disabled: #6d6d6d}:root{--glide-core-body-md-font-family: var(--glide-core-font-sans);--glide-core-body-md-font-size: 1rem;--glide-core-body-md-font-style: normal;--glide-core-body-md-font-weight: 400;--glide-core-body-md-line-height: normal;--glide-core-body-sm-font-family: var(--glide-core-font-sans);--glide-core-body-sm-font-size: .875rem;--glide-core-body-sm-font-variant: normal;--glide-core-body-sm-font-weight: 400;--glide-core-body-sm-line-height: 1.3;--glide-core-body-xs-font-family: var(--glide-core-font-sans);--glide-core-body-xs-font-size: .75rem;--glide-core-body-xs-font-variant: normal;--glide-core-body-xs-font-weight: 400;--glide-core-body-xs-line-height: 1.3;--glide-core-color-dark-blue: #054fb9;--glide-core-color-white: #ffffff;--glide-core-font-sans: "Nunito";--glide-core-font-weight-bold: 700;--glide-core-font-weight-semi-bold: 600;--glide-core-glow-sm: 0px 0px 2px 0px #2c97eee5;--glide-core-heading-xs-font-size: 1.25rem;--glide-core-heading-xs-font-weight: var(--glide-core-font-weight-semi-bold);--glide-core-heading-xxs-font-family: var(--glide-core-font-sans);--glide-core-heading-xxs-font-size: 1rem;--glide-core-heading-xxs-font-style: normal;--glide-core-heading-xxs-font-variant: normal;--glide-core-heading-xxs-font-weight: var(--glide-core-font-weight-bold);--glide-core-heading-xxxs-font-family: var(--glide-core-font-sans);--glide-core-heading-xxxs-font-size: .875rem;--glide-core-heading-xxxs-font-style: normal;--glide-core-heading-xxxs-font-variant: normal;--glide-core-heading-xxxs-font-weight: var(--glide-core-font-weight-bold);--glide-core-heading-xxxs-line-height: 1.7;--glide-core-shadow-lg: 0px 4px 14px 0px #00000040;--glide-core-shadow-sm: 0px 2.275px 8.342px 0px rgba(181, 181, 181, .25);--glide-core-shadow-xl: 0px 4px 60px 0px #adadad}
@@ -3,7 +3,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
3
3
  `,css`
4
4
  .component {
5
5
  align-items: center;
6
- background: var(--glide-core-surface-base);
6
+ background: var(--glide-core-surface-tag-default);
7
7
  border-radius: var(--glide-core-border-radius-round);
8
8
  color: var(--glide-core-text-body-1);
9
9
  display: flex;
@@ -43,8 +43,11 @@ export default class GlideCoreTextarea extends LitElement {
43
43
  formResetCallback(): void;
44
44
  render(): import("lit").TemplateResult<1>;
45
45
  reportValidity(): boolean;
46
+ setCustomValidity(message: string): void;
47
+ setValidity(flags?: ValidityStateFlags, message?: string): void;
46
48
  constructor();
47
49
  private isBlurring;
48
50
  private isCheckingValidity;
49
51
  private isReportValidityOrSubmit;
52
+ private validityMessage?;
50
53
  }
package/dist/textarea.js CHANGED
@@ -1,2 +1,58 @@
1
- var __decorate=this&&this.__decorate||function(e,t,i,a){var r,o=arguments.length,l=o<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,i):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,i,a);else for(var s=e.length-1;s>=0;s--)(r=e[s])&&(l=(o<3?r(l):o>3?r(t,i,l):r(t,i))||l);return o>3&&l&&Object.defineProperty(t,i,l),l};import"./label.js";import{LitElement,html,nothing}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import ow from"./library/ow.js";import styles from"./textarea.styles.js";let GlideCoreTextarea=class GlideCoreTextarea extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed",delegatesFocus:!0}}static{this.styles=styles}blur(){this.#e.value?.blur()}checkValidity(){this.isCheckingValidity=!0;const e=this.#t.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i)}get form(){return this.#t.form}get validity(){return!this.required||this.value||this.disabled?this.#a?this.#t.setValidity({tooLong:!0}," ",this.#e.value):this.#t.setValidity({}):this.#t.setValidity({valueMissing:!0}," ",this.#e.value),this.#t.validity}get willValidate(){return this.#t.willValidate}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){this.value=this.getAttribute("value")??""}render(){return html`<glide-core-private-label split="${ifDefined(this.privateSplit??void 0)}" orientation="${this.orientation}" ?disabled="${this.disabled}" ?error="${this.#r||this.#a}" ?hide="${this.hideLabel}" ?required="${this.required}"><slot name="tooltip" slot="tooltip"></slot><label class="label" for="textarea">${this.label}</label><div class="textarea-container" slot="control"><textarea aria-describedby="meta" aria-invalid="${this.#r||this.#a}" class="${classMap({error:this.#r||this.#a})}" id="textarea" name="${ifDefined(this.name)}" placeholder="${ifDefined(this.placeholder)}" rows="${this.rows}" autocapitalize="${this.autocapitalize}" autocomplete="${this.autocomplete}" spellcheck="${this.spellcheck}" .value="${this.value}" ?required="${this.required}" ?readonly="${this.readonly}" ?disabled="${this.disabled}" ${ref(this.#e)} @input="${this.#o}" @change="${this.#l}" @blur="${this.#s}">
2
- </textarea></div><div class="meta" id="meta" slot="description"><slot class="description" name="description"></slot>${this.maxlength?html`<div class="${classMap({"character-count":!0,error:this.#a})}" data-test="character-count-container"><span aria-hidden="true" data-test="character-count-text">${this.#d.term("displayedCharacterCount",this.#n,this.maxlength)} </span><span class="hidden" data-test="character-count-announcement">${this.#d.term("announcedCharacterCount",this.#n,this.maxlength)}</span></div>`:nothing}</div></glide-core-private-label>`}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#t.reportValidity();return this.requestUpdate(),e}constructor(){super(),this.value="",this.label="",this.hideLabel=!1,this.orientation="horizontal",this.placeholder="",this.rows=2,this.required=!1,this.readonly=!1,this.disabled=!1,this.name="",this.spellcheck=!1,this.autocapitalize="on",this.autocomplete="on",this.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#d=new LocalizeController(this),this.#e=createRef(),this.#i=({formData:e})=>{this.name&&this.value&&!this.disabled&&e.append(this.name,this.value)},this.#t=this.attachInternals(),this.addEventListener("invalid",(e=>{if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}))}#t;#d;#e;#i;get#r(){return!this.disabled&&!this.readonly&&!this.validity.valid&&this.isReportValidityOrSubmit}get#n(){return this.value.length}get#a(){return Boolean(!this.disabled&&!this.readonly&&this.maxlength&&this.#n>this.maxlength)}#s(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1}#l(e){ow(this.#e.value,ow.object.instanceOf(HTMLTextAreaElement)),this.value=this.#e.value.value,this.dispatchEvent(new Event(e.type,e))}#o(){ow(this.#e.value,ow.object.instanceOf(HTMLTextAreaElement)),this.value=this.#e.value.value}};__decorate([property()],GlideCoreTextarea.prototype,"value",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"label",void 0),__decorate([property({attribute:"hide-label",reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"hideLabel",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"orientation",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"placeholder",void 0),__decorate([property({reflect:!0,type:Number})],GlideCoreTextarea.prototype,"rows",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"required",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"readonly",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"disabled",void 0),__decorate([property({type:Number,converter:e=>e&&Number.parseInt(e,10),reflect:!0})],GlideCoreTextarea.prototype,"maxlength",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"name",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"spellcheck",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"autocapitalize",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"autocomplete",void 0),__decorate([property()],GlideCoreTextarea.prototype,"privateSplit",void 0),__decorate([state()],GlideCoreTextarea.prototype,"isBlurring",void 0),__decorate([state()],GlideCoreTextarea.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreTextarea.prototype,"isReportValidityOrSubmit",void 0),GlideCoreTextarea=__decorate([customElement("glide-core-textarea")],GlideCoreTextarea);export default GlideCoreTextarea;
1
+ var __decorate=this&&this.__decorate||function(e,t,i,a){var r,s=arguments.length,o=s<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,i):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,a);else for(var l=e.length-1;l>=0;l--)(r=e[l])&&(o=(s<3?r(o):s>3?r(t,i,o):r(t,i))||o);return s>3&&o&&Object.defineProperty(t,i,o),o};import"./label.js";import{LitElement,html,nothing}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{unsafeHTML}from"lit/directives/unsafe-html.js";import{when}from"lit/directives/when.js";import ow from"./library/ow.js";import styles from"./textarea.styles.js";let GlideCoreTextarea=class GlideCoreTextarea extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed",delegatesFocus:!0}}static{this.styles=styles}blur(){this.#e.value?.blur()}checkValidity(){this.isCheckingValidity=!0;const e=this.#t.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i)}get form(){return this.#t.form}get validity(){return!this.required||this.value||this.disabled?this.required&&this.#t.validity.valueMissing&&this.value?(this.#t.setValidity({}),this.#t.validity):(this.required||!this.#t.validity.valueMissing||this.value||this.#t.setValidity({}),this.#t.validity):(this.#t.setValidity({customError:Boolean(this.validityMessage),valueMissing:!0}," ",this.#e.value),this.#t.validity)}get willValidate(){return this.#t.willValidate}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){this.value=this.getAttribute("value")??""}render(){return html`<glide-core-private-label
2
+ split=${ifDefined(this.privateSplit??void 0)}
3
+ orientation=${this.orientation}
4
+ ?disabled=${this.disabled}
5
+ ?error=${this.#a||this.#r}
6
+ ?hide=${this.hideLabel}
7
+ ?required=${this.required}
8
+ >
9
+ <slot name="tooltip" slot="tooltip"></slot>
10
+
11
+ <label class="label" for="textarea">${this.label}</label>
12
+
13
+ <div class="textarea-container" slot="control">
14
+ <textarea
15
+ aria-describedby="meta"
16
+ aria-invalid=${this.#a||this.#r}
17
+ class=${classMap({error:this.#a||this.#r})}
18
+ id="textarea"
19
+ name=${ifDefined(this.name)}
20
+ placeholder=${ifDefined(this.placeholder)}
21
+ rows=${this.rows}
22
+ autocapitalize=${this.autocapitalize}
23
+ autocomplete=${this.autocomplete}
24
+ spellcheck=${this.spellcheck}
25
+ .value=${this.value}
26
+ ?required=${this.required}
27
+ ?readonly=${this.readonly}
28
+ ?disabled=${this.disabled}
29
+ ${ref(this.#e)}
30
+ @input=${this.#s}
31
+ @change=${this.#o}
32
+ @blur=${this.#l}
33
+ >
34
+ </textarea>
35
+ </div>
36
+
37
+ <div class="meta" id="meta" slot="description">
38
+ <slot
39
+ class=${classMap({description:!0,hidden:Boolean(this.#a&&this.validityMessage)})}
40
+ name="description"
41
+ ></slot>
42
+
43
+ ${when(this.#a&&this.validityMessage,(()=>html`<span class="validity-message" data-test="validity-message"
44
+ >${unsafeHTML(this.validityMessage)}</span
45
+ >`))}
46
+ ${this.maxlength?html`<div
47
+ class=${classMap({"character-count":!0,error:this.#r})}
48
+ data-test="character-count-container"
49
+ >
50
+ <span aria-hidden="true" data-test="character-count-text">
51
+ ${this.#d.term("displayedCharacterCount",this.#n,this.maxlength)}
52
+ </span>
53
+ <span class="hidden" data-test="character-count-announcement"
54
+ >${this.#d.term("announcedCharacterCount",this.#n,this.maxlength)}</span
55
+ >
56
+ </div>`:nothing}
57
+ </div></glide-core-private-label
58
+ >`}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#t.reportValidity();return this.requestUpdate(),e}setCustomValidity(e){this.validityMessage=e,""===e?this.#t.setValidity({customError:!1},"",this.#e.value):this.#t.setValidity({customError:!0,valueMissing:this.#t.validity.valueMissing}," ",this.#e.value)}setValidity(e,t){this.validityMessage=t,this.#t.setValidity(e," ",this.#e.value)}constructor(){super(),this.value="",this.label="",this.hideLabel=!1,this.orientation="horizontal",this.placeholder="",this.rows=2,this.required=!1,this.readonly=!1,this.disabled=!1,this.name="",this.spellcheck=!1,this.autocapitalize="on",this.autocomplete="on",this.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#d=new LocalizeController(this),this.#e=createRef(),this.#i=({formData:e})=>{this.name&&this.value&&!this.disabled&&e.append(this.name,this.value)},this.#t=this.attachInternals(),this.addEventListener("invalid",(e=>{if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}))}#t;#d;#e;#i;get#a(){return!this.disabled&&!this.readonly&&!this.validity.valid&&this.isReportValidityOrSubmit}get#n(){return this.value.length}get#r(){return Boolean(!this.disabled&&!this.readonly&&this.maxlength&&this.#n>this.maxlength)}#l(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1}#o(e){ow(this.#e.value,ow.object.instanceOf(HTMLTextAreaElement)),this.value=this.#e.value.value,this.dispatchEvent(new Event(e.type,e))}#s(){ow(this.#e.value,ow.object.instanceOf(HTMLTextAreaElement)),this.value=this.#e.value.value}};__decorate([property()],GlideCoreTextarea.prototype,"value",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"label",void 0),__decorate([property({attribute:"hide-label",reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"hideLabel",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"orientation",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"placeholder",void 0),__decorate([property({reflect:!0,type:Number})],GlideCoreTextarea.prototype,"rows",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"required",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"readonly",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"disabled",void 0),__decorate([property({type:Number,converter:e=>e&&Number.parseInt(e,10),reflect:!0})],GlideCoreTextarea.prototype,"maxlength",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"name",void 0),__decorate([property({reflect:!0,type:Boolean})],GlideCoreTextarea.prototype,"spellcheck",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"autocapitalize",void 0),__decorate([property({reflect:!0})],GlideCoreTextarea.prototype,"autocomplete",void 0),__decorate([property()],GlideCoreTextarea.prototype,"privateSplit",void 0),__decorate([state()],GlideCoreTextarea.prototype,"isBlurring",void 0),__decorate([state()],GlideCoreTextarea.prototype,"isCheckingValidity",void 0),__decorate([state()],GlideCoreTextarea.prototype,"isReportValidityOrSubmit",void 0),__decorate([state()],GlideCoreTextarea.prototype,"validityMessage",void 0),GlideCoreTextarea=__decorate([customElement("glide-core-textarea")],GlideCoreTextarea);export default GlideCoreTextarea;
@@ -12,6 +12,14 @@ import{css,unsafeCSS}from"lit";import visuallyHidden from"./styles/visually-hidd
12
12
 
13
13
  .description {
14
14
  display: block;
15
+
16
+ &.hidden {
17
+ display: none;
18
+ }
19
+ }
20
+
21
+ .validity-message {
22
+ display: block;
15
23
  }
16
24
 
17
25
  textarea {