@crowdstrike/glide-core 0.31.0 → 0.31.1

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.
package/dist/dropdown.js CHANGED
@@ -1556,8 +1556,8 @@ let Dropdown = class Dropdown extends LitElement {
1556
1556
  // Prevent page scroll. When filterable, also prevent the insertion point from
1557
1557
  // moving to the beginning of the field.
1558
1558
  event.preventDefault();
1559
- const firstOption = [...this.#optionElementsNotHiddenIncludingSelectAll]
1560
- .reverse()
1559
+ const firstOption = this.#optionElementsNotHiddenIncludingSelectAll
1560
+ .toReversed()
1561
1561
  .findLast((option) => !option.disabled);
1562
1562
  if (firstOption) {
1563
1563
  this.#previouslyActiveOption = this.activeOption;
package/dist/menu.js CHANGED
@@ -13,6 +13,7 @@ import { customElement, property } from 'lit/decorators.js';
13
13
  import packageJson from '../package.json' with { type: 'json' };
14
14
  import { LocalizeController } from './library/localize.js';
15
15
  import Options from './options.js';
16
+ import OptionsGroup from './options.group.js';
16
17
  import Option from './option.js';
17
18
  import Input from './input.js';
18
19
  import assertSlot from './library/assert-slot.js';
@@ -399,7 +400,9 @@ let Menu = class Menu extends LitElement {
399
400
  .flatMap((element) => {
400
401
  return element instanceof HTMLSlotElement
401
402
  ? element.assignedElements({ flatten: true })
402
- : element;
403
+ : element instanceof OptionsGroup
404
+ ? [...element.children]
405
+ : element;
403
406
  })
404
407
  ?.filter((element) => {
405
408
  return element instanceof Option;
@@ -415,8 +418,14 @@ let Menu = class Menu extends LitElement {
415
418
  // The "content" slot case.
416
419
  ':scope > glide-core-options > glide-core-option > [slot="content"] > glide-core-menu'),
417
420
  ...this.querySelectorAll(
421
+ // The "content" slot and Options Group case.
422
+ ':scope > glide-core-options > glide-core-options-group > glide-core-option > [slot="content"] > glide-core-menu'),
423
+ ...this.querySelectorAll(
418
424
  // The "content" slot fallback case.
419
425
  ':scope > glide-core-options > glide-core-option > [slot="submenu"]'),
426
+ ...this.querySelectorAll(
427
+ // The "content" slot fallback and Options Group case.
428
+ ':scope > glide-core-options > glide-core-options-group > glide-core-option > [slot="submenu"]'),
420
429
  ];
421
430
  }
422
431
  get #targetElement() {
@@ -496,6 +505,15 @@ let Menu = class Menu extends LitElement {
496
505
  if (this.#isSubMenu && event.target === this.#defaultSlotElementRef.value) {
497
506
  event.stopPropagation();
498
507
  }
508
+ // When Menu is in the shadow DOM of another component, `event.target` will be
509
+ // retargeted to the host of that component the moment the event bubbles out of
510
+ // it.
511
+ //
512
+ // So, when the timeout callback below is called, `event.target` will have been
513
+ // retargeted and the `instanceof` check will wrongly fail when an Option is
514
+ // clicked, and Menu will never close. So we store a reference to the original
515
+ // `event.target` and use it in the `instanceof` condition.
516
+ const originalEventTarget = event.target;
499
517
  // The timeout gives consumers a chance to cancel the event to prevent Menu from
500
518
  // closing.
501
519
  setTimeout(() => {
@@ -510,7 +528,7 @@ let Menu = class Menu extends LitElement {
510
528
  //
511
529
  // When the default slot's padding is clicked, Menu should remain open because the
512
530
  // user most likely meant to click an Option but missed.
513
- if (!event.defaultPrevented && event.target instanceof Option) {
531
+ if (!event.defaultPrevented && originalEventTarget instanceof Option) {
514
532
  this.open = false;
515
533
  }
516
534
  });
@@ -15,9 +15,11 @@ export default [
15
15
  font-weight: var(--glide-core-typography-weight-regular);
16
16
  inline-size: 100%;
17
17
  max-inline-size: 21.875rem;
18
+ min-block-size: 1.75rem;
18
19
  padding-block: var(--glide-core-spacing-base-xxs);
19
20
  padding-inline: var(--glide-core-spacing-base-sm);
20
- transition: background-color var(--glide-core-duration-fast-02) ease-in-out;
21
+ transition: background-color var(--glide-core-duration-fast-02)
22
+ ease-in-out;
21
23
  user-select: none;
22
24
 
23
25
  &.active {
@@ -0,0 +1,30 @@
1
+ import { LitElement } from 'lit';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'glide-core-options-group': OptionsGroup;
5
+ }
6
+ }
7
+ /**
8
+ * @attr {string} label
9
+ * @attr {boolean} [hide-label=false]
10
+ * @attr {'group'|'optgroup'} [role='group']
11
+ *
12
+ * @readonly
13
+ * @attr {string} [version]
14
+ *
15
+ * @slot {Option}
16
+ */
17
+ export default class OptionsGroup extends LitElement {
18
+ #private;
19
+ static shadowRootOptions: ShadowRootInit;
20
+ static styles: import("lit").CSSResult[];
21
+ /**
22
+ * @default undefined
23
+ */
24
+ get label(): string | undefined;
25
+ set label(label: string);
26
+ hideLabel: boolean;
27
+ role: 'group' | 'optgroup';
28
+ readonly version: string;
29
+ render(): import("lit").TemplateResult<1>;
30
+ }
@@ -0,0 +1,84 @@
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 { html, LitElement } from 'lit';
8
+ import { customElement, property } from 'lit/decorators.js';
9
+ import { classMap } from 'lit/directives/class-map.js';
10
+ import packageJson from '../package.json' with { type: 'json' };
11
+ import styles from './options.group.styles.js';
12
+ import shadowRootMode from './library/shadow-root-mode.js';
13
+ import final from './library/final.js';
14
+ import assertSlot from './library/assert-slot.js';
15
+ import Option from './option.js';
16
+ import required from './library/required.js';
17
+ /**
18
+ * @attr {string} label
19
+ * @attr {boolean} [hide-label=false]
20
+ * @attr {'group'|'optgroup'} [role='group']
21
+ *
22
+ * @readonly
23
+ * @attr {string} [version]
24
+ *
25
+ * @slot {Option}
26
+ */
27
+ let OptionsGroup = class OptionsGroup extends LitElement {
28
+ constructor() {
29
+ super(...arguments);
30
+ this.hideLabel = false;
31
+ this.role = 'group';
32
+ this.version = packageJson.version;
33
+ }
34
+ static { this.shadowRootOptions = {
35
+ ...LitElement.shadowRootOptions,
36
+ mode: shadowRootMode,
37
+ }; }
38
+ static { this.styles = styles; }
39
+ /**
40
+ * @default undefined
41
+ */
42
+ get label() {
43
+ return this.#label;
44
+ }
45
+ set label(label) {
46
+ this.#label = label;
47
+ this.ariaLabel = label;
48
+ }
49
+ render() {
50
+ return html `
51
+ <div class="component">
52
+ <div
53
+ aria-hidden="true"
54
+ class=${classMap({ label: true, 'visually-hidden': this.hideLabel })}
55
+ >
56
+ ${this.label}
57
+ </div>
58
+
59
+ <slot ${assertSlot([Option])}>
60
+ <!-- @type {Option} -->
61
+ </slot>
62
+ </div>
63
+ `;
64
+ }
65
+ #label;
66
+ };
67
+ __decorate([
68
+ property({ reflect: true }),
69
+ required
70
+ ], OptionsGroup.prototype, "label", null);
71
+ __decorate([
72
+ property({ attribute: 'hide-label', reflect: true, type: Boolean })
73
+ ], OptionsGroup.prototype, "hideLabel", void 0);
74
+ __decorate([
75
+ property({ reflect: true })
76
+ ], OptionsGroup.prototype, "role", void 0);
77
+ __decorate([
78
+ property({ reflect: true })
79
+ ], OptionsGroup.prototype, "version", void 0);
80
+ OptionsGroup = __decorate([
81
+ customElement('glide-core-options-group'),
82
+ final
83
+ ], OptionsGroup);
84
+ export default OptionsGroup;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("lit").CSSResult[];
2
+ export default _default;
@@ -0,0 +1,31 @@
1
+ import { css } from 'lit';
2
+ import visuallyHidden from './styles/visually-hidden.js';
3
+ export default [
4
+ css `
5
+ ${visuallyHidden('.label.visually-hidden')}
6
+ `,
7
+ css `
8
+ :host(:not(:last-of-type)) .component::after {
9
+ background-color: var(--glide-core-color-static-stroke-secondary);
10
+ block-size: 1px;
11
+ border-radius: var(--glide-core-rounding-base-radius-sm);
12
+ content: '';
13
+ display: block;
14
+ margin-block: var(--glide-core-spacing-base-xxxs);
15
+ }
16
+
17
+ .label {
18
+ block-size: 1.75rem;
19
+ box-sizing: border-box;
20
+ font-family: var(--glide-core-typography-family-primary);
21
+ font-size: var(--glide-core-typography-size-body-small);
22
+ font-weight: var(--glide-core-typography-weight-bold);
23
+ max-inline-size: 21.875rem;
24
+ overflow: hidden;
25
+ padding-block: var(--glide-core-spacing-base-xxs);
26
+ padding-inline: var(--glide-core-spacing-base-sm);
27
+ text-overflow: ellipsis;
28
+ white-space: nowrap;
29
+ }
30
+ `,
31
+ ];
package/dist/options.js CHANGED
@@ -17,6 +17,7 @@ import final from './library/final.js';
17
17
  import uniqueId from './library/unique-id.js';
18
18
  import assertSlot from './library/assert-slot.js';
19
19
  import Option from './option.js';
20
+ import OptionsGroup from './options.group.js';
20
21
  // This component exists because Menu's target and its menu (`"role="menu"` or
21
22
  // `role="listbox"`) both need to be in the light DOM so the target and menu can
22
23
  // reference each other's IDs in ARIA attributes.
@@ -82,7 +83,7 @@ let Options = class Options extends LitElement {
82
83
  loading: this.privateLoading,
83
84
  })}
84
85
  @slotchange=${this.#onDefaultSlotChange}
85
- ${assertSlot([Option, Text], true)}
86
+ ${assertSlot([OptionsGroup, Option, Text], true)}
86
87
  >
87
88
  <!-- @type {Option | Text} -->
88
89
  </slot>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdstrike/glide-core",
3
- "version": "0.31.0",
3
+ "version": "0.31.1",
4
4
  "description": "A Web Component design system",
5
5
  "author": "CrowdStrike UX Team",
6
6
  "license": "Apache-2.0",
@@ -94,13 +94,13 @@
94
94
  "comment-parser": "^1.4.1",
95
95
  "custom-elements-manifest": "^2.1.0",
96
96
  "esbuild": "^0.25.0",
97
- "eslint": "^9.28.0",
97
+ "eslint": "^9.31.0",
98
98
  "eslint-config-prettier": "^10.1.5",
99
99
  "eslint-plugin-import": "^2.31.0",
100
100
  "eslint-plugin-lit": "^1.15.0",
101
101
  "eslint-plugin-lit-a11y": "^4.1.4",
102
102
  "eslint-plugin-sort-class-members": "^1.21.0",
103
- "eslint-plugin-unicorn": "^58.0.0",
103
+ "eslint-plugin-unicorn": "^60.0.0",
104
104
  "globals": "^15.13.0",
105
105
  "globby": "^14.0.2",
106
106
  "husky": "^8.0.3",