@duskmoon-dev/el-tooltip 0.4.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.
@@ -0,0 +1,229 @@
1
+ // src/el-dm-tooltip.ts
2
+ import { BaseElement, css } from "@duskmoon-dev/el-core";
3
+ import { css as tooltipCSS } from "@duskmoon-dev/core/components/tooltip";
4
+ var POSITION_CLASSES = {
5
+ top: "tooltip-top",
6
+ bottom: "tooltip-bottom",
7
+ left: "tooltip-left",
8
+ right: "tooltip-right"
9
+ };
10
+ var coreStyles = tooltipCSS.replace(/@layer\s+components\s*\{/, "").replace(/\}\s*$/, "");
11
+ var styles = css`
12
+ :host {
13
+ display: inline-flex;
14
+ position: relative;
15
+ }
16
+
17
+ :host([hidden]) {
18
+ display: none !important;
19
+ }
20
+
21
+ ${coreStyles}
22
+
23
+ .tooltip-wrapper {
24
+ display: inline-flex;
25
+ position: relative;
26
+ }
27
+
28
+ .tooltip-content {
29
+ position: absolute;
30
+ z-index: 1000;
31
+ padding: 0.5rem 0.75rem;
32
+ background-color: var(--color-inverse-surface, #1f1f1f);
33
+ color: var(--color-inverse-on-surface, #fff);
34
+ font-size: 0.75rem;
35
+ line-height: 1rem;
36
+ border-radius: 0.375rem;
37
+ white-space: nowrap;
38
+ opacity: 0;
39
+ visibility: hidden;
40
+ transition:
41
+ opacity 150ms ease,
42
+ visibility 150ms ease;
43
+ pointer-events: none;
44
+ font-family: inherit;
45
+ }
46
+
47
+ .tooltip-content.visible {
48
+ opacity: 1;
49
+ visibility: visible;
50
+ }
51
+
52
+ .tooltip-top {
53
+ bottom: 100%;
54
+ left: 50%;
55
+ transform: translateX(-50%);
56
+ margin-bottom: 0.5rem;
57
+ }
58
+
59
+ .tooltip-bottom {
60
+ top: 100%;
61
+ left: 50%;
62
+ transform: translateX(-50%);
63
+ margin-top: 0.5rem;
64
+ }
65
+
66
+ .tooltip-left {
67
+ right: 100%;
68
+ top: 50%;
69
+ transform: translateY(-50%);
70
+ margin-right: 0.5rem;
71
+ }
72
+
73
+ .tooltip-right {
74
+ left: 100%;
75
+ top: 50%;
76
+ transform: translateY(-50%);
77
+ margin-left: 0.5rem;
78
+ }
79
+
80
+ .tooltip-arrow {
81
+ position: absolute;
82
+ width: 0;
83
+ height: 0;
84
+ border: 0.375rem solid transparent;
85
+ }
86
+
87
+ .tooltip-top .tooltip-arrow {
88
+ top: 100%;
89
+ left: 50%;
90
+ transform: translateX(-50%);
91
+ border-top-color: var(--color-inverse-surface, #1f1f1f);
92
+ border-bottom: 0;
93
+ }
94
+
95
+ .tooltip-bottom .tooltip-arrow {
96
+ bottom: 100%;
97
+ left: 50%;
98
+ transform: translateX(-50%);
99
+ border-bottom-color: var(--color-inverse-surface, #1f1f1f);
100
+ border-top: 0;
101
+ }
102
+
103
+ .tooltip-left .tooltip-arrow {
104
+ left: 100%;
105
+ top: 50%;
106
+ transform: translateY(-50%);
107
+ border-left-color: var(--color-inverse-surface, #1f1f1f);
108
+ border-right: 0;
109
+ }
110
+
111
+ .tooltip-right .tooltip-arrow {
112
+ right: 100%;
113
+ top: 50%;
114
+ transform: translateY(-50%);
115
+ border-right-color: var(--color-inverse-surface, #1f1f1f);
116
+ border-left: 0;
117
+ }
118
+ `;
119
+
120
+ class ElDmTooltip extends BaseElement {
121
+ static properties = {
122
+ content: { type: String, reflect: true },
123
+ position: { type: String, reflect: true, default: "top" },
124
+ trigger: { type: String, reflect: true, default: "hover" },
125
+ delay: { type: Number, reflect: true, default: 0 },
126
+ arrow: { type: Boolean, reflect: true, default: true },
127
+ disabled: { type: Boolean, reflect: true }
128
+ };
129
+ _showTimeout = null;
130
+ _isVisible = false;
131
+ constructor() {
132
+ super();
133
+ this.attachStyles(styles);
134
+ }
135
+ _show() {
136
+ if (this.disabled || !this.content)
137
+ return;
138
+ if (this.delay > 0) {
139
+ this._showTimeout = window.setTimeout(() => {
140
+ this._setVisible(true);
141
+ }, this.delay);
142
+ } else {
143
+ this._setVisible(true);
144
+ }
145
+ }
146
+ _hide() {
147
+ if (this._showTimeout) {
148
+ clearTimeout(this._showTimeout);
149
+ this._showTimeout = null;
150
+ }
151
+ this._setVisible(false);
152
+ }
153
+ _setVisible(visible) {
154
+ this._isVisible = visible;
155
+ const tooltipContent = this.shadowRoot?.querySelector(".tooltip-content");
156
+ if (tooltipContent) {
157
+ tooltipContent.classList.toggle("visible", visible);
158
+ }
159
+ }
160
+ _toggle() {
161
+ if (this._isVisible) {
162
+ this._hide();
163
+ } else {
164
+ this._show();
165
+ }
166
+ }
167
+ _getTooltipClasses() {
168
+ const classes = ["tooltip-content"];
169
+ if (this.position && POSITION_CLASSES[this.position]) {
170
+ classes.push(POSITION_CLASSES[this.position]);
171
+ } else {
172
+ classes.push("tooltip-top");
173
+ }
174
+ return classes.join(" ");
175
+ }
176
+ connectedCallback() {
177
+ super.connectedCallback();
178
+ this._setupListeners();
179
+ }
180
+ disconnectedCallback() {
181
+ super.disconnectedCallback?.();
182
+ this._removeListeners();
183
+ }
184
+ _setupListeners() {
185
+ if (this.trigger === "hover") {
186
+ this.addEventListener("mouseenter", this._show.bind(this));
187
+ this.addEventListener("mouseleave", this._hide.bind(this));
188
+ } else if (this.trigger === "click") {
189
+ this.addEventListener("click", this._toggle.bind(this));
190
+ }
191
+ if (this.trigger === "focus" || this.trigger === "hover") {
192
+ this.addEventListener("focusin", this._show.bind(this));
193
+ this.addEventListener("focusout", this._hide.bind(this));
194
+ }
195
+ }
196
+ _removeListeners() {
197
+ this.removeEventListener("mouseenter", this._show.bind(this));
198
+ this.removeEventListener("mouseleave", this._hide.bind(this));
199
+ this.removeEventListener("click", this._toggle.bind(this));
200
+ this.removeEventListener("focusin", this._show.bind(this));
201
+ this.removeEventListener("focusout", this._hide.bind(this));
202
+ }
203
+ render() {
204
+ const tooltipClasses = this._getTooltipClasses();
205
+ return `
206
+ <div class="tooltip-wrapper" part="tooltip">
207
+ <slot></slot>
208
+ <div class="${tooltipClasses}" role="tooltip" part="content">
209
+ ${this.content || ""}
210
+ ${this.arrow ? '<span class="tooltip-arrow" part="arrow"></span>' : ""}
211
+ </div>
212
+ </div>
213
+ `;
214
+ }
215
+ }
216
+
217
+ // src/index.ts
218
+ function register() {
219
+ if (!customElements.get("el-dm-tooltip")) {
220
+ customElements.define("el-dm-tooltip", ElDmTooltip);
221
+ }
222
+ }
223
+ export {
224
+ register,
225
+ ElDmTooltip
226
+ };
227
+
228
+ //# debugId=614341F72E9E7F9064756E2164756E21
229
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/el-dm-tooltip.ts", "../../src/index.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * DuskMoon Tooltip Element\n *\n * A tooltip component for displaying additional information on hover/focus.\n * Uses styles from @duskmoon-dev/core for consistent theming.\n *\n * @element el-dm-tooltip\n *\n * @attr {string} content - Tooltip text content\n * @attr {string} position - Tooltip position: top, bottom, left, right\n * @attr {string} trigger - Trigger mode: hover, click, focus\n * @attr {number} delay - Show delay in milliseconds\n * @attr {boolean} arrow - Whether to show arrow\n * @attr {boolean} disabled - Whether tooltip is disabled\n *\n * @slot - Default slot for trigger element\n *\n * @csspart tooltip - The tooltip container\n * @csspart content - The tooltip content\n * @csspart arrow - The tooltip arrow\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\nimport { css as tooltipCSS } from '@duskmoon-dev/core/components/tooltip';\n\nconst POSITION_CLASSES: Record<string, string> = {\n top: 'tooltip-top',\n bottom: 'tooltip-bottom',\n left: 'tooltip-left',\n right: 'tooltip-right',\n};\n\nexport type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';\nexport type TooltipTrigger = 'hover' | 'click' | 'focus';\n\n// Strip @layer wrapper for Shadow DOM compatibility\nconst coreStyles = tooltipCSS.replace(/@layer\\s+components\\s*\\{/, '').replace(/\\}\\s*$/, '');\n\nconst styles = css`\n :host {\n display: inline-flex;\n position: relative;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n ${coreStyles}\n\n .tooltip-wrapper {\n display: inline-flex;\n position: relative;\n }\n\n .tooltip-content {\n position: absolute;\n z-index: 1000;\n padding: 0.5rem 0.75rem;\n background-color: var(--color-inverse-surface, #1f1f1f);\n color: var(--color-inverse-on-surface, #fff);\n font-size: 0.75rem;\n line-height: 1rem;\n border-radius: 0.375rem;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition:\n opacity 150ms ease,\n visibility 150ms ease;\n pointer-events: none;\n font-family: inherit;\n }\n\n .tooltip-content.visible {\n opacity: 1;\n visibility: visible;\n }\n\n .tooltip-top {\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-bottom: 0.5rem;\n }\n\n .tooltip-bottom {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 0.5rem;\n }\n\n .tooltip-left {\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n margin-right: 0.5rem;\n }\n\n .tooltip-right {\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n margin-left: 0.5rem;\n }\n\n .tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border: 0.375rem solid transparent;\n }\n\n .tooltip-top .tooltip-arrow {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-top-color: var(--color-inverse-surface, #1f1f1f);\n border-bottom: 0;\n }\n\n .tooltip-bottom .tooltip-arrow {\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-bottom-color: var(--color-inverse-surface, #1f1f1f);\n border-top: 0;\n }\n\n .tooltip-left .tooltip-arrow {\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-left-color: var(--color-inverse-surface, #1f1f1f);\n border-right: 0;\n }\n\n .tooltip-right .tooltip-arrow {\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-right-color: var(--color-inverse-surface, #1f1f1f);\n border-left: 0;\n }\n`;\n\nexport class ElDmTooltip extends BaseElement {\n static properties = {\n content: { type: String, reflect: true },\n position: { type: String, reflect: true, default: 'top' },\n trigger: { type: String, reflect: true, default: 'hover' },\n delay: { type: Number, reflect: true, default: 0 },\n arrow: { type: Boolean, reflect: true, default: true },\n disabled: { type: Boolean, reflect: true },\n };\n\n declare content: string;\n declare position: TooltipPosition;\n declare trigger: TooltipTrigger;\n declare delay: number;\n declare arrow: boolean;\n declare disabled: boolean;\n\n private _showTimeout: number | null = null;\n private _isVisible = false;\n\n constructor() {\n super();\n this.attachStyles(styles);\n }\n\n private _show(): void {\n if (this.disabled || !this.content) return;\n\n if (this.delay > 0) {\n this._showTimeout = window.setTimeout(() => {\n this._setVisible(true);\n }, this.delay);\n } else {\n this._setVisible(true);\n }\n }\n\n private _hide(): void {\n if (this._showTimeout) {\n clearTimeout(this._showTimeout);\n this._showTimeout = null;\n }\n this._setVisible(false);\n }\n\n private _setVisible(visible: boolean): void {\n this._isVisible = visible;\n const tooltipContent = this.shadowRoot?.querySelector('.tooltip-content');\n if (tooltipContent) {\n tooltipContent.classList.toggle('visible', visible);\n }\n }\n\n private _toggle(): void {\n if (this._isVisible) {\n this._hide();\n } else {\n this._show();\n }\n }\n\n private _getTooltipClasses(): string {\n const classes = ['tooltip-content'];\n\n if (this.position && POSITION_CLASSES[this.position]) {\n classes.push(POSITION_CLASSES[this.position]);\n } else {\n classes.push('tooltip-top');\n }\n\n return classes.join(' ');\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this._setupListeners();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback?.();\n this._removeListeners();\n }\n\n private _setupListeners(): void {\n if (this.trigger === 'hover') {\n this.addEventListener('mouseenter', this._show.bind(this));\n this.addEventListener('mouseleave', this._hide.bind(this));\n } else if (this.trigger === 'click') {\n this.addEventListener('click', this._toggle.bind(this));\n }\n\n if (this.trigger === 'focus' || this.trigger === 'hover') {\n this.addEventListener('focusin', this._show.bind(this));\n this.addEventListener('focusout', this._hide.bind(this));\n }\n }\n\n private _removeListeners(): void {\n this.removeEventListener('mouseenter', this._show.bind(this));\n this.removeEventListener('mouseleave', this._hide.bind(this));\n this.removeEventListener('click', this._toggle.bind(this));\n this.removeEventListener('focusin', this._show.bind(this));\n this.removeEventListener('focusout', this._hide.bind(this));\n }\n\n render(): string {\n const tooltipClasses = this._getTooltipClasses();\n\n return `\n <div class=\"tooltip-wrapper\" part=\"tooltip\">\n <slot></slot>\n <div class=\"${tooltipClasses}\" role=\"tooltip\" part=\"content\">\n ${this.content || ''}\n ${this.arrow ? '<span class=\"tooltip-arrow\" part=\"arrow\"></span>' : ''}\n </div>\n </div>\n `;\n }\n}\n",
6
+ "/**\n * @duskmoon-dev/el-tooltip\n *\n * DuskMoon Tooltip custom element\n */\n\nimport { ElDmTooltip } from './el-dm-tooltip.js';\n\nexport { ElDmTooltip };\nexport type { TooltipPosition, TooltipTrigger } from './el-dm-tooltip.js';\n\n/**\n * Register the el-dm-tooltip custom element\n *\n * @example\n * ```ts\n * import { register } from '@duskmoon-dev/el-tooltip';\n * register();\n * ```\n */\nexport function register(): void {\n if (!customElements.get('el-dm-tooltip')) {\n customElements.define('el-dm-tooltip', ElDmTooltip);\n }\n}\n"
7
+ ],
8
+ "mappings": "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",
9
+ "debugId": "614341F72E9E7F9064756E2164756E21",
10
+ "names": []
11
+ }
@@ -0,0 +1,228 @@
1
+ // src/el-dm-tooltip.ts
2
+ import { BaseElement, css } from "@duskmoon-dev/el-core";
3
+ import { css as tooltipCSS } from "@duskmoon-dev/core/components/tooltip";
4
+ var POSITION_CLASSES = {
5
+ top: "tooltip-top",
6
+ bottom: "tooltip-bottom",
7
+ left: "tooltip-left",
8
+ right: "tooltip-right"
9
+ };
10
+ var coreStyles = tooltipCSS.replace(/@layer\s+components\s*\{/, "").replace(/\}\s*$/, "");
11
+ var styles = css`
12
+ :host {
13
+ display: inline-flex;
14
+ position: relative;
15
+ }
16
+
17
+ :host([hidden]) {
18
+ display: none !important;
19
+ }
20
+
21
+ ${coreStyles}
22
+
23
+ .tooltip-wrapper {
24
+ display: inline-flex;
25
+ position: relative;
26
+ }
27
+
28
+ .tooltip-content {
29
+ position: absolute;
30
+ z-index: 1000;
31
+ padding: 0.5rem 0.75rem;
32
+ background-color: var(--color-inverse-surface, #1f1f1f);
33
+ color: var(--color-inverse-on-surface, #fff);
34
+ font-size: 0.75rem;
35
+ line-height: 1rem;
36
+ border-radius: 0.375rem;
37
+ white-space: nowrap;
38
+ opacity: 0;
39
+ visibility: hidden;
40
+ transition:
41
+ opacity 150ms ease,
42
+ visibility 150ms ease;
43
+ pointer-events: none;
44
+ font-family: inherit;
45
+ }
46
+
47
+ .tooltip-content.visible {
48
+ opacity: 1;
49
+ visibility: visible;
50
+ }
51
+
52
+ .tooltip-top {
53
+ bottom: 100%;
54
+ left: 50%;
55
+ transform: translateX(-50%);
56
+ margin-bottom: 0.5rem;
57
+ }
58
+
59
+ .tooltip-bottom {
60
+ top: 100%;
61
+ left: 50%;
62
+ transform: translateX(-50%);
63
+ margin-top: 0.5rem;
64
+ }
65
+
66
+ .tooltip-left {
67
+ right: 100%;
68
+ top: 50%;
69
+ transform: translateY(-50%);
70
+ margin-right: 0.5rem;
71
+ }
72
+
73
+ .tooltip-right {
74
+ left: 100%;
75
+ top: 50%;
76
+ transform: translateY(-50%);
77
+ margin-left: 0.5rem;
78
+ }
79
+
80
+ .tooltip-arrow {
81
+ position: absolute;
82
+ width: 0;
83
+ height: 0;
84
+ border: 0.375rem solid transparent;
85
+ }
86
+
87
+ .tooltip-top .tooltip-arrow {
88
+ top: 100%;
89
+ left: 50%;
90
+ transform: translateX(-50%);
91
+ border-top-color: var(--color-inverse-surface, #1f1f1f);
92
+ border-bottom: 0;
93
+ }
94
+
95
+ .tooltip-bottom .tooltip-arrow {
96
+ bottom: 100%;
97
+ left: 50%;
98
+ transform: translateX(-50%);
99
+ border-bottom-color: var(--color-inverse-surface, #1f1f1f);
100
+ border-top: 0;
101
+ }
102
+
103
+ .tooltip-left .tooltip-arrow {
104
+ left: 100%;
105
+ top: 50%;
106
+ transform: translateY(-50%);
107
+ border-left-color: var(--color-inverse-surface, #1f1f1f);
108
+ border-right: 0;
109
+ }
110
+
111
+ .tooltip-right .tooltip-arrow {
112
+ right: 100%;
113
+ top: 50%;
114
+ transform: translateY(-50%);
115
+ border-right-color: var(--color-inverse-surface, #1f1f1f);
116
+ border-left: 0;
117
+ }
118
+ `;
119
+
120
+ class ElDmTooltip extends BaseElement {
121
+ static properties = {
122
+ content: { type: String, reflect: true },
123
+ position: { type: String, reflect: true, default: "top" },
124
+ trigger: { type: String, reflect: true, default: "hover" },
125
+ delay: { type: Number, reflect: true, default: 0 },
126
+ arrow: { type: Boolean, reflect: true, default: true },
127
+ disabled: { type: Boolean, reflect: true }
128
+ };
129
+ _showTimeout = null;
130
+ _isVisible = false;
131
+ constructor() {
132
+ super();
133
+ this.attachStyles(styles);
134
+ }
135
+ _show() {
136
+ if (this.disabled || !this.content)
137
+ return;
138
+ if (this.delay > 0) {
139
+ this._showTimeout = window.setTimeout(() => {
140
+ this._setVisible(true);
141
+ }, this.delay);
142
+ } else {
143
+ this._setVisible(true);
144
+ }
145
+ }
146
+ _hide() {
147
+ if (this._showTimeout) {
148
+ clearTimeout(this._showTimeout);
149
+ this._showTimeout = null;
150
+ }
151
+ this._setVisible(false);
152
+ }
153
+ _setVisible(visible) {
154
+ this._isVisible = visible;
155
+ const tooltipContent = this.shadowRoot?.querySelector(".tooltip-content");
156
+ if (tooltipContent) {
157
+ tooltipContent.classList.toggle("visible", visible);
158
+ }
159
+ }
160
+ _toggle() {
161
+ if (this._isVisible) {
162
+ this._hide();
163
+ } else {
164
+ this._show();
165
+ }
166
+ }
167
+ _getTooltipClasses() {
168
+ const classes = ["tooltip-content"];
169
+ if (this.position && POSITION_CLASSES[this.position]) {
170
+ classes.push(POSITION_CLASSES[this.position]);
171
+ } else {
172
+ classes.push("tooltip-top");
173
+ }
174
+ return classes.join(" ");
175
+ }
176
+ connectedCallback() {
177
+ super.connectedCallback();
178
+ this._setupListeners();
179
+ }
180
+ disconnectedCallback() {
181
+ super.disconnectedCallback?.();
182
+ this._removeListeners();
183
+ }
184
+ _setupListeners() {
185
+ if (this.trigger === "hover") {
186
+ this.addEventListener("mouseenter", this._show.bind(this));
187
+ this.addEventListener("mouseleave", this._hide.bind(this));
188
+ } else if (this.trigger === "click") {
189
+ this.addEventListener("click", this._toggle.bind(this));
190
+ }
191
+ if (this.trigger === "focus" || this.trigger === "hover") {
192
+ this.addEventListener("focusin", this._show.bind(this));
193
+ this.addEventListener("focusout", this._hide.bind(this));
194
+ }
195
+ }
196
+ _removeListeners() {
197
+ this.removeEventListener("mouseenter", this._show.bind(this));
198
+ this.removeEventListener("mouseleave", this._hide.bind(this));
199
+ this.removeEventListener("click", this._toggle.bind(this));
200
+ this.removeEventListener("focusin", this._show.bind(this));
201
+ this.removeEventListener("focusout", this._hide.bind(this));
202
+ }
203
+ render() {
204
+ const tooltipClasses = this._getTooltipClasses();
205
+ return `
206
+ <div class="tooltip-wrapper" part="tooltip">
207
+ <slot></slot>
208
+ <div class="${tooltipClasses}" role="tooltip" part="content">
209
+ ${this.content || ""}
210
+ ${this.arrow ? '<span class="tooltip-arrow" part="arrow"></span>' : ""}
211
+ </div>
212
+ </div>
213
+ `;
214
+ }
215
+ }
216
+
217
+ // src/index.ts
218
+ function register() {
219
+ if (!customElements.get("el-dm-tooltip")) {
220
+ customElements.define("el-dm-tooltip", ElDmTooltip);
221
+ }
222
+ }
223
+
224
+ // src/register.ts
225
+ register();
226
+
227
+ //# debugId=4BCED25038517C7564756E2164756E21
228
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/el-dm-tooltip.ts", "../../src/index.ts", "../../src/register.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * DuskMoon Tooltip Element\n *\n * A tooltip component for displaying additional information on hover/focus.\n * Uses styles from @duskmoon-dev/core for consistent theming.\n *\n * @element el-dm-tooltip\n *\n * @attr {string} content - Tooltip text content\n * @attr {string} position - Tooltip position: top, bottom, left, right\n * @attr {string} trigger - Trigger mode: hover, click, focus\n * @attr {number} delay - Show delay in milliseconds\n * @attr {boolean} arrow - Whether to show arrow\n * @attr {boolean} disabled - Whether tooltip is disabled\n *\n * @slot - Default slot for trigger element\n *\n * @csspart tooltip - The tooltip container\n * @csspart content - The tooltip content\n * @csspart arrow - The tooltip arrow\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\nimport { css as tooltipCSS } from '@duskmoon-dev/core/components/tooltip';\n\nconst POSITION_CLASSES: Record<string, string> = {\n top: 'tooltip-top',\n bottom: 'tooltip-bottom',\n left: 'tooltip-left',\n right: 'tooltip-right',\n};\n\nexport type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';\nexport type TooltipTrigger = 'hover' | 'click' | 'focus';\n\n// Strip @layer wrapper for Shadow DOM compatibility\nconst coreStyles = tooltipCSS.replace(/@layer\\s+components\\s*\\{/, '').replace(/\\}\\s*$/, '');\n\nconst styles = css`\n :host {\n display: inline-flex;\n position: relative;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n ${coreStyles}\n\n .tooltip-wrapper {\n display: inline-flex;\n position: relative;\n }\n\n .tooltip-content {\n position: absolute;\n z-index: 1000;\n padding: 0.5rem 0.75rem;\n background-color: var(--color-inverse-surface, #1f1f1f);\n color: var(--color-inverse-on-surface, #fff);\n font-size: 0.75rem;\n line-height: 1rem;\n border-radius: 0.375rem;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition:\n opacity 150ms ease,\n visibility 150ms ease;\n pointer-events: none;\n font-family: inherit;\n }\n\n .tooltip-content.visible {\n opacity: 1;\n visibility: visible;\n }\n\n .tooltip-top {\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-bottom: 0.5rem;\n }\n\n .tooltip-bottom {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n margin-top: 0.5rem;\n }\n\n .tooltip-left {\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n margin-right: 0.5rem;\n }\n\n .tooltip-right {\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n margin-left: 0.5rem;\n }\n\n .tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border: 0.375rem solid transparent;\n }\n\n .tooltip-top .tooltip-arrow {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-top-color: var(--color-inverse-surface, #1f1f1f);\n border-bottom: 0;\n }\n\n .tooltip-bottom .tooltip-arrow {\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n border-bottom-color: var(--color-inverse-surface, #1f1f1f);\n border-top: 0;\n }\n\n .tooltip-left .tooltip-arrow {\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-left-color: var(--color-inverse-surface, #1f1f1f);\n border-right: 0;\n }\n\n .tooltip-right .tooltip-arrow {\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n border-right-color: var(--color-inverse-surface, #1f1f1f);\n border-left: 0;\n }\n`;\n\nexport class ElDmTooltip extends BaseElement {\n static properties = {\n content: { type: String, reflect: true },\n position: { type: String, reflect: true, default: 'top' },\n trigger: { type: String, reflect: true, default: 'hover' },\n delay: { type: Number, reflect: true, default: 0 },\n arrow: { type: Boolean, reflect: true, default: true },\n disabled: { type: Boolean, reflect: true },\n };\n\n declare content: string;\n declare position: TooltipPosition;\n declare trigger: TooltipTrigger;\n declare delay: number;\n declare arrow: boolean;\n declare disabled: boolean;\n\n private _showTimeout: number | null = null;\n private _isVisible = false;\n\n constructor() {\n super();\n this.attachStyles(styles);\n }\n\n private _show(): void {\n if (this.disabled || !this.content) return;\n\n if (this.delay > 0) {\n this._showTimeout = window.setTimeout(() => {\n this._setVisible(true);\n }, this.delay);\n } else {\n this._setVisible(true);\n }\n }\n\n private _hide(): void {\n if (this._showTimeout) {\n clearTimeout(this._showTimeout);\n this._showTimeout = null;\n }\n this._setVisible(false);\n }\n\n private _setVisible(visible: boolean): void {\n this._isVisible = visible;\n const tooltipContent = this.shadowRoot?.querySelector('.tooltip-content');\n if (tooltipContent) {\n tooltipContent.classList.toggle('visible', visible);\n }\n }\n\n private _toggle(): void {\n if (this._isVisible) {\n this._hide();\n } else {\n this._show();\n }\n }\n\n private _getTooltipClasses(): string {\n const classes = ['tooltip-content'];\n\n if (this.position && POSITION_CLASSES[this.position]) {\n classes.push(POSITION_CLASSES[this.position]);\n } else {\n classes.push('tooltip-top');\n }\n\n return classes.join(' ');\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this._setupListeners();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback?.();\n this._removeListeners();\n }\n\n private _setupListeners(): void {\n if (this.trigger === 'hover') {\n this.addEventListener('mouseenter', this._show.bind(this));\n this.addEventListener('mouseleave', this._hide.bind(this));\n } else if (this.trigger === 'click') {\n this.addEventListener('click', this._toggle.bind(this));\n }\n\n if (this.trigger === 'focus' || this.trigger === 'hover') {\n this.addEventListener('focusin', this._show.bind(this));\n this.addEventListener('focusout', this._hide.bind(this));\n }\n }\n\n private _removeListeners(): void {\n this.removeEventListener('mouseenter', this._show.bind(this));\n this.removeEventListener('mouseleave', this._hide.bind(this));\n this.removeEventListener('click', this._toggle.bind(this));\n this.removeEventListener('focusin', this._show.bind(this));\n this.removeEventListener('focusout', this._hide.bind(this));\n }\n\n render(): string {\n const tooltipClasses = this._getTooltipClasses();\n\n return `\n <div class=\"tooltip-wrapper\" part=\"tooltip\">\n <slot></slot>\n <div class=\"${tooltipClasses}\" role=\"tooltip\" part=\"content\">\n ${this.content || ''}\n ${this.arrow ? '<span class=\"tooltip-arrow\" part=\"arrow\"></span>' : ''}\n </div>\n </div>\n `;\n }\n}\n",
6
+ "/**\n * @duskmoon-dev/el-tooltip\n *\n * DuskMoon Tooltip custom element\n */\n\nimport { ElDmTooltip } from './el-dm-tooltip.js';\n\nexport { ElDmTooltip };\nexport type { TooltipPosition, TooltipTrigger } from './el-dm-tooltip.js';\n\n/**\n * Register the el-dm-tooltip custom element\n *\n * @example\n * ```ts\n * import { register } from '@duskmoon-dev/el-tooltip';\n * register();\n * ```\n */\nexport function register(): void {\n if (!customElements.get('el-dm-tooltip')) {\n customElements.define('el-dm-tooltip', ElDmTooltip);\n }\n}\n",
7
+ "import { register } from './index.js';\nregister();\n"
8
+ ],
9
+ "mappings": "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",
10
+ "debugId": "4BCED25038517C7564756E2164756E21",
11
+ "names": []
12
+ }