@crowdstrike/glide-core 0.19.4 → 0.20.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 (139) hide show
  1. package/README.md +7 -26
  2. package/dist/accordion.d.ts +13 -4
  3. package/dist/accordion.js +1 -1
  4. package/dist/button-group.button.d.ts +16 -3
  5. package/dist/button-group.button.js +1 -1
  6. package/dist/button-group.d.ts +16 -5
  7. package/dist/button-group.js +1 -1
  8. package/dist/button.d.ts +16 -3
  9. package/dist/button.js +1 -1
  10. package/dist/checkbox-group.d.ts +49 -6
  11. package/dist/checkbox-group.js +16 -5
  12. package/dist/checkbox-group.styles.js +1 -1
  13. package/dist/checkbox.d.ts +50 -8
  14. package/dist/checkbox.js +22 -9
  15. package/dist/checkbox.styles.js +1 -1
  16. package/dist/drawer.d.ts +13 -3
  17. package/dist/drawer.js +1 -1
  18. package/dist/drawer.styles.js +6 -1
  19. package/dist/dropdown.d.ts +78 -11
  20. package/dist/dropdown.js +80 -52
  21. package/dist/dropdown.option.d.ts +31 -4
  22. package/dist/dropdown.option.js +1 -1
  23. package/dist/dropdown.option.styles.js +1 -1
  24. package/dist/dropdown.styles.js +14 -12
  25. package/dist/form-controls-layout.d.ts +10 -2
  26. package/dist/form-controls-layout.js +1 -1
  27. package/dist/icon-button.d.ts +12 -2
  28. package/dist/icon-button.js +1 -1
  29. package/dist/icon-button.styles.js +8 -8
  30. package/dist/icons/checked.js +1 -1
  31. package/dist/icons/chevron.js +1 -1
  32. package/dist/icons/magnifying-glass.js +1 -1
  33. package/dist/icons/pencil.js +1 -1
  34. package/dist/icons/severity-critical.d.ts +2 -0
  35. package/dist/icons/severity-critical.js +1 -0
  36. package/dist/icons/severity-informational.d.ts +2 -0
  37. package/dist/icons/severity-informational.js +1 -0
  38. package/dist/icons/severity-medium.d.ts +2 -0
  39. package/dist/icons/severity-medium.js +1 -0
  40. package/dist/icons/x.js +1 -1
  41. package/dist/inline-alert.d.ts +9 -10
  42. package/dist/inline-alert.js +1 -1
  43. package/dist/inline-alert.styles.js +3 -3
  44. package/dist/input.d.ts +53 -12
  45. package/dist/input.js +32 -13
  46. package/dist/input.styles.js +6 -3
  47. package/dist/label.d.ts +13 -7
  48. package/dist/label.js +1 -1
  49. package/dist/label.styles.js +10 -14
  50. package/dist/library/assert-slot.d.ts +2 -3
  51. package/dist/library/assert-slot.js +1 -1
  52. package/dist/library/assert-slot.test.js +10 -21
  53. package/dist/library/expect-unhandled-rejection.d.ts +1 -1
  54. package/dist/library/final.d.ts +3 -0
  55. package/dist/library/final.js +1 -0
  56. package/dist/library/final.test.d.ts +1 -0
  57. package/dist/library/final.test.js +44 -0
  58. package/dist/library/form-control.d.ts +7 -8
  59. package/dist/library/get-parent-class-name.d.ts +3 -0
  60. package/dist/library/get-parent-class-name.js +1 -0
  61. package/dist/library/localize.test.js +9 -12
  62. package/dist/library/on-resize.d.ts +12 -0
  63. package/dist/library/on-resize.js +1 -0
  64. package/dist/library/required.d.ts +2 -0
  65. package/dist/library/required.js +1 -0
  66. package/dist/library/required.test.d.ts +1 -0
  67. package/dist/library/required.test.js +47 -0
  68. package/dist/menu.button.d.ts +10 -1
  69. package/dist/menu.button.js +1 -1
  70. package/dist/menu.button.styles.js +3 -3
  71. package/dist/menu.d.ts +23 -7
  72. package/dist/menu.js +1 -1
  73. package/dist/menu.link.d.ts +11 -1
  74. package/dist/menu.link.js +1 -1
  75. package/dist/menu.link.styles.js +3 -3
  76. package/dist/menu.options.d.ts +8 -2
  77. package/dist/menu.options.js +1 -1
  78. package/dist/menu.options.styles.js +7 -7
  79. package/dist/modal.d.ts +19 -6
  80. package/dist/modal.icon-button.d.ts +7 -3
  81. package/dist/modal.icon-button.js +1 -1
  82. package/dist/modal.icon-button.styles.js +1 -1
  83. package/dist/modal.js +1 -1
  84. package/dist/modal.styles.js +26 -8
  85. package/dist/popover.d.ts +20 -3
  86. package/dist/popover.js +1 -1
  87. package/dist/popover.styles.js +6 -6
  88. package/dist/radio-group.d.ts +48 -6
  89. package/dist/radio-group.js +15 -6
  90. package/dist/radio-group.radio.d.ts +26 -2
  91. package/dist/radio-group.radio.js +1 -1
  92. package/dist/split-button.d.ts +15 -5
  93. package/dist/split-button.js +1 -1
  94. package/dist/split-button.primary-button.d.ts +10 -1
  95. package/dist/split-button.primary-button.js +1 -1
  96. package/dist/split-button.primary-link.d.ts +8 -1
  97. package/dist/split-button.primary-link.js +1 -1
  98. package/dist/split-button.secondary-button.d.ts +9 -1
  99. package/dist/split-button.secondary-button.js +1 -1
  100. package/dist/split-button.secondary-button.styles.js +2 -2
  101. package/dist/styles/variables.css +1 -1
  102. package/dist/tab.d.ts +16 -5
  103. package/dist/tab.group.d.ts +14 -15
  104. package/dist/tab.group.js +1 -1
  105. package/dist/tab.group.styles.js +8 -3
  106. package/dist/tab.js +1 -1
  107. package/dist/tab.panel.d.ts +11 -5
  108. package/dist/tab.panel.js +1 -1
  109. package/dist/tab.panel.styles.js +9 -2
  110. package/dist/tag.d.ts +11 -2
  111. package/dist/tag.js +1 -1
  112. package/dist/tag.styles.js +4 -4
  113. package/dist/textarea.d.ts +46 -6
  114. package/dist/textarea.js +12 -4
  115. package/dist/toasts.d.ts +18 -16
  116. package/dist/toasts.js +1 -1
  117. package/dist/toasts.toast.d.ts +11 -5
  118. package/dist/toasts.toast.js +1 -1
  119. package/dist/toasts.toast.styles.js +1 -1
  120. package/dist/toggle.d.ts +13 -4
  121. package/dist/toggle.js +1 -1
  122. package/dist/toggle.styles.js +3 -3
  123. package/dist/tooltip.container.d.ts +11 -2
  124. package/dist/tooltip.container.js +1 -1
  125. package/dist/tooltip.d.ts +40 -3
  126. package/dist/tooltip.js +1 -1
  127. package/dist/tooltip.styles.js +7 -7
  128. package/dist/tree.d.ts +7 -1
  129. package/dist/tree.item.d.ts +30 -12
  130. package/dist/tree.item.icon-button.d.ts +7 -2
  131. package/dist/tree.item.icon-button.js +1 -1
  132. package/dist/tree.item.icon-button.styles.js +3 -3
  133. package/dist/tree.item.js +1 -1
  134. package/dist/tree.item.menu.d.ts +9 -3
  135. package/dist/tree.item.menu.js +1 -1
  136. package/dist/tree.item.menu.styles.js +3 -3
  137. package/dist/tree.item.styles.js +10 -5
  138. package/dist/tree.js +1 -1
  139. package/package.json +81 -54
@@ -4,7 +4,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
4
4
  `,css`
