@crowdstrike/glide-core 0.29.2 → 0.30.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 (122) hide show
  1. package/dist/accordion.js +240 -1
  2. package/dist/accordion.styles.js +13 -7
  3. package/dist/button-group.button.js +143 -1
  4. package/dist/button-group.button.styles.js +43 -15
  5. package/dist/button-group.js +249 -1
  6. package/dist/button-group.styles.js +10 -5
  7. package/dist/button.js +206 -1
  8. package/dist/button.styles.js +12 -7
  9. package/dist/checkbox-group.js +479 -14
  10. package/dist/checkbox-group.styles.js +5 -2
  11. package/dist/checkbox.js +519 -32
  12. package/dist/checkbox.styles.js +10 -5
  13. package/dist/drawer.js +168 -1
  14. package/dist/drawer.styles.js +5 -2
  15. package/dist/dropdown.js +2423 -123
  16. package/dist/dropdown.option.js +536 -1
  17. package/dist/dropdown.option.styles.js +5 -2
  18. package/dist/dropdown.styles.js +14 -7
  19. package/dist/form-controls-layout.js +102 -1
  20. package/dist/form-controls-layout.styles.js +5 -2
  21. package/dist/icon-button.js +139 -1
  22. package/dist/icon-button.styles.js +19 -7
  23. package/dist/icons/checked.js +28 -1
  24. package/dist/icons/chevron.js +21 -1
  25. package/dist/icons/magnifying-glass.js +23 -1
  26. package/dist/icons/pencil.js +21 -1
  27. package/dist/icons/severity-critical.js +20 -1
  28. package/dist/icons/severity-informational.js +20 -1
  29. package/dist/icons/severity-medium.js +20 -1
  30. package/dist/icons/x.js +21 -1
  31. package/dist/inline-alert.js +118 -1
  32. package/dist/inline-alert.styles.js +5 -2
  33. package/dist/input.d.ts +8 -2
  34. package/dist/input.js +505 -41
  35. package/dist/input.styles.js +25 -4
  36. package/dist/label.js +303 -1
  37. package/dist/label.styles.js +11 -5
  38. package/dist/library/assert-slot.js +136 -1
  39. package/dist/library/expect-unhandled-rejection.js +14 -1
  40. package/dist/library/expect-window-error.js +26 -1
  41. package/dist/library/final.js +18 -1
  42. package/dist/library/form-control.js +1 -1
  43. package/dist/library/localize.js +10 -1
  44. package/dist/library/mouse.js +35 -1
  45. package/dist/library/on-resize.js +24 -1
  46. package/dist/library/required.js +35 -1
  47. package/dist/library/shadow-root-mode.js +4 -1
  48. package/dist/library/unique-id.js +3 -1
  49. package/dist/link.js +92 -1
  50. package/dist/link.styles.js +10 -5
  51. package/dist/menu.d.ts +3 -2
  52. package/dist/menu.js +1259 -1
  53. package/dist/menu.styles.js +34 -17
  54. package/dist/modal.d.ts +4 -0
  55. package/dist/modal.icon-button.js +60 -1
  56. package/dist/modal.icon-button.styles.js +5 -2
  57. package/dist/modal.js +473 -1
  58. package/dist/modal.styles.js +71 -22
  59. package/dist/option.d.ts +74 -0
  60. package/dist/option.js +498 -0
  61. package/dist/option.styles.js +140 -0
  62. package/dist/{menu.options.d.ts → options.d.ts} +5 -6
  63. package/dist/options.js +130 -0
  64. package/dist/options.styles.js +21 -0
  65. package/dist/popover.js +620 -1
  66. package/dist/popover.styles.js +11 -5
  67. package/dist/radio-group.js +624 -17
  68. package/dist/radio-group.radio.js +211 -1
  69. package/dist/radio-group.radio.styles.js +9 -4
  70. package/dist/radio-group.styles.js +5 -2
  71. package/dist/slider.js +1040 -61
  72. package/dist/slider.styles.js +9 -4
  73. package/dist/spinner.js +60 -1
  74. package/dist/spinner.styles.js +5 -2
  75. package/dist/split-button.js +116 -1
  76. package/dist/split-button.primary-button.js +100 -1
  77. package/dist/split-button.primary-button.styles.js +13 -6
  78. package/dist/split-button.primary-link.js +102 -1
  79. package/dist/split-button.secondary-button.d.ts +2 -3
  80. package/dist/split-button.secondary-button.js +121 -1
  81. package/dist/split-button.secondary-button.styles.js +12 -7
  82. package/dist/split-button.styles.js +9 -4
  83. package/dist/styles/focus-outline.js +9 -3
  84. package/dist/styles/fonts.css +6 -1
  85. package/dist/styles/opacity-and-scale-animation.js +6 -3
  86. package/dist/styles/skeleton.js +6 -3
  87. package/dist/styles/variables.css +410 -1
  88. package/dist/styles/visually-hidden.js +6 -3
  89. package/dist/tab.group.js +386 -1
  90. package/dist/tab.group.styles.js +5 -2
  91. package/dist/tab.js +133 -1
  92. package/dist/tab.panel.js +93 -1
  93. package/dist/tab.panel.styles.js +11 -5
  94. package/dist/tab.styles.js +9 -4
  95. package/dist/tag.js +207 -1
  96. package/dist/tag.styles.js +10 -5
  97. package/dist/textarea.js +353 -19
  98. package/dist/textarea.styles.js +23 -4
  99. package/dist/toast.js +130 -1
  100. package/dist/toast.toasts.js +248 -25
  101. package/dist/toast.toasts.styles.js +9 -4
  102. package/dist/toggle.js +178 -1
  103. package/dist/toggle.styles.js +25 -5
  104. package/dist/tooltip.container.js +130 -1
  105. package/dist/tooltip.container.styles.js +5 -2
  106. package/dist/tooltip.js +484 -1
  107. package/dist/tooltip.styles.js +21 -5
  108. package/dist/translations/en.js +36 -1
  109. package/dist/translations/fr.js +37 -1
  110. package/dist/translations/ja.js +37 -1
  111. package/package.json +8 -12
  112. package/dist/menu.button.d.ts +0 -42
  113. package/dist/menu.button.js +0 -1
  114. package/dist/menu.button.styles.js +0 -32
  115. package/dist/menu.link.d.ts +0 -44
  116. package/dist/menu.link.js +0 -1
  117. package/dist/menu.link.styles.js +0 -35
  118. package/dist/menu.options.js +0 -1
  119. package/dist/menu.options.styles.d.ts +0 -2
  120. package/dist/menu.options.styles.js +0 -20
  121. /package/dist/{menu.button.styles.d.ts → option.styles.d.ts} +0 -0
  122. /package/dist/{menu.link.styles.d.ts → options.styles.d.ts} +0 -0
