@crowdstrike/glide-core 0.29.1 → 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 (124) 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.d.ts +2 -0
  105. package/dist/tooltip.container.js +130 -1
  106. package/dist/tooltip.container.styles.js +18 -4
  107. package/dist/tooltip.d.ts +6 -0
  108. package/dist/tooltip.js +484 -1
  109. package/dist/tooltip.styles.js +21 -5
  110. package/dist/translations/en.js +36 -1
  111. package/dist/translations/fr.js +37 -1
  112. package/dist/translations/ja.js +37 -1
  113. package/package.json +8 -12
  114. package/dist/menu.button.d.ts +0 -42
  115. package/dist/menu.button.js +0 -1
  116. package/dist/menu.button.styles.js +0 -32
  117. package/dist/menu.link.d.ts +0 -44
  118. package/dist/menu.link.js +0 -1
  119. package/dist/menu.link.styles.js +0 -35
  120. package/dist/menu.options.js +0 -1
  121. package/dist/menu.options.styles.d.ts +0 -2
  122. package/dist/menu.options.styles.js +0 -20
  123. /package/dist/{menu.button.styles.d.ts → option.styles.d.ts} +0 -0
  124. /package/dist/{menu.link.styles.d.ts → options.styles.d.ts} +0 -0
@@ -1,19 +1,15 @@
1
- import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-scale-animation.js";export default[css`
2
- ${opacityAndScaleAnimation(".default-slot:popover-open")}
3
- `,css`
4
- :host {
5
- /* Contains elements with "padding", "margin", and "width". Inline by default. */
6
- display: inline-block;
7
- }
8
-
9
- .component {
10
- color: var(--glide-core-color-static-text-default);
11
- display: flex;
12
- }
13
-
1
+ import { css } from 'lit';
2
+ import opacityAndScaleAnimation from './styles/opacity-and-scale-animation.js';
3
+ export default [
4
+ css `
5
+ ${opacityAndScaleAnimation('.default-slot:popover-open')}
6
+ `,
7
+ css `
14
8
  .target-slot {
15
- display: flex;
16
- position: relative;
9
+ &::slotted(:is([disabled], [aria-disabled='true'])) {
10
+ color: var(--glide-core-color-interactive-icon-default--disabled);
11
+ cursor: default;
12
+ }
17
13
  }
18
14
 
19
15
  .default-slot {
@@ -25,11 +21,32 @@ import{css}from"lit";import opacityAndScaleAnimation from"./styles/opacity-and-s
25
21
  border-radius: var(--glide-core-rounding-base-radius-sm);
26
22
  box-shadow: var(--glide-core-effect-floating);
27
23
  box-sizing: border-box;
24
+ color: var(--glide-core-color-static-text-default);
25
+
26
+ /*
27
+ For submenus, which will inherit "cursor: pointer" from their Option(s).
28
+ "cursor: default" tells the user that clicking the padding around the
29
+ default slot won't select an Option.
30
+ */
31
+ cursor: default;
28
32
  inline-size: max-content;
29
33
  inset: unset;
30
34
  margin-block: 0;
31
35
  min-inline-size: 9.375rem;
32
- padding: var(--glide-core-spacing-base-xxxs);
36
+ padding-block-end: 0;
37
+ padding-block-start: var(--glide-core-spacing-base-xxxs);
38
+ padding-inline: var(--glide-core-spacing-base-xxxs);
33
39
  position: absolute;
40
+
41
+ /*
42
+ This little hack replaces "padding-block-end", which the last option overlaps
43
+ when the Option(s) overflow and scroll.
44
+ */
45
+ &::slotted(glide-core-options)::after {
46
+ block-size: var(--glide-core-spacing-base-xxxs);
47
+ content: '';
48
+ display: block;
49
+ }
34
50
  }
35
- `];
51
+ `,
52
+ ];
package/dist/modal.d.ts CHANGED
@@ -7,6 +7,7 @@ declare global {
7
7
  /**
8
8
  * @attr {string} label
9
9
  * @attr {boolean} [back-button=false]
10
+ * @attr {string} [description]
10
11
  * @attr {boolean} [open=false]
11
12
  * @attr {'critical'|'informational'|'medium'} [severity]
12
13
  * @attr {'small'|'medium'|'large'|'xlarge'} [size='medium']
@@ -28,6 +29,7 @@ export default class Modal extends LitElement {
28
29
  static styles: import("lit").CSSResult[];
29
30
  label?: string;
30
31
  backButton: boolean;
32
+ description?: string;
31
33
  /**
32
34
  * @default false
33
35
  */
@@ -43,4 +45,6 @@ export default class Modal extends LitElement {
43
45
  private hasPrimarySlotContent;
44
46
  private hasSecondarySlotContent;
45
47
  private hasTertiarySlotContent;
48
+ private isScrolledFromBottom;
49
+ private isScrolledFromTop;
46
50
  }
@@ -1 +1,60 @@
1
- var __decorate=this&&this.__decorate||function(t,o,e,r){var i,n=arguments.length,l=n<3?o:null===r?r=Object.getOwnPropertyDescriptor(o,e):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(t,o,e,r);else for(var s=t.length-1;s>=0;s--)(i=t[s])&&(l=(n<3?i(l):n>3?i(o,e,l):i(o,e))||l);return n>3&&l&&Object.defineProperty(o,e,l),l};import"./icon-button.js";import{html,LitElement}from"lit";import{customElement,property}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import packageJson from"../package.json"with{type:"json"};import styles from"./modal.icon-button.styles.js";import assertSlot from"./library/assert-slot.js";import shadowRootMode from"./library/shadow-root-mode.js";import final from"./library/final.js";import required from"./library/required.js";let ModalIconButton=class ModalIconButton extends LitElement{constructor(){super(...arguments),this.version=packageJson.version}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}render(){return html`<glide-core-icon-button label="${ifDefined(this.label)}" variant="tertiary"><slot ${assertSlot()}></slot></glide-core-icon-button>`}};__decorate([property({reflect:!0}),required],ModalIconButton.prototype,"label",void 0),__decorate([property({reflect:!0})],ModalIconButton.prototype,"version",void 0),ModalIconButton=__decorate([customElement("glide-core-modal-icon-button"),final],ModalIconButton);export default ModalIconButton;
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 './icon-button.js';
8
+ import { html, LitElement } from 'lit';
9
+ import { customElement, property } from 'lit/decorators.js';
10
+ import { ifDefined } from 'lit/directives/if-defined.js';
11
+ import packageJson from '../package.json' with { type: 'json' };
12
+ import styles from './modal.icon-button.styles.js';
13
+ import assertSlot from './library/assert-slot.js';
14
+ import shadowRootMode from './library/shadow-root-mode.js';
15
+ import final from './library/final.js';
16
+ import required from './library/required.js';
17
+ /**
18
+ * @attr {string} label
19
+ *
20
+ * @readonly
21
+ * @attr {string} [version]
22
+ *
23
+ * @slot {Element} - An icon
24
+ */
25
+ let ModalIconButton = class ModalIconButton extends LitElement {
26
+ constructor() {
27
+ super(...arguments);
28
+ this.version = packageJson.version;
29
+ }
30
+ static { this.shadowRootOptions = {
31
+ ...LitElement.shadowRootOptions,
32
+ mode: shadowRootMode,
33
+ }; }
34
+ static { this.styles = styles; }
35
+ render() {
36
+ return html `
37
+ <glide-core-icon-button label=${ifDefined(this.label)} variant="tertiary">
38
+ <slot ${assertSlot()}>
39
+ <!--
40
+ An icon
41
+ @required
42
+ @type {Element}
43
+ -->
44
+ </slot>
45
+ </glide-core-icon-button>
46
+ `;
47
+ }
48
+ };
49
+ __decorate([
50
+ property({ reflect: true }),
51
+ required
52
+ ], ModalIconButton.prototype, "label", void 0);
53
+ __decorate([
54
+ property({ reflect: true })
55
+ ], ModalIconButton.prototype, "version", void 0);
56
+ ModalIconButton = __decorate([
57
+ customElement('glide-core-modal-icon-button'),
58
+ final
59
+ ], ModalIconButton);
60
+ export default ModalIconButton;
@@ -1,8 +1,11 @@
1
- import{css}from"lit";export default[css`
1
+ import { css } from 'lit';
2
+ export default [
3
+ css `
2
4
  ::slotted(*) {
3
5
  --private-size: 1.125rem;
4
6
 
5
7
  block-size: 1.125rem;
6
8
  inline-size: 1.125rem;
7
9
  }
8
- `];
10
+ `,
11
+ ];
package/dist/modal.js CHANGED
@@ -1 +1,473 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,i){var n,s=arguments.length,l=s<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,o,i);else for(var r=e.length-1;r>=0;r--)(n=e[r])&&(l=(s<3?n(l):s>3?n(t,o,l):n(t,o))||l);return s>3&&l&&Object.defineProperty(t,o,l),l};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{when}from"lit/directives/when.js";import packageJson from"../package.json"with{type:"json"};import{LocalizeController}from"./library/localize.js";import ModalIconButton from"./modal.icon-button.js";import Button from"./button.js";import Tooltip from"./tooltip.js";import styles from"./modal.styles.js";import xIcon from"./icons/x.js";import assertSlot from"./library/assert-slot.js";import shadowRootMode from"./library/shadow-root-mode.js";import severityInformationalIcon from"./icons/severity-informational.js";import severityMediumIcon from"./icons/severity-medium.js";import severityCriticalIcon from"./icons/severity-critical.js";import final from"./library/final.js";import required from"./library/required.js";const globalStylesheet=new CSSStyleSheet;globalStylesheet.insertRule("\n .private-glide-core-modal-lock-scroll {\n scrollbar-gutter: stable !important;\n overflow: hidden !important;\n }\n");let Modal=class Modal extends LitElement{constructor(){super(...arguments),this.backButton=!1,this.size="medium",this.version=packageJson.version,this.hasPrimarySlotContent=!1,this.hasSecondarySlotContent=!1,this.hasTertiarySlotContent=!1,this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#i=createRef(),this.#n=createRef(),this.#s=!1,this.#l=!1,this.#r=new LocalizeController(this),this.#a=createRef(),this.#c=createRef(),this.#d=createRef(),this.#m=()=>{this.#s=!0},this.#h=()=>{this.#s=!0},this.#p=()=>{const e=this.open;setTimeout((()=>{this.#s?setTimeout((()=>{this.#s=!1})):e===this.open&&(this.open=!1)}))}}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}get open(){return this.#l}set open(e){const t=e!==this.#l;this.#l=e,e&&t?(this.#y(),this.dispatchEvent(new Event("toggle",{bubbles:!0,composed:!0}))):t&&(this.#u(),this.dispatchEvent(new Event("toggle",{bubbles:!0,composed:!0})))}connectedCallback(){super.connectedCallback();document.adoptedStyleSheets.includes(globalStylesheet)||document.adoptedStyleSheets.push(globalStylesheet),document.addEventListener("click",this.#p,{capture:!0})}disconnectedCallback(){super.disconnectedCallback(),document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),document.adoptedStyleSheets=document.adoptedStyleSheets.filter((e=>e!==globalStylesheet)),document.removeEventListener("click",this.#p,{capture:!0})}firstUpdated(){this.open&&this.#y(),this.#i.value?.addEventListener("click",this.#m,{capture:!0}),this.#i.value?.addEventListener("mouseup",this.#h)}render(){return html`<dialog class="component" data-test="component" @keydown="${this.#f}" ${ref(this.#o)}><div class="${classMap({container:!0,small:"small"===this.size,medium:"medium"===this.size,large:"large"===this.size,xlarge:"xlarge"===this.size})}" ${ref(this.#i)}><header class="header"><h2 class="label" data-test="heading" id="heading">${when(this.severity,(()=>html`<span aria-label="${this.#r.term("informational"===this.severity?"severityInformational":"critical"===this.severity?"severityCritical":"severityMedium")} - " class="${classMap({severity:!0,critical:"critical"===this.severity,informational:"informational"===this.severity,medium:"medium"===this.severity})}" data-test="severity">${this.severity&&icons[this.severity]}</span>`))} ${when(this.backButton&&!this.severity,(()=>html`<glide-core-modal-icon-button class="back-button" data-test="back-button" label="${this.#r.term("close")}" @click="${this.#v}" ${ref(this.#e)}>${icons.back}</glide-core-modal-icon-button>`))} ${this.label}</h2><div class="header-actions" role="toolbar"><slot name="header-actions" ${assertSlot([ModalIconButton],!0)} ${ref(this.#n)}></slot><glide-core-modal-icon-button class="close-button" data-test="close-button" label="${this.#r.term("close")}" @click="${this.#v}" ${ref(this.#t)}>${xIcon}</glide-core-modal-icon-button></div></header><article aria-labelledby="heading" class="body" role="region"><slot ${assertSlot()}></slot></article><footer><menu aria-hidden="${!this.hasTertiarySlotContent&&!this.hasSecondarySlotContent&&!this.hasPrimarySlotContent}" class="actions"><li aria-hidden="${!this.hasTertiarySlotContent}" class="action"><slot class="tertiary-slot" name="tertiary" @slotchange="${this.#C}" ${assertSlot([Button,Tooltip],!0)} ${ref(this.#d)}></slot></li><li aria-hidden="${!this.hasSecondarySlotContent}" class="action"><slot name="secondary" @slotchange="${this.#S}" ${assertSlot([Button],!0)} ${ref(this.#c)}></slot></li><li aria-hidden="${!this.hasPrimarySlotContent}" class="action"><slot name="primary" @slotchange="${this.#b}" ${assertSlot([Button],!0)} ${ref(this.#a)}></slot></li></menu></footer></div></dialog>`}#e;#t;#o;#i;#n;#s;#l;#r;#a;#c;#d;#m;#h;#p;#u(){document.documentElement.classList.remove("private-glide-core-modal-lock-scroll"),this.#o.value?.close()}#v(){this.open=!1}#f(e){"Escape"===e.key&&(this.open=!1,e.preventDefault())}#b(){this.hasPrimarySlotContent=Boolean(this.#a.value?.assignedElements().length)}#S(){this.hasSecondarySlotContent=Boolean(this.#c.value?.assignedElements().length)}#C(){this.hasTertiarySlotContent=Boolean(this.#d.value?.assignedElements().length)}#y(){document.documentElement.classList.add("private-glide-core-modal-lock-scroll"),this.#o.value?.showModal()}};__decorate([property({reflect:!0}),required],Modal.prototype,"label",void 0),__decorate([property({attribute:"back-button",type:Boolean,reflect:!0})],Modal.prototype,"backButton",void 0),__decorate([property({reflect:!0,type:Boolean})],Modal.prototype,"open",null),__decorate([property({reflect:!0})],Modal.prototype,"severity",void 0),__decorate([property({reflect:!0,useDefault:!0})],Modal.prototype,"size",void 0),__decorate([property({reflect:!0})],Modal.prototype,"version",void 0),__decorate([state()],Modal.prototype,"hasPrimarySlotContent",void 0),__decorate([state()],Modal.prototype,"hasSecondarySlotContent",void 0),__decorate([state()],Modal.prototype,"hasTertiarySlotContent",void 0),Modal=__decorate([customElement("glide-core-modal"),final],Modal);export default Modal;const icons={back:html`<svg style="${styleMap({height:"1.25rem",width:"1.25rem"})}" viewBox="0 0 24 24" fill="none"><path d="M12 18C11.4477 18 11 18.4477 11 19C11 19.5523 11.4477 20 12 20V18ZM20 14.5C20 16.433 18.433 18 16.5 18V20C19.5376 20 22 17.5376 22 14.5H20ZM16.5 11C18.433 11 20 12.567 20 14.5H22C22 11.4624 19.5376 9 16.5 9V11ZM16.5 18H12V20H16.5V18ZM16.5 9H3V11H16.5V9Z" fill="currentColor"/><path d="M7 6L3 10L7 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>`,critical:severityCriticalIcon,informational:severityInformationalIcon,medium:severityMediumIcon};
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 { classMap } from 'lit/directives/class-map.js';
9
+ import { createRef, ref } from 'lit/directives/ref.js';
10
+ import { customElement, property, state } from 'lit/decorators.js';
11
+ import { styleMap } from 'lit/directives/style-map.js';
12
+ import { when } from 'lit/directives/when.js';
13
+ import packageJson from '../package.json' with { type: 'json' };
14
+ import { LocalizeController } from './library/localize.js';
15
+ import ModalIconButton from './modal.icon-button.js';
16
+ import Button from './button.js';
17
+ import Tooltip from './tooltip.js';
18
+ import styles from './modal.styles.js';
19
+ import xIcon from './icons/x.js';
20
+ import assertSlot from './library/assert-slot.js';
21
+ import shadowRootMode from './library/shadow-root-mode.js';
22
+ import severityInformationalIcon from './icons/severity-informational.js';
23
+ import severityMediumIcon from './icons/severity-medium.js';
24
+ import severityCriticalIcon from './icons/severity-critical.js';
25
+ import final from './library/final.js';
26
+ import required from './library/required.js';
27
+ import onResize from './library/on-resize.js';
28
+ const globalStylesheet = new CSSStyleSheet();
29
+ globalStylesheet.insertRule(`
30
+ .private-glide-core-modal-lock-scroll {
31
+ scrollbar-gutter: stable !important;
32
+ overflow: hidden !important;
33
+ }
34
+ `);
35
+ /**
36
+ * @attr {string} label
37
+ * @attr {boolean} [back-button=false]
38
+ * @attr {string} [description]
39
+ * @attr {boolean} [open=false]
40
+ * @attr {'critical'|'informational'|'medium'} [severity]
41
+ * @attr {'small'|'medium'|'large'|'xlarge'} [size='medium']
42
+ *
43
+ * @readonly
44
+ * @attr {string} [version]
45
+ *
46
+ * @slot {Element | string}
47
+ * @slot {ModalIconButton} [header-actions]
48
+ * @slot {Button} [primary]
49
+ * @slot {Button} [secondary]
50
+ * @slot {Button | Tooltip} [tertiary]
51
+ *
52
+ * @fires {Event} toggle
53
+ */
54
+ let Modal = class Modal extends LitElement {
55
+ constructor() {
56
+ super(...arguments);
57
+ this.backButton = false;
58
+ this.size = 'medium';
59
+ this.version = packageJson.version;
60
+ this.hasPrimarySlotContent = false;
61
+ this.hasSecondarySlotContent = false;
62
+ this.hasTertiarySlotContent = false;
63
+ this.isScrolledFromBottom = false;
64
+ this.isScrolledFromTop = false;
65
+ this.#backButtonElementRef = createRef();
66
+ this.#bodyElementRef = createRef();
67
+ this.#closeButtonElementRef = createRef();
68
+ this.#componentElementRef = createRef();
69
+ this.#containerElementRef = createRef();
70
+ this.#headerActionsSlotElementRef = createRef();
71
+ this.#isContainerClick = false;
72
+ this.#isOpen = false;
73
+ this.#localize = new LocalizeController(this);
74
+ this.#primarySlotElementRef = createRef();
75
+ this.#secondarySlotElementRef = createRef();
76
+ this.#tertiarySlotElementRef = createRef();
77
+ // An arrow function field instead of a method so `this` is closed over and
78
+ // set to the component instead of `document`.
79
+ this.#onContainerClick = () => {
80
+ this.#isContainerClick = true;
81
+ };
82
+ // An arrow function field instead of a method so `this` is closed over and
83
+ // set to the component instead of `document`.
84
+ this.#onDocumentClick = () => {
85
+ const isOpen = this.open;
86
+ // There's a comment in `firstUpdated()` explaining the timeout.
87
+ setTimeout(() => {
88
+ if (this.#isContainerClick) {
89
+ // This handler will be called twice for a single click if the element clicked was
90
+ // a `<label>`. Because clicking a `<label>` produces two "click" events.
91
+ //
92
+ // If we immediately set `#isContainerClick` to `false`, Modal will close when this
93
+ // handler is called the second time. So we wait a tick to ensure both "click"
94
+ // events have been dispatched.
95
+ setTimeout(() => {
96
+ this.#isContainerClick = false;
97
+ });
98
+ // The click may be a result of the user clicking a button to open Modal.
99
+ // If so then `this.open` will have been set to `true` in the frame between
100
+ // when this handler was called and this timeout. And we don't want to
101
+ // immediately close Modal after the user has opened it. So we only close
102
+ // Modal if the state of `this.open` hasn't changed.
103
+ }
104
+ else if (isOpen === this.open) {
105
+ this.open = false;
106
+ }
107
+ });
108
+ };
109
+ }
110
+ static { this.shadowRootOptions = {
111
+ ...LitElement.shadowRootOptions,
112
+ mode: shadowRootMode,
113
+ }; }
114
+ static { this.styles = styles; }
115
+ /**
116
+ * @default false
117
+ */
118
+ get open() {
119
+ return this.#isOpen;
120
+ }
121
+ set open(isOpen) {
122
+ const hasChanged = isOpen !== this.#isOpen;
123
+ this.#isOpen = isOpen;
124
+ if (isOpen && hasChanged) {
125
+ this.#show();
126
+ this.dispatchEvent(new Event('toggle', { bubbles: true, composed: true }));
127
+ }
128
+ else if (hasChanged) {
129
+ this.#hide();
130
+ this.dispatchEvent(new Event('toggle', { bubbles: true, composed: true }));
131
+ }
132
+ }
133
+ connectedCallback() {
134
+ super.connectedCallback();
135
+ const isAdopted = document.adoptedStyleSheets.includes(globalStylesheet);
136
+ if (!isAdopted) {
137
+ document.adoptedStyleSheets.push(globalStylesheet);
138
+ }
139
+ // 1. The consumer has a click handler on a button.
140
+ // 2. The user clicks the button.
141
+ // 3. The button's click handler is called and sets `this.open` to `true`.
142
+ // 4. The "click" event bubbles up and is handled by `#onDocumentClick`.
143
+ // 5. That handler sets `open` to `false` because the click came from outside
144
+ // Modal.
145
+ // 6. Modal is opened then closed in the same frame and so never opens.
146
+ //
147
+ // `capture` ensures `#onDocumentClick` is called before #3, so the button click
148
+ // handler setting `open` to `true` isn't overwritten by this handler setting
149
+ // `open` to `false`.
150
+ document.addEventListener('click', this.#onDocumentClick, {
151
+ capture: true,
152
+ });
153
+ }
154
+ disconnectedCallback() {
155
+ super.disconnectedCallback();
156
+ document.documentElement.classList.remove('private-glide-core-modal-lock-scroll');
157
+ document.adoptedStyleSheets = document.adoptedStyleSheets.filter((stylesheet) => {
158
+ return stylesheet !== globalStylesheet;
159
+ });
160
+ document.removeEventListener('click', this.#onDocumentClick, {
161
+ capture: true,
162
+ });
163
+ }
164
+ firstUpdated() {
165
+ if (this.open) {
166
+ this.#show();
167
+ }
168
+ // Modals's "click" handler on `document` listens for clicks in the capture
169
+ // phase. There's a comment explaining why. `#isContainerClick` must be set
170
+ // by this handler before that handler is called. That handler will be called
171
+ // first because events travel down instead of up the `document` during their
172
+ // capture phase. But this "click" handler, because it listens in the capture
173
+ // phase, will be called in the same frame. So the `document` handler checks
174
+ // `#isContainerClick` after a timeout to give this handler a chance to be called.
175
+ //
176
+ // In short, we have to listen in the capture phase here because the `document`
177
+ // listener listens in the capture phase.
178
+ this.#containerElementRef.value?.addEventListener('click', this.#onContainerClick, { capture: true });
179
+ }
180
+ // The contents `<dialog>` are wrapped in a `<div>` so we can separate backdrop
181
+ // clicks from non-backdrop ones. We add "click" listeners to the `<div>` and the
182
+ // `document`. The former listener sets a boolean that the latter has a condition
183
+ // for. If the boolean is `false`, then we know the click came from the backdrop.
184
+ // That's also why the padding is on the `<div>`, so padding clicks come from
185
+ // inside it and Modal remains open.
186
+ render() {
187
+ return html `<dialog
188
+ class=${classMap({
189
+ component: true,
190
+ small: this.size === 'small',
191
+ medium: this.size === 'medium',
192
+ large: this.size === 'large',
193
+ xlarge: this.size === 'xlarge',
194
+ })}
195
+ data-test="component"
196
+ @keydown=${this.#onComponentKeyDown}
197
+ ${ref(this.#componentElementRef)}
198
+ ${onResize(this.#onScrollAndResize.bind(this))})}
199
+ >
200
+ <div
201
+ class="container"
202
+ @mouseup=${this.#onContainerMouseup}
203
+ ${ref(this.#containerElementRef)}
204
+ >
205
+ <header
206
+ class=${classMap({ header: true, shadow: this.isScrolledFromTop })}
207
+ >
208
+ <div class="label-and-actions">
209
+ <h2 class="label" data-test="heading" id="heading">
210
+ ${when(this.severity, () => html `<span
211
+ aria-label="${this.#localize.term(this.severity === 'informational'
212
+ ? 'severityInformational'
213
+ : this.severity === 'critical'
214
+ ? 'severityCritical'
215
+ : 'severityMedium')} - "
216
+ class=${classMap({
217
+ severity: true,
218
+ critical: this.severity === 'critical',
219
+ informational: this.severity === 'informational',
220
+ medium: this.severity === 'medium',
221
+ })}
222
+ data-test="severity"
223
+ >
224
+ ${this.severity && icons[this.severity]}
225
+ </span>`)}
226
+ ${when(this.backButton && !this.severity, () => html `<glide-core-modal-icon-button
227
+ class="back-button"
228
+ data-test="back-button"
229
+ label=${this.#localize.term('close')}
230
+ @click=${this.#onCloseButtonClick}
231
+ ${ref(this.#backButtonElementRef)}
232
+ >
233
+ ${icons.back}
234
+ </glide-core-modal-icon-button>`)}
235
+ ${this.label}
236
+ </h2>
237
+
238
+ <div class="header-actions" role="toolbar">
239
+ <slot
240
+ name="header-actions"
241
+ ${assertSlot([ModalIconButton], true)}
242
+ ${ref(this.#headerActionsSlotElementRef)}
243
+ >
244
+ <!-- @type {ModalIconButton} -->
245
+ </slot>
246
+
247
+ <glide-core-modal-icon-button
248
+ class="close-button"
249
+ data-test="close-button"
250
+ label=${this.#localize.term('close')}
251
+ @click=${this.#onCloseButtonClick}
252
+ ${ref(this.#closeButtonElementRef)}
253
+ >
254
+ ${xIcon}
255
+ </glide-core-modal-icon-button>
256
+ </div>
257
+ </div>
258
+
259
+ ${when(this.description, () => html `<h3
260
+ class="description"
261
+ data-test="description"
262
+ id="description"
263
+ >
264
+ ${this.description}
265
+ </h3>`)}
266
+ </header>
267
+
268
+ <div
269
+ aria-labelledby=${this.description
270
+ ? 'heading description'
271
+ : 'heading'}
272
+ class="body"
273
+ role="region"
274
+ @scroll=${this.#onScrollAndResize}
275
+ ${ref(this.#bodyElementRef)}
276
+ >
277
+ <slot ${assertSlot()}>
278
+ <!-- @type {Element | string} -->
279
+ </slot>
280
+ </div>
281
+
282
+ <footer
283
+ class=${classMap({
284
+ footer: true,
285
+ shadow: this.isScrolledFromBottom,
286
+ })}
287
+ >
288
+ <menu
289
+ aria-hidden=${!this.hasTertiarySlotContent &&
290
+ !this.hasSecondarySlotContent &&
291
+ !this.hasPrimarySlotContent}
292
+ class="actions"
293
+ >
294
+ <li aria-hidden=${!this.hasTertiarySlotContent} class="action">
295
+ <slot
296
+ class="tertiary-slot"
297
+ name="tertiary"
298
+ @slotchange=${this.#onTertiarySlotChange}
299
+ ${assertSlot([Button, Tooltip], true)}
300
+ ${ref(this.#tertiarySlotElementRef)}
301
+ >
302
+ <!-- @type {Button | Tooltip} -->
303
+ </slot>
304
+ </li>
305
+
306
+ <li aria-hidden=${!this.hasSecondarySlotContent} class="action">
307
+ <slot
308
+ name="secondary"
309
+ @slotchange=${this.#onSecondarySlotChange}
310
+ ${assertSlot([Button], true)}
311
+ ${ref(this.#secondarySlotElementRef)}
312
+ >
313
+ <!-- @type {Button} -->
314
+ </slot>
315
+ </li>
316
+
317
+ <li aria-hidden=${!this.hasPrimarySlotContent} class="action">
318
+ <slot
319
+ name="primary"
320
+ @slotchange=${this.#onPrimarySlotChange}
321
+ ${assertSlot([Button], true)}
322
+ ${ref(this.#primarySlotElementRef)}
323
+ >
324
+ <!-- @type {Button} -->
325
+ </slot>
326
+ </li>
327
+ </menu>
328
+ </footer>
329
+ </div>
330
+ </dialog>`;
331
+ }
332
+ #backButtonElementRef;
333
+ #bodyElementRef;
334
+ #closeButtonElementRef;
335
+ #componentElementRef;
336
+ #containerElementRef;
337
+ #headerActionsSlotElementRef;
338
+ #isContainerClick;
339
+ #isOpen;
340
+ #localize;
341
+ #primarySlotElementRef;
342
+ #secondarySlotElementRef;
343
+ #tertiarySlotElementRef;
344
+ // An arrow function field instead of a method so `this` is closed over and
345
+ // set to the component instead of `document`.
346
+ #onContainerClick;
347
+ // An arrow function field instead of a method so `this` is closed over and
348
+ // set to the component instead of `document`.
349
+ #onDocumentClick;
350
+ #hide() {
351
+ document.documentElement.classList.remove('private-glide-core-modal-lock-scroll');
352
+ this.#componentElementRef.value?.close();
353
+ }
354
+ #onCloseButtonClick() {
355
+ this.open = false;
356
+ }
357
+ #onComponentKeyDown(event) {
358
+ if (event.key === 'Escape') {
359
+ this.open = false;
360
+ // Prevent Safari from leaving full screen.
361
+ event.preventDefault();
362
+ }
363
+ }
364
+ // For the case where the user accidentally mouses down on the Modal's backdrop,
365
+ // then moves the mouse inside Modal before mousing up. Without this handler, Modal
366
+ // would close instead of remaining open. The reason it's needed in addition to
367
+ // the "click" handler is because programmatic clicks don't generate "mousedown"
368
+ // events. And we ran into a case where a consumer was calling `click()` on an
369
+ // element inside Modal, inadvertently closing it. Otherwise, this event handler
370
+ // would suffice.
371
+ #onContainerMouseup() {
372
+ this.#isContainerClick = true;
373
+ }
374
+ #onPrimarySlotChange() {
375
+ this.hasPrimarySlotContent = Boolean(this.#primarySlotElementRef.value?.assignedElements().length);
376
+ }
377
+ #onScrollAndResize() {
378
+ if (this.open && this.#bodyElementRef.value) {
379
+ if (this.#bodyElementRef.value.scrollHeight >
380
+ this.#bodyElementRef.value.clientHeight) {
381
+ this.isScrolledFromTop = this.#bodyElementRef.value.scrollTop > 0;
382
+ this.isScrolledFromBottom =
383
+ this.#bodyElementRef.value.scrollHeight -
384
+ this.#bodyElementRef.value.scrollTop -
385
+ this.#bodyElementRef.value.clientHeight >
386
+ 0;
387
+ }
388
+ else {
389
+ this.isScrolledFromTop = false;
390
+ this.isScrolledFromBottom = false;
391
+ }
392
+ }
393
+ }
394
+ #onSecondarySlotChange() {
395
+ this.hasSecondarySlotContent = Boolean(this.#secondarySlotElementRef.value?.assignedElements().length);
396
+ }
397
+ #onTertiarySlotChange() {
398
+ this.hasTertiarySlotContent = Boolean(this.#tertiarySlotElementRef.value?.assignedElements().length);
399
+ }
400
+ #show() {
401
+ document.documentElement.classList.add('private-glide-core-modal-lock-scroll');
402
+ this.#componentElementRef.value?.showModal();
403
+ }
404
+ };
405
+ __decorate([
406
+ property({ reflect: true }),
407
+ required
408
+ ], Modal.prototype, "label", void 0);
409
+ __decorate([
410
+ property({ attribute: 'back-button', type: Boolean, reflect: true })
411
+ ], Modal.prototype, "backButton", void 0);
412
+ __decorate([
413
+ property({ reflect: true })
414
+ ], Modal.prototype, "description", void 0);
415
+ __decorate([
416
+ property({ reflect: true, type: Boolean })
417
+ ], Modal.prototype, "open", null);
418
+ __decorate([
419
+ property({ reflect: true })
420
+ ], Modal.prototype, "severity", void 0);
421
+ __decorate([
422
+ property({ reflect: true, useDefault: true })
423
+ ], Modal.prototype, "size", void 0);
424
+ __decorate([
425
+ property({ reflect: true })
426
+ ], Modal.prototype, "version", void 0);
427
+ __decorate([
428
+ state()
429
+ ], Modal.prototype, "hasPrimarySlotContent", void 0);
430
+ __decorate([
431
+ state()
432
+ ], Modal.prototype, "hasSecondarySlotContent", void 0);
433
+ __decorate([
434
+ state()
435
+ ], Modal.prototype, "hasTertiarySlotContent", void 0);
436
+ __decorate([
437
+ state()
438
+ ], Modal.prototype, "isScrolledFromBottom", void 0);
439
+ __decorate([
440
+ state()
441
+ ], Modal.prototype, "isScrolledFromTop", void 0);
442
+ Modal = __decorate([
443
+ customElement('glide-core-modal'),
444
+ final
445
+ ], Modal);
446
+ export default Modal;
447
+ const icons = {
448
+ back: html `
449
+ <svg
450
+ style=${styleMap({
451
+ height: '1.25rem',
452
+ width: '1.25rem',
453
+ })}
454
+ viewBox="0 0 24 24"
455
+ fill="none"
456
+ >
457
+ <path
458
+ d="M12 18C11.4477 18 11 18.4477 11 19C11 19.5523 11.4477 20 12 20V18ZM20 14.5C20 16.433 18.433 18 16.5 18V20C19.5376 20 22 17.5376 22 14.5H20ZM16.5 11C18.433 11 20 12.567 20 14.5H22C22 11.4624 19.5376 9 16.5 9V11ZM16.5 18H12V20H16.5V18ZM16.5 9H3V11H16.5V9Z"
459
+ fill="currentColor"
460
+ />
461
+ <path
462
+ d="M7 6L3 10L7 14"
463
+ stroke="currentColor"
464
+ stroke-width="2"
465
+ stroke-linecap="round"
466
+ stroke-linejoin="round"
467
+ />
468
+ </svg>
469
+ `,
470
+ critical: severityCriticalIcon,
471
+ informational: severityInformationalIcon,
472
+ medium: severityMediumIcon,
473
+ };