@brightspot/ui 1.4.1 → 1.5.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 (80) hide show
  1. package/README.md +12 -0
  2. package/dist/components/avatar/Avatar.d.ts +1 -1
  3. package/dist/components/avatar/Avatar.d.ts.map +1 -1
  4. package/dist/components/avatar/Avatar.js +3 -1
  5. package/dist/components/avatar/Avatar.js.map +1 -1
  6. package/dist/components/popover/Popover.d.ts +161 -0
  7. package/dist/components/popover/Popover.d.ts.map +1 -0
  8. package/dist/components/popover/Popover.js +436 -0
  9. package/dist/components/popover/Popover.js.map +1 -0
  10. package/dist/components/widget/Widget.css +104 -0
  11. package/dist/components/widget/Widget.d.ts +170 -0
  12. package/dist/components/widget/Widget.d.ts.map +1 -0
  13. package/dist/components/widget/Widget.js +434 -0
  14. package/dist/components/widget/Widget.js.map +1 -0
  15. package/dist/custom-elements.json +687 -184
  16. package/dist/global.d.ts +5 -0
  17. package/dist/storybook/assets/{Avatar.stories-QxWs-YfX.js → Avatar.stories-CPVNxsaA.js} +37 -32
  18. package/dist/storybook/assets/AvatarGroup.stories-Bl65NGHl.js +225 -0
  19. package/dist/storybook/assets/{Badge.stories-BpaApWbR.js → Badge.stories-Bbnc6fRy.js} +1 -1
  20. package/dist/storybook/assets/{Button.stories-C5h2usmd.js → Button.stories-CRJ5n2y4.js} +1 -1
  21. package/dist/storybook/assets/{CircularProgress.stories-DlPOiGja.js → CircularProgress.stories-D9vBj3JJ.js} +1 -1
  22. package/dist/storybook/assets/{ClipboardMixin.stories-Bb45-UOM.js → ClipboardMixin.stories-Dm-Jm4yb.js} +7 -7
  23. package/dist/storybook/assets/Color-6BZIO3FS-BcNIJY1U.js +1 -0
  24. package/dist/storybook/assets/{Colors.stories-DP2JKWUJ.js → Colors.stories-B9_090wL.js} +1 -1
  25. package/dist/storybook/assets/ComponentStatesMixin-ChiFBCuo.js +1 -0
  26. package/dist/storybook/assets/{ComponentStatesMixin.stories-CyQ2aSTu.js → ComponentStatesMixin.stories-DHv9MHmE.js} +3 -3
  27. package/dist/storybook/assets/{CopyToClipboard.stories-DR7pckeV.js → CopyToClipboard.stories-gtJlTP1l.js} +1 -1
  28. package/dist/storybook/assets/{Debounce.stories-hkqyvqmg.js → Debounce.stories-BBNX7mJA.js} +1 -1
  29. package/dist/storybook/assets/{DocsRenderer-LL677BLK-Dtw9GMer.js → DocsRenderer-LL677BLK-D-E99pXl.js} +6 -6
  30. package/dist/storybook/assets/{Events.stories-BAgDzdyl.js → Events.stories-DDmydlh_.js} +1 -1
  31. package/dist/storybook/assets/{Heading.stories-CN_fPsRf.js → Heading.stories-BLGfko-i.js} +1 -1
  32. package/dist/storybook/assets/{Icon.stories-CSx_2K8V.js → Icon.stories-BHnAGcFF.js} +1 -1
  33. package/dist/storybook/assets/{LinearProgress.stories-In48DY2g.js → LinearProgress.stories-Dx26a0P_.js} +1 -1
  34. package/dist/storybook/assets/Popover.stories-CbqpY6YR.js +431 -0
  35. package/dist/storybook/assets/ReadyMixin-BHiHoIbr.js +1 -0
  36. package/dist/storybook/assets/{Rtc.stories-19d7WXe4.js → Rtc.stories-CAjDv_Ub.js} +1 -1
  37. package/dist/storybook/assets/{ScrollShadow.stories-BFjracVd.js → ScrollShadow.stories-BSV4U-tq.js} +1 -1
  38. package/dist/storybook/assets/{Throttle.stories-DD6ydiVq.js → Throttle.stories-kaxXQ8RZ.js} +1 -1
  39. package/dist/storybook/assets/Tooltip.stories-CsxXkztr.js +143 -0
  40. package/dist/storybook/assets/Widget.stories-DqATHnSq.js +233 -0
  41. package/dist/storybook/assets/{WithTooltip-65CFNBJE-Be1dKqOF.js → WithTooltip-65CFNBJE-BtbbFYSA.js} +2 -2
  42. package/dist/storybook/assets/custom-element-UsVr97OX.js +1 -0
  43. package/dist/storybook/assets/{formatter-EIJCOSYU-anC2P5HS.js → formatter-EIJCOSYU-C87Csnpu.js} +1 -1
  44. package/dist/storybook/assets/if-defined-COHr0XBn.js +1 -0
  45. package/dist/storybook/assets/{iframe-B4njXYq6.css → iframe-BkDGeDre.css} +1 -1
  46. package/dist/storybook/assets/{iframe-Bl9oHz5c.js → iframe-CcloOV09.js} +77 -77
  47. package/dist/storybook/assets/{index-Cn5E5A3G.js → index-DP7vnJf7.js} +1 -1
  48. package/dist/storybook/assets/{onFind.stories-BMDLUk0l.js → onFind.stories-BxvoC-Z-.js} +1 -1
  49. package/dist/storybook/assets/{onRemove.stories-C3FcxtYh.js → onRemove.stories-Dwoixzb0.js} +1 -1
  50. package/dist/storybook/assets/{onVisible.stories-B8Zyu0Th.js → onVisible.stories-CinmRF9w.js} +1 -1
  51. package/dist/storybook/assets/{syntaxhighlighter-ED5Y7EFY-BfTKsIVL.js → syntaxhighlighter-ED5Y7EFY-BHLkDkOn.js} +1 -1
  52. package/dist/storybook/iframe.html +2 -2
  53. package/dist/storybook/index.json +1 -1
  54. package/dist/storybook/project.json +1 -1
  55. package/dist/tailwind-plugin-popover.d.ts +2 -0
  56. package/dist/tailwind-plugin-popover.d.ts.map +1 -0
  57. package/dist/tailwind-plugin-popover.js +177 -0
  58. package/dist/tailwind-plugin-popover.js.map +1 -0
  59. package/dist/tailwind-plugin-popover.ts +202 -0
  60. package/dist/tailwind-plugin-tooltip.d.ts +2 -0
  61. package/dist/tailwind-plugin-tooltip.d.ts.map +1 -0
  62. package/dist/tailwind-plugin-tooltip.js +184 -0
  63. package/dist/tailwind-plugin-tooltip.js.map +1 -0
  64. package/dist/tailwind-plugin-tooltip.ts +209 -0
  65. package/dist/util/EventEmitterMixin.d.ts +11 -0
  66. package/dist/util/EventEmitterMixin.d.ts.map +1 -1
  67. package/dist/util/EventEmitterMixin.js +1 -1
  68. package/dist/util/EventEmitterMixin.js.map +1 -1
  69. package/dist/util/TooltipController.d.ts +37 -0
  70. package/dist/util/TooltipController.d.ts.map +1 -0
  71. package/dist/util/TooltipController.js +133 -0
  72. package/dist/util/TooltipController.js.map +1 -0
  73. package/dist/util/TooltipMixin.d.ts +42 -0
  74. package/dist/util/TooltipMixin.d.ts.map +1 -0
  75. package/dist/util/TooltipMixin.js +401 -0
  76. package/dist/util/TooltipMixin.js.map +1 -0
  77. package/package.json +1 -1
  78. package/dist/storybook/assets/AvatarGroup.stories-Cy_Bvn7E.js +0 -211
  79. package/dist/storybook/assets/Color-6BZIO3FS-CcgGYVAo.js +0 -1
  80. package/dist/storybook/assets/ComponentStatesMixin-B7ci0thi.js +0 -1
