@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 +1,130 @@
1
- var __decorate=this&&this.__decorate||function(t,e,o,i){var r,s=arguments.length,a=s<3?e:null===i?i=Object.getOwnPropertyDescriptor(e,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,o,i);else for(var l=t.length-1;l>=0;l--)(r=t[l])&&(a=(s<3?r(a):s>3?r(e,o,a):r(e,o))||a);return s>3&&a&&Object.defineProperty(e,o,a),a};import{html,LitElement}from"lit";import{customElement,property}from"lit/decorators.js";import{classMap}from"lit/directives/class-map.js";import{map}from"lit/directives/map.js";import{when}from"lit/directives/when.js";import styles from"./tooltip.container.styles.js";import shadowRootMode from"./library/shadow-root-mode.js";import final from"./library/final.js";import uniqueId from"./library/unique-id.js";let TooltipContainer=class TooltipContainer extends LitElement{constructor(){super(...arguments),this.screenreaderHidden=!1,this.shortcut=[],this.#t=!1}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}get disabled(){return this.#t}set disabled(t){this.#t=t,this.role=t||this.screenreaderHidden?"none":"tooltip"}connectedCallback(){super.connectedCallback(),this.id=uniqueId(),this.role=this.role=this.disabled||this.screenreaderHidden?"none":"tooltip",this.slot="private"}render(){return html`<div aria-hidden="${this.screenreaderHidden}" class="${classMap({component:!0})}"><div class="label-and-shortcut"><div class="label">${this.label}</div><kbd class="${classMap({shortcut:!0,visible:this.shortcut.length>0})}" data-test="shortcut">${1===this.shortcut.length?this.shortcut.at(0):map(this.shortcut,((t,e)=>html`<kbd>${t}</kbd> ${e===this.shortcut.length-1?"":" + "}`))}</kbd></div>${when(this.description,(()=>html`<div class="description">${this.description}</div>`))}</div>`}#t};__decorate([property({reflect:!0})],TooltipContainer.prototype,"description",void 0),__decorate([property({type:Boolean})],TooltipContainer.prototype,"disabled",null),__decorate([property()],TooltipContainer.prototype,"label",void 0),__decorate([property()],TooltipContainer.prototype,"placement",void 0),__decorate([property({attribute:"screenreader-hidden",type:Boolean})],TooltipContainer.prototype,"screenreaderHidden",void 0),__decorate([property({type:Array})],TooltipContainer.prototype,"shortcut",void 0),TooltipContainer=__decorate([customElement("glide-core-private-tooltip-container"),final],TooltipContainer);export default TooltipContainer;
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 { map } from 'lit/directives/map.js';
11
+ import { when } from 'lit/directives/when.js';
12
+ import styles from './tooltip.container.styles.js';
13
+ import shadowRootMode from './library/shadow-root-mode.js';
14
+ import final from './library/final.js';
15
+ import uniqueId from './library/unique-id.js';
16
+ // This component exists because Tooltip's target and its tooltip both need to
17
+ // be in the light DOM so the `aria-describedby` on its target can be associated
18
+ // with the ID it references. Tooltip adds this element to its light DOM and then
19
+ // associates it with its target.
20
+ //
21
+ // One alternative solution is to ask consumers to add this component to Tooltip's
22
+ // default slot. But that would be additional work for them and would be a less
23
+ // natural API because consumers would pass `label`, `shortcut`, and other
24
+ // attributes to Tooltip Container instead of Tooltip.
25
+ //
26
+ // Another is to require that consumers always wrap their default slot content
27
+ // in an element, such as `<div>`. But an apparently stray `<div>` in our Storybook
28
+ // code example would beget questions or may be removed by the consumer after
29
+ // copying the code, resulting in an error from Tooltip and frustration.
30
+ //
31
+ // The latter solution would also prevent us from restricting allowed content by
32
+ // using an attribute (`label`). We'd be forced to allow arbitrary content via a
33
+ // slot.
34
+ /**
35
+ * @attr {string} [description]
36
+ * @attr {boolean} [disabled=false]
37
+ * @attr {string} [label]
38
+ * @attr {'bottom'|'left'|'right'|'top'} [placement]
39
+ * @attr {boolean} [screenreader-hidden=false]
40
+ * @attr {string[]} [shortcut=[]]
41
+ */
42
+ let TooltipContainer = class TooltipContainer extends LitElement {
43
+ constructor() {
44
+ super(...arguments);
45
+ this.screenreaderHidden = false;
46
+ this.shortcut = [];
47
+ this.#isDisabled = false;
48
+ }
49
+ static { this.shadowRootOptions = {
50
+ ...LitElement.shadowRootOptions,
51
+ mode: shadowRootMode,
52
+ }; }
53
+ static { this.styles = styles; }
54
+ /**
55
+ * @default false
56
+ */
57
+ get disabled() {
58
+ return this.#isDisabled;
59
+ }
60
+ set disabled(isDisabled) {
61
+ this.#isDisabled = isDisabled;
62
+ this.role = isDisabled || this.screenreaderHidden ? 'none' : 'tooltip';
63
+ }
64
+ connectedCallback() {
65
+ super.connectedCallback();
66
+ this.id = uniqueId();
67
+ this.role = this.role =
68
+ this.disabled || this.screenreaderHidden ? 'none' : 'tooltip';
69
+ this.slot = 'private';
70
+ }
71
+ render() {
72
+ return html `
73
+ <div
74
+ aria-hidden=${this.screenreaderHidden}
75
+ class=${classMap({
76
+ component: true,
77
+ })}
78
+ >
79
+ <div class="label-and-shortcut">
80
+ <div class="label">${this.label}</div>
81
+
82
+ <kbd
83
+ class=${classMap({
84
+ shortcut: true,
85
+ visible: this.shortcut.length > 0,
86
+ })}
87
+ data-test="shortcut"
88
+ >
89
+ ${this.shortcut.length === 1
90
+ ? this.shortcut.at(0)
91
+ : map(this.shortcut, (shortcut, index) => {
92
+ return html `
93
+ <kbd>${shortcut}</kbd>
94
+ ${index === this.shortcut.length - 1 ? '' : ' + '}
95
+ `;
96
+ })}
97
+ </kbd>
98
+ </div>
99
+
100
+ ${when(this.description, () => {
101
+ return html `<div class="description">${this.description}</div>`;
102
+ })}
103
+ </div>
104
+ `;
105
+ }
106
+ #isDisabled;
107
+ };
108
+ __decorate([
109
+ property({ reflect: true })
110
+ ], TooltipContainer.prototype, "description", void 0);
111
+ __decorate([
112
+ property({ type: Boolean })
113
+ ], TooltipContainer.prototype, "disabled", null);
114
+ __decorate([
115
+ property()
116
+ ], TooltipContainer.prototype, "label", void 0);
117
+ __decorate([
118
+ property()
119
+ ], TooltipContainer.prototype, "placement", void 0);
120
+ __decorate([
121
+ property({ attribute: 'screenreader-hidden', type: Boolean })
122
+ ], TooltipContainer.prototype, "screenreaderHidden", void 0);
123
+ __decorate([
124
+ property({ type: Array })
125
+ ], TooltipContainer.prototype, "shortcut", void 0);
126
+ TooltipContainer = __decorate([
127
+ customElement('glide-core-private-tooltip-container'),
128
+ final
129
+ ], TooltipContainer);
130
+ export default TooltipContainer;
@@ -1,4 +1,6 @@
1
- import{css}from"lit";export default[css`
1
+ import { css } from 'lit';
2
+ export default [
3
+ css `
2
4
  .component {
3
5
  background-color: var(
4
6
  --glide-core-private-color-tooltip-surface-container
@@ -48,4 +50,5 @@ import{css}from"lit";export default[css`
48
50
  kbd {
49
51
  font-family: var(--glide-core-typography-family-primary);
50
52
  }
51
- `];
53
+ `,
54
+ ];
package/dist/tooltip.js CHANGED
@@ -1 +1,484 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,i){var r,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 a=e.length-1;a>=0;a--)(r=e[a])&&(l=(s<3?r(l):s>3?r(t,o,l):r(t,o))||l);return s>3&&l&&Object.defineProperty(t,o,l),l};import{html,LitElement}from"lit";import{arrow,autoUpdate,computePosition,flip,limitShift,offset,shift}from"@floating-ui/dom";import{choose}from"lit/directives/choose.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import packageJson from"../package.json"with{type:"json"};import styles from"./tooltip.styles.js";import"./tooltip.container.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 Tooltip=class Tooltip extends LitElement{constructor(){super(...arguments),this.version=packageJson.version,this.effectivePlacement=this.placement??"bottom",this.#e=createRef(),this.#t=!1,this.#o=!1,this.#i=!1,this.#r=[],this.#s=createRef(),this.#l=createRef()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}static{this.styles=styles}get label(){return this.#a}set label(e){this.#a=e;const t=this.querySelector("glide-core-private-tooltip-container");t&&(t.label=e)}get description(){return this.#n}set description(e){this.#n=e;const t=this.querySelector("glide-core-private-tooltip-container");t&&(t.description=e)}get disabled(){return this.#t}set disabled(e){this.#t=e,this.open&&!e?this.#c():this.#d();const t=this.querySelector("glide-core-private-tooltip-container");t&&(t.disabled=e);const o=this.#s.value?.assignedElements().at(0);t&&o&&!this.disabled&&!this.screenreaderHidden?o.setAttribute("aria-describedby",t.id):t&&o&&o.removeAttribute("aria-describedby")}get offset(){return this.#p??Number.parseFloat(window.getComputedStyle(document.body).getPropertyValue("--glide-core-spacing-base-xxs"))*Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize)}set offset(e){this.#p=e}get open(){return this.#o}set open(e){const t=e!==this.#o;this.#o=e,e&&t&&!this.disabled?(this.#c(),this.dispatchEvent(new Event("toggle",{bubbles:!0,composed:!0}))):t&&!this.disabled&&(this.#d(),this.dispatchEvent(new Event("toggle",{bubbles:!0,composed:!0})))}get screenreaderHidden(){return this.#i}set screenreaderHidden(e){this.#i=e;const t=this.querySelector("glide-core-private-tooltip-container");t&&(t.screenreaderHidden=e);const o=this.#s.value?.assignedElements().at(0);t&&o&&!this.disabled&&!this.screenreaderHidden?o.setAttribute("aria-describedby",t.id):t&&o&&o.removeAttribute("aria-describedby")}get shortcut(){return this.#r}set shortcut(e){this.#r=e;const t=this.querySelector("glide-core-private-tooltip-container");t&&(t.shortcut=e)}disconnectedCallback(){super.disconnectedCallback(),clearTimeout(this.#h),clearTimeout(this.#m)}firstUpdated(){this.#l.value&&(this.#l.value.popover="manual"),this.open&&!this.disabled&&this.#c();const e=document.createElement("glide-core-private-tooltip-container");e.label=this.label,e.description=this.description,e.screenreaderHidden=this.screenreaderHidden,e.shortcut=this.shortcut,this.append(e)}render(){return html`<div class="component" data-test="component" @mouseover="${this.#u}" @mouseout="${this.#f}"><div class="target-slot-container"><slot class="target-slot" data-test="target-slot" name="target" @focusin="${this.#v}" @focusout="${this.#g}" @keydown="${this.#y}" @slotchange="${this.#b}" ${assertSlot()} ${ref(this.#s)}></slot></div><div class="${classMap({tooltip:!0,[this.effectivePlacement]:!0})}" id="tooltip" data-test="tooltip" data-open-delay="300" data-close-delay="200" ${ref(this.#l)}><div class="${classMap({arrow:!0,[this.effectivePlacement]:!0})}" data-test="arrow" ${ref(this.#e)}>${choose(this.effectivePlacement,[["top",()=>icons.topArrow],["right",()=>icons.rightArrow],["bottom",()=>icons.bottomArrow],["left",()=>icons.leftArrow]])}</div><div class="${classMap({content:!0})}"><slot class="default-slot" name="private"></slot></div></div></div>`}#e;#w;#h;#n;#t;#o;#i;#a;#p;#m;#r;#s;#l;#E(){clearTimeout(this.#h)}#d(){this.#l.value?.hidePopover(),this.#w?.()}#f(){this.#R(),clearTimeout(this.#m)}#u(){this.#E(),this.#m=setTimeout((()=>{this.open=!0}),Number(this.#l.value?.dataset.openDelay))}#b(){const e=this.querySelector("glide-core-private-tooltip-container"),t=this.#s.value?.assignedElements().at(0);e&&t&&!this.disabled&&!this.screenreaderHidden&&t.setAttribute("aria-describedby",e.id)}#v(){this.open=!0}#g(){this.open=!1}#y(e){"Escape"===e.key&&(e.preventDefault(),this.open=!1)}#R(){this.#h=setTimeout((()=>{this.open=!1}),Number(this.#l.value?.dataset.closeDelay))}#c(){this.disabled||(this.#w?.(),this.#s.value&&this.#l.value&&(this.#w=autoUpdate(this.#s.value,this.#l.value,(()=>{(async()=>{if(this.#s.value&&this.#l.value&&this.#e.value){const{x:e,y:t,placement:o,middlewareData:i}=await computePosition(this.#s.value,this.#l.value,{placement:this.placement,middleware:[offset(this.offset),flip({fallbackStrategy:"initialPlacement"}),shift({crossAxis:!0,limiter:limitShift({offset:20})}),arrow({element:this.#e.value})]});Object.assign(this.#l.value.style,{left:`${e}px`,top:`${t}px`}),Object.assign(this.#e.value.style,{left:i.arrow?.x?`${i.arrow.x}px`:null,top:i.arrow?.y?`${i.arrow.y}px`:null}),this.effectivePlacement=o,this.#l.value.showPopover();const r=this.querySelector("glide-core-private-tooltip-container");r&&("bottom"===o||"left"===o||"right"===o||"top"===o)&&(r.placement=o)}})()}))))}};__decorate([property({reflect:!0}),required],Tooltip.prototype,"label",null),__decorate([property({reflect:!0})],Tooltip.prototype,"description",null),__decorate([property({reflect:!0,type:Boolean})],Tooltip.prototype,"disabled",null),__decorate([property({reflect:!0,type:Number})],Tooltip.prototype,"offset",null),__decorate([property({reflect:!0,type:Boolean})],Tooltip.prototype,"open",null),__decorate([property({reflect:!0})],Tooltip.prototype,"placement",void 0),__decorate([property({attribute:"screenreader-hidden",reflect:!0,type:Boolean})],Tooltip.prototype,"screenreaderHidden",null),__decorate([property({reflect:!0,type:Array})],Tooltip.prototype,"shortcut",null),__decorate([property({reflect:!0})],Tooltip.prototype,"version",void 0),__decorate([state()],Tooltip.prototype,"effectivePlacement",void 0),Tooltip=__decorate([customElement("glide-core-tooltip"),final],Tooltip);export default Tooltip;const icons={topArrow:html`<svg aria-hidden="true" viewBox="0 0 10 6" fill="none"><path d="M4.23178 5.07814C4.63157 5.55789 5.36843 5.55789 5.76822 5.07813L10 -7.9486e-08L-2.62268e-07 3.57628e-07L4.23178 5.07814Z" fill="currentColor"/></svg>`,rightArrow:html`<svg aria-hidden="true" viewBox="0 0 6 10" fill="none"><path d="M0.921865 4.23178C0.442111 4.63157 0.442112 5.36843 0.921866 5.76822L6 10L6 -2.62268e-07L0.921865 4.23178Z" fill="currentColor"/></svg>`,bottomArrow:html`<svg aria-hidden="true" viewBox="0 0 10 6" fill="none"><path d="M4.23178 0.921865C4.63157 0.442111 5.36843 0.442112 5.76822 0.921866L10 6L-2.62268e-07 6L4.23178 0.921865Z" fill="currentColor"/></svg>`,leftArrow:html`<svg aria-hidden="true" viewBox="0 0 6 10" fill="none"><path d="M5.07814 4.23178C5.55789 4.63157 5.55789 5.36843 5.07813 5.76822L-4.37114e-07 10L0 -2.62268e-07L5.07814 4.23178Z" 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 { html, LitElement } from 'lit';
8
+ import { arrow, autoUpdate, computePosition, flip, limitShift, offset, shift, } from '@floating-ui/dom';
9
+ import { choose } from 'lit/directives/choose.js';
10
+ import { classMap } from 'lit/directives/class-map.js';
11
+ import { createRef, ref } from 'lit/directives/ref.js';
12
+ import { customElement, property, state } from 'lit/decorators.js';
13
+ import packageJson from '../package.json' with { type: 'json' };
14
+ import styles from './tooltip.styles.js';
15
+ import './tooltip.container.js';
16
+ import assertSlot from './library/assert-slot.js';
17
+ import shadowRootMode from './library/shadow-root-mode.js';
18
+ import final from './library/final.js';
19
+ import required from './library/required.js';
20
+ /**
21
+ * @attr {string} label
22
+ * @attr {string} [description]
23
+ * @attr {boolean} [disabled=false]
24
+ * @attr {number} [offset=4]
25
+ * @attr {boolean} [open=false]
26
+ * @attr {'bottom'|'left'|'right'|'top'} [placement] - The placement of the tooltip relative to its target. Automatic placement will take over if the tooltip is cut off by the viewport.
27
+ * @attr {boolean} [screenreader-hidden=false]
28
+ * @attr {string[]} [shortcut=[]]
29
+ *
30
+ * @readonly
31
+ * @attr {string} [version]
32
+ *
33
+ * @slot {TooltipContainer} [private]
34
+ * @slot {Element} target - The element to which the tooltip will anchor. Can be any element with an implicit or explicit ARIA role.
35
+ *
36
+ * @fires {Event} toggle
37
+ */
38
+ let Tooltip = class Tooltip extends LitElement {
39
+ constructor() {
40
+ super(...arguments);
41
+ this.version = packageJson.version;
42
+ this.effectivePlacement = this.placement ?? 'bottom';
43
+ this.#arrowElementRef = createRef();
44
+ this.#isDisabled = false;
45
+ this.#isOpen = false;
46
+ this.#isScreenreaderHidden = false;
47
+ this.#shortcut = [];
48
+ this.#targetSlotElementRef = createRef();
49
+ this.#tooltipElementRef = createRef();
50
+ }
51
+ static { this.shadowRootOptions = {
52
+ ...LitElement.shadowRootOptions,
53
+ mode: shadowRootMode,
54
+ }; }
55
+ static { this.styles = styles; }
56
+ /**
57
+ * @default undefined
58
+ */
59
+ get label() {
60
+ return this.#label;
61
+ }
62
+ set label(label) {
63
+ this.#label = label;
64
+ const container = this.querySelector('glide-core-private-tooltip-container');
65
+ if (container) {
66
+ container.label = label;
67
+ }
68
+ }
69
+ /**
70
+ * @default undefined
71
+ */
72
+ get description() {
73
+ return this.#description;
74
+ }
75
+ set description(description) {
76
+ this.#description = description;
77
+ const container = this.querySelector('glide-core-private-tooltip-container');
78
+ if (container) {
79
+ container.description = description;
80
+ }
81
+ }
82
+ /**
83
+ * @default false
84
+ */
85
+ get disabled() {
86
+ return this.#isDisabled;
87
+ }
88
+ set disabled(isDisabled) {
89
+ this.#isDisabled = isDisabled;
90
+ if (this.open && !isDisabled) {
91
+ this.#show();
92
+ }
93
+ else {
94
+ this.#hide();
95
+ }
96
+ const container = this.querySelector('glide-core-private-tooltip-container');
97
+ if (container) {
98
+ container.disabled = isDisabled;
99
+ }
100
+ const target = this.#targetSlotElementRef.value?.assignedElements().at(0);
101
+ if (container && target && !this.disabled && !this.screenreaderHidden) {
102
+ target.setAttribute('aria-describedby', container.id);
103
+ }
104
+ else if (container && target) {
105
+ target.removeAttribute('aria-describedby');
106
+ }
107
+ }
108
+ /**
109
+ * @default 4
110
+ */
111
+ get offset() {
112
+ return (this.#offset ??
113
+ Number.parseFloat(window
114
+ .getComputedStyle(document.body)
115
+ .getPropertyValue('--glide-core-spacing-base-xxs')) *
116
+ Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize));
117
+ }
118
+ set offset(offset) {
119
+ this.#offset = offset;
120
+ }
121
+ /**
122
+ * @default false
123
+ */
124
+ get open() {
125
+ return this.#isOpen;
126
+ }
127
+ /**
128
+ * @default false
129
+ */
130
+ set open(isOpen) {
131
+ const hasChanged = isOpen !== this.#isOpen;
132
+ this.#isOpen = isOpen;
133
+ if (isOpen && hasChanged && !this.disabled) {
134
+ this.#show();
135
+ this.dispatchEvent(new Event('toggle', { bubbles: true, composed: true }));
136
+ }
137
+ else if (hasChanged && !this.disabled) {
138
+ this.#hide();
139
+ this.dispatchEvent(new Event('toggle', { bubbles: true, composed: true }));
140
+ }
141
+ }
142
+ /**
143
+ * @default false
144
+ */
145
+ get screenreaderHidden() {
146
+ return this.#isScreenreaderHidden;
147
+ }
148
+ set screenreaderHidden(isHidden) {
149
+ this.#isScreenreaderHidden = isHidden;
150
+ const container = this.querySelector('glide-core-private-tooltip-container');
151
+ if (container) {
152
+ container.screenreaderHidden = isHidden;
153
+ }
154
+ const target = this.#targetSlotElementRef.value?.assignedElements().at(0);
155
+ if (container && target && !this.disabled && !this.screenreaderHidden) {
156
+ target.setAttribute('aria-describedby', container.id);
157
+ }
158
+ else if (container && target) {
159
+ target.removeAttribute('aria-describedby');
160
+ }
161
+ }
162
+ /**
163
+ * @default []
164
+ */
165
+ get shortcut() {
166
+ return this.#shortcut;
167
+ }
168
+ set shortcut(shortcut) {
169
+ this.#shortcut = shortcut;
170
+ const container = this.querySelector('glide-core-private-tooltip-container');
171
+ if (container) {
172
+ container.shortcut = shortcut;
173
+ }
174
+ }
175
+ disconnectedCallback() {
176
+ super.disconnectedCallback();
177
+ clearTimeout(this.#closeTimeoutId);
178
+ clearTimeout(this.#openTimeoutId);
179
+ }
180
+ firstUpdated() {
181
+ if (this.#tooltipElementRef.value) {
182
+ // `popover` is used so the tooltip can break out of Modal or another container
183
+ // that has `overflow: hidden`. And elements with `popover` are positioned
184
+ // relative to the viewport. Thus Floating UI in addition to `popover`.
185
+ //
186
+ // Set here instead of in the template to escape Lit Analyzer, which isn't aware
187
+ // of `popover` and doesn't have a way to disable its "no-unknown-attribute" rule.
188
+ //
189
+ // "auto" means only one popover can be open at a time. Consumers, however, may
190
+ // have popovers in own components that need to be open while this one is open.
191
+ //
192
+ // "auto" also automatically opens the popover when its target is clicked. We
193
+ // only want it to open on hover or focus.
194
+ this.#tooltipElementRef.value.popover = 'manual';
195
+ }
196
+ if (this.open && !this.disabled) {
197
+ this.#show();
198
+ }
199
+ const container = document.createElement('glide-core-private-tooltip-container');
200
+ container.label = this.label;
201
+ container.description = this.description;
202
+ container.screenreaderHidden = this.screenreaderHidden;
203
+ container.shortcut = this.shortcut;
204
+ // There's a comment at the top of `./tooltip.container.ts` explaining why we
205
+ // append this component to the light DOM.
206
+ this.append(container);
207
+ }
208
+ render() {
209
+ // Lit-a11y calls for "blur" and "focus" handlers but doesn't account for "focusin"
210
+ // and "focusout".
211
+ /* eslint-disable lit-a11y/mouse-events-have-key-events */
212
+ return html `
213
+ <div
214
+ class="component"
215
+ data-test="component"
216
+ @mouseover=${this.#onComponentMouseOver}
217
+ @mouseout=${this.#onComponentMouseOut}
218
+ >
219
+ <div class="target-slot-container">
220
+ <slot
221
+ class="target-slot"
222
+ data-test="target-slot"
223
+ name="target"
224
+ @focusin=${this.#onTargetSlotFocusIn}
225
+ @focusout=${this.#onTargetSlotFocusOut}
226
+ @keydown=${this.#onTargetSlotKeyDown}
227
+ @slotchange=${this.#onTargetSlotChange}
228
+ ${assertSlot()}
229
+ ${ref(this.#targetSlotElementRef)}
230
+ >
231
+ <!--
232
+ The element to which the tooltip will anchor.
233
+ Can be any element with an implicit or explicit ARIA role.
234
+
235
+ @required
236
+ @type {Element}
237
+ -->
238
+ </slot>
239
+ </div>
240
+
241
+ <div
242
+ class=${classMap({
243
+ tooltip: true,
244
+ [this.effectivePlacement]: true,
245
+ })}
246
+ id="tooltip"
247
+ data-test="tooltip"
248
+ data-open-delay="300"
249
+ data-close-delay="200"
250
+ ${ref(this.#tooltipElementRef)}
251
+ >
252
+ <div
253
+ class=${classMap({
254
+ arrow: true,
255
+ [this.effectivePlacement]: true,
256
+ })}
257
+ data-test="arrow"
258
+ ${ref(this.#arrowElementRef)}
259
+ >
260
+ ${choose(this.effectivePlacement, [
261
+ ['top', () => icons.topArrow],
262
+ ['right', () => icons.rightArrow],
263
+ ['bottom', () => icons.bottomArrow],
264
+ ['left', () => icons.leftArrow],
265
+ ])}
266
+ </div>
267
+
268
+ <div
269
+ class=${classMap({
270
+ content: true,
271
+ })}
272
+ >
273
+ <slot class="default-slot" name="private">
274
+ <!--
275
+ @type {TooltipContainer}
276
+ -->
277
+ </slot>
278
+ </div>
279
+ </div>
280
+ </div>
281
+ `;
282
+ }
283
+ #arrowElementRef;
284
+ #cleanUpFloatingUi;
285
+ #closeTimeoutId;
286
+ #description;
287
+ #isDisabled;
288
+ #isOpen;
289
+ #isScreenreaderHidden;
290
+ #label;
291
+ #offset;
292
+ #openTimeoutId;
293
+ #shortcut;
294
+ #targetSlotElementRef;
295
+ #tooltipElementRef;
296
+ #cancelClose() {
297
+ clearTimeout(this.#closeTimeoutId);
298
+ }
299
+ #hide() {
300
+ this.#tooltipElementRef.value?.hidePopover();
301
+ this.#cleanUpFloatingUi?.();
302
+ }
303
+ #onComponentMouseOut(event) {
304
+ // The timeout gives consumers a chance to cancel the event to prevent Tooltip
305
+ // from closing.
306
+ setTimeout(() => {
307
+ if (!event.defaultPrevented) {
308
+ this.#scheduleClose();
309
+ clearTimeout(this.#openTimeoutId);
310
+ }
311
+ });
312
+ }
313
+ #onComponentMouseOver(event) {
314
+ // The timeout gives consumers a chance to cancel the event to prevent Tooltip
315
+ // from opening.
316
+ setTimeout(() => {
317
+ if (!event.defaultPrevented) {
318
+ this.#cancelClose();
319
+ // The open and close delays are stored in data attributes so tests can
320
+ // configure them. Tests configure them, rather than using fake timers,
321
+ // because they need real timers so they can await Floating UI's setup.
322
+ //
323
+ // Conditionals based on `window.navigator.webdriver` in here and in
324
+ // `#scheduleClose()` would be a lot nicer. But one of that condition's
325
+ // branches would never get hit in tests. So we'd fail to meet our coverage
326
+ // thresholds.
327
+ this.#openTimeoutId = setTimeout(() => {
328
+ this.open = true;
329
+ }, Number(this.#tooltipElementRef.value?.dataset.openDelay));
330
+ }
331
+ });
332
+ }
333
+ #onTargetSlotChange() {
334
+ const container = this.querySelector('glide-core-private-tooltip-container');
335
+ const target = this.#targetSlotElementRef.value?.assignedElements().at(0);
336
+ if (container && target && !this.disabled && !this.screenreaderHidden) {
337
+ target.setAttribute('aria-describedby', container.id);
338
+ }
339
+ }
340
+ #onTargetSlotFocusIn() {
341
+ this.open = true;
342
+ }
343
+ #onTargetSlotFocusOut() {
344
+ this.open = false;
345
+ }
346
+ #onTargetSlotKeyDown(event) {
347
+ if (event.key === 'Escape') {
348
+ // Prevent Safari from leaving full screen.
349
+ event.preventDefault();
350
+ this.open = false;
351
+ }
352
+ }
353
+ #scheduleClose() {
354
+ this.#closeTimeoutId = setTimeout(() => {
355
+ this.open = false;
356
+ }, Number(this.#tooltipElementRef.value?.dataset.closeDelay));
357
+ }
358
+ #show() {
359
+ if (!this.disabled) {
360
+ this.#cleanUpFloatingUi?.();
361
+ if (this.#targetSlotElementRef.value && this.#tooltipElementRef.value) {
362
+ this.#cleanUpFloatingUi = autoUpdate(this.#targetSlotElementRef.value, this.#tooltipElementRef.value, () => {
363
+ (async () => {
364
+ if (this.#targetSlotElementRef.value &&
365
+ this.#tooltipElementRef.value &&
366
+ this.#arrowElementRef.value) {
367
+ const { x, y, placement, middlewareData } = await computePosition(this.#targetSlotElementRef.value, this.#tooltipElementRef.value, {
368
+ placement: this.placement,
369
+ middleware: [
370
+ offset(this.offset),
371
+ flip({
372
+ fallbackStrategy: 'initialPlacement',
373
+ }),
374
+ shift({
375
+ // So the tooltip can overlap its target in cases where it would otherwise
376
+ // overflow the viewport.
377
+ //
378
+ // Give a form control a super long label. Now reduce the size of your viewport.
379
+ // The tooltip should flip to the left instead of overflowing on the right.
380
+ //
381
+ // https://github.com/floating-ui/floating-ui/blob/933cacc6672e2ccd9409cf0e9f64acd7ebf450c4/website/pages/docs/shift.mdx#crossaxiskey
382
+ crossAxis: true,
383
+ limiter: limitShift({
384
+ // Shifting is limited so the arrow is never near the tooltip's rounded
385
+ // corners, which would leave a gap between the arrow and the part of
386
+ // the corner that's missing due to rounding. `20` is just a round number.
387
+ // `15` isn't enough.
388
+ offset: 20,
389
+ }),
390
+ }),
391
+ arrow({ element: this.#arrowElementRef.value }),
392
+ ],
393
+ });
394
+ Object.assign(this.#tooltipElementRef.value.style, {
395
+ left: `${x}px`,
396
+ top: `${y}px`,
397
+ });
398
+ Object.assign(this.#arrowElementRef.value.style, {
399
+ left: middlewareData.arrow?.x
400
+ ? `${middlewareData.arrow.x}px`
401
+ : null,
402
+ top: middlewareData.arrow?.y
403
+ ? `${middlewareData.arrow.y}px`
404
+ : null,
405
+ });
406
+ this.effectivePlacement = placement;
407
+ this.#tooltipElementRef.value.showPopover();
408
+ const container = this.querySelector('glide-core-private-tooltip-container');
409
+ const isSupportedPlacement = placement === 'bottom' ||
410
+ placement === 'left' ||
411
+ placement === 'right' ||
412
+ placement === 'top';
413
+ if (container && isSupportedPlacement) {
414
+ container.placement = placement;
415
+ }
416
+ }
417
+ })();
418
+ });
419
+ }
420
+ }
421
+ }
422
+ };
423
+ __decorate([
424
+ property({ reflect: true }),
425
+ required
426
+ ], Tooltip.prototype, "label", null);
427
+ __decorate([
428
+ property({ reflect: true })
429
+ ], Tooltip.prototype, "description", null);
430
+ __decorate([
431
+ property({ reflect: true, type: Boolean })
432
+ ], Tooltip.prototype, "disabled", null);
433
+ __decorate([
434
+ property({ reflect: true, type: Number })
435
+ ], Tooltip.prototype, "offset", null);
436
+ __decorate([
437
+ property({ reflect: true, type: Boolean })
438
+ ], Tooltip.prototype, "open", null);
439
+ __decorate([
440
+ property({ reflect: true })
441
+ ], Tooltip.prototype, "placement", void 0);
442
+ __decorate([
443
+ property({ attribute: 'screenreader-hidden', reflect: true, type: Boolean })
444
+ ], Tooltip.prototype, "screenreaderHidden", null);
445
+ __decorate([
446
+ property({ reflect: true, type: Array })
447
+ ], Tooltip.prototype, "shortcut", null);
448
+ __decorate([
449
+ property({ reflect: true })
450
+ ], Tooltip.prototype, "version", void 0);
451
+ __decorate([
452
+ state()
453
+ ], Tooltip.prototype, "effectivePlacement", void 0);
454
+ Tooltip = __decorate([
455
+ customElement('glide-core-tooltip'),
456
+ final
457
+ ], Tooltip);
458
+ export default Tooltip;
459
+ const icons = {
460
+ topArrow: html `<svg aria-hidden="true" viewBox="0 0 10 6" fill="none">
461
+ <path
462
+ d="M4.23178 5.07814C4.63157 5.55789 5.36843 5.55789 5.76822 5.07813L10 -7.9486e-08L-2.62268e-07 3.57628e-07L4.23178 5.07814Z"
463
+ fill="currentColor"
464
+ />
465
+ </svg>`,
466
+ rightArrow: html `<svg aria-hidden="true" viewBox="0 0 6 10" fill="none">
467
+ <path
468
+ d="M0.921865 4.23178C0.442111 4.63157 0.442112 5.36843 0.921866 5.76822L6 10L6 -2.62268e-07L0.921865 4.23178Z"
469
+ fill="currentColor"
470
+ />
471
+ </svg>`,
472
+ bottomArrow: html `<svg aria-hidden="true" viewBox="0 0 10 6" fill="none">
473
+ <path
474
+ d="M4.23178 0.921865C4.63157 0.442111 5.36843 0.442112 5.76822 0.921866L10 6L-2.62268e-07 6L4.23178 0.921865Z"
475
+ fill="currentColor"
476
+ />
477
+ </svg>`,
478
+ leftArrow: html `<svg aria-hidden="true" viewBox="0 0 6 10" fill="none">
479
+ <path
480
+ d="M5.07814 4.23178C5.55789 4.63157 5.55789 5.36843 5.07813 5.76822L-4.37114e-07 10L0 -2.62268e-07L5.07814 4.23178Z"
481
+ fill="currentColor"
482
+ />
483
+ </svg>`,
484
+ };