5
5
  .component {
6
6
  &.horizontal {
7
- --column-gap: var(--glide-core-spacing-sm);
7
+ --private-column-gap: var(--glide-core-spacing-sm);
8
8
 
9
9
  column-gap: var(--glide-core-spacing-sm);
10
10
  display: grid;
@@ -21,8 +21,8 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
21
21
  }
22
22
 
23
23
  &.middle {
24
- grid-template-columns: calc(50% - var(--column-gap) / 2) calc(
25
- 50% - var(--column-gap) / 2
24
+ grid-template-columns: calc(50% - var(--private-column-gap) / 2) calc(
25
+ 50% - var(--private-column-gap) / 2
26
26
  );
27
27
  }
28
28
 
@@ -61,9 +61,9 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
61
61
 
62
62
  &.visible {
63
63
  /*
64
- The default is "display: content". But "order" does not work with
65
- "display: content" and "order" is needed above.
66
- */
64
+ The default is "display: content". But "order" does not work with
65
+ "display: content" and "order" is needed above.
66
+ */
67
67
  display: block;
68
68
  }
69
69
  }
@@ -75,11 +75,10 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
75
75
  color: var(--glide-core-text-body-1);
76
76
 
77
77
  /*
78
- Any "display" that's not inline-level will do. We don't want the button to
79
- acquire a line box, which will make it taller than its content and thus
80
- make it difficult to center vertically with the label.
81
- */
82
-
78
+ Any "display" that's not inline-level will do. We don't want the button to
79
+ acquire a line box, which will make it taller than its content and thus
80
+ make it difficult to center vertically with the label.
81
+ */
83
82
  display: flex;
84
83
  padding: 0;
85
84
 
@@ -133,9 +132,6 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
133
132
  align-items: center;
134
133
  display: flex;
135
134
  gap: var(--glide-core-spacing-sm);
136
-
137
- /* https://css-tricks.com/flexbox-truncated-text/#aa-the-solution-is-min-width-0-on-the-flex-child */
138
- min-inline-size: 0;
139
135
  }
140
136
 
