@crowdstrike/glide-core 0.12.3 → 0.13.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 (43) hide show
  1. package/dist/accordion.d.ts +1 -1
  2. package/dist/accordion.styles.js +2 -1
  3. package/dist/button-group.js +1 -1
  4. package/dist/button-group.stories.d.ts +0 -1
  5. package/dist/button-group.test.events.js +2 -0
  6. package/dist/checkbox.styles.js +6 -3
  7. package/dist/drawer.js +1 -1
  8. package/dist/dropdown.d.ts +5 -1
  9. package/dist/dropdown.js +64 -50
  10. package/dist/dropdown.option.js +1 -1
  11. package/dist/dropdown.option.styles.js +36 -6
  12. package/dist/dropdown.styles.js +31 -21
  13. package/dist/dropdown.test.basics.filterable.js +8 -3
  14. package/dist/dropdown.test.events.filterable.js +1 -13
  15. package/dist/dropdown.test.focus.single.js +1 -17
  16. package/dist/dropdown.test.interactions.filterable.js +84 -0
  17. package/dist/dropdown.test.interactions.js +1 -1
  18. package/dist/input.d.ts +1 -1
  19. package/dist/input.js +2 -1
  20. package/dist/input.styles.js +44 -30
  21. package/dist/library/localize.d.ts +2 -0
  22. package/dist/menu.js +1 -1
  23. package/dist/menu.stories.d.ts +1 -0
  24. package/dist/menu.styles.js +1 -1
  25. package/dist/menu.test.interactions.js +1 -1
  26. package/dist/modal.d.ts +1 -1
  27. package/dist/modal.js +1 -1
  28. package/dist/radio-group.stories.d.ts +0 -1
  29. package/dist/styles/variables.css +1 -1
  30. package/dist/tab.group.d.ts +0 -1
  31. package/dist/tab.group.js +1 -1
  32. package/dist/tab.group.styles.js +5 -7
  33. package/dist/tabs.stories.d.ts +0 -1
  34. package/dist/tag.js +1 -1
  35. package/dist/tag.styles.js +5 -3
  36. package/dist/tag.test.interactions.js +8 -8
  37. package/dist/translations/en.js +1 -1
  38. package/dist/translations/fr.d.ts +1 -1
  39. package/dist/translations/fr.js +1 -1
  40. package/dist/translations/ja.d.ts +1 -1
  41. package/dist/translations/ja.js +1 -1
  42. package/dist/tree.stories.d.ts +0 -1
  43. package/package.json +18 -18
@@ -1,6 +1,7 @@
1
1
  import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import opacityAndScaleAnimation from"./styles/opacity-and-scale-animation.js";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
2
2
  ${focusOutline(".add-button:focus-visible")}
3
3
  ${opacityAndScaleAnimation(".options-and-footer:popover-open")}
4
+ ${visuallyHidden(".item-count")}
4
5
  ${visuallyHidden(".selected-option-labels")}
5
6
  `,css`