@@ -1,6 +1,10 @@
1
- import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
2
- ${visuallyHidden(".character-count .hidden")}
3
- `,css`
1
+ import { css } from 'lit';
2
+ import visuallyHidden from './styles/visually-hidden.js';
3
+ export default [
4
+ css `
5
+ ${visuallyHidden('.character-count .hidden')}
6
+ `,
7
+ css `
4
8
  .meta {
5
9
  column-gap: var(--glide-core-spacing-base-xs);
6
10
  display: flex;
@@ -118,6 +122,22 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
118
122
  outline: 2px solid var(--glide-core-color-interactive-stroke-focus);
119
123
  }
120
124
  }
125
+
126
+ &[type='color']::-webkit-color-swatch {
127
+ border: none;
128
+ border-radius: var(--glide-core-rounding-base-radius-xxs);
129
+ }
130
+
131
+ /*
132
+ Unfortunately Firefox requires a different selector. It also
133
+ sets the element to 100% height of its container, so we set
134
+ a fixed block-size to match the other browsers.
135
+ */
136
+ &[type='color']::-moz-color-swatch {
137
+ block-size: 1.5rem;
138
+ border: none;
139
+ border-radius: var(--glide-core-rounding-base-radius-xxs);
140
+ }
121
141
  }
122
142
 
123
143
  .suffix-icon {
@@ -152,4 +172,5 @@ import{css}from"lit";import visuallyHidden from"./styles/visually-hidden.js";exp
152
172
  .empty .clear-icon-button {
153
173
  visibility: hidden;
154
174
  }
155
- `];
175
+ `,
176
+ ];
package/dist/label.js CHANGED
@@ -1 +1,303 @@
1
- var __decorate=this&&this.__decorate||function(t,e,o,i){var l,r=arguments.length,s=r<3?e:null===i?i=Object.getOwnPropertyDescriptor(e,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,o,i);else for(var a=t.length-1;a>=0;a--)(l=t[a])&&(s=(r<3?l(s):r>3?l(e,o,s):l(e,o))||s);return r>3&&s&&Object.defineProperty(e,o,s),s};import"./tooltip.js";import{html,LitElement}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{styleMap}from"lit/directives/style-map.js";import{ifDefined}from"lit/directives/if-defined.js";import{when}from"lit/directives/when.js";import styles from"./label.styles.js";import{LocalizeController}from"./library/localize.js";import assertSlot from"./library/assert-slot.js";import onResize from"./library/on-resize.js";import shadowRootMode from"./library/shadow-root-mode.js";import final from"./library/final.js";let Label=class Label extends LitElement{constructor(){super(...arguments),this.disabled=!1,this.error=!1,this.hide=!1,this.orientation="horizontal",this.required=!1,this.hasDescription=!1,this.hasSummarySlot=!1,this.isLabelTooltip=!1,this.#t=createRef(),this.#e=createRef(),this.#o=createRef(),this.#i=new LocalizeController(this),this.#l=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}render(){return html`<div class="${classMap({component:!0,horizontal:"horizontal"===this.orientation,vertical:"vertical"===this.orientation,left:"left"===this.split,middle:"middle"===this.split,right:"right"===this.split,"hidden-label":this.hide})}"><div class="${classMap({tooltips:!0,hidden:this.hide,left:"left"===this.split,middle:"middle"===this.split,right:"right"===this.split,vertical:"vertical"===this.orientation})}" part="private-tooltips">${when(this.tooltip,(()=>html`<glide-core-tooltip class="${classMap({"optional-tooltip":!0,vertical:"vertical"===this.orientation,visible:!!this.tooltip})}" label="${ifDefined(this.tooltip)}" placement="${"vertical"===this.orientation?"right":"bottom"}"><button aria-label="${this.#i.term("tooltip")}" class="optional-tooltip-target" slot="target" type="button">${icons.information}</button></glide-core-tooltip>`))}<glide-core-tooltip class="label-tooltip" data-test="label-tooltip" label="${this.label??""}" placement="right" ?disabled="${!this.isLabelTooltip}" screenreader-hidden><div class="${classMap({label:!0,disabled:this.disabled})}" data-test="label" slot="target" @mouseover="${this.#r}" ${ref(this.#o)}><slot ${assertSlot()} ${ref(this.#t)}></slot></div></glide-core-tooltip>${this.required?html`<span aria-hidden="true" class="required-symbol" data-test="required-symbol">*</span>`:""}</div><div class="control-and-summary" part="private-control-and-summary"><slot class="${classMap({control:!0,error:this.error,disabled:this.disabled,vertical:"vertical"===this.orientation,summaryless:!this.hasSummarySlot,"hidden-label":this.hide})}" name="control" ${assertSlot()}></slot><slot class="${classMap({summary:!0,error:this.error})}" name="summary" @slotchange="${this.#s}" ${ref(this.#l)}></slot></div><slot class="${classMap({description:!0,content:this.hasDescription,error:this.error,tooltip:!!this.tooltip})}" id="description" name="description" ${onResize(this.#a.bind(this))} ${ref(this.#e)}></slot></div>`}#t;#e;#o;#i;#l;#a(){this.hasDescription=Boolean(this.#e.value&&this.#e.value.offsetHeight>0)}#r(){const t=this.#t.value?.assignedElements().at(0);t&&this.#o.value&&(this.isLabelTooltip=t.getBoundingClientRect().width>this.#o.value.getBoundingClientRect().width)}#s(){const t=this.#l.value?.assignedNodes({flatten:!0});this.hasSummarySlot=Boolean(t&&t.length>0)}};__decorate([property({reflect:!0,type:Boolean})],Label.prototype,"disabled",void 0),__decorate([property({reflect:!0,type:Boolean})],Label.prototype,"error",void 0),__decorate([property({reflect:!0,type:Boolean})],Label.prototype,"hide",void 0),__decorate([property({reflect:!0,useDefault:!0})],Label.prototype,"orientation",void 0),__decorate([property({reflect:!0,type:Boolean})],Label.prototype,"required",void 0),__decorate([property()],Label.prototype,"split",void 0),__decorate([property()],Label.prototype,"tooltip",void 0),__decorate([property()],Label.prototype,"label",void 0),__decorate([state()],Label.prototype,"hasDescription",void 0),__decorate([state()],Label.prototype,"hasSummarySlot",void 0),__decorate([state()],Label.prototype,"isLabelTooltip",void 0),Label=__decorate([customElement("glide-core-private-label"),final],Label);export default Label;const icons={information:html`<svg aria-hidden="true" style="${styleMap({height:"1rem",width:"1rem"})}" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/><path d="M12 16L12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><circle cx="12" cy="8" r="1" fill="currentColor"/></svg>`};
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 './tooltip.js';
8
+ import { html, LitElement } from 'lit';
9
+ import { classMap } from 'lit/directives/class-map.js';
10
+ import { createRef, ref } from 'lit/directives/ref.js';
11
+ import { customElement, property, state } from 'lit/decorators.js';
12
+ import { styleMap } from 'lit/directives/style-map.js';
13
+ import { ifDefined } from 'lit/directives/if-defined.js';
14
+ import { when } from 'lit/directives/when.js';
15
+ import styles from './label.styles.js';
16
+ import { LocalizeController } from './library/localize.js';
17
+ import assertSlot from './library/assert-slot.js';
18
+ import onResize from './library/on-resize.js';
19
+ import shadowRootMode from './library/shadow-root-mode.js';
20
+ import final from './library/final.js';
21
+ /**
22
+ * @attr {boolean} [disabled=false]
23
+ * @attr {boolean} [error=false]
24
+ * @attr {boolean} [hide=false]
25
+ * @attr {string} [label]
26
+ * @attr {'horizontal'|'vertical'} [orientation='horizontal']
27
+ * @attr {boolean} [required=false]
28
+ * @attr {'left'|'middle'|'right'} [split]
29
+ * @attr {string} [tooltip]
30
+ *
31
+ * @slot {HTMLLabelElement}
32
+ * @slot {Element} [control] - The element with which the label is associated
33
+ * @slot {Element | string} [description] - Additional information or context
34
+ * @slot {Element | string} [summary] - Additional information or context
35
+ */
36
+ let Label = class Label extends LitElement {
37
+ constructor() {
38
+ super(...arguments);
39
+ this.disabled = false;
40
+ this.error = false;
41
+ this.hide = false;
42
+ this.orientation = 'horizontal';
43
+ this.required = false;
44
+ this.hasDescription = false;
45
+ this.hasSummarySlot = false;
46
+ this.isLabelTooltip = false;
47
+ this.#defaultSlotElementRef = createRef();
48
+ this.#descriptionSlotElementRef = createRef();
49
+ this.#labelElementRef = createRef();
50
+ this.#localize = new LocalizeController(this);
51
+ this.#summarySlotElementRef = createRef();
52
+ }
53
+ static { this.shadowRootOptions = {
54
+ ...LitElement.shadowRootOptions,
55
+ mode: shadowRootMode,
56
+ }; }
57
+ static { this.styles = styles; }
58
+ render() {
59
+ // `aria-hidden` is used on the tooltip so the contents of the label aren't
60
+ // read twice to screen readers. The label is truncated using CSS. So the full
61
+ // text of the label is always available to them.
62
+ // Lit-a11y doesn't know that we're only using a "mouseover" event to hide and
63
+ // show Tooltip, which is hidden from screenreaders because the truncated text
64
+ // is available to them without a tooltip.
65
+ //
66
+ /* eslint-disable lit-a11y/mouse-events-have-key-events */
67
+ return html `<div
68
+ class=${classMap({
69
+ component: true,
70
+ horizontal: this.orientation === 'horizontal',
71
+ vertical: this.orientation === 'vertical',
72
+ left: this.split === 'left',
73
+ middle: this.split === 'middle',
74
+ right: this.split === 'right',
75
+ 'hidden-label': this.hide,
76
+ })}
77
+ >
78
+ <div
79
+ class=${classMap({
80
+ tooltips: true,
81
+ hidden: this.hide,
82
+ left: this.split === 'left',
83
+ middle: this.split === 'middle',
84
+ right: this.split === 'right',
85
+ vertical: this.orientation === 'vertical',
86
+ })}
87
+ part="private-tooltips"
88
+ >
89
+ ${when(this.tooltip, () => html `<glide-core-tooltip
90
+ class=${classMap({
91
+ 'optional-tooltip': true,
92
+ vertical: this.orientation === 'vertical',
93
+ visible: this.tooltip ? true : false,
94
+ })}
95
+ label=${ifDefined(this.tooltip)}
96
+ placement=${this.orientation === 'vertical' ? 'right' : 'bottom'}
97
+ >
98
+ <button
99
+ aria-label=${this.#localize.term('tooltip')}
100
+ class="optional-tooltip-target"
101
+ slot="target"
102
+ type="button"
103
+ >
104
+ ${icons.information}
105
+ </button>
106
+ </glide-core-tooltip>`)}
107
+
108
+ <glide-core-tooltip
109
+ class="label-tooltip"
110
+ data-test="label-tooltip"
111
+ label=${this.label ?? ''}
112
+ placement="right"
113
+ ?disabled=${!this.isLabelTooltip}
114
+ screenreader-hidden
115
+ >
116
+ <div
117
+ class=${classMap({
118
+ label: true,
119
+ disabled: this.disabled,
120
+ })}
121
+ data-test="label"
122
+ slot="target"
123
+ @mouseover=${this.#onLabelMouseOver}
124
+ ${ref(this.#labelElementRef)}
125
+ >
126
+ <slot ${assertSlot()} ${ref(this.#defaultSlotElementRef)}>
127
+ <!-- @type {HTMLLabelElement} -->
128
+ </slot>
129
+ </div>
130
+ </glide-core-tooltip>
131
+
132
+ ${this.required
133
+ ? html `<span
134
+ aria-hidden="true"
135
+ class="required-symbol"
136
+ data-test="required-symbol"
137
+ >
138
+ *
139
+ </span>`
140
+ : ''}
141
+ </div>
142
+
143
+ <div class="control-and-summary" part="private-control-and-summary">
144
+ <slot
145
+ class=${classMap({
146
+ control: true,
147
+ error: this.error,
148
+ disabled: this.disabled,
149
+ vertical: this.orientation === 'vertical',
150
+ summaryless: !this.hasSummarySlot,
151
+ 'hidden-label': this.hide,
152
+ })}
153
+ name="control"
154
+ ${assertSlot()}
155
+ >
156
+ <!--
157
+ The element with which the label is associated
158
+ @type {Element}
159
+ -->
160
+ </slot>
161
+
162
+ <slot
163
+ class=${classMap({
164
+ summary: true,
165
+ error: this.error,
166
+ })}
167
+ name="summary"
168
+ @slotchange=${this.#onSummarySlotChange}
169
+ ${ref(this.#summarySlotElementRef)}
170
+ >
171
+ <!--
172
+ Additional information or context
173
+ @type {Element | string}
174
+ -->
175
+ </slot>
176
+ </div>
177
+
178
+ <slot
179
+ class=${classMap({
180
+ description: true,
181
+ content: this.hasDescription,
182
+ error: this.error,
183
+ tooltip: this.tooltip ? true : false,
184
+ })}
185
+ id="description"
186
+ name="description"
187
+ ${onResize(this.#onDescriptionSlotResize.bind(this))}
188
+ ${ref(this.#descriptionSlotElementRef)}
189
+ >
190
+ <!--
191
+ Additional information or context
192
+ @type {Element | string}
193
+ -->
194
+ </slot>
195
+ </div>`;
196
+ }
197
+ #defaultSlotElementRef;
198
+ #descriptionSlotElementRef;
199
+ #labelElementRef;
200
+ #localize;
201
+ #summarySlotElementRef;
202
+ #onDescriptionSlotResize() {
203
+ // The "description" slot has a top margin that needs to be conditionally
204
+ // applied only if content is slotted so there's not stray whitespace
205
+ // when there's no description.
206
+ //
207
+ // Normally, we'd listen for "slotchange" and set `this.hasDescription`
208
+ // in the event handler. But form controls always slot content. We need
209
+ // to know if any text has been slotted instead.
210
+ //
211
+ // A Resize Observer is the best proxy for that. If the slot has a height,
212
+ // then we know it has text.
213
+ this.hasDescription = Boolean(this.#descriptionSlotElementRef.value &&
214
+ this.#descriptionSlotElementRef.value.offsetHeight > 0);
215
+ }
216
+ #onLabelMouseOver() {
217
+ const defaultSlotAssignedElement = this.#defaultSlotElementRef.value
218
+ ?.assignedElements()
219
+ .at(0);
220
+ if (defaultSlotAssignedElement && this.#labelElementRef.value) {
221
+ // `getBoundingClientRect()` is used so we're comparing apples to apples.
222
+ //
223
+ // `clientWidth` on `defaultSlotAssignedElement` is zero if the element is
224
+ // `display: inline`. The label, on the other hand, isn't inline.
225
+ //
226
+ // But `clientWidth` returns an integer and `getBoundingClientRect().width`
227
+ // return a float. So using `clientWidth` with `#labelElementRef.value` would
228
+ // mean the width of `defaultSlotAssignedElement` is always fractionally
229
+ // greater than that of `#labelElementRef.value`.
230
+ this.isLabelTooltip =
231
+ defaultSlotAssignedElement.getBoundingClientRect().width >
232
+ this.#labelElementRef.value.getBoundingClientRect().width;
233
+ }
234
+ }
235
+ #onSummarySlotChange() {
236
+ const assignedNodes = this.#summarySlotElementRef.value?.assignedNodes({
237
+ flatten: true,
238
+ });
239
+ this.hasSummarySlot = Boolean(assignedNodes && assignedNodes.length > 0);
240
+ }
241
+ };
242
+ __decorate([
243
+ property({ reflect: true, type: Boolean })
244
+ ], Label.prototype, "disabled", void 0);
245
+ __decorate([
246
+ property({ reflect: true, type: Boolean })
247
+ ], Label.prototype, "error", void 0);
248
+ __decorate([
249
+ property({ reflect: true, type: Boolean })
250
+ ], Label.prototype, "hide", void 0);
251
+ __decorate([
252
+ property({ reflect: true, useDefault: true })
253
+ ], Label.prototype, "orientation", void 0);
254
+ __decorate([
255
+ property({ reflect: true, type: Boolean })
256
+ ], Label.prototype, "required", void 0);
257
+ __decorate([
258
+ property()
259
+ ], Label.prototype, "split", void 0);
260
+ __decorate([
261
+ property()
262
+ ], Label.prototype, "tooltip", void 0);
263
+ __decorate([
264
+ property()
265
+ ], Label.prototype, "label", void 0);
266
+ __decorate([
267
+ state()
268
+ ], Label.prototype, "hasDescription", void 0);
269
+ __decorate([
270
+ state()
271
+ ], Label.prototype, "hasSummarySlot", void 0);
272
+ __decorate([
273
+ state()
274
+ ], Label.prototype, "isLabelTooltip", void 0);
275
+ Label = __decorate([
276
+ customElement('glide-core-private-label'),
277
+ final
278
+ ], Label);
279
+ export default Label;
280
+ const icons = {
281
+ information: html `
282
+ <svg
283
+ aria-hidden="true"
284
+ style=${styleMap({
285
+ height: '1rem',
286
+ width: '1rem',
287
+ })}
288
+ viewBox="0 0 24 24"
289
+ fill="none"
290
+ >
291
+ <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" />
292
+
293
+ <path
294
+ d="M12 16L12 12"
295
+ stroke="currentColor"
296
+ stroke-width="2"
297
+ stroke-linecap="round"
298
+ />
299
+
300
+ <circle cx="12" cy="8" r="1" fill="currentColor" />
301
+ </svg>
302
+ `,
303
+ };
@@ -1,7 +1,12 @@
1
- import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
2
- ${focusOutline(".optional-tooltip-target:focus-visible ")}
3
- ${visuallyHidden(".tooltips.hidden")}
4
- `,css`
1
+ import { css } from 'lit';
2
+ import focusOutline from './styles/focus-outline.js';
3
+ import visuallyHidden from './styles/visually-hidden.js';
4
+ export default [
5
+ css `
6
+ ${focusOutline('.optional-tooltip-target:focus-visible ')}
7
+ ${visuallyHidden('.tooltips.hidden')}
8
+ `,
9
+ css `
5
10
  .component {
6
11
  &.horizontal {
7
12
  --private-column-gap: var(--glide-core-spacing-base-sm);
@@ -184,4 +189,5 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
184
189
  color: var(--glide-core-color-advisory-text-error);
185
190
  }
186
191
  }
187
- `];
192
+ `,
193
+ ];
@@ -1 +1,136 @@
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);
1
+ import { LitElement, noChange } from 'lit';
2
+ import { Directive, directive, PartType, } from 'lit/directive.js';
3
+ const isThrow = ['localhost', '127.0.0.1'].some((host) => {
4
+ return window.location.host.includes(host);
5
+ });
6
+ class AssertSlot extends Directive {
7
+ render(
8
+ // This method is required, both by `Directive` and so the directive's
9
+ // options are typed at `assertSlot()` callsite.
10
+ //
11
+ /* eslint-disable @typescript-eslint/no-unused-vars */
12
+ slotted, isOptional) {
13
+ return noChange;
14
+ }
15
+ update(part, [slotted, isOptional]) {
16
+ if (part.options?.host instanceof LitElement && isThrow) {
17
+ const host = part.options.host;
18
+ if (part.options?.host instanceof LitElement &&
19
+ !part.options.host.hasUpdated &&
20
+ isThrow) {
21
+ // Equivalent to `firstUpdated()`. We need this in addition to the "slotchange"
22
+ // handler because the handler won't be called if the slot is empty.
23
+ part.options.host.updateComplete.then(() => {
24
+ if (!isOptional &&
25
+ part.element instanceof HTMLSlotElement &&
26
+ part.element.assignedNodes().length === 0 &&
27
+ slotted?.length) {
28
+ const message = part.element.name
29
+ ? `Expected the "${part.element.name}" slot of ${host.constructor.name} to have a slotted element that extends ${slotted
30
+ .map(({ name }) => name)
31
+ .join(' or ')}.`
32
+ : `Expected ${host.constructor.name} to have a slotted element that extends ${slotted
33
+ .map(({ name }) => name)
34
+ .join(' or ')}.`;
35
+ throw new TypeError(message);
36
+ }
37
+ if (!isOptional &&
38
+ part.element instanceof HTMLSlotElement &&
39
+ part.element.assignedNodes().length === 0) {
40
+ const message = part.element.name
41
+ ? `Expected ${host.constructor.name} to have a "${part.element.name}" slot.`
42
+ : `Expected ${host.constructor.name} to have a default slot.`;
43
+ throw new TypeError(message);
44
+ }
45
+ });
46
+ if (part.options?.host instanceof LitElement &&
47
+ !part.options.host.hasUpdated) {
48
+ part.element?.addEventListener('slotchange', () => {
49
+ if (isOptional &&
50
+ part.element instanceof HTMLSlotElement &&
51
+ part.element.assignedNodes().length === 0) {
52
+ return;
53
+ }
54
+ if (part.element instanceof HTMLSlotElement &&
55
+ part.element.assignedNodes().length === 0) {
56
+ if (slotted && slotted.length > 0) {
57
+ const message = part.element.name
58
+ ? `Expected the "${part.element.name}" slot of ${host.constructor.name} to have a slotted element that extends ${slotted
59
+ .map(({ name }) => name)
60
+ .join(' or ')}.`
61
+ : `Expected ${host.constructor.name} to have a slotted element that extends ${slotted
62
+ .map(({ name }) => name)
63
+ .join(' or ')}.`;
64
+ throw new TypeError(message);
65
+ }
66
+ const message = part.element.name
67
+ ? `Expected a "${part.element.name}" slot.`
68
+ : 'Expected a default slot.';
69
+ throw new TypeError(message);
70
+ }
71
+ if (slotted?.length && part.element instanceof HTMLSlotElement) {
72
+ const nodes = part.element
73
+ .assignedNodes({ flatten: true })
74
+ .filter((node) => {
75
+ // If `assignedNodes()` includes a `Text` node but `Text` isn't included in
76
+ // `slotted`, then it's filtered out so `isAllowed` doesn't result in a false
77
+ // positive. This doesn't mean that a slot can't contain `Text` node. It just
78
+ // means the presence of a `Text` node isn't enough to satisfy the requirements.
79
+ return node instanceof Text && slotted.includes(Text)
80
+ ? true
81
+ : node instanceof Text
82
+ ? false
83
+ : true;
84
+ });
85
+ // If `nodes` is empty after filtering, then the slot only contains `Text`
86
+ // nodes and `types` does not include `Text`. This is usually a case where
87
+ // the slot only contains whitespace.
88
+ if (nodes.length === 0) {
89
+ // "node" is technically correct because a consumer could have slotted text,
90
+ // and "node" covers both text and elements. But "element" probably gets
91
+ // the point across better for most developers.
92
+ const message = `Expected ${host.constructor.name} to have a slotted element that extends ${slotted
93
+ .map(({ name }) => name)
94
+ .join(' or ')}.`;
95
+ throw new TypeError(message);
96
+ }
97
+ for (const node of nodes) {
98
+ const isAllowed = slotted.some((Constructor) => node instanceof Constructor);
99
+ if (!isAllowed) {
100
+ const message = part.element.name
101
+ ? `Expected the "${part.element.name}" slot of ${host.constructor.name} to have a slotted element that extends ${slotted
102
+ .map(({ name }) => name)
103
+ .join(' or ')}. Extends ${node.constructor.name} instead.`
104
+ : `Expected ${host.constructor.name} to have a slotted element that extends ${slotted
105
+ .map(({ name }) => name)
106
+ .join(' or ')}. Extends ${node.constructor.name} instead.`;
107
+ throw new TypeError(message);
108
+ }
109
+ }
110
+ }
111
+ });
112
+ }
113
+ }
114
+ }
115
+ // Purely for test coverage purposes. If `update()` doesn't call `render()`,
116
+ // nothing will because `update()` exists.
117
+ return this.render();
118
+ }
119
+ constructor(partInfo) {
120
+ super(partInfo);
121
+ if (partInfo.type !== PartType.ELEMENT) {
122
+ throw new TypeError("Directive must be inside the element's opening tag.");
123
+ }
124
+ if ('element' in partInfo) {
125
+ const isSlot = partInfo.element instanceof HTMLSlotElement;
126
+ if (!isSlot) {
127
+ throw new TypeError('Directive can only be used on slots.');
128
+ }
129
+ }
130
+ }
131
+ }
132
+ /**
133
+ * @param {(Element | Text)[] | null } nodes - An array of node constructors allowed in the slot or `null` is any constructor is allowed
134
+ * @param {boolean} [isOptional] - `false` by default. Set to `true` if the slot is optional
135
+ */
136
+ export default directive(AssertSlot);
@@ -1 +1,14 @@
1
- import{expect,waitUntil}from"@open-wc/testing";import sinon from"sinon";export default async function(e){const n=sinon.stub(console,"error"),t=sinon.spy();window.addEventListener("unhandledrejection",t,{once:!0}),await e.call(context),await waitUntil((()=>t.callCount)),expect(t.callCount).to.equal(1),expect(t.args.at(0)?.at(0)instanceof PromiseRejectionEvent).to.be.true,window.removeEventListener("unhandledrejection",t),n.restore()}
1
+ import { expect, waitUntil } from '@open-wc/testing';
2
+ import sinon from 'sinon';
3
+ export default async function (callback) {
4
+ const stub = sinon.stub(console, 'error');
5
+ const spy = sinon.spy();
6
+ window.addEventListener('unhandledrejection', spy, { once: true });
7
+ await callback.call(context);
8
+ await waitUntil(() => spy.callCount);
9
+ expect(spy.callCount).to.equal(1);
10
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
11
+ expect(spy.args.at(0)?.at(0) instanceof PromiseRejectionEvent).to.be.true;
12
+ window.removeEventListener('unhandledrejection', spy);
13
+ stub.restore();
14
+ }
@@ -1 +1,26 @@
1
- import{expect,waitUntil}from"@open-wc/testing";import sinon from"sinon";export default async function(o){const t=sinon.stub(console,"error"),n=sinon.spy(),r=window.onerror;window.onerror=n,await o.call(context),await waitUntil((()=>n.callCount)),expect(n.callCount).to.be.greaterThan(0),expect(n.args.at(0)?.at(4)instanceof Error).to.be.true,window.onerror=r,t.restore()}
1
+ import { expect, waitUntil } from '@open-wc/testing';
2
+ import sinon from 'sinon';
3
+ export default async function (callback) {
4
+ const stub = sinon.stub(console, 'error');
5
+ const spy = sinon.spy();
6
+ const onerror = window.onerror;
7
+ // eslint-disable-next-line unicorn/prefer-add-event-listener
8
+ window.onerror = spy;
9
+ await callback.call(context);
10
+ await waitUntil(() => spy.callCount);
11
+ // Some components assert against a slot that is itself slotted content for
12
+ // a component. For example, Split Button Secondary Button and its default slot.
13
+ //
14
+ // Split Button Secondary Button passes its default slot into Menu's default slot,
15
+ // and Menu asserts against its default slot. So Split Button Secondary Button's
16
+ // default slot test produces two errors: one from itself and one from Menu.
17
+ //
18
+ // Rather than account for cases like that in each test, we simply use
19
+ // `to.be.greaterThan()` instead of `to.equal(1)`.
20
+ expect(spy.callCount).to.be.greaterThan(0);
21
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
22
+ expect(spy.args.at(0)?.at(4) instanceof Error).to.be.true;
23
+ // eslint-disable-next-line unicorn/prefer-add-event-listener
24
+ window.onerror = onerror;
25
+ stub.restore();
26
+ }
@@ -1 +1,18 @@
1
- export default function(e){class Final extends e{constructor(...n){if(new.target!==Final)throw new TypeError(`${e.name} doesn't allow extension. Please talk to us if a component doesn't meet your needs.`);super(...n)}}return Object.defineProperty(Final,"name",{value:e.name}),Final}
1
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
+ export default function (constructor) {
3
+ class Final extends constructor {
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ constructor(...arguments_) {
6
+ if (new.target !== Final) {
7
+ throw new TypeError(`${constructor.name} doesn't allow extension. Please talk to us if a component doesn't meet your needs.`);
8
+ }
9
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
10
+ super(...arguments_);
11
+ }
12
+ }
13
+ // Particularly helpful when dealing with `event.target`. Consumers
14
+ // expect that property's name to be that of the original constructor
15
+ // and not "Final".
16
+ Object.defineProperty(Final, 'name', { value: constructor.name });
17
+ return Final;
18
+ }
@@ -1 +1 @@
1
- export{};
1
+ export {};
@@ -1 +1,10 @@
1
- import{LocalizeController as DefaultLocalizationController,registerTranslation}from"@shoelace-style/localize";import en from"../translations/en.js";import fr from"../translations/fr.js";import ja from"../translations/ja.js";export class LocalizeController extends DefaultLocalizationController{static{registerTranslation(en,ja,fr)}}
1
+ import { LocalizeController as DefaultLocalizationController, registerTranslation, } from '@shoelace-style/localize';
2
+ import en from '../translations/en.js'; // Register English as the default/fallback language
3
+ import fr from '../translations/fr.js';
4
+ import ja from '../translations/ja.js';
5
+ // Extend the controller and apply our own translation interface for better typings
6
+ export class LocalizeController extends DefaultLocalizationController {
7
+ static {
8
+ registerTranslation(en, ja, fr);
9
+ }
10
+ }
@@ -1 +1,35 @@
1
- import{assert}from"@open-wc/testing";import{resetMouse,sendMouse}from"@web/test-runner-commands";export function click(t,e="center"){return mouse(t,e,"click")}export function hover(t,e="center"){return mouse(t,e,"move")}async function mouse(t,e="center",o){assert(t);const{height:i,width:r,x:c,y:n}=t.getBoundingClientRect();await sendMouse({type:o,position:"top"===e?[Math.ceil(c+r/2),Math.ceil(n)]:"right"===e?[Math.floor(c+r),Math.ceil(n+i/2)]:"bottom"===e?[Math.ceil(c+r/2),Math.floor(n+i)]:"left"===e?[Math.ceil(c),Math.ceil(n+i/2)]:"outside"===e?[Math.floor(c-1),Math.floor(n-1)]:[Math.ceil(c+r/2),Math.ceil(n+i/2)]}),afterEach((async()=>{await resetMouse()}))}
1
+ import { assert } from '@open-wc/testing';
2
+ import { resetMouse, sendMouse } from '@web/test-runner-commands';
3
+ export function click(element, position = 'center') {
4
+ return mouse(element, position, 'click');
5
+ }
6
+ export function hover(element, position = 'center') {
7
+ return mouse(element, position, 'move');
8
+ }
9
+ async function mouse(element, position = 'center', type) {
10
+ assert(element);
11
+ const { height, width, x, y } = element.getBoundingClientRect();
12
+ await sendMouse({
13
+ type,
14
+ position: position === 'top'
15
+ ? [Math.ceil(x + width / 2), Math.ceil(y)]
16
+ : position === 'right'
17
+ ? [Math.floor(x + width), Math.ceil(y + height / 2)]
18
+ : position === 'bottom'
19
+ ? [Math.ceil(x + width / 2), Math.floor(y + height)]
20
+ : position === 'left'
21
+ ? [Math.ceil(x), Math.ceil(y + height / 2)]
22
+ : position === 'outside'
23
+ ? [Math.floor(x - 1), Math.floor(y - 1)]
24
+ : // Center
25
+ [Math.ceil(x + width / 2), Math.ceil(y + height / 2)],
26
+ });
27
+ // You'd think you'd be able to call `resetMouse()` anywhere. But, for whatever
28
+ // reason, calling it outside `afterEach()` results in sporadic bouts of the
29
+ // following error via Playwright:
30
+ //
31
+ // "mouse.move: Target page, context or browser has been closed".
32
+ afterEach(async () => {
33
+ await resetMouse();
34
+ });
35
+ }