141
137
  .control {
@@ -1,7 +1,6 @@
1
1
  import { type ElementPart } from 'lit';
2
2
  import { Directive, type PartInfo } from 'lit/directive.js';
3
3
  declare class AssertSlot extends Directive {
4
- #private;
5
4
  render(slotted?: (typeof Element | typeof Text)[] | null, isOptional?: boolean): symbol;
6
5
  update(part: ElementPart, [slotted, isOptional]: [
7
6
  (typeof Element | typeof Text)[] | undefined | null,
@@ -9,11 +8,11 @@ declare class AssertSlot extends Directive {
9
8
  ]): symbol;
10
9
  constructor(partInfo: PartInfo);
11
10
  }
12
- declare const assertSlot: (slotted?: ({
11
+ declare const _default: (slotted?: ({
13
12
  new (): Element;
14
13
  prototype: Element;
15
14
  } | {
16
15
  new (data?: string): Text;
17
16
  prototype: Text;
18
17
  })[] | null | undefined, isOptional?: boolean | undefined) => import("lit/directive.js").DirectiveResult<typeof AssertSlot>;
19
- export default assertSlot;
18
+ export default _default;
@@ -1 +1 @@
1
- import{LitElement,noChange}from"lit";import{Directive,directive,PartType}from"lit/directive.js";const isThrow=["localhost","127.0.0.1"].some((e=>window.location.host.includes(e)));class AssertSlot extends Directive{render(e,t){return noChange}update(e,[t,n]){if(e.options?.host instanceof LitElement&&isThrow){const o=e.options.host;!this.#e&&e.element&&isThrow&&(e.options.host.updateComplete.then((()=>{if(!n&&e.element instanceof HTMLSlotElement&&0===e.element.assignedNodes().length&&t?.length){const n=e.element.name?`Expected the "${e.element.name}" slot of ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`:`Expected ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`;throw new TypeError(n)}if(!n&&e.element instanceof HTMLSlotElement&&0===e.element.assignedNodes().length){const t=e.element.name?`Expected ${o.constructor.name} to have a "${e.element.name}" slot.`:`Expected ${o.constructor.name} to have a default slot.`;throw new TypeError(t)}})),this.#e||e.element?.addEventListener("slotchange",(()=>{if(!(n&&e.element instanceof HTMLSlotElement&&0===e.element.assignedNodes().length)){if(e.element instanceof HTMLSlotElement&&0===e.element.assignedNodes().length){if(t&&t.length>0){const n=e.element.name?`Expected the "${e.element.name}" slot of ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`:`Expected ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`;throw new TypeError(n)}const n=e.element.name?`Expected a "${e.element.name}" slot.`:"Expected a default slot.";throw new TypeError(n)}if(t?.length&&e.element instanceof HTMLSlotElement){const n=e.element.assignedNodes({flatten:!0}).filter((e=>!!(e instanceof Text&&t.includes(Text))||!(e instanceof Text)));if(0===n.length){const e=`Expected ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`;throw new TypeError(e)}for(const s of n){if(!t.some((e=>s instanceof e))){const n=e.element.name?`Expected the "${e.element.name}" slot of ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}. Extends ${s.constructor.name} instead.`:`Expected ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}. Extends ${s.constructor.name} instead.`;throw new TypeError(n)}}}}})),this.#e=!0)}return this.render()}constructor(e){if(super(e),e.type!==PartType.ELEMENT)throw new TypeError("Directive must be inside the element's opening tag.");if("element"in e){if(!(e.element instanceof HTMLSlotElement))throw new TypeError("Directive can only be used on slots.")}}#e=!1}const assertSlot=directive(AssertSlot);export default assertSlot;
1
+ import{LitElement,noChange}from"lit";import{Directive,directive,PartType}from"lit/directive.js";const isThrow=["localhost","127.0.0.1"].some((e=>window.location.host.includes(e)));class AssertSlot extends Directive{render(e,t){return noChange}update(e,[t,n]){if(e.options?.host instanceof LitElement&&isThrow){const o=e.options.host;e.options?.host instanceof LitElement&&!e.options.host.hasUpdated&&isThrow&&(e.options.host.updateComplete.then((()=>{if(!n&&e.element instanceof HTMLSlotElement&&0===e.element.assignedNodes().length&&t?.length){const n=e.element.name?`Expected the "${e.element.name}" slot of ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`:`Expected ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`;throw new TypeError(n)}if(!n&&e.element instanceof HTMLSlotElement&&0===e.element.assignedNodes().length){const t=e.element.name?`Expected ${o.constructor.name} to have a "${e.element.name}" slot.`:`Expected ${o.constructor.name} to have a default slot.`;throw new TypeError(t)}})),e.options?.host instanceof LitElement&&!e.options.host.hasUpdated&&e.element?.addEventListener("slotchange",(()=>{if(!(n&&e.element instanceof HTMLSlotElement&&0===e.element.assignedNodes().length)){if(e.element instanceof HTMLSlotElement&&0===e.element.assignedNodes().length){if(t&&t.length>0){const n=e.element.name?`Expected the "${e.element.name}" slot of ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`:`Expected ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`;throw new TypeError(n)}const n=e.element.name?`Expected a "${e.element.name}" slot.`:"Expected a default slot.";throw new TypeError(n)}if(t?.length&&e.element instanceof HTMLSlotElement){const n=e.element.assignedNodes({flatten:!0}).filter((e=>!!(e instanceof Text&&t.includes(Text))||!(e instanceof Text)));if(0===n.length){const e=`Expected ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}.`;throw new TypeError(e)}for(const s of n){if(!t.some((e=>s instanceof e))){const n=e.element.name?`Expected the "${e.element.name}" slot of ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}. Extends ${s.constructor.name} instead.`:`Expected ${o.constructor.name} to have a slotted element that extends ${t.map((({name:e})=>e)).join(" or ")}. Extends ${s.constructor.name} instead.`;throw new TypeError(n)}}}}})))}return this.render()}constructor(e){if(super(e),e.type!==PartType.ELEMENT)throw new TypeError("Directive must be inside the element's opening tag.");if("element"in e){if(!(e.element instanceof HTMLSlotElement))throw new TypeError("Directive can only be used on slots.")}}}export default directive(AssertSlot);
@@ -16,9 +16,6 @@ let GlideCoreWithSlot = class GlideCoreWithSlot extends LitElement {
16
16
  this.optional = false;
17
17
  this.slotted = [];
18
18
  }
19
- static { this.shadowRootOptions = {
20
- ...LitElement.shadowRootOptions,
21
- }; }
22
19
  render() {
23
20
  return html `<slot
24
21
  name=${ifDefined(this.name)}
@@ -39,9 +36,6 @@ GlideCoreWithSlot = __decorate([
39
36
  customElement('glide-core-with-slot')
40
37
  ], GlideCoreWithSlot);
41
38
  let GlideCoreWhenNotUsedOnSlot = class GlideCoreWhenNotUsedOnSlot extends LitElement {
42
- static { this.shadowRootOptions = {
43
- ...LitElement.shadowRootOptions,
44
- }; }
45
39
  render() {
46
40
  return html `<div ${assertSlot()}></div>`;
47
41
  }
@@ -50,9 +44,6 @@ GlideCoreWhenNotUsedOnSlot = __decorate([
50
44
  customElement('glide-core-when-not-used-on-slot')
51
45
  ], GlideCoreWhenNotUsedOnSlot);
52
46
  let GlideCorewhenNotUsedInsideTag = class GlideCorewhenNotUsedInsideTag extends LitElement {
53
- static { this.shadowRootOptions = {
54
- ...LitElement.shadowRootOptions,
55
- }; }
56
47
  render() {
57
48
  return html `<slot>${assertSlot()}</slot>`;
58
49
  }
@@ -72,7 +63,7 @@ it('throws when a required default slot is empty', async () => {
72
63
  stub.restore();
73
64
  });
74
65
  it('throws when a required default slot is emptied', async () => {
75
- const component = await fixture(html `<glide-core-with-slot>
66
+ const host = await fixture(html `<glide-core-with-slot>
76
67
  <button>Button</button>
77
68
  </glide-core-with-slot>`);
78
69
  const stub = sinon.stub(console, 'error');
@@ -80,7 +71,7 @@ it('throws when a required default slot is emptied', async () => {
80
71
  const onerror = window.onerror;
81
72
  // eslint-disable-next-line unicorn/prefer-add-event-listener
82
73
  window.onerror = spy;
83
- component.innerHTML = '';
74
+ host.innerHTML = '';
84
75
  await waitUntil(() => spy.callCount);
85
76
  expect(spy.callCount).to.equal(1);
86
77
  expect(spy.args.at(0)?.at(0)).to.equal('Uncaught TypeError: Expected a default slot.');
@@ -100,7 +91,7 @@ it('throws when a required named slot is empty', async () => {
100
91
  stub.restore();
101
92
  });
102
93
  it('throws when a required named slot is emptied', async () => {
103
- const component = await fixture(html `<glide-core-with-slot name="test">
94
+ const host = await fixture(html `<glide-core-with-slot name="test">
104
95
  <button slot="test">Button</button>
105
96
  </glide-core-with-slot>`);
106
97
  const stub = sinon.stub(console, 'error');
@@ -108,7 +99,7 @@ it('throws when a required named slot is emptied', async () => {
108
99
  const onerror = window.onerror;
109
100
  // eslint-disable-next-line unicorn/prefer-add-event-listener
110
101
  window.onerror = spy;
111
- component.innerHTML = '';
102
+ host.innerHTML = '';
112
103
  await waitUntil(() => spy.callCount);
113
104
  expect(spy.callCount).to.equal(1);
114
105
  expect(spy.args.at(0)?.at(0)).to.equal('Uncaught TypeError: Expected a "test" slot.');
@@ -130,7 +121,7 @@ it('throws when a typed and required default slot is empty', async () => {
130
121
  stub.restore();
131
122
  });
132
123
  it('throws when a typed and required default slot is emptied', async () => {
133
- const component = await fixture(html `<glide-core-with-slot .slotted=${[HTMLButtonElement]}>
124
+ const host = await fixture(html `<glide-core-with-slot .slotted=${[HTMLButtonElement]}>
134
125
  <button>Button</button>
135
126
  </glide-core-with-slot>`);
136
127
  const stub = sinon.stub(console, 'error');
@@ -138,7 +129,7 @@ it('throws when a typed and required default slot is emptied', async () => {
138
129
  const onerror = window.onerror;
139
130
  // eslint-disable-next-line unicorn/prefer-add-event-listener
140
131
  window.onerror = spy;
141
- component.innerHTML = '';
132
+ host.innerHTML = '';
142
133
  await waitUntil(() => spy.callCount);
143
134
  expect(spy.callCount).to.equal(1);
144
135
  expect(spy.args.at(0)?.at(0)).to.equal('Uncaught TypeError: Expected GlideCoreWithSlot to have a slotted element that extends HTMLButtonElement.');
@@ -193,7 +184,7 @@ it('throws when a typed and required named slot is empty', async () => {
193
184
  stub.restore();
194
185
  });
195
186
  it('throws when a typed and required named slot is emptied', async () => {
196
- const component = await fixture(html `<glide-core-with-slot name="test" .slotted=${[HTMLButtonElement]}>
187
+ const host = await fixture(html `<glide-core-with-slot name="test" .slotted=${[HTMLButtonElement]}>
197
188
  <button slot="test">Button</button>
198
189
  </glide-core-with-slot>`);
199
190
  const stub = sinon.stub(console, 'error');
@@ -201,7 +192,7 @@ it('throws when a typed and required named slot is emptied', async () => {
201
192
  const onerror = window.onerror;
202
193
  // eslint-disable-next-line unicorn/prefer-add-event-listener
203
194
  window.onerror = spy;
204
- component.innerHTML = '';
195
+ host.innerHTML = '';
205
196
  await waitUntil(() => spy.callCount);
206
197
  expect(spy.callCount).to.equal(1);
207
198
  expect(spy.args.at(0)?.at(0)).to.equal('Uncaught TypeError: Expected the "test" slot of GlideCoreWithSlot to have a slotted element that extends HTMLButtonElement.');
@@ -231,17 +222,15 @@ it('does not throw when an optional slot is empty', async () => {
231
222
  const spy = sinon.spy();
232
223
  window.addEventListener('unhandledrejection', spy, { once: true });
233
224
  await fixture(html `<glide-core-with-slot optional></glide-core-with-slot>`);
234
- // Wait for the event handler to be called.
235
- await aTimeout(0);
236
225
  expect(spy.callCount).to.equal(0);
237
226
  });
238
227
  it('does not throw when an optional slot is emptied', async () => {
239
228
  const spy = sinon.spy();
240
229
  window.addEventListener('error', spy);
241
- const component = await fixture(html `<glide-core-with-slot optional>
230
+ const host = await fixture(html `<glide-core-with-slot optional>
242
231
  <button>Button</button>
243
232
  </glide-core-with-slot>`);
244
- component.innerHTML = '';
233
+ host.innerHTML = '';
245
234
  // Wait for the event handler to be called.
246
235
  await aTimeout(0);
247
236
  expect(spy.callCount).to.equal(0);
@@ -1 +1 @@
1
- export default function (callback: () => Promise<unknown>): Promise<void>;
1
+ export default function (callback: () => unknown): Promise<void>;
@@ -0,0 +1,3 @@
1
+ export default function <Type extends new (...arguments_: any[]) => object>(constructor: Type): {
2
+ new (...arguments_: any[]): {};
3
+ } & Type;
@@ -0,0 +1 @@
1
+ export default function(e){return class Final extends e{constructor(...n){if(new.target!==Final)throw new TypeError(`${e.name} does not allow extension.`);super(...n)}}}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement } from 'lit';
8
+ import { customElement } from 'lit/decorators.js';
9
+ import { expect } from '@open-wc/testing';
10
+ import sinon from 'sinon';
11
+ import final from './final.js';
12
+ let GlideCoreFinal = class GlideCoreFinal extends LitElement {
13
+ };
14
+ GlideCoreFinal = __decorate([
15
+ customElement('glide-core-final'),
16
+ final
17
+ ], GlideCoreFinal);
18
+ let GlideCoreSubclassed = class GlideCoreSubclassed extends GlideCoreFinal {
19
+ };
20
+ GlideCoreSubclassed = __decorate([
21
+ customElement('glide-core-subclassed')
22
+ ], GlideCoreSubclassed);
23
+ it('throws when a class is extended', async () => {
24
+ const spy = sinon.spy();
25
+ try {
26
+ new GlideCoreSubclassed();
27
+ }
28
+ catch (error) {
29
+ spy(error);
30
+ }
31
+ expect(spy.callCount).to.equal(1);
32
+ expect(spy.args.at(0)?.at(0) instanceof TypeError).to.be.true;
33
+ expect(spy.args.at(0)?.at(0).message).to.equal('GlideCoreFinal does not allow extension.');
34
+ });
35
+ it('does not throw when a class is not extended', () => {
36
+ const spy = sinon.spy();
37
+ try {
38
+ new GlideCoreFinal();
39
+ }
40
+ catch (error) {
41
+ spy(error);
42
+ }
43
+ expect(spy.callCount).to.equal(0);
44
+ });
@@ -11,12 +11,11 @@ export default interface FormControl {
11
11
  tooltip?: string;
12
12
  validity: ValidityState;
13
13
  value: string | string[];
14
- willValidate: boolean;
15
- checkValidity: () => boolean;
16
- formAssociatedCallback: () => void;
17
- formResetCallback: () => void;
18
- reportValidity: () => boolean;
19
- resetValidityFeedback: () => void;
20
- setCustomValidity: (message: string) => void;
21
- setValidity: (flags?: ValidityStateFlags, message?: string) => void;
14
+ checkValidity(): boolean;
15
+ formAssociatedCallback(): void;
16
+ formResetCallback(): void;
17
+ reportValidity(): boolean;
18
+ resetValidityFeedback(): void;
19
+ setCustomValidity(message: string): void;
20
+ setValidity(flags?: ValidityStateFlags, message?: string): void;
22
21
  }
@@ -0,0 +1,3 @@
1
+ import { type Node } from 'typescript';
2
+ declare const _default: (node: Node) => string | undefined;
3
+ export default _default;
@@ -0,0 +1 @@
1
+ import{isClassDeclaration,isIdentifier}from"typescript";export default e=>{if(isClassDeclaration(e)&&e.name&&isIdentifier(e.name))return e.name.text;let t=e.parent;for(;t&&!isClassDeclaration(t);)t=t.parent;return t?.name&&isIdentifier(t.name)?t.name.text:void 0};
@@ -14,28 +14,25 @@ let GlideCoreMockComponent = class GlideCoreMockComponent extends LitElement {
14
14
  super(...arguments);
15
15
  this.localize = new LocalizeController(this);
16
16
  }
17
- static { this.shadowRootOptions = {
18
- ...LitElement.shadowRootOptions,
19
- }; }
20
17
  };
21
18
  GlideCoreMockComponent = __decorate([
22
- customElement('mock-component')
19
+ customElement('mock-host')
23
20
  ], GlideCoreMockComponent);
24
21
  it('can call any term from en translation if locale is Japanese', async () => {
25
- const component = await fixture(html `<mock-component></mock-component>`);
26
- component.lang = 'ja';
27
- expect(component.localize.lang()).to.equal('ja');
22
+ const host = await fixture(html `<mock-host></mock-host>`);
23
+ host.lang = 'ja';
24
+ expect(host.localize.lang()).to.equal('ja');
28
25
  const keys = Object.keys(en);
29
26
  for (const key of keys) {
30
- expect(component.localize.term(key)).to.be.ok;
27
+ expect(host.localize.term(key)).to.be.ok;
31
28
  }
32
29
  });
33
30
  it('can call any term from en translation if locale is French', async () => {
34
- const component = await fixture(html `<mock-component></mock-component>`);
35
- component.lang = 'fr';
36
- expect(component.localize.lang()).to.equal('fr');
31
+ const host = await fixture(html `<mock-host></mock-host>`);
32
+ host.lang = 'fr';
33
+ expect(host.localize.lang()).to.equal('fr');
37
34
  const keys = Object.keys(en);
38
35
  for (const key of keys) {
39
- expect(component.localize.term(key)).to.be.ok;
36
+ expect(host.localize.term(key)).to.be.ok;
40
37
  }
41
38
  });
@@ -0,0 +1,12 @@
1
+ import { type ElementPart } from 'lit';
2
+ import { Directive } from 'lit/directive.js';
3
+ declare class OnResize extends Directive {
4
+ #private;
5
+ render(callback: (entries: ResizeObserverEntry[], observer: ResizeObserver) => unknown, options?: ResizeObserverOptions): symbol;
6
+ update(part: ElementPart, [callback, options]: [
7
+ (entries: ResizeObserverEntry[], observer: ResizeObserver) => unknown,
8
+ ResizeObserverOptions
9
+ ]): symbol;
10
+ }
11
+ declare const _default: (callback: (entries: ResizeObserverEntry[], observer: ResizeObserver) => unknown, options?: ResizeObserverOptions | undefined) => import("lit/directive.js").DirectiveResult<typeof OnResize>;
12
+ export default _default;
@@ -0,0 +1 @@
1
+ import{LitElement,noChange}from"lit";import{Directive,directive}from"lit/directive.js";class OnResize extends Directive{render(e,t){return noChange}update(e,[t,r]){return e.options?.host instanceof LitElement&&!e.options.host.hasUpdated&&(this.#e=new ResizeObserver(t),this.#e.observe(e.element,r)),this.render(t,r)}#e}export default directive(OnResize);
@@ -0,0 +1,2 @@
1
+ import { ReactiveElement } from 'lit';
2
+ export default function (prototype: ReactiveElement, key: string): void;
@@ -0,0 +1 @@
1
+ import{ReactiveElement}from"lit";const isThrow=["localhost","127.0.0.1"].some((t=>window.location.host.includes(t)));class RequiredController{hostUpdate(){if((void 0===this.#t[this.#o]||null===this.#t[this.#o])&&isThrow)throw new TypeError(`Expected ${this.#e} to have a \`${this.#o}\` property.`)}constructor(t,o,e){t.addController(this),this.#t=t,this.#o=o,this.#e=e}#t;#o;#e}export default function(t,o){if(Object.prototype.isPrototypeOf.call(ReactiveElement,t.constructor)){t.constructor.addInitializer((e=>{new RequiredController(e,o,t.constructor.name)}))}}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement } from 'lit';
8
+ import { customElement, property } from 'lit/decorators.js';
9
+ import { expect, fixture, html, waitUntil } from '@open-wc/testing';
10
+ import sinon from 'sinon';
11
+ import required from './required.js';
12
+ import final from './final.js';
13
+ // In non-test scenarios, both `@required` and `@final` are
14
+ // used together. Using both decorators in tests allow us
15
+ // to verifying the component name is included in the
16
+ // message.
17
+ let GlideCoreWithRequiredProperty = class GlideCoreWithRequiredProperty extends LitElement {
18
+ };
19
+ __decorate([
20
+ property(),
21
+ required
22
+ ], GlideCoreWithRequiredProperty.prototype, "label", void 0);
23
+ GlideCoreWithRequiredProperty = __decorate([
24
+ customElement('glide-core-with-required-property'),
25
+ final
26
+ ], GlideCoreWithRequiredProperty);
27
+ it('throws when a required attribute is missing', async () => {
28
+ const stub = sinon.stub(console, 'error');
29
+ const spy = sinon.spy();
30
+ window.addEventListener('unhandledrejection', spy, { once: true });
31
+ fixture(html `<glide-core-with-required-property></glide-core-with-required-property>`);
32
+ await waitUntil(() => spy.callCount);
33
+ expect(spy.callCount).to.equal(1);
34
+ expect(spy.args.at(0)?.at(0) instanceof PromiseRejectionEvent).to.be.true;
35
+ expect(spy.args.at(0)?.at(0).reason.message).to.equal('Expected GlideCoreWithRequiredProperty to have a `label` property.');
36
+ stub.restore();
37
+ });
38
+ it('does not throw when a required attribute is not missing', async () => {
39
+ const stub = sinon.stub(console, 'error');
40
+ const spy = sinon.spy();
41
+ window.addEventListener('unhandledrejection', spy, { once: true });
42
+ await fixture(html `<glide-core-with-required-property
43
+ label="Label"
44
+ ></glide-core-with-required-property>`);
45
+ expect(spy.callCount).to.equal(0);
46
+ stub.restore();
47
+ });
@@ -5,12 +5,21 @@ declare global {
5
5
  }
6
6
  }
7
7
  /**
8
- * @slot icon - An optional icon.
8
+ * @attr {string} label
9
+ * @attr {boolean} [disabled=false]
10
+ *
11
+ * @readonly
12
+ * @attr {0.19.5} [version]
13
+ *
14
+ * @slot {Element} [icon]
9
15
  */
10
16
  export default class GlideCoreMenuButton extends LitElement {
11
17
  #private;
12
18
  static shadowRootOptions: ShadowRootInit;
13
19
  static styles: import("lit").CSSResult[];
20
+ /**
21
+ * @default false
22
+ */
14
23
  get disabled(): boolean;
15
24
  set disabled(isDisabled: boolean);
16
25
  label?: string;
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,i){var r,s=arguments.length,n=s<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,o,i);else for(var l=e.length-1;l>=0;l--)(r=e[l])&&(n=(s<3?r(n):s>3?r(t,o,n):r(t,o))||n);return s>3&&n&&Object.defineProperty(t,o,n),n};import{html,LitElement}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{nanoid}from"nanoid";import packageJson from"../package.json"with{type:"json"};import styles from"./menu.button.styles.js";import shadowRootMode from"./library/shadow-root-mode.js";let GlideCoreMenuButton=class GlideCoreMenuButton extends LitElement{constructor(){super(...arguments),this.privateActive=!1,this.version=packageJson.version,this.#e=createRef(),this.#t=nanoid(),this.#o=!1}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}get disabled(){return this.#o}set disabled(e){this.#o=e,e&&this.privateActive&&this.dispatchEvent(new Event("private-disabled",{bubbles:!0}))}click(){this.#e.value?.click()}connectedCallback(){super.connectedCallback(),this.id=this.#t,this.role="menuitem",this.tabIndex=-1}render(){return html`<button class="${classMap({component:!0,active:this.privateActive,disabled:this.disabled})}" ?disabled="${this.disabled}" data-test="component" type="button" ${ref(this.#e)}><slot name="icon"></slot>${this.label}</button>`}#e;#t;#o};__decorate([property({reflect:!0,type:Boolean})],GlideCoreMenuButton.prototype,"disabled",null),__decorate([property({reflect:!0})],GlideCoreMenuButton.prototype,"label",void 0),__decorate([property({type:Boolean})],GlideCoreMenuButton.prototype,"privateActive",void 0),__decorate([property({reflect:!0})],GlideCoreMenuButton.prototype,"version",void 0),GlideCoreMenuButton=__decorate([customElement("glide-core-menu-button")],GlideCoreMenuButton);export default GlideCoreMenuButton;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,i){var r,s=arguments.length,n=s<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,o,i);else for(var l=e.length-1;l>=0;l--)(r=e[l])&&(n=(s<3?r(n):s>3?r(t,o,n):r(t,o))||n);return s>3&&n&&Object.defineProperty(t,o,n),n};import{html,LitElement}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{nanoid}from"nanoid";import packageJson from"../package.json"with{type:"json"};import styles from"./menu.button.styles.js";import shadowRootMode from"./library/shadow-root-mode.js";import final from"./library/final.js";import required from"./library/required.js";let GlideCoreMenuButton=class GlideCoreMenuButton extends LitElement{constructor(){super(...arguments),this.privateActive=!1,this.version=packageJson.version,this.#e=createRef(),this.#t=nanoid(),this.#o=!1}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}get disabled(){return this.#o}set disabled(e){this.#o=e,e&&this.privateActive&&this.dispatchEvent(new Event("private-disabled",{bubbles:!0}))}click(){this.#e.value?.click()}connectedCallback(){super.connectedCallback(),this.id=this.#t,this.role="menuitem",this.tabIndex=-1}render(){return html`<button class="${classMap({component:!0,active:this.privateActive,disabled:this.disabled})}" ?disabled="${this.disabled}" data-test="component" type="button" ${ref(this.#e)}><slot name="icon"></slot>${this.label}</button>`}#e;#t;#o};__decorate([property({reflect:!0,type:Boolean})],GlideCoreMenuButton.prototype,"disabled",null),__decorate([property({reflect:!0}),required],GlideCoreMenuButton.prototype,"label",void 0),__decorate([property({type:Boolean})],GlideCoreMenuButton.prototype,"privateActive",void 0),__decorate([property({reflect:!0})],GlideCoreMenuButton.prototype,"version",void 0),GlideCoreMenuButton=__decorate([customElement("glide-core-menu-button"),final],GlideCoreMenuButton);export default GlideCoreMenuButton;
@@ -6,10 +6,10 @@ import{css}from"lit";export default[css`
6
6
  border-radius: var(--glide-core-spacing-sm);
7
7
  display: flex;
8
8
  font: inherit;
9
- gap: var(--gap);
9
+ gap: var(--private-gap);
10
10
  inline-size: 100%;
11
- padding-block: var(--padding-block);
12
- padding-inline: var(--padding-inline);
11
+ padding-block: var(--private-padding-block);
12
+ padding-inline: var(--private-padding-inline);
13
13
  transition: background-color 100ms ease-in-out;
14
14
  user-select: none;
15
15
 
package/dist/menu.d.ts CHANGED
@@ -1,27 +1,43 @@
1
1
  import { LitElement } from 'lit';
2
- import { type Placement } from '@floating-ui/dom';
3
2
  declare global {
4
3
  interface HTMLElementTagNameMap {
5
4
  'glide-core-menu': GlideCoreMenu;
6
5
  }
7
6
  }
8
7
  /**
9
- * @event toggle
8
+ * @attr {number} [offset=4]
9
+ * @attr {boolean} [open=false]
10
+ * @attr {'bottom'|'left'|'right'|'top'|'bottom-start'|'bottom-end'|'left-start'|'left-end'|'right-start'|'right-end'|'top-start'|'top-end'} [placement='bottom-start']
11
+ * @attr {'large'|'small'} [size='large']
10
12
  *
11
- * @slot - One of `<glide-core-menu-options>`.
12
- * @slot target - The element to which the menu will anchor, which can be any focusable element.
13
+ * @readonly
14
+ * @attr {0.19.5} [version]
15
+ *
16
+ * @slot {GlideCoreMenuOptions}
17
+ * @slot {Element} [target] - The element to which the popover will anchor. Can be any focusable element.
18
+ *
19
+ * @fires {Event} toggle
13
20
  */
14
21
  export default class GlideCoreMenu extends LitElement {
15
22
  #private;
16
23
  static shadowRootOptions: ShadowRootInit;
17
24
  static styles: import("lit").CSSResult[];
25
+ /**
26
+ * @default 4
27
+ */
18
28
  get offset(): number;
19
29
  set offset(offset: number);
30
+ /**
31
+ * @default false
32
+ */
20
33
  get open(): boolean;
21
34
  set open(isOpen: boolean);
22
- placement: Placement;
23
- get size(): "small" | "large";
24
- set size(size: 'small' | 'large');
35
+ placement: 'bottom' | 'left' | 'right' | 'top' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end' | 'top-start' | 'top-end';
36
+ /**
37
+ * @default 'large'
38
+ */
39
+ get size(): 'large' | 'small';
40
+ set size(size: 'large' | 'small');
25
41
  readonly version: string;
26
42
  connectedCallback(): void;
27
43
  createRenderRoot(): ShadowRoot;
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{html,LitElement}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 packageJson from"../package.json"with{type:"json"};import GlideCoreMenuButton from"./menu.button.js";import GlideCoreMenuLink from"./menu.link.js";import GlideCoreMenuOptions from"./menu.options.js";import assertSlot from"./library/assert-slot.js";import styles from"./menu.styles.js";import shadowRootMode from"./library/shadow-root-mode.js";let GlideCoreMenu=class GlideCoreMenu extends LitElement{constructor(){super(...arguments),this.placement="bottom-start",this.version=packageJson.version,this.#e=createRef(),this.#t=createRef(),this.#i=!1,this.#o=!1,this.#n=!1,this.#s=!1,this.#l=!1,this.#a="large",this.#r=createRef(),this.#d=e=>{e.target===this.#t.value&&e.preventDefault()},this.#c=e=>{if(e.target===this.#t.value&&(this.#o=!0),e.target instanceof Element){const t=e.target?.closest("glide-core-menu-link");t?.disabled&&(this.#n=!0)}},this.#h=()=>{this.#o?this.#o=!1:this.#n?this.#n=!1:this.#l?this.#l=!1:(this.open=!1,this.#p&&(this.#p.ariaActivedescendant=""))},this.#u=()=>{this.#l=!0}}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}get offset(){return this.#m??Number.parseFloat(window.getComputedStyle(document.body).getPropertyValue("--glide-core-spacing-xxs"))*Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize)}set offset(e){this.#m=e}get open(){return this.#s}set open(e){const t=e!==this.#s;this.#s=e,e&&t&&!this.isTargetDisabled?(this.#f(),this.dispatchEvent(new Event("toggle",{bubbles:!0,composed:!0}))):t&&(this.#E(),this.dispatchEvent(new Event("toggle",{bubbles:!0,composed:!0})))}get size(){return this.#a}set size(e){this.#a=e,this.#p&&(this.#p.privateSize=e)}connectedCallback(){super.connectedCallback(),document.addEventListener("click",this.#h,{capture:!0})}createRenderRoot(){return this.#v=super.createRenderRoot(),this.#v}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("click",this.#h,{capture:!0})}firstUpdated(){this.#t.value&&(this.#t.value.popover="manual",this.open&&!this.isTargetDisabled&&this.#f()),this.#r.value?.addEventListener("mouseup",this.#u),this.#t.value?.addEventListener("mousedown",this.#d),this.#t.value?.addEventListener("mouseup",this.#c)}get isTargetDisabled(){const e=this.#g&&"disabled"in this.#g&&this.#g.disabled,t=this.#g&&"true"===this.#g.ariaDisabled;return Boolean(e)||Boolean(t)}render(){return html`<div class="component" @focusout="${this.#S}" ${ref(this.#e)}><slot class="target-slot" name="target" @click="${this.#C}" @keydown="${this.#k}" @slotchange="${this.#b}" ${assertSlot([Element])} ${ref(this.#r)}></slot><slot class="default-slot" @click="${this.#y}" @focusin="${this.#D}" @keydown="${this.#k}" @mouseover="${this.#R}" @private-disabled="${this.#w}" @private-slot-change="${this.#M}" @slotchange="${this.#O}" ${assertSlot([GlideCoreMenuOptions])} ${ref(this.#t)}></slot></div>`}#A;#e;#t;#i;#o;#n;#s;#l;#m;#v;#a;#r;get#L(){return this.#T?.find((({privateActive:e})=>e))}#d;#c;#h;#u;#G(e){this.#g&&"focus"in this.#g&&this.#g?.focus(e)}#E(){this.#A?.(),this.#p&&(this.#p.ariaActivedescendant=""),this.#g&&(this.#g.ariaExpanded="false"),this.#t.value?.hidePopover()}#S(e){const t=e.relatedTarget instanceof HTMLElement&&this.#v?.contains(e.relatedTarget),i=e.relatedTarget instanceof GlideCoreMenuOptions,o=e.relatedTarget instanceof GlideCoreMenuButton||e.relatedTarget instanceof GlideCoreMenuLink;t||i||o||(this.open=!1)}#O(){this.#p&&(this.#p.privateSize=this.size)}#y(e){e.target!==this.#t.value&&(this.open=!1)}#D(e){(e.target instanceof GlideCoreMenuButton||e.target instanceof GlideCoreMenuLink)&&this.#L&&this.#p&&!e.target.disabled&&(this.#L.privateActive=!1,e.target.privateActive=!0,this.#p.ariaActivedescendant=e.target.id)}#R(e){if((e.target instanceof GlideCoreMenuLink||e.target instanceof GlideCoreMenuButton)&&!e.target.disabled){if(this.#T)for(const t of this.#T)t.privateActive=t===e.target;this.#p&&(this.#p.ariaActivedescendant=e.target.id)}}#w(){if(this.#T&&this.#L){const e=this.#T.indexOf(this.#L);this.#L.privateActive=!1;const t=this.#T?.find(((t,i)=>!t.disabled&&i>e));if(t)return void(t.privateActive=!0);const i=this.#T.findLast(((t,i)=>!t.disabled&&i<e));i&&(i.privateActive=!0)}}#M(){const e=this.#T?.find((e=>!e.disabled));!this.#L&&e&&(e.privateActive=!0)}#k(e){const t=this.#g instanceof HTMLSpanElement||this.#g instanceof HTMLDivElement;if([" ","Enter"].includes(e.key)&&this.open)return" "===e.key&&t&&e.preventDefault(),this.open=!1,this.#G(),this.#L?.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.#G();if(["ArrowUp","ArrowDown"].includes(e.key)&&!this.open&&this.#L&&this.#p)return e.preventDefault(),this.open=!0,void(this.#p.ariaActivedescendant=this.#L.id);if(this.open&&this.#L&&this.#T){const t=this.#T.indexOf(this.#L);if("ArrowUp"===e.key&&!e.metaKey){e.preventDefault();const i=this.#T.findLast(((e,i)=>!e.disabled&&i<t));return void(i&&this.#p&&(this.#L.privateActive=!1,this.#p.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowDown"===e.key&&!e.metaKey){e.preventDefault();const i=this.#T.find(((e,i)=>!e.disabled&&i>t));return void(i&&this.#p&&(this.#L.privateActive=!1,this.#p.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowUp"===e.key&&e.metaKey||"Home"===e.key||"PageUp"===e.key){e.preventDefault();const t=[...this.#T].reverse().findLast((e=>!e.disabled));return void(t&&this.#p&&(this.#L.privateActive=!1,this.#p.ariaActivedescendant=t.id,t.privateActive=!0))}if("ArrowDown"===e.key&&e.metaKey||"End"===e.key||"PageDown"===e.key){e.preventDefault();const t=[...this.#T].findLast((e=>!e.disabled));return void(t&&this.#p&&(this.#L.privateActive=!1,this.#p.ariaActivedescendant=t.id,t.privateActive=!0))}}}#b(){const e=new MutationObserver((()=>{this.open&&!this.isTargetDisabled?this.#f():this.#E()}));this.#g&&this.#p&&(e.observe(this.#g,{attributes:!0,attributeFilter:["aria-disabled","disabled"]}),this.#g.ariaHasPopup="true",this.#g.id=nanoid(),this.#g.setAttribute("aria-controls",this.#p.id),this.#p.ariaLabelledby=this.#g.id);(this.#g instanceof HTMLSpanElement||this.#g instanceof HTMLDivElement)&&this.#g instanceof HTMLElement&&(this.#g.tabIndex=0),this.open&&!this.isTargetDisabled?this.#f():this.#E()}#C(){this.isTargetDisabled?this.#E():this.#i?this.#i=!1:this.#T&&this.#T.length>0&&(this.open=!this.open)}get#p(){const e=this.#t.value?.assignedElements().at(0);return e instanceof GlideCoreMenuOptions?e:null}get#T(){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))}#f(){this.#A?.(),this.#g&&this.#t.value&&(this.#A=autoUpdate(this.#g,this.#t.value,(()=>{(async()=>{if(this.#g&&this.#t.value){const{x:e,y:t,placement:i}=await computePosition(this.#g,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.#p&&this.#L?.id&&(this.#p.ariaActivedescendant=this.#L.id),this.#g&&(this.#g.ariaExpanded="true")})()})))}get#g(){return this.#r.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),__decorate([property({reflect:!0})],GlideCoreMenu.prototype,"version",void 0),GlideCoreMenu=__decorate([customElement("glide-core-menu")],GlideCoreMenu);export default GlideCoreMenu;
1
+ var __decorate=this&&this.__decorate||function(e,t,i,o){var n,s=arguments.length,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{html,LitElement}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 packageJson from"../package.json"with{type:"json"};import GlideCoreMenuButton from"./menu.button.js";import GlideCoreMenuLink from"./menu.link.js";import GlideCoreMenuOptions from"./menu.options.js";import assertSlot from"./library/assert-slot.js";import styles from"./menu.styles.js";import shadowRootMode from"./library/shadow-root-mode.js";import final from"./library/final.js";let GlideCoreMenu=class GlideCoreMenu extends LitElement{constructor(){super(...arguments),this.placement="bottom-start",this.version=packageJson.version,this.#e=createRef(),this.#t=createRef(),this.#i=!1,this.#o=!1,this.#n=!1,this.#s=!1,this.#l=!1,this.#a="large",this.#r=createRef(),this.#d=e=>{e.target===this.#t.value&&e.preventDefault()},this.#h=e=>{if(e.target===this.#t.value&&(this.#o=!0),e.target instanceof Element){const t=e.target?.closest("glide-core-menu-link");t?.disabled&&(this.#n=!0)}},this.#c=()=>{this.#o?this.#o=!1:this.#n?this.#n=!1:this.#l?this.#l=!1:(this.open=!1,this.#p&&(this.#p.ariaActivedescendant=""))},this.#u=()=>{this.#l=!0}}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}get offset(){return this.#m??Number.parseFloat(window.getComputedStyle(document.body).getPropertyValue("--glide-core-spacing-xxs"))*Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize)}set offset(e){this.#m=e}get open(){return this.#s}set open(e){const t=e!==this.#s;this.#s=e,e&&t&&!this.isTargetDisabled?(this.#f(),this.dispatchEvent(new Event("toggle",{bubbles:!0,composed:!0}))):t&&(this.#E(),this.dispatchEvent(new Event("toggle",{bubbles:!0,composed:!0})))}get size(){return this.#a}set size(e){this.#a=e,this.#p&&(this.#p.privateSize=e)}connectedCallback(){super.connectedCallback(),document.addEventListener("click",this.#c,{capture:!0})}createRenderRoot(){return this.#v=super.createRenderRoot(),this.#v}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("click",this.#c,{capture:!0})}firstUpdated(){this.#t.value&&(this.#t.value.popover="manual",this.open&&!this.isTargetDisabled&&this.#f()),this.#r.value?.addEventListener("mouseup",this.#u),this.#t.value?.addEventListener("mousedown",this.#d),this.#t.value?.addEventListener("mouseup",this.#h)}get isTargetDisabled(){const e=this.#g&&"disabled"in this.#g&&this.#g.disabled,t=this.#g&&"true"===this.#g.ariaDisabled;return Boolean(e)||Boolean(t)}render(){return html`<div class="component" @focusout="${this.#S}" ${ref(this.#e)}><slot class="target-slot" name="target" @click="${this.#C}" @keydown="${this.#b}" @slotchange="${this.#k}" ${assertSlot([Element])} ${ref(this.#r)}></slot><slot class="default-slot" @click="${this.#y}" @focusin="${this.#D}" @keydown="${this.#b}" @mouseover="${this.#w}" @private-disabled="${this.#R}" @private-slot-change="${this.#M}" @slotchange="${this.#O}" ${assertSlot([GlideCoreMenuOptions])} ${ref(this.#t)}></slot></div>`}#A;#e;#t;#i;#o;#n;#s;#l;#m;#v;#a;#r;get#T(){return this.#L?.find((({privateActive:e})=>e))}#d;#h;#c;#u;#G(e){this.#g&&"focus"in this.#g&&this.#g?.focus(e)}#E(){this.#A?.(),this.#p&&(this.#p.ariaActivedescendant=""),this.#g&&(this.#g.ariaExpanded="false"),this.#t.value?.hidePopover()}#S(e){const t=e.relatedTarget instanceof HTMLElement&&this.#v?.contains(e.relatedTarget),i=e.relatedTarget instanceof GlideCoreMenuOptions,o=e.relatedTarget instanceof GlideCoreMenuButton||e.relatedTarget instanceof GlideCoreMenuLink;t||i||o||(this.open=!1)}#O(){this.#p&&(this.#p.privateSize=this.size)}#y(e){e.target!==this.#t.value&&(this.open=!1)}#D(e){(e.target instanceof GlideCoreMenuButton||e.target instanceof GlideCoreMenuLink)&&this.#T&&this.#p&&!e.target.disabled&&(this.#T.privateActive=!1,e.target.privateActive=!0,this.#p.ariaActivedescendant=e.target.id)}#w(e){if((e.target instanceof GlideCoreMenuLink||e.target instanceof GlideCoreMenuButton)&&!e.target.disabled){if(this.#L)for(const t of this.#L)t.privateActive=t===e.target;this.#p&&(this.#p.ariaActivedescendant=e.target.id)}}#R(){if(this.#L&&this.#T){const e=this.#L.indexOf(this.#T);this.#T.privateActive=!1;const t=this.#L?.find(((t,i)=>!t.disabled&&i>e));if(t)return void(t.privateActive=!0);const i=this.#L.findLast(((t,i)=>!t.disabled&&i<e));i&&(i.privateActive=!0)}}#M(){const e=this.#L?.find((e=>!e.disabled));!this.#T&&e&&(e.privateActive=!0)}#b(e){const t=this.#g instanceof HTMLSpanElement||this.#g instanceof HTMLDivElement;if([" ","Enter"].includes(e.key)&&this.open)return" "===e.key&&t&&e.preventDefault(),this.open=!1,this.#G(),this.#T?.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.#G();if(["ArrowUp","ArrowDown"].includes(e.key)&&!this.open&&this.#T&&this.#p)return e.preventDefault(),this.open=!0,void(this.#p.ariaActivedescendant=this.#T.id);if(this.open&&this.#T&&this.#L){const t=this.#L.indexOf(this.#T);if("ArrowUp"===e.key&&!e.metaKey){e.preventDefault();const i=this.#L.findLast(((e,i)=>!e.disabled&&i<t));return void(i&&this.#p&&(this.#T.privateActive=!1,this.#p.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowDown"===e.key&&!e.metaKey){e.preventDefault();const i=this.#L.find(((e,i)=>!e.disabled&&i>t));return void(i&&this.#p&&(this.#T.privateActive=!1,this.#p.ariaActivedescendant=i.id,i.privateActive=!0))}if("ArrowUp"===e.key&&e.metaKey||"Home"===e.key||"PageUp"===e.key){e.preventDefault();const t=[...this.#L].reverse().findLast((e=>!e.disabled));return void(t&&this.#p&&(this.#T.privateActive=!1,this.#p.ariaActivedescendant=t.id,t.privateActive=!0))}if("ArrowDown"===e.key&&e.metaKey||"End"===e.key||"PageDown"===e.key){e.preventDefault();const t=[...this.#L].findLast((e=>!e.disabled));return void(t&&this.#p&&(this.#T.privateActive=!1,this.#p.ariaActivedescendant=t.id,t.privateActive=!0))}}}#k(){const e=new MutationObserver((()=>{this.open&&!this.isTargetDisabled?this.#f():this.#E()}));this.#g&&this.#p&&(e.observe(this.#g,{attributes:!0,attributeFilter:["aria-disabled","disabled"]}),this.#g.ariaHasPopup="true",this.#g.id=nanoid(),this.#g.setAttribute("aria-controls",this.#p.id),this.#p.ariaLabelledby=this.#g.id);(this.#g instanceof HTMLSpanElement||this.#g instanceof HTMLDivElement)&&this.#g instanceof HTMLElement&&(this.#g.tabIndex=0),this.open&&!this.isTargetDisabled?this.#f():this.#E()}#C(){this.isTargetDisabled?this.#E():this.#i?this.#i=!1:this.#L&&this.#L.length>0&&(this.open=!this.open)}get#p(){const e=this.#t.value?.assignedElements().at(0);return e instanceof GlideCoreMenuOptions?e:null}get#L(){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))}#f(){this.#A?.(),this.#g&&this.#t.value&&(this.#A=autoUpdate(this.#g,this.#t.value,(()=>{(async()=>{if(this.#g&&this.#t.value){const{x:e,y:t,placement:i}=await computePosition(this.#g,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.#p&&this.#T?.id&&(this.#p.ariaActivedescendant=this.#T.id),this.#g&&(this.#g.ariaExpanded="true")})()})))}get#g(){return this.#r.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),__decorate([property({reflect:!0})],GlideCoreMenu.prototype,"version",void 0),GlideCoreMenu=__decorate([customElement("glide-core-menu"),final],GlideCoreMenu);export default GlideCoreMenu;
@@ -5,12 +5,22 @@ declare global {
5
5
  }
6
6
  }
7
7
  /**
8
- * @slot icon - An optional icon.
8
+ * @attr {string} label
9
+ * @attr {boolean} [disabled=false]
10
+ * @attr {string} [url]
11
+ *
12
+ * @readonly
13
+ * @attr {0.19.5} [version]
14
+ *
15
+ * @slot {Element} [icon]
9
16
  */
10
17
  export default class GlideCoreMenuLink extends LitElement {
11
18
  #private;
12
19
  static shadowRootOptions: ShadowRootInit;
13
20
  static styles: import("lit").CSSResult[];
21
+ /**
22
+ * @default false
23
+ */
14
24
  get disabled(): boolean;
15
25
  set disabled(isDisabled: boolean);
16
26
  label?: string;
package/dist/menu.link.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,i,o){var r,s=arguments.length,n=s<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,i,o);else for(var l=e.length-1;l>=0;l--)(r=e[l])&&(n=(s<3?r(n):s>3?r(t,i,n):r(t,i))||n);return s>3&&n&&Object.defineProperty(t,i,n),n};import{html,LitElement}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{nanoid}from"nanoid";import packageJson from"../package.json"with{type:"json"};import styles from"./menu.link.styles.js";import shadowRootMode from"./library/shadow-root-mode.js";let GlideCoreMenuLink=class GlideCoreMenuLink extends LitElement{constructor(){super(...arguments),this.privateActive=!1,this.version=packageJson.version,this.#e=createRef(),this.#t=nanoid(),this.#i=!1}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}get disabled(){return this.#i}set disabled(e){this.#i=e,e&&this.privateActive&&this.dispatchEvent(new Event("private-disabled",{bubbles:!0}))}click(){this.disabled||this.#e.value?.click()}connectedCallback(){super.connectedCallback(),this.id=this.#t,this.role="menuitem",this.tabIndex=-1}render(){return html`<a class="${classMap({component:!0,active:this.privateActive,disabled:this.disabled})}" data-test="component" href="${ifDefined(this.url)}" @click="${this.#o}" ${ref(this.#e)}><slot name="icon"></slot>${this.label}</a>`}#e;#t;#i;#o(e){this.disabled&&(e.preventDefault(),e.stopPropagation())}};__decorate([property({reflect:!0,type:Boolean})],GlideCoreMenuLink.prototype,"disabled",null),__decorate([property({reflect:!0})],GlideCoreMenuLink.prototype,"label",void 0),__decorate([property({reflect:!0})],GlideCoreMenuLink.prototype,"url",void 0),__decorate([property({type:Boolean})],GlideCoreMenuLink.prototype,"privateActive",void 0),__decorate([property({reflect:!0})],GlideCoreMenuLink.prototype,"version",void 0),GlideCoreMenuLink=__decorate([customElement("glide-core-menu-link")],GlideCoreMenuLink);export default GlideCoreMenuLink;
1
+ var __decorate=this&&this.__decorate||function(e,t,i,o){var r,s=arguments.length,n=s<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,i,o);else for(var l=e.length-1;l>=0;l--)(r=e[l])&&(n=(s<3?r(n):s>3?r(t,i,n):r(t,i))||n);return s>3&&n&&Object.defineProperty(t,i,n),n};import{html,LitElement}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{nanoid}from"nanoid";import packageJson from"../package.json"with{type:"json"};import styles from"./menu.link.styles.js";import shadowRootMode from"./library/shadow-root-mode.js";import final from"./library/final.js";import required from"./library/required.js";let GlideCoreMenuLink=class GlideCoreMenuLink extends LitElement{constructor(){super(...arguments),this.privateActive=!1,this.version=packageJson.version,this.#e=createRef(),this.#t=nanoid(),this.#i=!1}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}get disabled(){return this.#i}set disabled(e){this.#i=e,e&&this.privateActive&&this.dispatchEvent(new Event("private-disabled",{bubbles:!0}))}click(){this.disabled||this.#e.value?.click()}connectedCallback(){super.connectedCallback(),this.id=this.#t,this.role="menuitem",this.tabIndex=-1}render(){return html`<a class="${classMap({component:!0,active:this.privateActive,disabled:this.disabled})}" data-test="component" href="${ifDefined(this.url)}" @click="${this.#o}" ${ref(this.#e)}><slot name="icon"></slot>${this.label}</a>`}#e;#t;#i;#o(e){this.disabled&&(e.preventDefault(),e.stopPropagation())}};__decorate([property({reflect:!0,type:Boolean})],GlideCoreMenuLink.prototype,"disabled",null),__decorate([property({reflect:!0}),required],GlideCoreMenuLink.prototype,"label",void 0),__decorate([property({reflect:!0})],GlideCoreMenuLink.prototype,"url",void 0),__decorate([property({type:Boolean})],GlideCoreMenuLink.prototype,"privateActive",void 0),__decorate([property({reflect:!0})],GlideCoreMenuLink.prototype,"version",void 0),GlideCoreMenuLink=__decorate([customElement("glide-core-menu-link"),final],GlideCoreMenuLink);export default GlideCoreMenuLink;
@@ -7,10 +7,10 @@ import{css}from"lit";export default[css`
7
7
  box-sizing: border-box;
8
8
  display: flex;
9
9
  font: inherit;
10
- gap: var(--gap);
10
+ gap: var(--private-gap);
11
11
  inline-size: 100%;
12
- padding-block: var(--padding-block);
13
- padding-inline: var(--padding-inline);
12
+ padding-block: var(--private-padding-block);
13
+ padding-inline: var(--private-padding-inline);
14
14
  text-decoration: none;
15
15
  transition: background-color 100ms ease-in-out;
16
16
  user-select: none;