package/README.md CHANGED
@@ -99,6 +99,18 @@ An example of including a plugin:
99
99
  ...
100
100
  ```
101
101
 
102
+ ## Web Components
103
+
104
+ Brightspot UI includes custom web components built with LitElement. FOUC (Flash of Unstyled Content) prevention is handled automatically when you import the components.
105
+
106
+ Import components in your JavaScript/TypeScript:
107
+
108
+ ```ts
109
+ import '@brightspot/ui/dist/components/widget/Widget'
110
+ ```
111
+
112
+ See the Storybook documentation for detailed usage examples and API references.
113
+
102
114
  ## Examples
103
115
 
104
116
  We use [Storybook](https://storybook.js.org/) for interactive previewing of our ui components. Launch that in the browser by running:
@@ -5,7 +5,7 @@ export interface AvatarProps {
5
5
  fallback?: string;
6
6
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
7
7
  }
8
- declare const Avatar_base: (new (...args: any[]) => import("../../util/EventEmitterMixin.js").EventEmitterMixinInterface) & (new (...args: any[]) => import("../../util/ReadyMixin.js").ReadyMixinInterface) & typeof LitElement;
8
+ declare const Avatar_base: (new (...args: any[]) => import("../../util/TooltipMixin.js").TooltipMixinInterface) & (new (...args: any[]) => import("../../util/EventEmitterMixin.js").EventEmitterMixinInterface) & (new (...args: any[]) => import("../../util/ReadyMixin.js").ReadyMixinInterface) & typeof LitElement;
9
9
  /**
10
10
  * An avatar component for displaying user profile images with fallback support.
11
11
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/avatar/Avatar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,MAAM,KAAK,CAAA;AAKtC,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAA;CAChD;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAAyC;IAC3E;;;OAGG;IAEH,GAAG,SAAK;IAER;;;OAGG;IAEH,GAAG,SAAK;IAER;;;OAGG;IAEH,QAAQ,SAAK;IAEb;;;;;;;;;OASG;IAEH,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAO;IAErD,gBAAgB;IAChB,OAAO,CAAC,cAAc,CAAe;IAErC,gBAAgB;IAEhB,OAAO,CAAC,WAAW,CAAQ;IAE3B,gBAAgB;IAEhB,OAAO,CAAC,UAAU,CAAQ;IAE1B,iBAAiB,IAAI,IAAI;IAQzB,gBAAgB;IAIhB,UAAU,IAAI,IAAI;IAWlB,YAAY,IAAI,IAAI;IAqBpB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAyBlD,MAAM;CAMP;AAMD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,MAAM,CAAA;KACrB;CACF"}
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/avatar/Avatar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,MAAM,KAAK,CAAA;AAMtC,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAA;CAChD;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,WAAuD;IACzF;;;OAGG;IAEH,GAAG,SAAK;IAER;;;OAGG;IAEH,GAAG,SAAK;IAER;;;OAGG;IAEH,QAAQ,SAAK;IAEb;;;;;;;;;OASG;IAEH,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAO;IAErD,gBAAgB;IAChB,OAAO,CAAC,cAAc,CAAe;IAErC,gBAAgB;IAEhB,OAAO,CAAC,WAAW,CAAQ;IAE3B,gBAAgB;IAEhB,OAAO,CAAC,UAAU,CAAQ;IAE1B,iBAAiB,IAAI,IAAI;IAQzB,gBAAgB;IAIhB,UAAU,IAAI,IAAI;IAWlB,YAAY,IAAI,IAAI;IAqBpB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IA2BlD,MAAM;CAMP;AAMD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,MAAM,CAAA;KACrB;CACF"}
@@ -8,6 +8,7 @@ import { LitElement, html } from 'lit';
8
8
  import { property, state } from 'lit/decorators.js';
9
9
  import { EventEmitterMixin } from '../../util/EventEmitterMixin.js';
10
10
  import { ReadyMixin } from '../../util/ReadyMixin.js';
11
+ import { TooltipMixin } from '../../util/TooltipMixin.js';
11
12
  /**
12
13
  * An avatar component for displaying user profile images with fallback support.
13
14
  *
@@ -35,7 +36,7 @@ import { ReadyMixin } from '../../util/ReadyMixin.js';
35
36
  * <btu-avatar fallback="JD" size="lg"></btu-avatar>
36
37
  * ```