6
7
  .component {
@@ -16,11 +17,11 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
16
17
 
17
18
  glide-core-private-label {
18
19
  &::part(private-control-and-summary) {
19
- /*
20
- The Label component's grid column styling combined with the fact that
21
- ".dropdown-and-options" isn't a direct descendant of that grid means that
22
- Dropdown's label won't shrink when space constrained without a minimum
23
- width on Label's ".control-and-summary". It's not clear to me why Grid
20
+ /*
21
+ The Label component's grid column styling combined with the fact that
22
+ ".dropdown-and-options" isn't a direct descendant of that grid means that
23
+ Dropdown's label won't shrink when space constrained without a minimum
24
+ width on Label's ".control-and-summary". It's not clear to me why Grid
24
25
  behaves this way.
25
26
  */
26
27
  min-inline-size: var(--min-inline-size);
@@ -91,6 +92,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
91
92
 
92
93
  &:is(
93
94
  :hover,
95
+ :has(.primary-button:hover),
94
96
  :has(.primary-button:focus-visible, .input:focus-visible)
95
97
  ):not(&.disabled, &.error, &.quiet, &.readonly) {
96
98
  border-color: var(--glide-core-border-focus);
@@ -114,22 +116,15 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
114
116
  min-inline-size: var(--min-inline-size);
115
117
  padding: 0;
116
118
  position: absolute;
117
-
118
- &.hidden {
119
- display: none;
120
- }
121
119
  }
122
120
 
123
121
  .options {
124
- --padding: var(--glide-core-spacing-xxxs);
125
-
126
122
  box-sizing: border-box;
127
123
  max-block-size: calc(
128
- var(--private-option-height) * 9 + var(--padding) * 2 +
124
+ var(--private-option-height) * 9 + var(--glide-core-spacing-xxxs) * 2 +
129
125
  var(--border-width) * 2
130
126
  );
131
127
  overflow: auto;
132
- padding: var(--padding);
133
128
  scroll-behavior: smooth;
134
129
 
135
130
  &.large {
@@ -139,20 +134,26 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
139
134
  &.small {
140
135
  --private-option-height: 1.25rem;
141
136
  }
137
+
138
+ &.hidden {
139
+ display: none;
140
+ }
141
+ }
142
+
143
+ .options-slot {
144
+ display: block;
145
+ padding: var(--glide-core-spacing-xxxs);
142
146
  }
143
147
 
144
148
  .footer {
145
- background-color: var(--glide-core-surface-page);
146
149
  border-block-start: 1px solid var(--glide-core-border-base);
147
- box-shadow: 0 -8px 8px -8px
148
- var(--glide-core-surface-base-gray, rgb(0 0 0 / 40%));
149
150
  display: none;
150
151
  inline-size: calc(100% - var(--glide-core-spacing-xxxs) * 2);
151
152
  inset-block-end: 0;
152
153
  padding: var(--glide-core-spacing-xxxs);
153
154
 
154
- /*
155
- "sticky" is a little hack so that footer is absolutely positioned but
155
+ /*
156
+ "sticky" is a little hack so that footer is absolutely positioned but
156
157
  its space in layout is preserved, so it doesn't overlap the last option.
157
158
  */
158
159
  position: sticky;
@@ -207,15 +208,23 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
207
208
  }
208
209
 
209
210
  .select-all {
210
- border-block-end: 1px solid var(--glide-core-border-base-light);
211
- margin-block-end: var(--glide-core-spacing-xxxs);
212
- padding-block-end: var(--glide-core-spacing-xxxs);
211
+ border-block-end: 1px solid var(--glide-core-border-base);
212
+ padding: var(--glide-core-spacing-xxxs);
213
213
 
214
214
  &:not([hidden]) {
215
215
  display: block;
216
216
  }
217
217
  }
218
218
 
219
+ .no-results {
220
+ font-family: var(--glide-core-body-sm-font-family);
221
+ font-size: var(--glide-core-body-sm-font-size);
222
+ font-weight: var(--glide-core-body-sm-font-weight);
223
+ line-height: var(--glide-core-body-sm-line-height);
224
+ padding: 0.625rem 0.875rem;
225
+ text-transform: capitalize;
226
+ }
227
+
219
228
  .placeholder {
220
229
  /*
221
230
  Using the browser's default placeholder color for now, as
@@ -261,6 +270,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
261
270
  align-content: center;
262
271
  color: var(--glide-core-text-link);
263
272
  margin-inline-end: var(--glide-core-spacing-md);
273
+ white-space: nowrap;
264
274
  }
265
275
 
266
276
  .single-select-icon-slot {
@@ -21,9 +21,14 @@ it('is accessible', async () => {
21
21
  ${defaultSlot}
22
22
  </glide-core-dropdown>`);
23
23
  await expect(component).to.be.accessible({
24
- // Axe doesn't search within slots when determining whether an element
25
- // has an ID that matches `aria-activedescendant` exists.
26
- ignoredRules: ['aria-valid-attr-value'],
24
+ ignoredRules: [
25
+ // Axe doesn't like that our item count element doesn't have a `role`. Yet
26
+ // it does label `<input>` and is announced correctly, at least by VoiceOver.
27
+ 'aria-prohibited-attr',
28
+ // Axe doesn't search within slots when determining whether an element
29
+ // has an ID that matches `aria-activedescendant` exists.
30
+ 'aria-valid-attr-value',
31
+ ],
27
32
  });
28
33
  });
29
34
  it('is filterable', async () => {
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-expressions */
2
2
  import * as sinon from 'sinon';
3
- import { expect, fixture, html, oneEvent } from '@open-wc/testing';
3
+ import { expect, fixture, html } from '@open-wc/testing';
4
4
  import { sendKeys } from '@web/test-runner-commands';
5
5
  import GlideCoreDropdown from './dropdown.js';
6
6
  import GlideCoreDropdownOption from './dropdown.option.js';
@@ -19,18 +19,6 @@ const defaultSlot = html `
19
19
  <glide-core-dropdown-option label="Ten"></glide-core-dropdown-option>
20
20
  <glide-core-dropdown-option label="Eleven"></glide-core-dropdown-option>
21
21
  `;
22
- it('dispatches a "filter" event on "input"', async () => {
23
- const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
24
- ${defaultSlot}
25
- </glide-core-dropdown>`);
26
- component.focus();
27
- sendKeys({ type: 'o' });
28
- const event = await oneEvent(component, 'filter');
29
- expect(event instanceof CustomEvent).to.be.true;
30
- expect(event.bubbles).to.be.true;
31
- expect(event.composed).to.be.true;
32
- expect(event.detail).to.equal('o');
33
- });
34
22
  it('does not dispatch "input" events on input', async () => {
35
23
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
36
24
  ${defaultSlot}
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-expressions */
2
2
  import './dropdown.option.js';
3
- import { aTimeout, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
3
+ import { expect, fixture, html } from '@open-wc/testing';
4
4
  import GlideCoreDropdown from './dropdown.js';
5
5
  import GlideCoreDropdownOption from './dropdown.option.js';
6
6
  GlideCoreDropdown.shadowRootOptions.mode = 'open';
@@ -40,19 +40,3 @@ it('does not focus the primary button when `checkValidity` is called', async ()
40
40
  component.checkValidity();
41
41
  expect(component.shadowRoot?.activeElement).to.equal(null);
42
42
  });
43
- it('has a tooltip on focus when its internal label is overflowing', async () => {
44
- // The period is arbitrary. 500 of them ensures we overflow.
45
- const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
46
- <glide-core-dropdown-option
47
- label=${'.'.repeat(500)}
48
- selected
49
- ></glide-core-dropdown-option>
50
- </glide-core-dropdown>`);
51
- component.focus();
52
- await elementUpdated(component);
53
- // Wait for the Resize Observer to do its thing.
54
- await aTimeout(0);
55
- const tooltip = component.shadowRoot?.querySelector('[data-test="internal-label-tooltip"]');
56
- expect(tooltip?.open).to.be.true;
57
- expect(tooltip?.disabled).to.be.false;
58
- });
@@ -264,6 +264,34 @@ it('hides Select All when filtering', async () => {
264
264
  const selectAll = component.shadowRoot?.querySelector('[data-test="select-all"]');
265
265
  expect(selectAll?.checkVisibility()).to.not.be.ok;
266
266
  });
267
+ it('unhides every option after filtering when one is selected and Dropdown is reopened', async () => {
268
+ const component = await fixture(html `<glide-core-dropdown
269
+ label="Label"
270
+ placeholder="Placeholder"
271
+ open
272
+ filterable
273
+ >
274
+ <glide-core-dropdown-option
275
+ label="One"
276
+ selected
277
+ ></glide-core-dropdown-option>
278
+
279
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
280
+ </glide-core-dropdown>`);
281
+ // Wait for it to open.
282
+ await aTimeout(0);
283
+ component.focus();
284
+ await sendKeys({ type: 'two' });
285
+ component.blur();
286
+ await elementUpdated(component);
287
+ component.open = true;
288
+ // Wait for it to open.
289
+ await aTimeout(0);
290
+ const options = [
291
+ ...component.querySelectorAll('glide-core-dropdown-option'),
292
+ ].filter(({ hidden }) => !hidden);
293
+ expect(options.length).to.equal(2);
294
+ });
267
295
  it('sets the first unfiltered option as active when the previously active option is filtered out', async () => {
268
296
  const component = await fixture(html `<glide-core-dropdown
269
297
  label="Label"
@@ -719,3 +747,59 @@ it('has no icon when filtering and an option is selected', async () => {
719
747
  const iconSlot = component.shadowRoot?.querySelector('[data-test="single-select-icon-slot"]');
720
748
  expect(iconSlot).to.be.null;
721
749
  });
750
+ it('supports custom filtering', async () => {
751
+ const component = await fixture(html `<glide-core-dropdown
752
+ label="Label"
753
+ placeholder="Placeholder"
754
+ filterable
755
+ >
756
+ <glide-core-dropdown-option label="One"></glide-core-dropdown-option>
757
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
758
+ </glide-core-dropdown>`);
759
+ component.filter = async (filter) => {
760
+ const options = [
761
+ ...component.querySelectorAll('glide-core-dropdown-option'),
762
+ ];
763
+ return options.filter(({ label }) => label.includes(filter));
764
+ };
765
+ component.focus();
766
+ await sendKeys({ type: 'O' });
767
+ const options = [
768
+ ...component.querySelectorAll('glide-core-dropdown-option'),
769
+ ].filter(({ hidden }) => !hidden);
770
+ expect(options.length).to.equal(1);
771
+ expect(options[0].label).to.equal('One');
772
+ });
773
+ it('does nothing when filtering fails', async () => {
774
+ const component = await fixture(html `<glide-core-dropdown
775
+ label="Label"
776
+ placeholder="Placeholder"
777
+ filterable
778
+ >
779
+ <glide-core-dropdown-option label="One"></glide-core-dropdown-option>
780
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
781
+ </glide-core-dropdown>`);
782
+ component.filter = () => {
783
+ return Promise.reject();
784
+ };
785
+ component.focus();
786
+ await sendKeys({ type: 'O' });
787
+ const options = [
788
+ ...component.querySelectorAll('glide-core-dropdown-option'),
789
+ ].filter(({ hidden }) => !hidden);
790
+ expect(options.length).to.equal(2);
791
+ });
792
+ it('updates its item count after filtering', async () => {
793
+ const component = await fixture(html `<glide-core-dropdown
794
+ label="Label"
795
+ placeholder="Placeholder"
796
+ filterable
797
+ >
798
+ <glide-core-dropdown-option label="One"></glide-core-dropdown-option>
799
+ <glide-core-dropdown-option label="Two"></glide-core-dropdown-option>
800
+ </glide-core-dropdown>`);
801
+ component.focus();
802
+ await sendKeys({ type: 'one' });
803
+ const itemCount = component.shadowRoot?.querySelector('[data-test="item-count"]');
804
+ expect(itemCount?.ariaLabel).to.equal('1 items');
805
+ });
@@ -135,7 +135,7 @@ it('does not open on Space when `readonly`', async () => {
135
135
  expect(component.open).to.be.false;
136
136
  expect(options?.checkVisibility()).to.be.false;
137
137
  });
138
- // See the `document` click listener comment in `dropdown.ts` for an explanation.
138
+ // See the `document` click handler comment in `dropdown.ts` for an explanation.
139
139
  it('opens when opened programmatically via the click handler of another element', async () => {
140
140
  const div = document.createElement('div');
141
141
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
package/dist/input.d.ts CHANGED
@@ -6,7 +6,7 @@ declare global {
6
6
  'glide-core-input': GlideCoreInput;
7
7
  }
8
8
  }
9
- export declare const SUPPORTED_TYPES: readonly ["email", "number", "password", "search", "tel", "text", "url"];
9
+ export declare const SUPPORTED_TYPES: readonly ["date", "email", "number", "password", "search", "tel", "text", "url"];
10
10
  type SupportedTypes = (typeof SUPPORTED_TYPES)[number];
11
11
  /**
12
12
  * @event change - `(event: Event) => void`
package/dist/input.js CHANGED
@@ -1,4 +1,4 @@
1
- var __decorate=this&&this.__decorate||function(t,e,i,s){var a,r=arguments.length,o=r<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(t,e,i,s);else for(var l=t.length-1;l>=0;l--)(a=t[l])&&(o=(r<3?a(o):r>3?a(e,i,o):a(e,i))||o);return r>3&&o&&Object.defineProperty(e,i,o),o};import"./icon-button.js";import"./label.js";import{LitElement,html,nothing}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{unsafeHTML}from"lit/directives/unsafe-html.js";import{when}from"lit/directives/when.js";import magnifyingGlassIcon from"./icons/magnifying-glass.js";import ow from"./library/ow.js";import styles from"./input.styles.js";export const SUPPORTED_TYPES=["email","number","password","search","tel","text","url"];let GlideCoreInput=class GlideCoreInput extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed",delegatesFocus:!0}}static{this.styles=styles}get form(){return this.#t.form}get validity(){return this.pattern?(this.#t.setValidity({customError:Boolean(this.validityMessage),patternMismatch:!new RegExp(this.pattern).test(this.value),valueMissing:Boolean(this.required&&!this.value)}," ",this.#e.value),this.#t.validity):!this.pattern&&this.#t.validity.patternMismatch?(this.#t.setValidity({}),this.#t.validity):!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}blur(){this.#e.value?.blur()}checkValidity(){this.isCheckingValidity=!0;const t=this.#t.checkValidity();return this.isCheckingValidity=!1,t}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i)}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){this.value=this.getAttribute("value")??""}get hasClearIcon(){return this.clearable&&!this.disabled&&!this.readonly}get isClearIconVisible(){return this.hasClearIcon&&this.value.length>0}render(){return html`
1
+ var __decorate=this&&this.__decorate||function(t,e,i,s){var a,r=arguments.length,o=r<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(t,e,i,s);else for(var l=t.length-1;l>=0;l--)(a=t[l])&&(o=(r<3?a(o):r>3?a(e,i,o):a(e,i))||o);return r>3&&o&&Object.defineProperty(e,i,o),o};import"./icon-button.js";import"./label.js";import{LitElement,html,nothing}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{unsafeHTML}from"lit/directives/unsafe-html.js";import{when}from"lit/directives/when.js";import magnifyingGlassIcon from"./icons/magnifying-glass.js";import ow from"./library/ow.js";import styles from"./input.styles.js";export const SUPPORTED_TYPES=["date","email","number","password","search","tel","text","url"];let GlideCoreInput=class GlideCoreInput extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed",delegatesFocus:!0}}static{this.styles=styles}get form(){return this.#t.form}get validity(){return this.pattern?(this.#t.setValidity({customError:Boolean(this.validityMessage),patternMismatch:!new RegExp(this.pattern).test(this.value),valueMissing:Boolean(this.required&&!this.value)}," ",this.#e.value),this.#t.validity):!this.pattern&&this.#t.validity.patternMismatch?(this.#t.setValidity({}),this.#t.validity):!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}blur(){this.#e.value?.blur()}checkValidity(){this.isCheckingValidity=!0;const t=this.#t.checkValidity();return this.isCheckingValidity=!1,t}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#i)}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#i)}formResetCallback(){this.value=this.getAttribute("value")??""}get hasClearIcon(){return this.clearable&&!this.disabled&&!this.readonly}get isClearIconVisible(){return this.hasClearIcon&&this.value.length>0}render(){return html`
2
2
  <glide-core-private-label
3
3
  class=${classMap({left:"left"===this.privateSplit,middle:"middle"===this.privateSplit})}
4
4
  orientation=${this.orientation}
@@ -20,6 +20,7 @@ var __decorate=this&&this.__decorate||function(t,e,i,s){var a,r=arguments.length
20
20
  <input
21
21
  aria-describedby="meta"
22
22
  aria-invalid=${this.#s||this.#a}
23
+ class="input"
23
24
  id="input"
24
25
  type=${"password"===this.type&&this.passwordVisible?"text":this.type}
25
26
  .value=${this.value}
@@ -35,18 +35,16 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
35
35
  .input-container {
36
36
  align-items: center;
37
37
  background-color: var(--glide-core-surface-base-lighter);
38
- block-size: 2.125rem;
39
38
  border: 1px solid var(--glide-core-border-base);
40
39
  border-radius: var(--glide-core-spacing-xs);
41
- box-sizing: border-box;
42
40
  color: var(--glide-core-text-body-1);
43
41
  display: flex;
44
- gap: var(--glide-core-spacing-xxs);
45
42
  line-height: var(--glide-core-body-xs-line-height);
46
43
  padding-inline: var(--glide-core-spacing-sm);
47
44
 
48
45
  &.focused,
49
- &:hover {
46
+ &:hover,
47
+ &:has(.input:hover) {
50
48
  border-color: var(--glide-core-border-focus);
51
49
  transition: border-color 200ms ease-in-out;
52
50
  }
@@ -56,9 +54,8 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
56
54
  }
57
55
 
58
56
  /* We had to resort to a class selector because there may be a bug in Chrome and Safari
59
- * with ":read-only"
60
- * https://bugs.chromium.org/p/chromium/issues/detail?id=1519649
61
- */
57
+ * with ":read-only": https://bugs.chromium.org/p/chromium/issues/detail?id=1519649
58
+ */
62
59
  &.readonly {
63
60
  border: 1px solid transparent;
64
61
  padding-inline-start: 0;
@@ -69,34 +66,47 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
69
66
  border-color: var(--glide-core-border-base-light);
70
67
  color: var(--glide-core-text-tertiary-disabled);
71
68
  }
69
+ }
72
70
 
73
- input {
74
- background-color: transparent;
75
- border: none;
76
- color: inherit;
77
- cursor: inherit;
78
- font-family: var(--glide-core-font-sans);
79
- font-size: var(--glide-core-body-sm-font-size);
80
- font-weight: var(--glide-core-body-xs-font-weight);
81
- inline-size: 100%;
82
- min-inline-size: 0;
83
- outline: none;
84
- padding: 0;
85
-
86
- &::-webkit-search-decoration,
87
- &::-webkit-search-cancel-button,
88
- &::-webkit-search-results-button,
89
- &::-webkit-search-results-decoration {
90
- appearance: none;
91
- }
71
+ .input {
72
+ background-color: transparent;
73
+ block-size: 2rem;
74
+ border: none;
75
+ color: inherit;
76
+ cursor: inherit;
77
+ font-family: var(--glide-core-font-sans);
78
+ font-size: var(--glide-core-body-sm-font-size);
79
+ font-weight: var(--glide-core-body-xs-font-weight);
80
+ inline-size: 100%;
81
+ min-inline-size: 0;
82
+ outline: none;
83
+ padding: 0;
84
+
85
+ &::-webkit-search-decoration,
86
+ &::-webkit-search-cancel-button,
87
+ &::-webkit-search-results-button,
88
+ &::-webkit-search-results-decoration {
89
+ appearance: none;
92
90
  }
93
91
 
94
- .suffix-icon {
95
- align-items: center;
96
- display: flex;
92
+ /* The input obscures an offset outline for -webkit-calendar-picker-indicator, so 'focus-outline' is not used */
93
+ &[type='date'] {
94
+ &::-webkit-calendar-picker-indicator {
95
+ border-radius: 0.125rem;
96
+ padding: var(--glide-core-spacing-xxs);
97
+ }
98
+ /* stylelint-disable-next-line csstools/use-nesting */
99
+ &::-webkit-calendar-picker-indicator:focus-visible {
100
+ outline: 2px solid var(--glide-core-border-focus);
101
+ }
97
102
  }
98
103
  }
99
104
 
105
+ .suffix-icon {
106
+ align-items: center;
107
+ display: flex;
108
+ }
109
+
100
110
  .clear-icon-button,
101
111
  .password-toggle,
102
112
  ::slotted([slot='suffix-icon']) {
@@ -106,7 +116,7 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
106
116
  color: var(--glide-core-icon-default);
107
117
  display: inline-flex;
108
118
  justify-content: center;
109
- padding: 0;
119
+ padding-inline-start: var(--glide-core-spacing-xxs);
110
120
  }
111
121
 
112
122
  .clear-icon-button,
@@ -117,6 +127,10 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
117
127
  display: flex;
118
128
  }
119
129
 
130
+ ::slotted([slot='prefix-icon']) {
131
+ padding-inline-end: var(--glide-core-spacing-xxs);
132
+ }
133
+
120
134
  .empty .clear-icon-button {
121
135
  visibility: hidden;
122
136
  }
@@ -14,6 +14,7 @@ export interface Translation extends DefaultTranslation {
14
14
  notifications: string;
15
15
  nextTab: string;
16
16
  previousTab: string;
17
+ noResults: string;
17
18
  announcedCharacterCount: (current: number, maximum: number) => string;
18
19
  displayedCharacterCount: (current: number, maximum: number) => string;
19
20
  clearEntry: (label: string) => string;
@@ -21,4 +22,5 @@ export interface Translation extends DefaultTranslation {
21
22
  editTag: (name: string) => string;
22
23
  removeTag: (name: string) => string;
23
24
  actionsFor: (label: string) => string;
25
+ itemCount: (count: string) => string;
24
26
  }
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 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}" @private-slot-change="${this.#y}" @slotchange="${this.#R}" ${ref(this.#t)}></slot></div>`}#k;#e;#t;#i;#o;#n;#c;#d;#s;#l;get#O(){return this.#m?.find((({privateActive:e})=>e))}#a;#b(e){this.#u&&"focus"in this.#u&&this.#u?.focus(e)}#p(){this.#k?.(),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}#R(){ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),owSlot(this.#t.value),owSlotType(this.#t.value,[GlideCoreMenuOptions]),this.#r.privateSize=this.size}#S(){this.open=!1}#w(e){(e.target instanceof GlideCoreMenuButton||e.target instanceof GlideCoreMenuLink)&&this.#O&&this.#r&&(this.#O.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)}#y(){const e=this.#m?.find((({privateActive:e})=>e)),t=this.#m?.at(0);!e&&t&&(t.privateActive=!0)}#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.#b(),this.#O?.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.#b();if(["ArrowUp","ArrowDown"].includes(e.key)&&!this.open&&this.#O)return e.preventDefault(),this.open=!0,void(this.#r.ariaActivedescendant=this.#O.id);if(this.open){ow(this.#m,ow.array),ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),ow(this.#O,ow.object.is((e=>e instanceof GlideCoreMenuButton||e instanceof GlideCoreMenuLink)));const t=this.#m.indexOf(this.#O);if("ArrowUp"===e.key&&!e.metaKey){e.preventDefault();const i=this.#m.at(t-1);return void(i&&0!==t&&(this.#O.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.#O.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.#O.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.#O.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.#k?.(),this.#u&&this.#t.value&&(this.#k=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.#O?.id&&(this.#r.ariaActivedescendant=this.#O.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
+ 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}" @private-slot-change="${this.#y}" @slotchange="${this.#R}" ${ref(this.#t)}></slot></div>`}#k;#e;#t;#i;#o;#n;#c;#d;#s;#l;get#O(){return this.#m?.find((({privateActive:e})=>e))}#a;#b(e){this.#u&&"focus"in this.#u&&this.#u?.focus(e)}#p(){this.#k?.(),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}#R(){ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),owSlot(this.#t.value),owSlotType(this.#t.value,[GlideCoreMenuOptions]),this.#r.privateSize=this.size}#S(){this.open=!1}#w(e){(e.target instanceof GlideCoreMenuButton||e.target instanceof GlideCoreMenuLink)&&this.#O&&this.#r&&(this.#O.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)}#y(){const e=this.#m?.find((({privateActive:e})=>e)),t=this.#m?.at(0);!e&&t&&(t.privateActive=!0)}#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.#b(),this.#O?.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 e.preventDefault(),this.open=!1,void this.#b();if(["ArrowUp","ArrowDown"].includes(e.key)&&!this.open&&this.#O)return e.preventDefault(),this.open=!0,void(this.#r.ariaActivedescendant=this.#O.id);if(this.open){ow(this.#m,ow.array),ow(this.#r,ow.object.instanceOf(GlideCoreMenuOptions)),ow(this.#O,ow.object.is((e=>e instanceof GlideCoreMenuButton||e instanceof GlideCoreMenuLink)));const t=this.#m.indexOf(this.#O);if("ArrowUp"===e.key&&!e.metaKey){e.preventDefault();const i=this.#m.at(t-1);return void(i&&0!==t&&(this.#O.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.#O.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.#O.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.#O.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.#k?.(),this.#u&&this.#t.value&&(this.#k=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.#O?.id&&(this.#r.ariaActivedescendant=this.#O.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,3 +1,4 @@
1
+ import './button.js';
1
2
  import './icons/storybook.js';
2
3
  import './menu.button.js';
3
4
  import './menu.js';
@@ -18,7 +18,7 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
18
18
 
19
19
  .default-slot {
20
20
  background-color: var(--glide-core-surface-modal);
21
- border: 1px solid var(--glide-core-surface-modal);
21
+ border: 1px solid var(--glide-core-border-base-lighter);
22
22
  border-radius: var(--glide-core-spacing-xs);
23
23
  box-shadow: var(--glide-core-shadow-lg);
24
24
  box-sizing: border-box;
@@ -399,7 +399,7 @@ it('opens when opened programmatically', async () => {
399
399
  expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
400
400
  expect(target?.ariaExpanded).to.equal('true');
401
401
  });
402
- // See the `document` click listener comment in `menu.ts` for an explanation.
402
+ // See the `document` click handler comment in `menu.ts` for an explanation.
403
403
  it('opens when opened programmatically via the click handler of another element', async () => {
404
404
  const div = document.createElement('div');
405
405
  const component = await fixture(html `<glide-core-menu>
package/dist/modal.d.ts CHANGED
@@ -6,7 +6,7 @@ declare global {
6
6
  }
7
7
  }
8
8
  /**
9
- * @event close - `(event: "close", listener: (event: Event)) => void) => void`
9
+ * @event close - `(event: "close", handler: (event: Event)) => void) => void`
10
10
  *
11
11
  * @slot - The content of the modal.
12
12
  * @slot header-actions - One or more of `<glide-core-modal-icon-button>`.
package/dist/modal.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,l){var n,r=arguments.length,i=r<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,l);else for(var s=e.length-1;s>=0;s--)(n=e[s])&&(i=(r<3?n(i):r>3?n(t,o,i):n(t,o))||i);return r>3&&i&&Object.defineProperty(t,o,i),i};import"./modal.icon-button.js";import{LitElement,html}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{when}from"lit/directives/when.js";import GlideCoreButton from"./button.js";import GlideCoreModalIconButton from"./modal.icon-button.js";import GlideCoreModalTertiaryIcon from"./modal.tertiary-icon.js";import ow,{owSlot,owSlotType}from"./library/ow.js";import styles from"./modal.styles.js";const globalStylesheet=new CSSStyleSheet;globalStylesheet.insertRule("\n @supports (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n scrollbar-gutter: stable !important;\n overflow: hidden !important;\n }\n }\n"),globalStylesheet.insertRule("\n @supports not (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n padding-right: var(--glide-scroll-size, 0.9375rem) !important;\n overflow: hidden !important;\n }\n }\n");let GlideCoreModal=class GlideCoreModal extends LitElement{constructor(){super(...arguments),this.label="",this.backButton=!1,this.size="medium",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=createRef(),this.#n=createRef(),this.#r=createRef(),this.#i=new LocalizeController(this)}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}close(){this.#e.value?.open&&(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}connectedCallback(){super.connectedCallback();document.adoptedStyleSheets.includes(globalStylesheet)||document.adoptedStyleSheets.push(globalStylesheet)}disconnectedCallback(){super.disconnectedCallback(),document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),document.adoptedStyleSheets=document.adoptedStyleSheets.filter((e=>e!==globalStylesheet))}firstUpdated(){owSlot(this.#t.value),owSlotType(this.#r.value,[GlideCoreModalIconButton]),owSlotType(this.#o.value,[GlideCoreButton]),owSlotType(this.#l.value,[GlideCoreButton]),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}render(){return html`<dialog class="${classMap({component:!0,small:"small"===this.size,medium:"medium"===this.size,large:"large"===this.size,xlarge:"xlarge"===this.size})}" tabindex="-1" @keydown="${this.#s}" @mousedown="${this.#a}" ${ref(this.#e)}><header class="header"><h2 class="label" data-test="heading" id="heading">${when(this.backButton,(()=>html`<glide-core-modal-icon-button class="icon-button" data-test="back-button" @click="${this.#c}"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("dismiss")}</title><path d="M12 18C11.4477 18 11 18.4477 11 19C11 19.5523 11.4477 20 12 20V18ZM20 14.5C20 16.433 18.433 18 16.5 18V20C19.5376 20 22 17.5376 22 14.5H20ZM16.5 11C18.433 11 20 12.567 20 14.5H22C22 11.4624 19.5376 9 16.5 9V11ZM16.5 18H12V20H16.5V18ZM16.5 9H3V11H16.5V9Z" fill="currentColor"/><path d="M7 6L3 10L7 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button>`))} ${this.label}</h2><div class="header-actions" role="toolbar"><slot name="header-actions" @slotchange="${this.#d}" ${ref(this.#r)}></slot><glide-core-modal-icon-button class="icon-button" data-test="close-button" @click="${this.#c}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("close")}</title><path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button></div></header><article aria-labelledby="heading" class="body" role="region" tabindex="0"><slot @slotchange="${this.#m}" ${ref(this.#t)}></slot></article><footer class="footer"><menu class="menu"><li class="flex align-center"><slot name="tertiary" @slotchange="${this.#u}" ${ref(this.#n)}></slot></li><li><menu class="actions"><li><slot name="secondary" @slotchange="${this.#h}" ${ref(this.#l)}></slot></li><li><slot name="primary" @slotchange="${this.#f}" ${ref(this.#o)}></slot></li></menu></li></menu></footer></dialog>`}showModal(){if(!this.#e.value?.open){if(document.documentElement.classList.add("private-glide-core-modal-lock-scroll"),!window.CSS.supports("scrollbar-gutter","stable")){const e=Math.abs(window.innerWidth-document.documentElement.clientWidth);document.documentElement.style.setProperty("--glide-scroll-size",`${e}px`)}this.#e.value?.showModal(),this.#e.value?.focus()}}#e;#t;#o;#l;#n;#r;#i;#c(){document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close()}#m(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlot(this.#t.value)}#f(){owSlotType(this.#o.value,[GlideCoreButton])}#h(){owSlotType(this.#l.value,[GlideCoreButton])}#u(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}#d(){owSlotType(this.#r.value,[GlideCoreModalIconButton])}#s(e){"Escape"===e.key&&(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}#a(e){if(e.target!==this.#e.value)return;const t=this.#e.value?.getBoundingClientRect();if(t){t.top<=e.clientY&&e.clientY<=t.top+t.height&&t.left<=e.clientX&&e.clientX<=t.left+t.width||(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}}};__decorate([property({reflect:!0})],GlideCoreModal.prototype,"label",void 0),__decorate([property({attribute:"back-button",type:Boolean,reflect:!0})],GlideCoreModal.prototype,"backButton",void 0),__decorate([property({reflect:!0})],GlideCoreModal.prototype,"size",void 0),GlideCoreModal=__decorate([customElement("glide-core-modal")],GlideCoreModal);export default GlideCoreModal;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,l){var n,r=arguments.length,i=r<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,l);else for(var s=e.length-1;s>=0;s--)(n=e[s])&&(i=(r<3?n(i):r>3?n(t,o,i):n(t,o))||i);return r>3&&i&&Object.defineProperty(t,o,i),i};import"./modal.icon-button.js";import{LitElement,html}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{when}from"lit/directives/when.js";import GlideCoreButton from"./button.js";import GlideCoreModalIconButton from"./modal.icon-button.js";import GlideCoreModalTertiaryIcon from"./modal.tertiary-icon.js";import ow,{owSlot,owSlotType}from"./library/ow.js";import styles from"./modal.styles.js";const globalStylesheet=new CSSStyleSheet;globalStylesheet.insertRule("\n @supports (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n scrollbar-gutter: stable !important;\n overflow: hidden !important;\n }\n }\n"),globalStylesheet.insertRule("\n @supports not (scrollbar-gutter: stable) {\n .private-glide-core-modal-lock-scroll {\n padding-right: var(--glide-scroll-size, 0.9375rem) !important;\n overflow: hidden !important;\n }\n }\n");let GlideCoreModal=class GlideCoreModal extends LitElement{constructor(){super(...arguments),this.label="",this.backButton=!1,this.size="medium",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=createRef(),this.#n=createRef(),this.#r=createRef(),this.#i=new LocalizeController(this)}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}close(){this.#e.value?.open&&(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}connectedCallback(){super.connectedCallback();document.adoptedStyleSheets.includes(globalStylesheet)||document.adoptedStyleSheets.push(globalStylesheet)}disconnectedCallback(){super.disconnectedCallback(),document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),document.adoptedStyleSheets=document.adoptedStyleSheets.filter((e=>e!==globalStylesheet))}firstUpdated(){owSlot(this.#t.value),owSlotType(this.#r.value,[GlideCoreModalIconButton]),owSlotType(this.#o.value,[GlideCoreButton]),owSlotType(this.#l.value,[GlideCoreButton]),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}render(){return html`<dialog class="${classMap({component:!0,small:"small"===this.size,medium:"medium"===this.size,large:"large"===this.size,xlarge:"xlarge"===this.size})}" tabindex="-1" @keydown="${this.#s}" @mousedown="${this.#a}" ${ref(this.#e)}><header class="header"><h2 class="label" data-test="heading" id="heading">${when(this.backButton,(()=>html`<glide-core-modal-icon-button class="icon-button" data-test="back-button" @click="${this.#c}"><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("dismiss")}</title><path d="M12 18C11.4477 18 11 18.4477 11 19C11 19.5523 11.4477 20 12 20V18ZM20 14.5C20 16.433 18.433 18 16.5 18V20C19.5376 20 22 17.5376 22 14.5H20ZM16.5 11C18.433 11 20 12.567 20 14.5H22C22 11.4624 19.5376 9 16.5 9V11ZM16.5 18H12V20H16.5V18ZM16.5 9H3V11H16.5V9Z" fill="currentColor"/><path d="M7 6L3 10L7 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button>`))} ${this.label}</h2><div class="header-actions" role="toolbar"><slot name="header-actions" @slotchange="${this.#d}" ${ref(this.#r)}></slot><glide-core-modal-icon-button class="icon-button" data-test="close-button" @click="${this.#c}"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"><title>${this.#i.term("close")}</title><path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></glide-core-modal-icon-button></div></header><article aria-labelledby="heading" class="body" role="region" tabindex="0"><slot @slotchange="${this.#m}" ${ref(this.#t)}></slot></article><footer class="footer"><menu class="menu"><li class="flex align-center"><slot name="tertiary" @slotchange="${this.#u}" ${ref(this.#n)}></slot></li><li><menu class="actions"><li><slot name="secondary" @slotchange="${this.#h}" ${ref(this.#l)}></slot></li><li><slot name="primary" @slotchange="${this.#f}" ${ref(this.#o)}></slot></li></menu></li></menu></footer></dialog>`}showModal(){if(!this.#e.value?.open){if(document.documentElement.classList.add("private-glide-core-modal-lock-scroll"),!window.CSS.supports("scrollbar-gutter","stable")){const e=Math.abs(window.innerWidth-document.documentElement.clientWidth);document.documentElement.style.setProperty("--glide-scroll-size",`${e}px`)}this.#e.value?.showModal(),this.#e.value?.focus()}}#e;#t;#o;#l;#n;#r;#i;#c(){document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close()}#m(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlot(this.#t.value)}#f(){owSlotType(this.#o.value,[GlideCoreButton])}#h(){owSlotType(this.#l.value,[GlideCoreButton])}#u(){ow(this.#e.value,ow.object.instanceOf(HTMLDialogElement)),owSlotType(this.#n.value,[GlideCoreModalTertiaryIcon,GlideCoreButton])}#d(){owSlotType(this.#r.value,[GlideCoreModalIconButton])}#s(e){"Escape"===e.key&&(e.preventDefault(),document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}#a(e){if(e.target!==this.#e.value)return;const t=this.#e.value?.getBoundingClientRect();if(t){t.top<=e.clientY&&e.clientY<=t.top+t.height&&t.left<=e.clientX&&e.clientX<=t.left+t.width||(document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.dispatchEvent(new Event("close")),this.#e.value?.close())}}};__decorate([property({reflect:!0})],GlideCoreModal.prototype,"label",void 0),__decorate([property({attribute:"back-button",type:Boolean,reflect:!0})],GlideCoreModal.prototype,"backButton",void 0),__decorate([property({reflect:!0})],GlideCoreModal.prototype,"size",void 0),GlideCoreModal=__decorate([customElement("glide-core-modal")],GlideCoreModal);export default GlideCoreModal;
@@ -1,5 +1,4 @@
1
1
  import './radio-group.js';
2
- import './radio.js';
3
2
  import type { Meta, StoryObj } from '@storybook/web-components';
4
3
  declare const meta: Meta;
5
4
  export default meta;