37
38
  */
38
- export default class Avatar extends EventEmitterMixin(ReadyMixin(LitElement)) {
39
+ export default class Avatar extends TooltipMixin(EventEmitterMixin(ReadyMixin(LitElement))) {
39
40
  constructor() {
40
41
  super(...arguments);
41
42
  /**
@@ -109,6 +110,7 @@ export default class Avatar extends EventEmitterMixin(ReadyMixin(LitElement)) {
109
110
  }
110
111
  }
111
112
  updated(changedProperties) {
113
+ super.updated(changedProperties);
112
114
  // Reset image error state when src changes
113
115
  if (changedProperties.has('src')) {
114
116
  this.imageError = false;
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../../../src/components/avatar/Avatar.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../../../src/components/avatar/Avatar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,161 @@
1
+ import { LitElement } from 'lit';
2
+ export type PopoverOffset = 'sm' | 'md' | 'lg' | 'xl';
3
+ export interface PopoverProps {
4
+ position?: 'top' | 'bottom' | 'left' | 'right';
5
+ trigger?: 'click' | 'hover' | 'focus';
6
+ delay?: number;
7
+ offset?: PopoverOffset | null;
8
+ noArrow?: boolean;
9
+ open?: boolean;
10
+ }
11
+ declare const Popover_base: (new (...args: any[]) => import("../../util/EventEmitterMixin.js").EventEmitterMixinInterface) & (new (...args: any[]) => import("../../util/ReadyMixin.js").ReadyMixinInterface) & typeof LitElement;
12
+ /**
13
+ * A popover component for displaying rich interactive content anchored to a trigger element.
14
+ *
15
+ * Uses the native HTML Popover API for top-layer rendering, light dismiss (click-outside
16
+ * and Escape for click triggers), and focus management. CSS anchor positioning handles
17
+ * viewport-aware placement.
18
+ *
19
+ * For click triggers (`popover="auto"`), the browser provides:
20
+ * - Light dismiss (Escape key and click-outside)
21
+ * - Top-layer rendering (no z-index needed)
22
+ * - Focus restoration on close
23
+ * - `autofocus` support — add `autofocus` to an element inside `slot="content"`
24
+ * to have it receive focus when the popover opens
25
+ *
26
+ * @element btu-popover
27
+ *
28
+ * @fires {CustomEvent} btu-popover-show - Fired when the popover opens
29
+ * @fires {CustomEvent} btu-popover-hide - Fired when the popover closes
30
+ *
31
+ * @slot trigger - The element that activates the popover
32
+ * @slot content - Rich HTML content displayed inside the popover panel
33
+ *
34
+ * @example
35
+ * ```html
36
+ * <btu-popover position="bottom" trigger="click">
37
+ * <button slot="trigger">Open</button>
38
+ * <div slot="content">
39
+ * <h3>Title</h3>
40
+ * <p>Rich content here</p>
41
+ * </div>
42
+ * </btu-popover>
43
+ * ```
44
+ */
45
+ export default class Popover extends Popover_base {
46
+ /**
47
+ * Position relative to the trigger element.
48
+ * Auto-flips when constrained by the viewport.
49
+ * @attr
50
+ */
51
+ position: 'top' | 'bottom' | 'left' | 'right';
52
+ /**
53
+ * How the popover is activated.
54
+ * - 'click': Toggle on click with light dismiss
55
+ * - 'hover': Show on mouseenter with delay
56
+ * - 'focus': Show on focusin
57
+ * @attr
58
+ */
59
+ trigger: 'click' | 'hover' | 'focus';
60
+ /**
61
+ * Show delay in milliseconds (hover trigger only).
62
+ * @attr
63
+ */
64
+ delay: number;
65
+ /**
66
+ * Gap between trigger and popover (sm=4px, md=8px, lg=12px, xl=16px).
67
+ * @attr
68
+ */
69
+ offset: PopoverOffset | null;
70
+ /**
71
+ * Hide the arrow pseudo-element.
72
+ * @attr
73
+ */
74
+ noArrow: boolean;
75
+ /**
76
+ * Programmatic open/close state (reflected).
77
+ * @attr
78
+ */
79
+ open: boolean;
80
+ /**
81
+ * Accessible label for the popover panel (applied as aria-label on the dialog).
82
+ * @attr panel-label
83
+ */
84
+ panelLabel: string;
85
+ /** @internal */
86
+ private _panelEl;
87
+ /** @internal */
88
+ private _panelId;
89
+ /** @internal */
90
+ private _anchorName;
91
+ /** @internal */
92
+ private _showTimer;
93
+ /** @internal */
94
+ private _hideTimer;
95
+ /** @internal */
96
+ private _isVisible;
97
+ /** @internal */
98
+ private initialClasses;
99
+ /** @internal bound listeners */
100
+ private _onTriggerMouseEnter;
101
+ private _onTriggerMouseLeave;
102
+ private _onTriggerFocusIn;
103
+ private _onTriggerFocusOut;
104
+ private _onPanelMouseEnter;
105
+ private _onPanelMouseLeave;
106
+ private _onNativeToggle;
107
+ private _onKeyDown;
108
+ createRenderRoot(): this;
109
+ connectedCallback(): void;
110
+ disconnectedCallback(): void;
111
+ willUpdate(): void;
112
+ firstUpdated(): void;
113
+ updated(changedProperties: Map<string | number | symbol, unknown>): void;
114
+ /** @internal Creates the popover panel and moves slot="content" children into it */
115
+ private _setupPanel;
116
+ /** @internal */
117
+ private _buildPanelClasses;
118
+ /** @internal */
119
+ private _getTriggerEl;
120
+ /** @internal */
121
+ private _bindTriggerListeners;
122
+ /** @internal */
123
+ private _unbindTriggerListeners;
124
+ /** @internal */
125
+ private _bindPanelListeners;
126
+ /** @internal */
127
+ private _unbindPanelListeners;
128
+ /** @internal */
129
+ private _show;
130
+ /** @internal */
131
+ private _hide;
132
+ /** @internal Native toggle event — single source of truth for state changes */
133
+ private _handleNativeToggle;
134
+ /** @internal Escape dismisses for popover="manual" (hover/focus triggers) */
135
+ private _handleKeyDown;
136
+ /** @internal */
137
+ private _clearShowTimer;
138
+ /** @internal */
139
+ private _clearHideTimer;
140
+ /** @internal */
141
+ private _clearTimers;
142
+ /** @internal Hover trigger: show with delay */
143
+ private _handleTriggerMouseEnter;
144
+ /** @internal Hover trigger: hide with small delay for cursor travel */
145
+ private _handleTriggerMouseLeave;
146
+ /** @internal Focus trigger: show immediately */
147
+ private _handleTriggerFocusIn;
148
+ /** @internal Focus trigger: hide immediately */
149
+ private _handleTriggerFocusOut;
150
+ /** @internal Keep popover open when hovering the panel (hover trigger) */
151
+ private _handlePanelMouseEnter;
152
+ /** @internal Hide when mouse leaves the panel (hover trigger) */
153
+ private _handlePanelMouseLeave;
154
+ }
155
+ declare global {
156
+ interface HTMLElementTagNameMap {
157
+ 'btu-popover': Popover;
158
+ }
159
+ }
160
+ export {};
161
+ //# sourceMappingURL=Popover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Popover.d.ts","sourceRoot":"","sources":["../../../src/components/popover/Popover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,436 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement } from 'lit';
8
+ import { property } from 'lit/decorators.js';
9
+ import { EventEmitterMixin } from '../../util/EventEmitterMixin.js';
10
+ import { ReadyMixin } from '../../util/ReadyMixin.js';
11
+ // Tailwind content scanning requires complete class names (no template literals).
12
+ const POSITION_CLASSES = {
13
+ top: 'btu-popover-top',
14
+ bottom: 'btu-popover-bottom',
15
+ left: 'btu-popover-left',
16
+ right: 'btu-popover-right',
17
+ };
18
+ const OFFSET_CLASSES = {
19
+ sm: 'btu-popover-offset-sm',
20
+ md: 'btu-popover-offset-md',
21
+ lg: 'btu-popover-offset-lg',
22
+ xl: 'btu-popover-offset-xl',
23
+ };
24
+ /**
25
+ * A popover component for displaying rich interactive content anchored to a trigger element.
26
+ *
27
+ * Uses the native HTML Popover API for top-layer rendering, light dismiss (click-outside
28
+ * and Escape for click triggers), and focus management. CSS anchor positioning handles
29
+ * viewport-aware placement.
30
+ *
31
+ * For click triggers (`popover="auto"`), the browser provides:
32
+ * - Light dismiss (Escape key and click-outside)
33
+ * - Top-layer rendering (no z-index needed)
34
+ * - Focus restoration on close
35
+ * - `autofocus` support — add `autofocus` to an element inside `slot="content"`
36
+ * to have it receive focus when the popover opens
37
+ *
38
+ * @element btu-popover
39
+ *
40
+ * @fires {CustomEvent} btu-popover-show - Fired when the popover opens
41
+ * @fires {CustomEvent} btu-popover-hide - Fired when the popover closes
42
+ *
43
+ * @slot trigger - The element that activates the popover
44
+ * @slot content - Rich HTML content displayed inside the popover panel
45
+ *
46
+ * @example
47
+ * ```html
48
+ * <btu-popover position="bottom" trigger="click">
49
+ * <button slot="trigger">Open</button>
50
+ * <div slot="content">
51
+ * <h3>Title</h3>
52
+ * <p>Rich content here</p>
53
+ * </div>
54
+ * </btu-popover>
55
+ * ```
56
+ */
57
+ export default class Popover extends EventEmitterMixin(ReadyMixin(LitElement)) {
58
+ constructor() {
59
+ super(...arguments);
60
+ /**
61
+ * Position relative to the trigger element.
62
+ * Auto-flips when constrained by the viewport.
63
+ * @attr
64
+ */
65
+ this.position = 'bottom';
66
+ /**
67
+ * How the popover is activated.
68
+ * - 'click': Toggle on click with light dismiss
69
+ * - 'hover': Show on mouseenter with delay
70
+ * - 'focus': Show on focusin
71
+ * @attr
72
+ */
73
+ this.trigger = 'click';
74
+ /**
75
+ * Show delay in milliseconds (hover trigger only).
76
+ * @attr
77
+ */
78
+ this.delay = 300;
79
+ /**
80
+ * Gap between trigger and popover (sm=4px, md=8px, lg=12px, xl=16px).
81
+ * @attr
82
+ */
83
+ this.offset = null;
84
+ /**
85
+ * Hide the arrow pseudo-element.
86
+ * @attr
87
+ */
88
+ this.noArrow = false;
89
+ /**
90
+ * Programmatic open/close state (reflected).
91
+ * @attr
92
+ */
93
+ this.open = false;
94
+ /**
95
+ * Accessible label for the popover panel (applied as aria-label on the dialog).
96
+ * @attr panel-label
97
+ */
98
+ this.panelLabel = '';
99
+ /** @internal */
100
+ this._panelEl = null;
101
+ /** @internal */
102
+ this._panelId = `btu-popover-${crypto.randomUUID()}`;
103
+ /** @internal */
104
+ this._anchorName = `--btu-popover-trigger-${crypto.randomUUID()}`;
105
+ /** @internal */
106
+ this._showTimer = null;
107
+ /** @internal */
108
+ this._hideTimer = null;
109
+ /** @internal */
110
+ this._isVisible = false;
111
+ /** @internal */
112
+ this.initialClasses = [];
113
+ /** @internal bound listeners */
114
+ this._onTriggerMouseEnter = this._handleTriggerMouseEnter.bind(this);
115
+ this._onTriggerMouseLeave = this._handleTriggerMouseLeave.bind(this);
116
+ this._onTriggerFocusIn = this._handleTriggerFocusIn.bind(this);
117
+ this._onTriggerFocusOut = this._handleTriggerFocusOut.bind(this);
118
+ this._onPanelMouseEnter = this._handlePanelMouseEnter.bind(this);
119
+ this._onPanelMouseLeave = this._handlePanelMouseLeave.bind(this);
120
+ this._onNativeToggle = this._handleNativeToggle.bind(this);
121
+ this._onKeyDown = this._handleKeyDown.bind(this);
122
+ }
123
+ createRenderRoot() {
124
+ return this;
125
+ }
126
+ connectedCallback() {
127
+ super.connectedCallback();
128
+ if (this.className) {
129
+ this.initialClasses = this.className.split(' ').filter(c => c.trim());
130
+ }
131
+ }
132
+ disconnectedCallback() {
133
+ this._clearTimers();
134
+ this._unbindTriggerListeners();
135
+ this._unbindPanelListeners();
136
+ document.removeEventListener('keydown', this._onKeyDown);
137
+ if (this._panelEl) {
138
+ try {
139
+ this._panelEl.hidePopover();
140
+ }
141
+ catch (e) {
142
+ if (!(e instanceof DOMException && e.name === 'InvalidStateError')) {
143
+ console.warn('[btu-popover] Failed to hide popover during disconnect:', e);
144
+ }
145
+ }
146
+ this._panelEl.removeEventListener('toggle', this._onNativeToggle);
147
+ this._panelEl.remove();
148
+ this._panelEl = null;
149
+ }
150
+ this._isVisible = false;
151
+ super.disconnectedCallback();
152
+ }
153
+ willUpdate() {
154
+ const classes = [...this.initialClasses];
155
+ this.className = classes.filter(Boolean).join(' ');
156
+ }
157
+ firstUpdated() {
158
+ this._setupPanel();
159
+ this._bindTriggerListeners();
160
+ // If initially open, show immediately
161
+ if (this.open) {
162
+ this._show();
163
+ }
164
+ }
165
+ updated(changedProperties) {
166
+ super.updated(changedProperties);
167
+ if (changedProperties.has('trigger') && changedProperties.get('trigger') !== undefined) {
168
+ this._unbindTriggerListeners();
169
+ this._bindTriggerListeners();
170
+ // Update popover mode when trigger changes
171
+ if (this._panelEl) {
172
+ if (this._isVisible) {
173
+ this._hide();
174
+ }
175
+ this._panelEl.setAttribute('popover', this.trigger === 'click' ? 'auto' : 'manual');
176
+ }
177
+ }
178
+ if (changedProperties.has('position') || changedProperties.has('noArrow') || changedProperties.has('offset')) {
179
+ if (this._panelEl) {
180
+ this._panelEl.className = this._buildPanelClasses();
181
+ }
182
+ }
183
+ if (changedProperties.has('panelLabel') && this._panelEl) {
184
+ if (this.panelLabel) {
185
+ this._panelEl.setAttribute('aria-label', this.panelLabel);
186
+ }
187
+ else {
188
+ this._panelEl.removeAttribute('aria-label');
189
+ }
190
+ }
191
+ // Sync programmatic open/close
192
+ if (changedProperties.has('open') && changedProperties.get('open') !== undefined) {
193
+ if (this.open && !this._isVisible) {
194
+ this._show();
195
+ }
196
+ else if (!this.open && this._isVisible) {
197
+ this._hide();
198
+ }
199
+ }
200
+ }
201
+ /** @internal Creates the popover panel and moves slot="content" children into it */
202
+ _setupPanel() {
203
+ const triggerEl = this.querySelector('[slot="trigger"]');
204
+ const contentEl = this.querySelector('[slot="content"]');
205
+ if (!triggerEl) {
206
+ console.warn('[btu-popover] Missing required slot="trigger" element.');
207
+ return;
208
+ }
209
+ // Set anchor name on trigger element
210
+ triggerEl.style.setProperty('anchor-name', this._anchorName);
211
+ // Create panel
212
+ this._panelEl = document.createElement('div');
213
+ this._panelEl.id = this._panelId;
214
+ this._panelEl.className = this._buildPanelClasses();
215
+ this._panelEl.setAttribute('role', 'dialog');
216
+ if (this.panelLabel) {
217
+ this._panelEl.setAttribute('aria-label', this.panelLabel);
218
+ }
219
+ this._panelEl.setAttribute('data-popover-internal', '');
220
+ this._panelEl.style.setProperty('position-anchor', this._anchorName);
221
+ // Set native popover attribute
222
+ this._panelEl.setAttribute('popover', this.trigger === 'click' ? 'auto' : 'manual');
223
+ // Listen for native toggle events — single source of truth for state
224
+ this._panelEl.addEventListener('toggle', this._onNativeToggle);
225
+ // Move content into panel
226
+ if (contentEl) {
227
+ contentEl.removeAttribute('slot');
228
+ contentEl.style.display = '';
229
+ this._panelEl.appendChild(contentEl);
230
+ }
231
+ this.appendChild(this._panelEl);
232
+ // Set up aria on trigger
233
+ triggerEl.setAttribute('aria-expanded', 'false');
234
+ triggerEl.setAttribute('aria-controls', this._panelId);
235
+ // Bind panel listeners for hover trigger
236
+ this._bindPanelListeners();
237
+ }
238
+ /** @internal */
239
+ _buildPanelClasses() {
240
+ const classes = ['btu-popover', POSITION_CLASSES[this.position]];
241
+ if (this.offset && OFFSET_CLASSES[this.offset])
242
+ classes.push(OFFSET_CLASSES[this.offset]);
243
+ if (this.noArrow)
244
+ classes.push('btu-popover-no-arrow');
245
+ return classes.join(' ');
246
+ }
247
+ /** @internal */
248
+ _getTriggerEl() {
249
+ return this.querySelector('[slot="trigger"]');
250
+ }
251
+ /** @internal */
252
+ _bindTriggerListeners() {
253
+ const triggerEl = this._getTriggerEl();
254
+ if (!triggerEl)
255
+ return;
256
+ if (this.trigger === 'click') {
257
+ triggerEl.setAttribute('popovertarget', this._panelId);
258
+ }
259
+ if (this.trigger === 'hover') {
260
+ triggerEl.addEventListener('mouseenter', this._onTriggerMouseEnter);
261
+ triggerEl.addEventListener('mouseleave', this._onTriggerMouseLeave);
262
+ }
263
+ if (this.trigger === 'focus') {
264
+ triggerEl.addEventListener('focusin', this._onTriggerFocusIn);
265
+ triggerEl.addEventListener('focusout', this._onTriggerFocusOut);
266
+ }
267
+ // popover="manual" doesn't get browser Escape handling — add it ourselves
268
+ if (this.trigger !== 'click') {
269
+ document.addEventListener('keydown', this._onKeyDown);
270
+ }
271
+ }
272
+ /** @internal */
273
+ _unbindTriggerListeners() {
274
+ const triggerEl = this._getTriggerEl();
275
+ if (!triggerEl)
276
+ return;
277
+ triggerEl.removeAttribute('popovertarget');
278
+ triggerEl.removeEventListener('mouseenter', this._onTriggerMouseEnter);
279
+ triggerEl.removeEventListener('mouseleave', this._onTriggerMouseLeave);
280
+ triggerEl.removeEventListener('focusin', this._onTriggerFocusIn);
281
+ triggerEl.removeEventListener('focusout', this._onTriggerFocusOut);
282
+ document.removeEventListener('keydown', this._onKeyDown);
283
+ }
284
+ /** @internal */
285
+ _bindPanelListeners() {
286
+ if (!this._panelEl)
287
+ return;
288
+ this._panelEl.addEventListener('mouseenter', this._onPanelMouseEnter);
289
+ this._panelEl.addEventListener('mouseleave', this._onPanelMouseLeave);
290
+ }
291
+ /** @internal */
292
+ _unbindPanelListeners() {
293
+ if (!this._panelEl)
294
+ return;
295
+ this._panelEl.removeEventListener('mouseenter', this._onPanelMouseEnter);
296
+ this._panelEl.removeEventListener('mouseleave', this._onPanelMouseLeave);
297
+ }
298
+ /** @internal */
299
+ _show() {
300
+ this._clearHideTimer();
301
+ if (this._isVisible || !this._panelEl)
302
+ return;
303
+ try {
304
+ this._panelEl.showPopover();
305
+ }
306
+ catch (e) {
307
+ if (!(e instanceof DOMException && e.name === 'InvalidStateError')) {
308
+ console.warn('[btu-popover] Failed to show popover:', e);
309
+ }
310
+ }
311
+ }
312
+ /** @internal */
313
+ _hide() {
314
+ this._clearTimers();
315
+ if (!this._isVisible || !this._panelEl)
316
+ return;
317
+ try {
318
+ this._panelEl.hidePopover();
319
+ }
320
+ catch (e) {
321
+ if (!(e instanceof DOMException && e.name === 'InvalidStateError')) {
322
+ console.warn('[btu-popover] Failed to hide popover:', e);
323
+ }
324
+ }
325
+ }
326
+ /** @internal Native toggle event — single source of truth for state changes */
327
+ _handleNativeToggle(e) {
328
+ const { newState } = e;
329
+ if (newState === 'open') {
330
+ this._isVisible = true;
331
+ this.open = true;
332
+ const triggerEl = this._getTriggerEl();
333
+ if (triggerEl) {
334
+ triggerEl.setAttribute('aria-expanded', 'true');
335
+ }
336
+ this.emit('btu-popover-show');
337
+ }
338
+ else {
339
+ this._isVisible = false;
340
+ this.open = false;
341
+ const triggerEl = this._getTriggerEl();
342
+ if (triggerEl) {
343
+ triggerEl.setAttribute('aria-expanded', 'false');
344
+ // Restore focus to trigger if focus was lost (e.g., programmatic close)
345
+ if (document.activeElement === document.body) {
346
+ triggerEl.focus();
347
+ }
348
+ }
349
+ this.emit('btu-popover-hide');
350
+ }
351
+ }
352
+ /** @internal Escape dismisses for popover="manual" (hover/focus triggers) */
353
+ _handleKeyDown(e) {
354
+ if (e.key === 'Escape') {
355
+ this._clearTimers();
356
+ this._hide();
357
+ }
358
+ }
359
+ /** @internal */
360
+ _clearShowTimer() {
361
+ if (this._showTimer !== null) {
362
+ clearTimeout(this._showTimer);
363
+ this._showTimer = null;
364
+ }
365
+ }
366
+ /** @internal */
367
+ _clearHideTimer() {
368
+ if (this._hideTimer !== null) {
369
+ clearTimeout(this._hideTimer);
370
+ this._hideTimer = null;
371
+ }
372
+ }
373
+ /** @internal */
374
+ _clearTimers() {
375
+ this._clearShowTimer();
376
+ this._clearHideTimer();
377
+ }
378
+ /** @internal Hover trigger: show with delay */
379
+ _handleTriggerMouseEnter() {
380
+ this._clearTimers();
381
+ this._showTimer = setTimeout(() => this._show(), this.delay);
382
+ }
383
+ /** @internal Hover trigger: hide with small delay for cursor travel */
384
+ _handleTriggerMouseLeave() {
385
+ this._clearTimers();
386
+ this._hideTimer = setTimeout(() => this._hide(), 100);
387
+ }
388
+ /** @internal Focus trigger: show immediately */
389
+ _handleTriggerFocusIn() {
390
+ this._clearTimers();
391
+ this._show();
392
+ }
393
+ /** @internal Focus trigger: hide immediately */
394
+ _handleTriggerFocusOut() {
395
+ this._clearTimers();
396
+ this._hide();
397
+ }
398
+ /** @internal Keep popover open when hovering the panel (hover trigger) */
399
+ _handlePanelMouseEnter() {
400
+ if (this.trigger === 'hover') {
401
+ this._clearTimers();
402
+ }
403
+ }
404
+ /** @internal Hide when mouse leaves the panel (hover trigger) */
405
+ _handlePanelMouseLeave() {
406
+ if (this.trigger === 'hover') {
407
+ this._clearTimers();
408
+ this._hideTimer = setTimeout(() => this._hide(), 100);
409
+ }
410
+ }
411
+ }
412
+ __decorate([
413
+ property({ attribute: 'position' })
414
+ ], Popover.prototype, "position", void 0);
415
+ __decorate([
416
+ property({ attribute: 'trigger' })
417
+ ], Popover.prototype, "trigger", void 0);
418
+ __decorate([
419
+ property({ attribute: 'delay', type: Number })
420
+ ], Popover.prototype, "delay", void 0);
421
+ __decorate([
422
+ property({ attribute: 'offset' })
423
+ ], Popover.prototype, "offset", void 0);
424
+ __decorate([
425
+ property({ attribute: 'no-arrow', type: Boolean })
426
+ ], Popover.prototype, "noArrow", void 0);
427
+ __decorate([
428
+ property({ attribute: 'open', type: Boolean, reflect: true })
429
+ ], Popover.prototype, "open", void 0);
430
+ __decorate([
431
+ property({ attribute: 'panel-label' })
432
+ ], Popover.prototype, "panelLabel", void 0);
433
+ if (!customElements.get('btu-popover')) {
434
+ customElements.define('btu-popover', Popover);
435
+ }
436
+ //# sourceMappingURL=Popover.js.map