@ssaprt/tooltip 1.0.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,2355 @@
1
+ "use client";
2
+
3
+ // src/components/Tooltip.tsx
4
+ import {
5
+ Children,
6
+ cloneElement,
7
+ useCallback as useCallback2,
8
+ useLayoutEffect as useLayoutEffect3,
9
+ useMemo as useMemo2,
10
+ useRef as useRef3,
11
+ useState as useState3
12
+ } from "react";
13
+ import { createPortal } from "react-dom";
14
+
15
+ // src/config/presets.ts
16
+ var animations = {
17
+ soft: {
18
+ show: "fade",
19
+ hide: "fade",
20
+ speed: "160ms",
21
+ easing: "ease-in-out"
22
+ },
23
+ slide: {
24
+ show: "slide",
25
+ hide: "fade",
26
+ speed: "160ms",
27
+ easing: "ease-out"
28
+ },
29
+ pop: {
30
+ show: "scale",
31
+ hide: "scale",
32
+ speed: "170ms",
33
+ easing: "cubic-bezier(0.22, 1, 0.36, 1)"
34
+ },
35
+ bounce: {
36
+ show: "bounce",
37
+ hide: "scale",
38
+ speed: "240ms",
39
+ easing: "cubic-bezier(0.34, 1.56, 0.64, 1)"
40
+ },
41
+ flip: {
42
+ show: "flip",
43
+ hide: "fade",
44
+ speed: "210ms",
45
+ easing: "cubic-bezier(0.22, 1, 0.36, 1)"
46
+ },
47
+ blur: {
48
+ show: "blur",
49
+ hide: "blur",
50
+ speed: "200ms",
51
+ easing: "ease-out"
52
+ },
53
+ zoom: {
54
+ show: "zoom",
55
+ hide: "zoom",
56
+ speed: "170ms",
57
+ easing: "ease-out"
58
+ },
59
+ snap: {
60
+ show: "zoom",
61
+ hide: "fade",
62
+ speed: "110ms",
63
+ easing: "steps(4, end)"
64
+ },
65
+ instant: {
66
+ show: "none",
67
+ hide: "none",
68
+ speed: "1ms",
69
+ easing: "linear"
70
+ }
71
+ };
72
+ var createTheme = ({
73
+ background,
74
+ color,
75
+ fontFamily = "Inter, Arial, sans-serif",
76
+ fontSize = "12px",
77
+ fontWeight = 500,
78
+ fontStyle,
79
+ lineHeight = 1.4,
80
+ borderRadius = "7px",
81
+ border,
82
+ filter,
83
+ padding = "7px 12px",
84
+ letterSpacing,
85
+ textShadow,
86
+ textTransform,
87
+ textAlign = "center",
88
+ backdropFilter,
89
+ arrowSize = "7px",
90
+ arrowWidth = "14px",
91
+ animation = animations.slide,
92
+ style
93
+ }) => {
94
+ return {
95
+ body: {
96
+ background,
97
+ filter,
98
+ style: {
99
+ color,
100
+ fontFamily,
101
+ fontSize,
102
+ fontWeight,
103
+ fontStyle,
104
+ lineHeight,
105
+ borderRadius,
106
+ border,
107
+ padding,
108
+ letterSpacing,
109
+ textShadow,
110
+ textTransform,
111
+ textAlign,
112
+ backdropFilter,
113
+ WebkitBackdropFilter: backdropFilter,
114
+ ...style
115
+ }
116
+ },
117
+ arrow: {
118
+ size: arrowSize,
119
+ width: arrowWidth
120
+ },
121
+ animation
122
+ };
123
+ };
124
+ var presets = {
125
+ primary: createTheme({
126
+ background: "linear-gradient(135deg, #2563eb, #1d4ed8)",
127
+ color: "#ffffff",
128
+ filter: "drop-shadow(0 7px 12px rgba(37, 99, 235, 0.38))",
129
+ border: "1px solid rgba(255, 255, 255, 0.18)",
130
+ borderRadius: "8px"
131
+ }),
132
+ secondary: createTheme({
133
+ background: "linear-gradient(135deg, #64748b, #475569)",
134
+ color: "#ffffff",
135
+ filter: "drop-shadow(0 7px 12px rgba(15, 23, 42, 0.3))",
136
+ border: "1px solid rgba(255, 255, 255, 0.15)",
137
+ animation: animations.soft
138
+ }),
139
+ dark: createTheme({
140
+ background: "linear-gradient(145deg, #18181b, #09090b)",
141
+ color: "#fafafa",
142
+ border: "1px solid #3f3f46",
143
+ borderRadius: "10px",
144
+ filter: "drop-shadow(0 11px 18px rgba(0, 0, 0, 0.56))",
145
+ animation: animations.pop
146
+ }),
147
+ light: createTheme({
148
+ background: "linear-gradient(145deg, #ffffff, #f4f4f5)",
149
+ color: "#18181b",
150
+ border: "1px solid #d4d4d8",
151
+ borderRadius: "10px",
152
+ filter: "drop-shadow(0 9px 15px rgba(15, 23, 42, 0.18))",
153
+ animation: animations.soft
154
+ }),
155
+ comic: createTheme({
156
+ background: "#fde047",
157
+ color: "#18181b",
158
+ fontFamily: "Comic Sans MS, Comic Sans, cursive",
159
+ fontSize: "13px",
160
+ fontWeight: 700,
161
+ border: "3px solid #18181b",
162
+ borderRadius: "12px",
163
+ filter: "drop-shadow(5px 5px 0 #18181b)",
164
+ padding: "8px 14px",
165
+ textTransform: "uppercase",
166
+ arrowSize: "9px",
167
+ arrowWidth: "20px",
168
+ animation: animations.bounce
169
+ }),
170
+ manga: createTheme({
171
+ background: "radial-gradient(circle at 2px 2px, rgba(0, 0, 0, 0.2) 1px, transparent 1.5px) 0 0 / 6px 6px, #ffffff",
172
+ color: "#000000",
173
+ fontFamily: "Impact, Haettenschweiler, Arial Narrow Bold, sans-serif",
174
+ fontSize: "13px",
175
+ fontWeight: 900,
176
+ border: "3px solid #000000",
177
+ borderRadius: "18px 5px 18px 5px",
178
+ filter: "drop-shadow(4px 4px 0 #000000)",
179
+ padding: "9px 15px",
180
+ letterSpacing: "0.04em",
181
+ textTransform: "uppercase",
182
+ arrowSize: "11px",
183
+ arrowWidth: "17px",
184
+ animation: animations.snap
185
+ }),
186
+ newspaper: createTheme({
187
+ background: "repeating-linear-gradient(0deg, rgba(68, 64, 60, 0.035) 0, rgba(68, 64, 60, 0.035) 1px, transparent 1px, transparent 4px), #f5f0e6",
188
+ color: "#292524",
189
+ fontFamily: "Times New Roman, Times, serif",
190
+ fontSize: "13px",
191
+ fontWeight: 600,
192
+ border: "2px solid #44403c",
193
+ borderRadius: "1px",
194
+ filter: "drop-shadow(3px 4px 0 rgba(68, 64, 60, 0.28))",
195
+ padding: "9px 15px",
196
+ letterSpacing: "0.02em",
197
+ textAlign: "left",
198
+ arrowSize: "8px",
199
+ arrowWidth: "18px",
200
+ animation: animations.soft,
201
+ style: {
202
+ fontVariantCaps: "small-caps"
203
+ }
204
+ }),
205
+ stickyNote: createTheme({
206
+ background: "linear-gradient(145deg, #fff7a8 0%, #fde96b 70%, #e9cc42 100%)",
207
+ color: "#4a3c00",
208
+ fontFamily: "Comic Sans MS, cursive",
209
+ fontSize: "13px",
210
+ fontWeight: 600,
211
+ border: "1px solid #d6b936",
212
+ borderRadius: "3px 14px 5px 11px",
213
+ filter: "drop-shadow(3px 6px 5px rgba(78, 65, 0, 0.28))",
214
+ padding: "10px 15px",
215
+ textAlign: "left",
216
+ arrowSize: "8px",
217
+ arrowWidth: "19px",
218
+ animation: animations.pop
219
+ }),
220
+ blueprint: createTheme({
221
+ background: "linear-gradient(rgba(147, 197, 253, 0.15) 1px, transparent 1px), linear-gradient(90deg, rgba(147, 197, 253, 0.15) 1px, transparent 1px), #0c4a6e",
222
+ color: "#e0f2fe",
223
+ fontFamily: "Courier New, Consolas, monospace",
224
+ fontSize: "12px",
225
+ fontWeight: 600,
226
+ border: "2px dashed #7dd3fc",
227
+ borderRadius: "2px",
228
+ filter: "drop-shadow(0 0 7px rgba(56, 189, 248, 0.45))",
229
+ padding: "9px 13px",
230
+ letterSpacing: "0.05em",
231
+ textAlign: "left",
232
+ arrowSize: "8px",
233
+ arrowWidth: "16px",
234
+ animation: animations.flip,
235
+ style: {
236
+ backgroundSize: "12px 12px"
237
+ }
238
+ }),
239
+ terminal: createTheme({
240
+ background: "linear-gradient(180deg, #020617, #000000)",
241
+ color: "#22c55e",
242
+ fontFamily: "Consolas, Monaco, Courier New, monospace",
243
+ fontSize: "12px",
244
+ fontWeight: 600,
245
+ border: "1px solid #22c55e",
246
+ borderRadius: "3px",
247
+ filter: "drop-shadow(0 0 5px rgba(34, 197, 94, 0.65))",
248
+ padding: "8px 12px",
249
+ letterSpacing: "0.035em",
250
+ textShadow: "0 0 5px rgba(34, 197, 94, 0.9)",
251
+ textAlign: "left",
252
+ arrowSize: "7px",
253
+ arrowWidth: "13px",
254
+ animation: animations.instant
255
+ }),
256
+ crt: createTheme({
257
+ background: "repeating-linear-gradient(0deg, rgba(34, 197, 94, 0.08) 0, rgba(34, 197, 94, 0.08) 1px, transparent 1px, transparent 3px), radial-gradient(circle at center, #07150b, #000000)",
258
+ color: "#86efac",
259
+ fontFamily: "Lucida Console, Monaco, monospace",
260
+ fontSize: "12px",
261
+ fontWeight: 600,
262
+ border: "2px solid #166534",
263
+ borderRadius: "18px",
264
+ filter: "drop-shadow(0 0 8px rgba(34, 197, 94, 0.5)) drop-shadow(0 0 18px rgba(34, 197, 94, 0.18))",
265
+ padding: "10px 15px",
266
+ textShadow: "0 0 6px rgba(134, 239, 172, 0.85)",
267
+ arrowSize: "8px",
268
+ arrowWidth: "18px",
269
+ animation: animations.blur
270
+ }),
271
+ pixel: createTheme({
272
+ background: "linear-gradient(135deg, #4c1d95 25%, #581c87 25%, #581c87 50%, #4c1d95 50%, #4c1d95 75%, #581c87 75%) 0 0 / 8px 8px",
273
+ color: "#fef08a",
274
+ fontFamily: "Press Start 2P, Courier New, monospace",
275
+ fontSize: "10px",
276
+ fontWeight: 700,
277
+ lineHeight: 1.7,
278
+ border: "4px solid #fef08a",
279
+ borderRadius: "0px",
280
+ filter: "drop-shadow(6px 6px 0 #18181b)",
281
+ padding: "10px 14px",
282
+ letterSpacing: "0.03em",
283
+ textShadow: "2px 2px 0 #18181b",
284
+ textTransform: "uppercase",
285
+ arrowSize: "10px",
286
+ arrowWidth: "18px",
287
+ animation: animations.snap
288
+ }),
289
+ arcade: createTheme({
290
+ background: "radial-gradient(circle at 20% 0%, rgba(34, 211, 238, 0.45), transparent 38%), radial-gradient(circle at 90% 100%, rgba(236, 72, 153, 0.55), transparent 45%), #150629",
291
+ color: "#ffffff",
292
+ fontFamily: "Arial Black, Impact, sans-serif",
293
+ fontSize: "12px",
294
+ fontWeight: 900,
295
+ border: "2px solid #22d3ee",
296
+ borderRadius: "12px",
297
+ filter: "drop-shadow(3px 3px 0 #ec4899) drop-shadow(-3px -3px 0 #22d3ee)",
298
+ padding: "9px 15px",
299
+ letterSpacing: "0.07em",
300
+ textShadow: "0 0 6px #22d3ee",
301
+ textTransform: "uppercase",
302
+ arrowSize: "9px",
303
+ arrowWidth: "18px",
304
+ animation: animations.bounce
305
+ }),
306
+ cyberpunk: createTheme({
307
+ background: "repeating-linear-gradient(135deg, rgba(0, 0, 0, 0.12) 0, rgba(0, 0, 0, 0.12) 5px, transparent 5px, transparent 10px), linear-gradient(135deg, #fde047, #facc15)",
308
+ color: "#18181b",
309
+ fontFamily: "Impact, Arial Black, sans-serif",
310
+ fontSize: "12px",
311
+ fontWeight: 900,
312
+ border: "2px solid #22d3ee",
313
+ borderRadius: "1px 12px 1px 12px",
314
+ filter: "drop-shadow(5px 5px 0 #ec4899) drop-shadow(-2px -2px 0 #22d3ee)",
315
+ padding: "9px 15px",
316
+ letterSpacing: "0.08em",
317
+ textTransform: "uppercase",
318
+ arrowSize: "10px",
319
+ arrowWidth: "21px",
320
+ animation: animations.flip
321
+ }),
322
+ synthwave: createTheme({
323
+ background: "linear-gradient(180deg, rgba(15, 23, 42, 0.2), rgba(15, 23, 42, 0.75)), linear-gradient(135deg, #7c3aed, #db2777)",
324
+ color: "#fdf4ff",
325
+ fontFamily: "Trebuchet MS, Arial, sans-serif",
326
+ fontSize: "12px",
327
+ fontWeight: 700,
328
+ border: "2px solid #67e8f9",
329
+ borderRadius: "16px 3px 16px 3px",
330
+ filter: "drop-shadow(0 0 7px #ec4899) drop-shadow(0 0 14px rgba(103, 232, 249, 0.5))",
331
+ padding: "9px 15px",
332
+ letterSpacing: "0.07em",
333
+ textShadow: "0 0 6px rgba(255, 255, 255, 0.7)",
334
+ textTransform: "uppercase",
335
+ arrowSize: "9px",
336
+ arrowWidth: "20px",
337
+ animation: animations.zoom
338
+ }),
339
+ vaporwave: createTheme({
340
+ background: "linear-gradient(135deg, rgba(255, 255, 255, 0.2), transparent 50%), linear-gradient(135deg, #67e8f9, #f0abfc 52%, #f9a8d4)",
341
+ color: "#4c1d95",
342
+ fontFamily: "Arial Rounded MT Bold, Arial, sans-serif",
343
+ fontSize: "12px",
344
+ fontWeight: 700,
345
+ border: "2px solid #ffffff",
346
+ borderRadius: "18px",
347
+ filter: "drop-shadow(5px 6px 0 rgba(124, 58, 237, 0.42))",
348
+ padding: "9px 16px",
349
+ letterSpacing: "0.06em",
350
+ textShadow: "1px 1px 0 rgba(255, 255, 255, 0.8)",
351
+ textTransform: "uppercase",
352
+ arrowSize: "9px",
353
+ arrowWidth: "21px",
354
+ animation: animations.bounce
355
+ }),
356
+ hologram: createTheme({
357
+ background: "linear-gradient(115deg, rgba(34, 211, 238, 0.42), rgba(168, 85, 247, 0.35), rgba(236, 72, 153, 0.35), rgba(34, 211, 238, 0.42)), rgba(8, 47, 73, 0.72)",
358
+ color: "#ecfeff",
359
+ fontFamily: "Segoe UI, Arial, sans-serif",
360
+ fontSize: "12px",
361
+ fontWeight: 600,
362
+ border: "1px solid rgba(165, 243, 252, 0.75)",
363
+ borderRadius: "14px",
364
+ filter: "drop-shadow(0 0 7px rgba(34, 211, 238, 0.75)) drop-shadow(0 0 16px rgba(168, 85, 247, 0.4))",
365
+ padding: "9px 15px",
366
+ letterSpacing: "0.06em",
367
+ backdropFilter: "blur(8px)",
368
+ arrowSize: "8px",
369
+ arrowWidth: "18px",
370
+ animation: animations.blur
371
+ }),
372
+ glass: createTheme({
373
+ background: "linear-gradient(135deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.07)), rgba(15, 23, 42, 0.68)",
374
+ color: "#f8fafc",
375
+ border: "1px solid rgba(255, 255, 255, 0.34)",
376
+ borderRadius: "16px",
377
+ filter: "drop-shadow(0 12px 20px rgba(15, 23, 42, 0.38))",
378
+ padding: "9px 15px",
379
+ backdropFilter: "blur(16px)",
380
+ arrowSize: "8px",
381
+ arrowWidth: "18px",
382
+ animation: animations.blur
383
+ }),
384
+ frost: createTheme({
385
+ background: "radial-gradient(circle at 15% 20%, rgba(255, 255, 255, 0.85), transparent 35%), linear-gradient(135deg, rgba(224, 242, 254, 0.92), rgba(186, 230, 253, 0.72))",
386
+ color: "#075985",
387
+ fontWeight: 600,
388
+ border: "1px solid rgba(125, 211, 252, 0.9)",
389
+ borderRadius: "18px",
390
+ filter: "drop-shadow(0 8px 15px rgba(14, 116, 144, 0.24))",
391
+ padding: "9px 15px",
392
+ textShadow: "0 1px 0 rgba(255, 255, 255, 0.8)",
393
+ backdropFilter: "blur(14px)",
394
+ arrowSize: "8px",
395
+ arrowWidth: "19px",
396
+ animation: animations.blur
397
+ }),
398
+ clay: createTheme({
399
+ background: "linear-gradient(145deg, #f3d5bc, #d9a77d)",
400
+ color: "#5b2d16",
401
+ fontFamily: "Arial Rounded MT Bold, Arial, sans-serif",
402
+ fontSize: "12px",
403
+ fontWeight: 700,
404
+ border: "1px solid #c78f63",
405
+ borderRadius: "24px",
406
+ filter: "drop-shadow(7px 9px 10px rgba(91, 45, 22, 0.28)) drop-shadow(-3px -3px 5px rgba(255, 242, 229, 0.72))",
407
+ padding: "10px 17px",
408
+ arrowSize: "9px",
409
+ arrowWidth: "22px",
410
+ animation: animations.pop
411
+ }),
412
+ bubblegum: createTheme({
413
+ background: "radial-gradient(circle at 25% 15%, rgba(255, 255, 255, 0.55), transparent 28%), linear-gradient(135deg, #f9a8d4, #f472b6)",
414
+ color: "#831843",
415
+ fontFamily: "Arial Rounded MT Bold, Arial, sans-serif",
416
+ fontSize: "12px",
417
+ fontWeight: 700,
418
+ border: "2px solid #fdf2f8",
419
+ borderRadius: "999px",
420
+ filter: "drop-shadow(0 8px 12px rgba(219, 39, 119, 0.34))",
421
+ padding: "9px 18px",
422
+ textShadow: "0 1px 0 rgba(255, 255, 255, 0.8)",
423
+ arrowSize: "9px",
424
+ arrowWidth: "22px",
425
+ animation: animations.bounce
426
+ }),
427
+ candy: createTheme({
428
+ background: "repeating-linear-gradient(135deg, #ffffff 0, #ffffff 8px, #ef4444 8px, #ef4444 16px)",
429
+ color: "#991b1b",
430
+ fontFamily: "Arial Rounded MT Bold, Arial, sans-serif",
431
+ fontSize: "12px",
432
+ fontWeight: 900,
433
+ border: "3px solid #991b1b",
434
+ borderRadius: "16px",
435
+ filter: "drop-shadow(4px 5px 0 rgba(127, 29, 29, 0.5))",
436
+ padding: "9px 16px",
437
+ textShadow: "1px 1px 0 #ffffff, -1px -1px 0 #ffffff",
438
+ textTransform: "uppercase",
439
+ arrowSize: "10px",
440
+ arrowWidth: "22px",
441
+ animation: animations.bounce
442
+ }),
443
+ watermelon: createTheme({
444
+ background: "radial-gradient(ellipse at 22% 30%, #111827 0 2px, transparent 3px), radial-gradient(ellipse at 72% 68%, #111827 0 2px, transparent 3px), linear-gradient(180deg, #fb7185 0%, #f43f5e 72%, #f8fafc 72%, #f8fafc 82%, #22c55e 82%)",
445
+ color: "#4c0519",
446
+ fontFamily: "Trebuchet MS, sans-serif",
447
+ fontSize: "12px",
448
+ fontWeight: 800,
449
+ border: "2px solid #166534",
450
+ borderRadius: "20px 20px 8px 8px",
451
+ filter: "drop-shadow(0 8px 11px rgba(22, 101, 52, 0.32))",
452
+ padding: "9px 16px 12px",
453
+ arrowSize: "9px",
454
+ arrowWidth: "22px",
455
+ animation: animations.pop
456
+ }),
457
+ lemon: createTheme({
458
+ background: "radial-gradient(circle at 25% 25%, rgba(255, 255, 255, 0.65), transparent 22%), linear-gradient(135deg, #fef08a, #facc15)",
459
+ color: "#713f12",
460
+ fontFamily: "Arial Rounded MT Bold, Arial, sans-serif",
461
+ fontSize: "12px",
462
+ fontWeight: 800,
463
+ border: "2px dotted #a16207",
464
+ borderRadius: "999px",
465
+ filter: "drop-shadow(0 7px 10px rgba(202, 138, 4, 0.32))",
466
+ padding: "8px 17px",
467
+ arrowSize: "9px",
468
+ arrowWidth: "22px",
469
+ animation: animations.bounce
470
+ }),
471
+ lava: createTheme({
472
+ background: "radial-gradient(circle at 18% 20%, #facc15 0, #f97316 8%, transparent 22%), radial-gradient(circle at 78% 70%, #ef4444 0, #7f1d1d 18%, transparent 34%), linear-gradient(135deg, #450a0a, #09090b)",
473
+ color: "#fef3c7",
474
+ fontFamily: "Impact, Arial Black, sans-serif",
475
+ fontSize: "12px",
476
+ fontWeight: 800,
477
+ border: "2px solid #f97316",
478
+ borderRadius: "14px 4px 18px 6px",
479
+ filter: "drop-shadow(0 0 7px rgba(249, 115, 22, 0.8)) drop-shadow(0 8px 15px rgba(69, 10, 10, 0.6))",
480
+ padding: "9px 15px",
481
+ letterSpacing: "0.04em",
482
+ textShadow: "0 0 5px rgba(253, 186, 116, 0.8)",
483
+ textTransform: "uppercase",
484
+ arrowSize: "10px",
485
+ arrowWidth: "19px",
486
+ animation: animations.zoom
487
+ }),
488
+ ember: createTheme({
489
+ background: "radial-gradient(circle at 15% 40%, rgba(251, 146, 60, 0.72), transparent 22%), radial-gradient(circle at 75% 20%, rgba(239, 68, 68, 0.48), transparent 25%), #291208",
490
+ color: "#fed7aa",
491
+ fontFamily: "Georgia, serif",
492
+ fontSize: "13px",
493
+ fontWeight: 600,
494
+ border: "1px solid #c2410c",
495
+ borderRadius: "8px 18px 8px 18px",
496
+ filter: "drop-shadow(0 0 7px rgba(234, 88, 12, 0.5))",
497
+ padding: "9px 15px",
498
+ textShadow: "0 0 4px rgba(251, 146, 60, 0.7)",
499
+ arrowSize: "9px",
500
+ arrowWidth: "18px",
501
+ animation: animations.blur
502
+ }),
503
+ toxic: createTheme({
504
+ background: "repeating-linear-gradient(135deg, rgba(0, 0, 0, 0.17) 0, rgba(0, 0, 0, 0.17) 5px, transparent 5px, transparent 10px), #a3e635",
505
+ color: "#1a2e05",
506
+ fontFamily: "Arial Black, Impact, sans-serif",
507
+ fontSize: "12px",
508
+ fontWeight: 900,
509
+ border: "3px solid #1a2e05",
510
+ borderRadius: "2px 12px 2px 12px",
511
+ filter: "drop-shadow(4px 5px 0 #365314)",
512
+ padding: "9px 14px",
513
+ letterSpacing: "0.08em",
514
+ textTransform: "uppercase",
515
+ arrowSize: "10px",
516
+ arrowWidth: "20px",
517
+ animation: animations.snap
518
+ }),
519
+ radioactive: createTheme({
520
+ background: "conic-gradient(from 45deg at 50% 50%, #facc15 0 12.5%, #18181b 12.5% 25%, #facc15 25% 37.5%, #18181b 37.5% 50%, #facc15 50% 62.5%, #18181b 62.5% 75%, #facc15 75% 87.5%, #18181b 87.5%)",
521
+ color: "#ffffff",
522
+ fontFamily: "Arial Black, sans-serif",
523
+ fontSize: "12px",
524
+ fontWeight: 900,
525
+ border: "3px solid #000000",
526
+ borderRadius: "50%",
527
+ filter: "drop-shadow(0 0 8px rgba(250, 204, 21, 0.7))",
528
+ padding: "13px 18px",
529
+ letterSpacing: "0.05em",
530
+ textShadow: "2px 2px 0 #000000, -1px -1px 0 #000000",
531
+ textTransform: "uppercase",
532
+ arrowSize: "11px",
533
+ arrowWidth: "21px",
534
+ animation: animations.zoom
535
+ }),
536
+ hazard: createTheme({
537
+ background: "repeating-linear-gradient(135deg, #f97316 0, #f97316 10px, #18181b 10px, #18181b 20px)",
538
+ color: "#ffffff",
539
+ fontFamily: "Arial Black, Impact, sans-serif",
540
+ fontSize: "12px",
541
+ fontWeight: 900,
542
+ border: "3px solid #18181b",
543
+ borderRadius: "4px",
544
+ filter: "drop-shadow(5px 5px 0 rgba(24, 24, 27, 0.6))",
545
+ padding: "9px 15px",
546
+ textShadow: "2px 2px 0 #18181b, -1px -1px 0 #18181b",
547
+ textTransform: "uppercase",
548
+ arrowSize: "10px",
549
+ arrowWidth: "20px",
550
+ animation: animations.snap
551
+ }),
552
+ policeTape: createTheme({
553
+ background: "repeating-linear-gradient(135deg, #f8fafc 0, #f8fafc 11px, #2563eb 11px, #2563eb 22px)",
554
+ color: "#172554",
555
+ fontFamily: "Arial Narrow, Arial, sans-serif",
556
+ fontSize: "12px",
557
+ fontWeight: 900,
558
+ border: "3px solid #1e3a8a",
559
+ borderRadius: "1px",
560
+ filter: "drop-shadow(4px 5px 0 rgba(30, 58, 138, 0.42))",
561
+ padding: "8px 15px",
562
+ letterSpacing: "0.1em",
563
+ textShadow: "1px 1px 0 #ffffff, -1px -1px 0 #ffffff",
564
+ textTransform: "uppercase",
565
+ arrowSize: "9px",
566
+ arrowWidth: "20px",
567
+ animation: animations.slide
568
+ }),
569
+ construction: createTheme({
570
+ background: "repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.045) 0, rgba(255, 255, 255, 0.045) 1px, transparent 1px, transparent 7px), linear-gradient(135deg, #52525b, #27272a)",
571
+ color: "#fed7aa",
572
+ fontFamily: "DIN Condensed, Arial Narrow, sans-serif",
573
+ fontSize: "12px",
574
+ fontWeight: 800,
575
+ border: "3px dashed #f97316",
576
+ borderRadius: "3px",
577
+ filter: "drop-shadow(5px 6px 0 rgba(24, 24, 27, 0.52))",
578
+ padding: "9px 15px",
579
+ letterSpacing: "0.07em",
580
+ textTransform: "uppercase",
581
+ arrowSize: "10px",
582
+ arrowWidth: "20px",
583
+ animation: animations.flip
584
+ }),
585
+ parchment: createTheme({
586
+ background: "radial-gradient(circle at 12% 20%, rgba(120, 83, 36, 0.12), transparent 20%), radial-gradient(circle at 82% 70%, rgba(120, 83, 36, 0.16), transparent 25%), linear-gradient(135deg, #f5deb3, #e7c78e)",
587
+ color: "#5b3716",
588
+ fontFamily: "Garamond, Georgia, serif",
589
+ fontSize: "14px",
590
+ fontWeight: 600,
591
+ border: "2px solid #9a6b32",
592
+ borderRadius: "14px 3px 12px 5px",
593
+ filter: "drop-shadow(4px 6px 5px rgba(91, 55, 22, 0.3))",
594
+ padding: "10px 16px",
595
+ textAlign: "left",
596
+ arrowSize: "9px",
597
+ arrowWidth: "20px",
598
+ animation: animations.soft
599
+ }),
600
+ pirateMap: createTheme({
601
+ background: "radial-gradient(circle at 75% 25%, transparent 0 6px, rgba(127, 29, 29, 0.55) 7px 8px, transparent 9px), repeating-radial-gradient(circle at 15% 85%, rgba(120, 83, 36, 0.08) 0 2px, transparent 2px 9px), #e7c78e",
602
+ color: "#422006",
603
+ fontFamily: "Papyrus, Harrington, Georgia, serif",
604
+ fontSize: "13px",
605
+ fontWeight: 700,
606
+ border: "2px dashed #78350f",
607
+ borderRadius: "5px 17px 7px 12px",
608
+ filter: "drop-shadow(4px 7px 5px rgba(66, 32, 6, 0.36))",
609
+ padding: "10px 16px",
610
+ letterSpacing: "0.025em",
611
+ textAlign: "left",
612
+ arrowSize: "10px",
613
+ arrowWidth: "19px",
614
+ animation: animations.flip
615
+ }),
616
+ royal: createTheme({
617
+ background: "radial-gradient(circle at 50% -20%, rgba(250, 204, 21, 0.5), transparent 46%), linear-gradient(135deg, #581c87, #2e1065)",
618
+ color: "#fef3c7",
619
+ fontFamily: "Palatino Linotype, Book Antiqua, serif",
620
+ fontSize: "13px",
621
+ fontWeight: 700,
622
+ border: "2px solid #facc15",
623
+ borderRadius: "6px 20px 6px 20px",
624
+ filter: "drop-shadow(0 8px 14px rgba(46, 16, 101, 0.55)) drop-shadow(0 0 5px rgba(250, 204, 21, 0.4))",
625
+ padding: "10px 17px",
626
+ letterSpacing: "0.05em",
627
+ textShadow: "0 1px 2px rgba(0, 0, 0, 0.7)",
628
+ arrowSize: "10px",
629
+ arrowWidth: "21px",
630
+ animation: animations.flip,
631
+ style: {
632
+ fontVariantCaps: "small-caps"
633
+ }
634
+ }),
635
+ noir: createTheme({
636
+ background: "linear-gradient(115deg, #000000 0%, #27272a 48%, #09090b 52%, #000000 100%)",
637
+ color: "#ffffff",
638
+ fontFamily: "Helvetica Neue, Arial, sans-serif",
639
+ fontSize: "12px",
640
+ fontWeight: 700,
641
+ border: "1px solid #a1a1aa",
642
+ borderRadius: "0px",
643
+ filter: "drop-shadow(7px 9px 0 rgba(0, 0, 0, 0.6))",
644
+ padding: "9px 15px",
645
+ letterSpacing: "0.12em",
646
+ textTransform: "uppercase",
647
+ arrowSize: "9px",
648
+ arrowWidth: "16px",
649
+ animation: animations.soft
650
+ }),
651
+ detective: createTheme({
652
+ background: "repeating-linear-gradient(0deg, rgba(68, 64, 60, 0.05) 0, rgba(68, 64, 60, 0.05) 1px, transparent 1px, transparent 5px), #d6c29f",
653
+ color: "#292524",
654
+ fontFamily: "Courier New, monospace",
655
+ fontSize: "12px",
656
+ fontWeight: 700,
657
+ border: "2px solid #57534e",
658
+ borderRadius: "2px",
659
+ filter: "drop-shadow(5px 7px 0 rgba(68, 64, 60, 0.34))",
660
+ padding: "10px 15px",
661
+ letterSpacing: "0.04em",
662
+ textAlign: "left",
663
+ arrowSize: "8px",
664
+ arrowWidth: "17px",
665
+ animation: animations.slide
666
+ }),
667
+ dossier: createTheme({
668
+ background: "linear-gradient(90deg, rgba(127, 29, 29, 0.15) 0 4px, transparent 4px), repeating-linear-gradient(0deg, transparent 0 14px, rgba(120, 83, 36, 0.13) 14px 15px), #e7d7b5",
669
+ color: "#3f2d1d",
670
+ fontFamily: "Courier New, monospace",
671
+ fontSize: "11px",
672
+ fontWeight: 800,
673
+ border: "2px solid #92400e",
674
+ borderRadius: "1px 8px 1px 8px",
675
+ filter: "drop-shadow(5px 7px 0 rgba(120, 53, 15, 0.35))",
676
+ padding: "11px 16px",
677
+ letterSpacing: "0.08em",
678
+ textTransform: "uppercase",
679
+ textAlign: "left",
680
+ arrowSize: "8px",
681
+ arrowWidth: "17px",
682
+ animation: animations.snap
683
+ }),
684
+ medical: createTheme({
685
+ background: "linear-gradient(90deg, transparent 44%, rgba(14, 165, 233, 0.08) 44% 56%, transparent 56%), linear-gradient(0deg, transparent 44%, rgba(14, 165, 233, 0.08) 44% 56%, transparent 56%), #f8fafc",
686
+ color: "#075985",
687
+ fontFamily: "Arial, Helvetica, sans-serif",
688
+ fontSize: "12px",
689
+ fontWeight: 700,
690
+ border: "2px solid #38bdf8",
691
+ borderRadius: "10px",
692
+ filter: "drop-shadow(0 8px 12px rgba(14, 165, 233, 0.2))",
693
+ padding: "9px 15px",
694
+ arrowSize: "8px",
695
+ arrowWidth: "18px",
696
+ animation: animations.soft
697
+ }),
698
+ laboratory: createTheme({
699
+ background: "linear-gradient(rgba(34, 211, 238, 0.09) 1px, transparent 1px), linear-gradient(90deg, rgba(34, 211, 238, 0.09) 1px, transparent 1px), linear-gradient(135deg, #082f49, #0f172a)",
700
+ color: "#a5f3fc",
701
+ fontFamily: "Roboto Mono, Consolas, monospace",
702
+ fontSize: "11px",
703
+ fontWeight: 600,
704
+ border: "1px solid #22d3ee",
705
+ borderRadius: "7px",
706
+ filter: "drop-shadow(0 0 7px rgba(34, 211, 238, 0.45))",
707
+ padding: "9px 14px",
708
+ letterSpacing: "0.04em",
709
+ textAlign: "left",
710
+ arrowSize: "8px",
711
+ arrowWidth: "16px",
712
+ animation: animations.blur,
713
+ style: {
714
+ backgroundSize: "10px 10px"
715
+ }
716
+ }),
717
+ circuit: createTheme({
718
+ background: "linear-gradient(90deg, transparent 48%, rgba(34, 197, 94, 0.2) 48% 52%, transparent 52%) 0 0 / 18px 18px, linear-gradient(0deg, transparent 48%, rgba(34, 197, 94, 0.2) 48% 52%, transparent 52%) 0 0 / 18px 18px, radial-gradient(circle at 9px 9px, #22c55e 0 1.5px, transparent 2px) 0 0 / 18px 18px, #052e16",
719
+ color: "#bbf7d0",
720
+ fontFamily: "Consolas, monospace",
721
+ fontSize: "11px",
722
+ fontWeight: 700,
723
+ border: "2px solid #22c55e",
724
+ borderRadius: "5px",
725
+ filter: "drop-shadow(0 0 7px rgba(34, 197, 94, 0.55))",
726
+ padding: "9px 14px",
727
+ letterSpacing: "0.05em",
728
+ textShadow: "0 0 4px rgba(34, 197, 94, 0.75)",
729
+ arrowSize: "8px",
730
+ arrowWidth: "16px",
731
+ animation: animations.snap
732
+ }),
733
+ galaxy: createTheme({
734
+ background: "radial-gradient(circle at 12% 25%, #ffffff 0 1px, transparent 1.5px), radial-gradient(circle at 76% 18%, #c4b5fd 0 1px, transparent 1.5px), radial-gradient(circle at 63% 78%, #ffffff 0 1.2px, transparent 1.8px), radial-gradient(circle at 28% 72%, rgba(236, 72, 153, 0.55), transparent 22%), radial-gradient(circle at 70% 20%, rgba(99, 102, 241, 0.55), transparent 32%), #09051f",
735
+ color: "#f5f3ff",
736
+ fontFamily: "Trebuchet MS, sans-serif",
737
+ fontSize: "12px",
738
+ fontWeight: 600,
739
+ border: "1px solid #8b5cf6",
740
+ borderRadius: "18px",
741
+ filter: "drop-shadow(0 0 9px rgba(139, 92, 246, 0.62)) drop-shadow(0 9px 16px rgba(9, 5, 31, 0.6))",
742
+ padding: "10px 16px",
743
+ textShadow: "0 0 5px rgba(196, 181, 253, 0.8)",
744
+ arrowSize: "9px",
745
+ arrowWidth: "20px",
746
+ animation: animations.blur
747
+ }),
748
+ aurora: createTheme({
749
+ background: "radial-gradient(ellipse at 15% 0%, rgba(45, 212, 191, 0.85), transparent 45%), radial-gradient(ellipse at 90% 100%, rgba(217, 70, 239, 0.72), transparent 50%), linear-gradient(135deg, #0f172a, #312e81)",
750
+ color: "#f0fdfa",
751
+ fontFamily: "Segoe UI, Arial, sans-serif",
752
+ fontSize: "12px",
753
+ fontWeight: 600,
754
+ border: "1px solid rgba(153, 246, 228, 0.6)",
755
+ borderRadius: "20px 8px 20px 8px",
756
+ filter: "drop-shadow(0 10px 17px rgba(49, 46, 129, 0.48))",
757
+ padding: "10px 16px",
758
+ backdropFilter: "blur(8px)",
759
+ arrowSize: "9px",
760
+ arrowWidth: "21px",
761
+ animation: animations.blur
762
+ }),
763
+ oceanDepths: createTheme({
764
+ background: "radial-gradient(circle at 20% 10%, rgba(34, 211, 238, 0.32), transparent 32%), radial-gradient(circle at 80% 90%, rgba(14, 116, 144, 0.42), transparent 36%), linear-gradient(160deg, #083344, #020617)",
765
+ color: "#cffafe",
766
+ fontFamily: "Trebuchet MS, sans-serif",
767
+ fontSize: "12px",
768
+ fontWeight: 600,
769
+ border: "1px solid #0e7490",
770
+ borderRadius: "4px 20px 4px 20px",
771
+ filter: "drop-shadow(0 10px 16px rgba(2, 6, 23, 0.56)) drop-shadow(0 0 6px rgba(34, 211, 238, 0.3))",
772
+ padding: "10px 16px",
773
+ arrowSize: "10px",
774
+ arrowWidth: "19px",
775
+ animation: animations.slide
776
+ }),
777
+ coralReef: createTheme({
778
+ background: "radial-gradient(circle at 15% 100%, rgba(251, 113, 133, 0.75), transparent 30%), radial-gradient(circle at 90% 0%, rgba(45, 212, 191, 0.72), transparent 34%), linear-gradient(135deg, #0e7490, #155e75)",
779
+ color: "#fff7ed",
780
+ fontFamily: "Trebuchet MS, sans-serif",
781
+ fontSize: "12px",
782
+ fontWeight: 700,
783
+ border: "2px solid #fdba74",
784
+ borderRadius: "18px 8px 14px 5px",
785
+ filter: "drop-shadow(0 9px 14px rgba(14, 116, 144, 0.4))",
786
+ padding: "9px 16px",
787
+ textShadow: "0 1px 2px rgba(12, 74, 110, 0.8)",
788
+ arrowSize: "9px",
789
+ arrowWidth: "21px",
790
+ animation: animations.bounce
791
+ }),
792
+ forest: createTheme({
793
+ background: "radial-gradient(ellipse at 20% 20%, rgba(74, 222, 128, 0.18), transparent 30%), repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.025) 0 2px, transparent 2px 7px), linear-gradient(135deg, #14532d, #052e16)",
794
+ color: "#dcfce7",
795
+ fontFamily: "Georgia, serif",
796
+ fontSize: "13px",
797
+ fontWeight: 600,
798
+ border: "2px solid #4d7c0f",
799
+ borderRadius: "13px 4px 17px 6px",
800
+ filter: "drop-shadow(0 9px 14px rgba(5, 46, 22, 0.5))",
801
+ padding: "9px 16px",
802
+ arrowSize: "9px",
803
+ arrowWidth: "19px",
804
+ animation: animations.slide
805
+ }),
806
+ moss: createTheme({
807
+ background: "radial-gradient(circle at 20% 30%, rgba(190, 242, 100, 0.16) 0 3px, transparent 4px), radial-gradient(circle at 72% 65%, rgba(132, 204, 22, 0.14) 0 4px, transparent 5px), linear-gradient(135deg, #3f6212, #1a2e05)",
808
+ color: "#ecfccb",
809
+ fontFamily: "Palatino Linotype, serif",
810
+ fontSize: "13px",
811
+ fontWeight: 600,
812
+ border: "2px dotted #84cc16",
813
+ borderRadius: "18px 7px 14px 10px",
814
+ filter: "drop-shadow(0 8px 13px rgba(26, 46, 5, 0.5))",
815
+ padding: "10px 16px",
816
+ arrowSize: "9px",
817
+ arrowWidth: "20px",
818
+ animation: animations.blur
819
+ }),
820
+ desert: createTheme({
821
+ background: "radial-gradient(ellipse at 20% 120%, #f59e0b 0 35%, transparent 36%), radial-gradient(ellipse at 85% 110%, #d97706 0 40%, transparent 41%), linear-gradient(180deg, #fde68a, #fbbf24)",
822
+ color: "#78350f",
823
+ fontFamily: "Georgia, serif",
824
+ fontSize: "13px",
825
+ fontWeight: 700,
826
+ border: "2px solid #b45309",
827
+ borderRadius: "22px 22px 7px 7px",
828
+ filter: "drop-shadow(0 9px 13px rgba(180, 83, 9, 0.32))",
829
+ padding: "10px 16px",
830
+ arrowSize: "9px",
831
+ arrowWidth: "21px",
832
+ animation: animations.soft
833
+ }),
834
+ snow: createTheme({
835
+ background: "radial-gradient(circle at 15% 25%, #ffffff 0 2px, transparent 2.5px), radial-gradient(circle at 75% 65%, #ffffff 0 1.5px, transparent 2px), linear-gradient(135deg, #e0f2fe, #bae6fd)",
836
+ color: "#0c4a6e",
837
+ fontFamily: "Helvetica Neue, Arial, sans-serif",
838
+ fontSize: "12px",
839
+ fontWeight: 600,
840
+ border: "2px solid #ffffff",
841
+ borderRadius: "20px",
842
+ filter: "drop-shadow(0 8px 13px rgba(14, 116, 144, 0.22))",
843
+ padding: "10px 16px",
844
+ textShadow: "0 1px 0 rgba(255, 255, 255, 0.9)",
845
+ arrowSize: "9px",
846
+ arrowWidth: "20px",
847
+ animation: animations.blur
848
+ }),
849
+ chrome: createTheme({
850
+ background: "linear-gradient(180deg, #ffffff 0%, #a1a1aa 18%, #f4f4f5 38%, #52525b 52%, #d4d4d8 72%, #71717a 100%)",
851
+ color: "#18181b",
852
+ fontFamily: "Arial Black, sans-serif",
853
+ fontSize: "12px",
854
+ fontWeight: 900,
855
+ border: "2px solid #27272a",
856
+ borderRadius: "10px",
857
+ filter: "drop-shadow(0 8px 12px rgba(24, 24, 27, 0.45))",
858
+ padding: "9px 16px",
859
+ letterSpacing: "0.04em",
860
+ textShadow: "0 1px 0 #ffffff",
861
+ textTransform: "uppercase",
862
+ arrowSize: "9px",
863
+ arrowWidth: "20px",
864
+ animation: animations.flip
865
+ }),
866
+ goldFoil: createTheme({
867
+ background: "linear-gradient(115deg, #713f12 0%, #facc15 18%, #fef08a 32%, #ca8a04 52%, #fef9c3 70%, #a16207 100%)",
868
+ color: "#422006",
869
+ fontFamily: "Palatino Linotype, serif",
870
+ fontSize: "13px",
871
+ fontWeight: 800,
872
+ border: "2px solid #713f12",
873
+ borderRadius: "5px 16px 5px 16px",
874
+ filter: "drop-shadow(0 9px 14px rgba(113, 63, 18, 0.45))",
875
+ padding: "10px 17px",
876
+ letterSpacing: "0.04em",
877
+ textShadow: "0 1px 0 rgba(255, 255, 255, 0.55)",
878
+ arrowSize: "10px",
879
+ arrowWidth: "21px",
880
+ animation: animations.flip,
881
+ style: {
882
+ fontVariantCaps: "small-caps"
883
+ }
884
+ }),
885
+ bronze: createTheme({
886
+ background: "repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.08) 0 1px, transparent 1px 5px), linear-gradient(135deg, #d97706, #78350f)",
887
+ color: "#ffedd5",
888
+ fontFamily: "Georgia, serif",
889
+ fontSize: "13px",
890
+ fontWeight: 700,
891
+ border: "2px solid #fdba74",
892
+ borderRadius: "8px",
893
+ filter: "drop-shadow(0 9px 14px rgba(120, 53, 15, 0.5))",
894
+ padding: "9px 16px",
895
+ textShadow: "0 1px 2px rgba(66, 32, 6, 0.8)",
896
+ arrowSize: "9px",
897
+ arrowWidth: "19px",
898
+ animation: animations.pop
899
+ }),
900
+ brutalist: createTheme({
901
+ background: "#ffffff",
902
+ color: "#000000",
903
+ fontFamily: "Arial Black, Helvetica, sans-serif",
904
+ fontSize: "12px",
905
+ fontWeight: 900,
906
+ border: "4px solid #000000",
907
+ borderRadius: "0px",
908
+ filter: "drop-shadow(7px 7px 0 #ef4444)",
909
+ padding: "10px 16px",
910
+ letterSpacing: "-0.03em",
911
+ textTransform: "uppercase",
912
+ textAlign: "left",
913
+ arrowSize: "11px",
914
+ arrowWidth: "19px",
915
+ animation: animations.snap
916
+ }),
917
+ chalkboard: createTheme({
918
+ background: "repeating-linear-gradient(175deg, rgba(255, 255, 255, 0.018) 0, rgba(255, 255, 255, 0.018) 2px, transparent 2px, transparent 7px), #163a2c",
919
+ color: "#f5f5dc",
920
+ fontFamily: "Comic Sans MS, Chalkboard, cursive",
921
+ fontSize: "13px",
922
+ fontWeight: 600,
923
+ border: "3px solid #8b5e3c",
924
+ borderRadius: "2px",
925
+ filter: "drop-shadow(4px 6px 0 rgba(66, 32, 6, 0.45))",
926
+ padding: "10px 16px",
927
+ letterSpacing: "0.025em",
928
+ textShadow: "0 0 2px rgba(255, 255, 255, 0.55)",
929
+ textAlign: "left",
930
+ arrowSize: "9px",
931
+ arrowWidth: "18px",
932
+ animation: animations.soft
933
+ })
934
+ };
935
+ var presetThemeNames = Object.keys(presets);
936
+
937
+ // src/hooks/useTooltip.ts
938
+ import {
939
+ useCallback,
940
+ useEffect,
941
+ useLayoutEffect,
942
+ useRef,
943
+ useState
944
+ } from "react";
945
+ var DEFAULT_HIDE_DELAY = 120;
946
+ var DEFAULT_INTERACTIVE_HIDE_DELAY = 240;
947
+ var VIEWPORT_PADDING = 8;
948
+ var DEFAULT_ARROW_SIZE = 6;
949
+ var DEFAULT_TOOLTIP_GAP = 10;
950
+ var ARROW_EDGE_OFFSET = 10;
951
+ var oppositePlacement = {
952
+ top: "bottom",
953
+ bottom: "top",
954
+ left: "right",
955
+ right: "left"
956
+ };
957
+ var clamp = (value, min, max) => {
958
+ const resolvedMax = Math.max(min, max);
959
+ return Math.min(Math.max(value, min), resolvedMax);
960
+ };
961
+ var useTooltip = ({
962
+ anchor,
963
+ preferredPlacement,
964
+ disabled = false,
965
+ interactive = false,
966
+ hideDelay
967
+ }) => {
968
+ const tooltipRef = useRef(null);
969
+ const bodyRef = useRef(null);
970
+ const hideTimerRef = useRef(null);
971
+ const firstFrameRef = useRef(null);
972
+ const secondFrameRef = useRef(null);
973
+ const phaseRef = useRef("hidden");
974
+ const pendingHideRef = useRef(false);
975
+ const [mounted, setMounted] = useState(false);
976
+ const [phase, setPhase] = useState("hidden");
977
+ const [placement, setPlacement] = useState(preferredPlacement);
978
+ const [showVersion, setShowVersion] = useState(0);
979
+ const [position, setPosition] = useState({
980
+ top: "0px",
981
+ left: "0px",
982
+ "--tooltip-arrow-offset": "50%"
983
+ });
984
+ const resolvedHideDelay = hideDelay ?? (interactive ? DEFAULT_INTERACTIVE_HIDE_DELAY : DEFAULT_HIDE_DELAY);
985
+ const updatePhase = useCallback((nextPhase) => {
986
+ phaseRef.current = nextPhase;
987
+ setPhase(nextPhase);
988
+ }, []);
989
+ const clearHideTimer = useCallback(() => {
990
+ if (hideTimerRef.current === null) {
991
+ return;
992
+ }
993
+ window.clearTimeout(hideTimerRef.current);
994
+ hideTimerRef.current = null;
995
+ }, []);
996
+ const clearEnterFrames = useCallback(() => {
997
+ if (firstFrameRef.current !== null) {
998
+ window.cancelAnimationFrame(firstFrameRef.current);
999
+ firstFrameRef.current = null;
1000
+ }
1001
+ if (secondFrameRef.current !== null) {
1002
+ window.cancelAnimationFrame(secondFrameRef.current);
1003
+ secondFrameRef.current = null;
1004
+ }
1005
+ }, []);
1006
+ const getAvailableSpace = useCallback(
1007
+ (currentPlacement, rect) => {
1008
+ switch (currentPlacement) {
1009
+ case "top":
1010
+ return rect.top - VIEWPORT_PADDING;
1011
+ case "bottom":
1012
+ return window.innerHeight - rect.bottom - VIEWPORT_PADDING;
1013
+ case "left":
1014
+ return rect.left - VIEWPORT_PADDING;
1015
+ case "right":
1016
+ return window.innerWidth - rect.right - VIEWPORT_PADDING;
1017
+ }
1018
+ },
1019
+ []
1020
+ );
1021
+ const calculatePosition = useCallback(() => {
1022
+ const tooltip = tooltipRef.current;
1023
+ const body = bodyRef.current;
1024
+ if (!anchor || !tooltip || !body) {
1025
+ return;
1026
+ }
1027
+ const rect = anchor.getBoundingClientRect();
1028
+ const computedStyle = window.getComputedStyle(tooltip);
1029
+ const arrowSize = Number.parseFloat(
1030
+ computedStyle.getPropertyValue("--tooltip-arrow-size")
1031
+ ) || DEFAULT_ARROW_SIZE;
1032
+ const tooltipGap = Number.parseFloat(
1033
+ computedStyle.getPropertyValue("--tooltip-gap")
1034
+ ) || DEFAULT_TOOLTIP_GAP;
1035
+ const bodyWidth = body.offsetWidth;
1036
+ const bodyHeight = body.offsetHeight;
1037
+ const distance = arrowSize + tooltipGap;
1038
+ const opposite = oppositePlacement[preferredPlacement];
1039
+ const getRequiredSpace = (currentPlacement) => {
1040
+ if (currentPlacement === "top" || currentPlacement === "bottom") {
1041
+ return bodyHeight + distance;
1042
+ }
1043
+ return bodyWidth + distance;
1044
+ };
1045
+ const preferredAvailable = getAvailableSpace(
1046
+ preferredPlacement,
1047
+ rect
1048
+ );
1049
+ const preferredRequired = getRequiredSpace(preferredPlacement);
1050
+ let nextPlacement = preferredPlacement;
1051
+ if (preferredAvailable < preferredRequired) {
1052
+ const oppositeAvailable = getAvailableSpace(opposite, rect);
1053
+ const oppositeRequired = getRequiredSpace(opposite);
1054
+ if (oppositeAvailable >= oppositeRequired || oppositeAvailable > preferredAvailable) {
1055
+ nextPlacement = opposite;
1056
+ }
1057
+ }
1058
+ const anchorCenterX = rect.left + rect.width / 2;
1059
+ const anchorCenterY = rect.top + rect.height / 2;
1060
+ let top = 0;
1061
+ let left = 0;
1062
+ let arrowOffset = "50%";
1063
+ if (nextPlacement === "top") {
1064
+ top = rect.top - bodyHeight - distance;
1065
+ left = anchorCenterX - bodyWidth / 2;
1066
+ }
1067
+ if (nextPlacement === "bottom") {
1068
+ top = rect.bottom + distance;
1069
+ left = anchorCenterX - bodyWidth / 2;
1070
+ }
1071
+ if (nextPlacement === "left") {
1072
+ top = anchorCenterY - bodyHeight / 2;
1073
+ left = rect.left - bodyWidth - distance;
1074
+ }
1075
+ if (nextPlacement === "right") {
1076
+ top = anchorCenterY - bodyHeight / 2;
1077
+ left = rect.right + distance;
1078
+ }
1079
+ const maxLeft = window.innerWidth - bodyWidth - VIEWPORT_PADDING;
1080
+ const maxTop = window.innerHeight - bodyHeight - VIEWPORT_PADDING;
1081
+ left = clamp(left, VIEWPORT_PADDING, maxLeft);
1082
+ top = clamp(top, VIEWPORT_PADDING, maxTop);
1083
+ if (nextPlacement === "top" || nextPlacement === "bottom") {
1084
+ const offset = clamp(
1085
+ anchorCenterX - left,
1086
+ ARROW_EDGE_OFFSET,
1087
+ bodyWidth - ARROW_EDGE_OFFSET
1088
+ );
1089
+ arrowOffset = `${offset}px`;
1090
+ }
1091
+ if (nextPlacement === "left" || nextPlacement === "right") {
1092
+ const offset = clamp(
1093
+ anchorCenterY - top,
1094
+ ARROW_EDGE_OFFSET,
1095
+ bodyHeight - ARROW_EDGE_OFFSET
1096
+ );
1097
+ arrowOffset = `${offset}px`;
1098
+ }
1099
+ setPlacement(nextPlacement);
1100
+ setPosition({
1101
+ top: `${top}px`,
1102
+ left: `${left}px`,
1103
+ "--tooltip-arrow-offset": arrowOffset
1104
+ });
1105
+ }, [anchor, getAvailableSpace, preferredPlacement]);
1106
+ const removeTooltip = useCallback(() => {
1107
+ clearHideTimer();
1108
+ clearEnterFrames();
1109
+ pendingHideRef.current = false;
1110
+ updatePhase("hidden");
1111
+ }, [clearEnterFrames, clearHideTimer, updatePhase]);
1112
+ const runHide = useCallback(() => {
1113
+ const currentPhase = phaseRef.current;
1114
+ if (currentPhase === "hidden" || currentPhase === "leaving") {
1115
+ return;
1116
+ }
1117
+ if (currentPhase === "preparing") {
1118
+ removeTooltip();
1119
+ return;
1120
+ }
1121
+ if (currentPhase === "entering") {
1122
+ pendingHideRef.current = true;
1123
+ return;
1124
+ }
1125
+ updatePhase("leaving");
1126
+ }, [removeTooltip, updatePhase]);
1127
+ const hideTooltip = useCallback(
1128
+ (immediate = false) => {
1129
+ clearHideTimer();
1130
+ if (immediate) {
1131
+ runHide();
1132
+ return;
1133
+ }
1134
+ hideTimerRef.current = window.setTimeout(() => {
1135
+ hideTimerRef.current = null;
1136
+ runHide();
1137
+ }, resolvedHideDelay);
1138
+ },
1139
+ [clearHideTimer, resolvedHideDelay, runHide]
1140
+ );
1141
+ const showTooltip = useCallback(() => {
1142
+ if (!anchor || disabled) {
1143
+ return;
1144
+ }
1145
+ clearHideTimer();
1146
+ clearEnterFrames();
1147
+ pendingHideRef.current = false;
1148
+ setMounted(true);
1149
+ if (phaseRef.current === "entering" || phaseRef.current === "visible") {
1150
+ return;
1151
+ }
1152
+ updatePhase("preparing");
1153
+ setShowVersion((value) => value + 1);
1154
+ }, [anchor, clearEnterFrames, clearHideTimer, disabled, updatePhase]);
1155
+ const keepTooltipOpen = useCallback(() => {
1156
+ if (!interactive || disabled) {
1157
+ return;
1158
+ }
1159
+ clearHideTimer();
1160
+ pendingHideRef.current = false;
1161
+ if (phaseRef.current === "leaving") {
1162
+ updatePhase("visible");
1163
+ }
1164
+ }, [clearHideTimer, disabled, interactive, updatePhase]);
1165
+ const onAnimationEnd = useCallback(() => {
1166
+ const currentPhase = phaseRef.current;
1167
+ if (currentPhase === "entering") {
1168
+ if (pendingHideRef.current) {
1169
+ pendingHideRef.current = false;
1170
+ updatePhase("leaving");
1171
+ return;
1172
+ }
1173
+ updatePhase("visible");
1174
+ return;
1175
+ }
1176
+ if (currentPhase === "leaving") {
1177
+ removeTooltip();
1178
+ }
1179
+ }, [removeTooltip, updatePhase]);
1180
+ useLayoutEffect(() => {
1181
+ if (phase !== "preparing" || !anchor) {
1182
+ return;
1183
+ }
1184
+ calculatePosition();
1185
+ firstFrameRef.current = window.requestAnimationFrame(() => {
1186
+ firstFrameRef.current = null;
1187
+ secondFrameRef.current = window.requestAnimationFrame(() => {
1188
+ secondFrameRef.current = null;
1189
+ if (!anchor || phaseRef.current !== "preparing") {
1190
+ return;
1191
+ }
1192
+ updatePhase("entering");
1193
+ });
1194
+ });
1195
+ return clearEnterFrames;
1196
+ }, [
1197
+ anchor,
1198
+ calculatePosition,
1199
+ clearEnterFrames,
1200
+ phase,
1201
+ showVersion,
1202
+ updatePhase
1203
+ ]);
1204
+ useEffect(() => {
1205
+ if (!anchor) {
1206
+ removeTooltip();
1207
+ return;
1208
+ }
1209
+ const onPointerEnter = (event) => {
1210
+ if (event.pointerType === "touch") {
1211
+ return;
1212
+ }
1213
+ showTooltip();
1214
+ };
1215
+ const onPointerLeave = (event) => {
1216
+ if (event.pointerType === "touch") {
1217
+ return;
1218
+ }
1219
+ const relatedTarget = event.relatedTarget;
1220
+ const tooltip = tooltipRef.current;
1221
+ if (interactive && relatedTarget instanceof Node && tooltip?.contains(relatedTarget)) {
1222
+ keepTooltipOpen();
1223
+ return;
1224
+ }
1225
+ hideTooltip(false);
1226
+ };
1227
+ const onPointerDown = (event) => {
1228
+ if (event.pointerType !== "touch") {
1229
+ return;
1230
+ }
1231
+ if (phaseRef.current === "hidden" || phaseRef.current === "leaving") {
1232
+ showTooltip();
1233
+ } else {
1234
+ hideTooltip(true);
1235
+ }
1236
+ };
1237
+ const onFocusIn = () => {
1238
+ showTooltip();
1239
+ };
1240
+ const onFocusOut = (event) => {
1241
+ const relatedTarget = event.relatedTarget;
1242
+ const tooltip = tooltipRef.current;
1243
+ if (relatedTarget instanceof Node && (anchor.contains(relatedTarget) || interactive && tooltip?.contains(relatedTarget))) {
1244
+ return;
1245
+ }
1246
+ hideTooltip(false);
1247
+ };
1248
+ anchor.addEventListener("pointerenter", onPointerEnter);
1249
+ anchor.addEventListener("pointerleave", onPointerLeave);
1250
+ anchor.addEventListener("pointerdown", onPointerDown);
1251
+ anchor.addEventListener("focusin", onFocusIn);
1252
+ anchor.addEventListener("focusout", onFocusOut);
1253
+ return () => {
1254
+ anchor.removeEventListener("pointerenter", onPointerEnter);
1255
+ anchor.removeEventListener("pointerleave", onPointerLeave);
1256
+ anchor.removeEventListener("pointerdown", onPointerDown);
1257
+ anchor.removeEventListener("focusin", onFocusIn);
1258
+ anchor.removeEventListener("focusout", onFocusOut);
1259
+ clearHideTimer();
1260
+ clearEnterFrames();
1261
+ };
1262
+ }, [
1263
+ anchor,
1264
+ clearEnterFrames,
1265
+ clearHideTimer,
1266
+ hideTooltip,
1267
+ interactive,
1268
+ keepTooltipOpen,
1269
+ removeTooltip,
1270
+ showTooltip
1271
+ ]);
1272
+ useEffect(() => {
1273
+ if (!interactive || !mounted) {
1274
+ return;
1275
+ }
1276
+ const tooltip = tooltipRef.current;
1277
+ if (!tooltip) {
1278
+ return;
1279
+ }
1280
+ const onPointerEnter = (event) => {
1281
+ if (event.pointerType === "touch") {
1282
+ return;
1283
+ }
1284
+ keepTooltipOpen();
1285
+ };
1286
+ const onPointerLeave = (event) => {
1287
+ if (event.pointerType === "touch") {
1288
+ return;
1289
+ }
1290
+ const relatedTarget = event.relatedTarget;
1291
+ if (relatedTarget instanceof Node && anchor?.contains(relatedTarget)) {
1292
+ keepTooltipOpen();
1293
+ return;
1294
+ }
1295
+ hideTooltip(false);
1296
+ };
1297
+ const onFocusIn = () => {
1298
+ keepTooltipOpen();
1299
+ };
1300
+ const onFocusOut = (event) => {
1301
+ const relatedTarget = event.relatedTarget;
1302
+ if (relatedTarget instanceof Node && (tooltip.contains(relatedTarget) || anchor?.contains(relatedTarget))) {
1303
+ return;
1304
+ }
1305
+ hideTooltip(false);
1306
+ };
1307
+ tooltip.addEventListener("pointerenter", onPointerEnter);
1308
+ tooltip.addEventListener("pointerleave", onPointerLeave);
1309
+ tooltip.addEventListener("focusin", onFocusIn);
1310
+ tooltip.addEventListener("focusout", onFocusOut);
1311
+ return () => {
1312
+ tooltip.removeEventListener("pointerenter", onPointerEnter);
1313
+ tooltip.removeEventListener("pointerleave", onPointerLeave);
1314
+ tooltip.removeEventListener("focusin", onFocusIn);
1315
+ tooltip.removeEventListener("focusout", onFocusOut);
1316
+ };
1317
+ }, [
1318
+ anchor,
1319
+ hideTooltip,
1320
+ interactive,
1321
+ keepTooltipOpen,
1322
+ mounted
1323
+ ]);
1324
+ useEffect(() => {
1325
+ if (!anchor || phase === "hidden") {
1326
+ return;
1327
+ }
1328
+ const onDocumentPointerDown = (event) => {
1329
+ const target = event.target;
1330
+ const tooltip = tooltipRef.current;
1331
+ if (target instanceof Node && (anchor.contains(target) || interactive && tooltip?.contains(target))) {
1332
+ return;
1333
+ }
1334
+ hideTooltip(true);
1335
+ };
1336
+ const onKeyDown = (event) => {
1337
+ if (event.key === "Escape") {
1338
+ hideTooltip(true);
1339
+ }
1340
+ };
1341
+ document.addEventListener(
1342
+ "pointerdown",
1343
+ onDocumentPointerDown,
1344
+ true
1345
+ );
1346
+ document.addEventListener("keydown", onKeyDown);
1347
+ window.addEventListener("resize", calculatePosition);
1348
+ window.addEventListener("scroll", calculatePosition, true);
1349
+ return () => {
1350
+ document.removeEventListener(
1351
+ "pointerdown",
1352
+ onDocumentPointerDown,
1353
+ true
1354
+ );
1355
+ document.removeEventListener("keydown", onKeyDown);
1356
+ window.removeEventListener("resize", calculatePosition);
1357
+ window.removeEventListener("scroll", calculatePosition, true);
1358
+ };
1359
+ }, [
1360
+ anchor,
1361
+ calculatePosition,
1362
+ hideTooltip,
1363
+ interactive,
1364
+ phase
1365
+ ]);
1366
+ useLayoutEffect(() => {
1367
+ if (phase === "hidden") {
1368
+ return;
1369
+ }
1370
+ const body = bodyRef.current;
1371
+ if (!body) {
1372
+ return;
1373
+ }
1374
+ const resizeObserver = new ResizeObserver(calculatePosition);
1375
+ resizeObserver.observe(body);
1376
+ return () => {
1377
+ resizeObserver.disconnect();
1378
+ };
1379
+ }, [calculatePosition, phase]);
1380
+ useEffect(() => {
1381
+ if (!disabled) {
1382
+ return;
1383
+ }
1384
+ hideTooltip(true);
1385
+ }, [disabled, hideTooltip]);
1386
+ return {
1387
+ shouldRender: mounted,
1388
+ phase,
1389
+ placement,
1390
+ position,
1391
+ tooltipRef,
1392
+ bodyRef,
1393
+ calculatePosition,
1394
+ onAnimationEnd
1395
+ };
1396
+ };
1397
+
1398
+ // src/utils/tooltipTheme.ts
1399
+ var BORDER_STYLE_VALUES = /* @__PURE__ */ new Set([
1400
+ "none",
1401
+ "hidden",
1402
+ "dotted",
1403
+ "dashed",
1404
+ "solid",
1405
+ "double",
1406
+ "groove",
1407
+ "ridge",
1408
+ "inset",
1409
+ "outset",
1410
+ "inherit",
1411
+ "initial",
1412
+ "revert",
1413
+ "revert-layer",
1414
+ "unset"
1415
+ ]);
1416
+ var splitCssTokens = (value) => {
1417
+ const tokens = [];
1418
+ let current = "";
1419
+ let depth = 0;
1420
+ for (const character of value.trim()) {
1421
+ if (character === "(") {
1422
+ depth += 1;
1423
+ }
1424
+ if (character === ")") {
1425
+ depth = Math.max(0, depth - 1);
1426
+ }
1427
+ if (/\s/.test(character) && depth === 0) {
1428
+ if (current.trim()) {
1429
+ tokens.push(current.trim());
1430
+ }
1431
+ current = "";
1432
+ continue;
1433
+ }
1434
+ current += character;
1435
+ }
1436
+ if (current.trim()) {
1437
+ tokens.push(current.trim());
1438
+ }
1439
+ return tokens;
1440
+ };
1441
+ var splitOutsideParentheses = (value, separator) => {
1442
+ const result = [];
1443
+ let current = "";
1444
+ let depth = 0;
1445
+ for (const character of value) {
1446
+ if (character === "(") {
1447
+ depth += 1;
1448
+ }
1449
+ if (character === ")") {
1450
+ depth = Math.max(0, depth - 1);
1451
+ }
1452
+ if (character === separator && depth === 0) {
1453
+ if (current.trim()) {
1454
+ result.push(current.trim());
1455
+ }
1456
+ current = "";
1457
+ continue;
1458
+ }
1459
+ current += character;
1460
+ }
1461
+ if (current.trim()) {
1462
+ result.push(current.trim());
1463
+ }
1464
+ return result;
1465
+ };
1466
+ var expandQuad = (values) => {
1467
+ if (values.length === 0) {
1468
+ return [void 0, void 0, void 0, void 0];
1469
+ }
1470
+ if (values.length === 1) {
1471
+ return [values[0], values[0], values[0], values[0]];
1472
+ }
1473
+ if (values.length === 2) {
1474
+ return [values[0], values[1], values[0], values[1]];
1475
+ }
1476
+ if (values.length === 3) {
1477
+ return [values[0], values[1], values[2], values[1]];
1478
+ }
1479
+ return [values[0], values[1], values[2], values[3]];
1480
+ };
1481
+ var isBorderWidthToken = (value) => {
1482
+ return value === "thin" || value === "medium" || value === "thick" || value === "0" || value === "inherit" || value === "initial" || value === "revert" || value === "revert-layer" || value === "unset" || /^-?(?:\d+|\d*\.\d+)(?:px|rem|em|vh|vw|vmin|vmax|%)?$/.test(value) || value.startsWith("calc(") || value.startsWith("var(");
1483
+ };
1484
+ var isBorderStyleToken = (value) => {
1485
+ return BORDER_STYLE_VALUES.has(value);
1486
+ };
1487
+ var parseBorder = (value) => {
1488
+ if (typeof value !== "string" || !value.trim()) {
1489
+ return {};
1490
+ }
1491
+ const tokens = splitCssTokens(value);
1492
+ const widthToken = tokens.find(isBorderWidthToken);
1493
+ const styleToken = tokens.find(isBorderStyleToken);
1494
+ const colorTokens = tokens.filter((token) => {
1495
+ return token !== widthToken && token !== styleToken;
1496
+ });
1497
+ return {
1498
+ width: widthToken ? widthToken : void 0,
1499
+ style: styleToken,
1500
+ color: colorTokens.length ? colorTokens.join(" ") : void 0
1501
+ };
1502
+ };
1503
+ var expandBorderWidths = (value) => {
1504
+ if (value === void 0) {
1505
+ return [void 0, void 0, void 0, void 0];
1506
+ }
1507
+ if (typeof value === "number") {
1508
+ return [value, value, value, value];
1509
+ }
1510
+ return expandQuad(
1511
+ splitCssTokens(String(value)).map((token) => token)
1512
+ );
1513
+ };
1514
+ var expandBorderStyles = (value) => {
1515
+ if (value === void 0) {
1516
+ return [void 0, void 0, void 0, void 0];
1517
+ }
1518
+ return expandQuad(splitCssTokens(String(value)).filter(isBorderStyleToken));
1519
+ };
1520
+ var expandBorderColors = (value) => {
1521
+ if (value === void 0) {
1522
+ return [void 0, void 0, void 0, void 0];
1523
+ }
1524
+ return expandQuad(
1525
+ splitCssTokens(String(value)).map((token) => token)
1526
+ );
1527
+ };
1528
+ var expandBorderRadii = (value) => {
1529
+ if (value === void 0) {
1530
+ return [void 0, void 0, void 0, void 0];
1531
+ }
1532
+ if (typeof value === "number") {
1533
+ return [value, value, value, value];
1534
+ }
1535
+ const parts = splitOutsideParentheses(String(value), "/");
1536
+ const horizontal = expandQuad(
1537
+ splitCssTokens(parts[0] ?? "").map(
1538
+ (token) => token
1539
+ )
1540
+ );
1541
+ if (!parts[1]) {
1542
+ return horizontal;
1543
+ }
1544
+ const vertical = expandQuad(
1545
+ splitCssTokens(parts[1]).map((token) => token)
1546
+ );
1547
+ return horizontal.map((horizontalRadius, index) => {
1548
+ const verticalRadius = vertical[index];
1549
+ if (horizontalRadius === void 0) {
1550
+ return void 0;
1551
+ }
1552
+ if (verticalRadius === void 0 || verticalRadius === horizontalRadius) {
1553
+ return horizontalRadius;
1554
+ }
1555
+ return `${horizontalRadius} ${verticalRadius}`;
1556
+ });
1557
+ };
1558
+ var resolveSurfaceStyle = (style) => {
1559
+ const border = parseBorder(style.border);
1560
+ const borderTop = parseBorder(style.borderTop);
1561
+ const borderRight = parseBorder(style.borderRight);
1562
+ const borderBottom = parseBorder(style.borderBottom);
1563
+ const borderLeft = parseBorder(style.borderLeft);
1564
+ const widths = expandBorderWidths(style.borderWidth ?? border.width);
1565
+ const styles = expandBorderStyles(style.borderStyle ?? border.style);
1566
+ const colors = expandBorderColors(style.borderColor ?? border.color);
1567
+ const radii = expandBorderRadii(style.borderRadius);
1568
+ return {
1569
+ borderTopWidth: style.borderTopWidth ?? borderTop.width ?? widths[0],
1570
+ borderRightWidth: style.borderRightWidth ?? borderRight.width ?? widths[1],
1571
+ borderBottomWidth: style.borderBottomWidth ?? borderBottom.width ?? widths[2],
1572
+ borderLeftWidth: style.borderLeftWidth ?? borderLeft.width ?? widths[3],
1573
+ borderTopStyle: style.borderTopStyle ?? borderTop.style ?? styles[0],
1574
+ borderRightStyle: style.borderRightStyle ?? borderRight.style ?? styles[1],
1575
+ borderBottomStyle: style.borderBottomStyle ?? borderBottom.style ?? styles[2],
1576
+ borderLeftStyle: style.borderLeftStyle ?? borderLeft.style ?? styles[3],
1577
+ borderTopColor: style.borderTopColor ?? borderTop.color ?? colors[0],
1578
+ borderRightColor: style.borderRightColor ?? borderRight.color ?? colors[1],
1579
+ borderBottomColor: style.borderBottomColor ?? borderBottom.color ?? colors[2],
1580
+ borderLeftColor: style.borderLeftColor ?? borderLeft.color ?? colors[3],
1581
+ borderTopLeftRadius: style.borderTopLeftRadius ?? radii[0],
1582
+ borderTopRightRadius: style.borderTopRightRadius ?? radii[1],
1583
+ borderBottomRightRadius: style.borderBottomRightRadius ?? radii[2],
1584
+ borderBottomLeftRadius: style.borderBottomLeftRadius ?? radii[3]
1585
+ };
1586
+ };
1587
+ var splitShadowTokens = (value) => {
1588
+ const tokens = [];
1589
+ let current = "";
1590
+ let depth = 0;
1591
+ for (const character of value.trim()) {
1592
+ if (character === "(") {
1593
+ depth += 1;
1594
+ }
1595
+ if (character === ")") {
1596
+ depth = Math.max(0, depth - 1);
1597
+ }
1598
+ if (/\s/.test(character) && depth === 0) {
1599
+ if (current.trim()) {
1600
+ tokens.push(current.trim());
1601
+ }
1602
+ current = "";
1603
+ continue;
1604
+ }
1605
+ current += character;
1606
+ }
1607
+ if (current.trim()) {
1608
+ tokens.push(current.trim());
1609
+ }
1610
+ return tokens;
1611
+ };
1612
+ var isShadowLengthToken = (value) => {
1613
+ return value === "0" || /^-?(?:\d+|\d*\.\d+)(?:px|rem|em|vh|vw|vmin|vmax|%)?$/.test(value) || value.startsWith("calc(") || value.startsWith("var(");
1614
+ };
1615
+ var isShadowColorToken = (value) => {
1616
+ return value.startsWith("#") || value.startsWith("rgb(") || value.startsWith("rgba(") || value.startsWith("hsl(") || value.startsWith("hsla(") || value.startsWith("oklch(") || value.startsWith("oklab(") || value.startsWith("lab(") || value.startsWith("lch(") || value.startsWith("color(") || value.startsWith("color-mix(") || value.startsWith("var(") || /^[a-zA-Z]+$/.test(value);
1617
+ };
1618
+ var boxShadowToDropShadow = (boxShadow) => {
1619
+ if (typeof boxShadow !== "string" || !boxShadow.trim() || boxShadow.trim() === "none") {
1620
+ return void 0;
1621
+ }
1622
+ const shadows = splitOutsideParentheses(boxShadow, ",");
1623
+ const filters = shadows.map((shadow) => {
1624
+ const tokens = splitShadowTokens(shadow);
1625
+ if (tokens.includes("inset")) {
1626
+ return null;
1627
+ }
1628
+ const lengths = tokens.filter(isShadowLengthToken);
1629
+ if (lengths.length < 2) {
1630
+ return null;
1631
+ }
1632
+ const color = tokens.find((token) => {
1633
+ return token !== "inset" && !isShadowLengthToken(token) && isShadowColorToken(token);
1634
+ });
1635
+ const offsetX = lengths[0];
1636
+ const offsetY = lengths[1];
1637
+ const blur = lengths[2] ?? "0px";
1638
+ return `drop-shadow(${offsetX} ${offsetY} ${blur} ${color ?? "rgba(0, 0, 0, 0.25)"})`;
1639
+ }).filter((value) => {
1640
+ return value !== null;
1641
+ });
1642
+ return filters.length ? filters.join(" ") : void 0;
1643
+ };
1644
+ var mergeThemes = (presetTheme, customTheme) => {
1645
+ if (!customTheme) {
1646
+ return presetTheme;
1647
+ }
1648
+ return {
1649
+ ...presetTheme,
1650
+ ...customTheme,
1651
+ body: {
1652
+ ...presetTheme.body,
1653
+ ...customTheme.body,
1654
+ style: {
1655
+ ...presetTheme.body?.style,
1656
+ ...customTheme.body?.style
1657
+ },
1658
+ background: customTheme.body?.background ?? presetTheme.body?.background,
1659
+ filter: customTheme.body?.filter ?? presetTheme.body?.filter,
1660
+ className: customTheme.body?.className ?? presetTheme.body?.className
1661
+ },
1662
+ arrow: {
1663
+ ...presetTheme.arrow,
1664
+ ...customTheme.arrow
1665
+ },
1666
+ animation: {
1667
+ ...presetTheme.animation,
1668
+ ...customTheme.animation
1669
+ }
1670
+ };
1671
+ };
1672
+ var resolveThemeStyles = (theme) => {
1673
+ const bodyStyle = theme.body?.style ?? {};
1674
+ const surfaceStyle = resolveSurfaceStyle(bodyStyle);
1675
+ const {
1676
+ background,
1677
+ backgroundColor,
1678
+ backgroundImage,
1679
+ border,
1680
+ borderTop,
1681
+ borderRight,
1682
+ borderBottom,
1683
+ borderLeft,
1684
+ borderWidth,
1685
+ borderStyle,
1686
+ borderColor,
1687
+ borderTopWidth,
1688
+ borderRightWidth,
1689
+ borderBottomWidth,
1690
+ borderLeftWidth,
1691
+ borderTopStyle,
1692
+ borderRightStyle,
1693
+ borderBottomStyle,
1694
+ borderLeftStyle,
1695
+ borderTopColor,
1696
+ borderRightColor,
1697
+ borderBottomColor,
1698
+ borderLeftColor,
1699
+ borderRadius,
1700
+ borderTopLeftRadius,
1701
+ borderTopRightRadius,
1702
+ borderBottomRightRadius,
1703
+ borderBottomLeftRadius,
1704
+ boxShadow,
1705
+ filter,
1706
+ backdropFilter,
1707
+ WebkitBackdropFilter,
1708
+ color,
1709
+ ...contentStyle
1710
+ } = bodyStyle;
1711
+ const resolvedBackground = theme.body?.background ?? background ?? backgroundImage ?? backgroundColor ?? "var(--global-color-link)";
1712
+ const resolvedColor = color ?? "var(--global-bg-color)";
1713
+ const resolvedFilter = theme.body?.filter ?? filter ?? boxShadowToDropShadow(boxShadow);
1714
+ return {
1715
+ background: resolvedBackground,
1716
+ color: resolvedColor,
1717
+ contentStyle,
1718
+ surfaceStyle,
1719
+ fillStyle: {
1720
+ backdropFilter,
1721
+ WebkitBackdropFilter
1722
+ },
1723
+ filter: resolvedFilter
1724
+ };
1725
+ };
1726
+
1727
+ // src/components/TooltipProvider.tsx
1728
+ import { createContext, useContext, useMemo } from "react";
1729
+ import { jsx } from "react/jsx-runtime";
1730
+ var DEFAULT_TOOLTIP_VALUES = {
1731
+ defaultRenderPosition: "top",
1732
+ selectTheme: "primary"
1733
+ };
1734
+ var TooltipContext = createContext(DEFAULT_TOOLTIP_VALUES);
1735
+ var TooltipProvider = ({
1736
+ children,
1737
+ defaultRenderPosition = DEFAULT_TOOLTIP_VALUES.defaultRenderPosition,
1738
+ selectTheme = DEFAULT_TOOLTIP_VALUES.selectTheme,
1739
+ customTheme,
1740
+ animation
1741
+ }) => {
1742
+ const value = useMemo(() => {
1743
+ return {
1744
+ defaultRenderPosition,
1745
+ selectTheme,
1746
+ customTheme,
1747
+ animation
1748
+ };
1749
+ }, [animation, customTheme, defaultRenderPosition, selectTheme]);
1750
+ return /* @__PURE__ */ jsx(TooltipContext.Provider, { value, children });
1751
+ };
1752
+ var useTooltipDefaults = () => {
1753
+ return useContext(TooltipContext);
1754
+ };
1755
+
1756
+ // src/components/TooltipSurface.tsx
1757
+ import {
1758
+ useLayoutEffect as useLayoutEffect2,
1759
+ useRef as useRef2,
1760
+ useState as useState2
1761
+ } from "react";
1762
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
1763
+ var EMPTY_METRICS = {
1764
+ width: 0,
1765
+ height: 0,
1766
+ left: 0,
1767
+ top: 0,
1768
+ path: "",
1769
+ strokeWidth: 0,
1770
+ strokeColor: "transparent"
1771
+ };
1772
+ var clamp2 = (value, min, max) => {
1773
+ return Math.min(Math.max(value, min), Math.max(min, max));
1774
+ };
1775
+ var resolveCssLength = (value, base) => {
1776
+ const normalized = value.trim();
1777
+ if (!normalized) {
1778
+ return 0;
1779
+ }
1780
+ if (normalized.endsWith("%")) {
1781
+ return base * (Number.parseFloat(normalized) / 100);
1782
+ }
1783
+ const parsed = Number.parseFloat(normalized);
1784
+ return Number.isFinite(parsed) ? parsed : 0;
1785
+ };
1786
+ var resolveCornerRadius = (value, width, height) => {
1787
+ const parts = value.trim().split(/\s+/).filter(Boolean);
1788
+ const horizontal = resolveCssLength(parts[0] ?? "0", width);
1789
+ const vertical = resolveCssLength(parts[1] ?? parts[0] ?? "0", height);
1790
+ return Math.min(horizontal, vertical);
1791
+ };
1792
+ var normalizeRadii = (radii, width, height) => {
1793
+ const top = radii.topLeft + radii.topRight;
1794
+ const bottom = radii.bottomLeft + radii.bottomRight;
1795
+ const left = radii.topLeft + radii.bottomLeft;
1796
+ const right = radii.topRight + radii.bottomRight;
1797
+ const scale = Math.min(
1798
+ 1,
1799
+ top > 0 ? width / top : 1,
1800
+ bottom > 0 ? width / bottom : 1,
1801
+ left > 0 ? height / left : 1,
1802
+ right > 0 ? height / right : 1
1803
+ );
1804
+ return {
1805
+ topLeft: radii.topLeft * scale,
1806
+ topRight: radii.topRight * scale,
1807
+ bottomRight: radii.bottomRight * scale,
1808
+ bottomLeft: radii.bottomLeft * scale
1809
+ };
1810
+ };
1811
+ var resolveArrowOffset = (value, edgeLength) => {
1812
+ const normalized = value.trim();
1813
+ if (normalized.endsWith("%")) {
1814
+ return edgeLength * (Number.parseFloat(normalized) / 100);
1815
+ }
1816
+ const parsed = Number.parseFloat(normalized);
1817
+ return Number.isFinite(parsed) ? parsed : edgeLength / 2;
1818
+ };
1819
+ var createSurfacePath = ({
1820
+ placement,
1821
+ bodyWidth,
1822
+ bodyHeight,
1823
+ arrowHeight,
1824
+ arrowWidth,
1825
+ requestedArrowOffset,
1826
+ radii
1827
+ }) => {
1828
+ let x0 = 0;
1829
+ let y0 = 0;
1830
+ let x1 = bodyWidth;
1831
+ let y1 = bodyHeight;
1832
+ let width = bodyWidth;
1833
+ let height = bodyHeight;
1834
+ let left = 0;
1835
+ let top = 0;
1836
+ if (placement === "top") {
1837
+ height += arrowHeight;
1838
+ }
1839
+ if (placement === "bottom") {
1840
+ y0 = arrowHeight;
1841
+ y1 = arrowHeight + bodyHeight;
1842
+ height += arrowHeight;
1843
+ top = -arrowHeight;
1844
+ }
1845
+ if (placement === "left") {
1846
+ width += arrowHeight;
1847
+ }
1848
+ if (placement === "right") {
1849
+ x0 = arrowHeight;
1850
+ x1 = arrowHeight + bodyWidth;
1851
+ width += arrowHeight;
1852
+ left = -arrowHeight;
1853
+ }
1854
+ let edgeLength = bodyWidth;
1855
+ let edgeStartRadius = radii.bottomLeft;
1856
+ let edgeEndRadius = radii.bottomRight;
1857
+ if (placement === "bottom") {
1858
+ edgeStartRadius = radii.topLeft;
1859
+ edgeEndRadius = radii.topRight;
1860
+ }
1861
+ if (placement === "left") {
1862
+ edgeLength = bodyHeight;
1863
+ edgeStartRadius = radii.topRight;
1864
+ edgeEndRadius = radii.bottomRight;
1865
+ }
1866
+ if (placement === "right") {
1867
+ edgeLength = bodyHeight;
1868
+ edgeStartRadius = radii.topLeft;
1869
+ edgeEndRadius = radii.bottomLeft;
1870
+ }
1871
+ const availableStraightEdge = Math.max(
1872
+ 0,
1873
+ edgeLength - edgeStartRadius - edgeEndRadius - 2
1874
+ );
1875
+ const arrowHalf = Math.min(arrowWidth / 2, availableStraightEdge / 2);
1876
+ const minArrowCenter = edgeStartRadius + arrowHalf + 1;
1877
+ const maxArrowCenter = edgeLength - edgeEndRadius - arrowHalf - 1;
1878
+ const arrowCenter = minArrowCenter <= maxArrowCenter ? clamp2(requestedArrowOffset, minArrowCenter, maxArrowCenter) : edgeLength / 2;
1879
+ const tl = radii.topLeft;
1880
+ const tr = radii.topRight;
1881
+ const br = radii.bottomRight;
1882
+ const bl = radii.bottomLeft;
1883
+ let path = "";
1884
+ if (placement === "top") {
1885
+ path = [
1886
+ `M ${x0 + tl} ${y0}`,
1887
+ `H ${x1 - tr}`,
1888
+ `Q ${x1} ${y0} ${x1} ${y0 + tr}`,
1889
+ `V ${y1 - br}`,
1890
+ `Q ${x1} ${y1} ${x1 - br} ${y1}`,
1891
+ `H ${arrowCenter + arrowHalf}`,
1892
+ `L ${arrowCenter} ${y1 + arrowHeight}`,
1893
+ `L ${arrowCenter - arrowHalf} ${y1}`,
1894
+ `H ${x0 + bl}`,
1895
+ `Q ${x0} ${y1} ${x0} ${y1 - bl}`,
1896
+ `V ${y0 + tl}`,
1897
+ `Q ${x0} ${y0} ${x0 + tl} ${y0}`,
1898
+ "Z"
1899
+ ].join(" ");
1900
+ }
1901
+ if (placement === "bottom") {
1902
+ path = [
1903
+ `M ${x0 + tl} ${y0}`,
1904
+ `H ${arrowCenter - arrowHalf}`,
1905
+ `L ${arrowCenter} ${y0 - arrowHeight}`,
1906
+ `L ${arrowCenter + arrowHalf} ${y0}`,
1907
+ `H ${x1 - tr}`,
1908
+ `Q ${x1} ${y0} ${x1} ${y0 + tr}`,
1909
+ `V ${y1 - br}`,
1910
+ `Q ${x1} ${y1} ${x1 - br} ${y1}`,
1911
+ `H ${x0 + bl}`,
1912
+ `Q ${x0} ${y1} ${x0} ${y1 - bl}`,
1913
+ `V ${y0 + tl}`,
1914
+ `Q ${x0} ${y0} ${x0 + tl} ${y0}`,
1915
+ "Z"
1916
+ ].join(" ");
1917
+ }
1918
+ if (placement === "left") {
1919
+ path = [
1920
+ `M ${x0 + tl} ${y0}`,
1921
+ `H ${x1 - tr}`,
1922
+ `Q ${x1} ${y0} ${x1} ${y0 + tr}`,
1923
+ `V ${arrowCenter - arrowHalf}`,
1924
+ `L ${x1 + arrowHeight} ${arrowCenter}`,
1925
+ `L ${x1} ${arrowCenter + arrowHalf}`,
1926
+ `V ${y1 - br}`,
1927
+ `Q ${x1} ${y1} ${x1 - br} ${y1}`,
1928
+ `H ${x0 + bl}`,
1929
+ `Q ${x0} ${y1} ${x0} ${y1 - bl}`,
1930
+ `V ${y0 + tl}`,
1931
+ `Q ${x0} ${y0} ${x0 + tl} ${y0}`,
1932
+ "Z"
1933
+ ].join(" ");
1934
+ }
1935
+ if (placement === "right") {
1936
+ path = [
1937
+ `M ${x0 + tl} ${y0}`,
1938
+ `H ${x1 - tr}`,
1939
+ `Q ${x1} ${y0} ${x1} ${y0 + tr}`,
1940
+ `V ${y1 - br}`,
1941
+ `Q ${x1} ${y1} ${x1 - br} ${y1}`,
1942
+ `H ${x0 + bl}`,
1943
+ `Q ${x0} ${y1} ${x0} ${y1 - bl}`,
1944
+ `V ${arrowCenter + arrowHalf}`,
1945
+ `L ${x0 - arrowHeight} ${arrowCenter}`,
1946
+ `L ${x0} ${arrowCenter - arrowHalf}`,
1947
+ `V ${y0 + tl}`,
1948
+ `Q ${x0} ${y0} ${x0 + tl} ${y0}`,
1949
+ "Z"
1950
+ ].join(" ");
1951
+ }
1952
+ return {
1953
+ width,
1954
+ height,
1955
+ left,
1956
+ top,
1957
+ path
1958
+ };
1959
+ };
1960
+ var getStrokeConfig = (computedStyle) => {
1961
+ const widths = [
1962
+ Number.parseFloat(computedStyle.borderTopWidth) || 0,
1963
+ Number.parseFloat(computedStyle.borderRightWidth) || 0,
1964
+ Number.parseFloat(computedStyle.borderBottomWidth) || 0,
1965
+ Number.parseFloat(computedStyle.borderLeftWidth) || 0
1966
+ ];
1967
+ const styles = [
1968
+ computedStyle.borderTopStyle,
1969
+ computedStyle.borderRightStyle,
1970
+ computedStyle.borderBottomStyle,
1971
+ computedStyle.borderLeftStyle
1972
+ ];
1973
+ const colors = [
1974
+ computedStyle.borderTopColor,
1975
+ computedStyle.borderRightColor,
1976
+ computedStyle.borderBottomColor,
1977
+ computedStyle.borderLeftColor
1978
+ ];
1979
+ const activeIndexes = widths.map((width, index) => ({
1980
+ width,
1981
+ index
1982
+ })).filter(({ width, index }) => {
1983
+ return width > 0 && styles[index] !== "none" && styles[index] !== "hidden";
1984
+ });
1985
+ if (!activeIndexes.length) {
1986
+ return {
1987
+ strokeWidth: 0,
1988
+ strokeColor: "transparent",
1989
+ strokeDasharray: void 0,
1990
+ strokeLinecap: void 0
1991
+ };
1992
+ }
1993
+ const active = activeIndexes.reduce((largest, current) => {
1994
+ return current.width > largest.width ? current : largest;
1995
+ });
1996
+ const strokeWidth = active.width;
1997
+ const strokeStyle = styles[active.index];
1998
+ const strokeColor = colors[active.index];
1999
+ if (strokeStyle === "dashed") {
2000
+ return {
2001
+ strokeWidth,
2002
+ strokeColor,
2003
+ strokeDasharray: `${strokeWidth * 3} ${strokeWidth * 2}`,
2004
+ strokeLinecap: "butt"
2005
+ };
2006
+ }
2007
+ if (strokeStyle === "dotted") {
2008
+ return {
2009
+ strokeWidth,
2010
+ strokeColor,
2011
+ strokeDasharray: `${strokeWidth} ${strokeWidth * 1.6}`,
2012
+ strokeLinecap: "round"
2013
+ };
2014
+ }
2015
+ return {
2016
+ strokeWidth,
2017
+ strokeColor,
2018
+ strokeDasharray: void 0,
2019
+ strokeLinecap: "round"
2020
+ };
2021
+ };
2022
+ var createMaskImage = (width, height, path) => {
2023
+ const svg = [
2024
+ '<svg xmlns="http://www.w3.org/2000/svg"',
2025
+ ` viewBox="0 0 ${width} ${height}"`,
2026
+ ` width="${width}"`,
2027
+ ` height="${height}">`,
2028
+ `<path fill="white" d="${path}"/>`,
2029
+ "</svg>"
2030
+ ].join("");
2031
+ return `url("data:image/svg+xml,${encodeURIComponent(svg)}")`;
2032
+ };
2033
+ var TooltipSurface = ({
2034
+ bodyRef,
2035
+ placement,
2036
+ arrowOffset,
2037
+ surfaceStyle,
2038
+ fillStyle,
2039
+ filter
2040
+ }) => {
2041
+ const surfaceProbeRef = useRef2(null);
2042
+ const arrowProbeRef = useRef2(null);
2043
+ const [metrics, setMetrics] = useState2(EMPTY_METRICS);
2044
+ useLayoutEffect2(() => {
2045
+ const body = bodyRef.current;
2046
+ const surfaceProbe = surfaceProbeRef.current;
2047
+ const arrowProbe = arrowProbeRef.current;
2048
+ if (!body || !surfaceProbe || !arrowProbe) {
2049
+ return;
2050
+ }
2051
+ const update = () => {
2052
+ const bodyWidth = body.offsetWidth;
2053
+ const bodyHeight = body.offsetHeight;
2054
+ if (bodyWidth <= 0 || bodyHeight <= 0) {
2055
+ return;
2056
+ }
2057
+ surfaceProbe.style.width = `${bodyWidth}px`;
2058
+ surfaceProbe.style.height = `${bodyHeight}px`;
2059
+ const surfaceComputedStyle = window.getComputedStyle(surfaceProbe);
2060
+ const arrowComputedStyle = window.getComputedStyle(arrowProbe);
2061
+ const arrowHeight = Number.parseFloat(arrowComputedStyle.height) || 6;
2062
+ const arrowWidth = Number.parseFloat(arrowComputedStyle.width) || arrowHeight * 2;
2063
+ const radii = normalizeRadii(
2064
+ {
2065
+ topLeft: resolveCornerRadius(
2066
+ surfaceComputedStyle.borderTopLeftRadius,
2067
+ bodyWidth,
2068
+ bodyHeight
2069
+ ),
2070
+ topRight: resolveCornerRadius(
2071
+ surfaceComputedStyle.borderTopRightRadius,
2072
+ bodyWidth,
2073
+ bodyHeight
2074
+ ),
2075
+ bottomRight: resolveCornerRadius(
2076
+ surfaceComputedStyle.borderBottomRightRadius,
2077
+ bodyWidth,
2078
+ bodyHeight
2079
+ ),
2080
+ bottomLeft: resolveCornerRadius(
2081
+ surfaceComputedStyle.borderBottomLeftRadius,
2082
+ bodyWidth,
2083
+ bodyHeight
2084
+ )
2085
+ },
2086
+ bodyWidth,
2087
+ bodyHeight
2088
+ );
2089
+ const requestedArrowOffset = resolveArrowOffset(
2090
+ arrowOffset,
2091
+ placement === "top" || placement === "bottom" ? bodyWidth : bodyHeight
2092
+ );
2093
+ const surface = createSurfacePath({
2094
+ placement,
2095
+ bodyWidth,
2096
+ bodyHeight,
2097
+ arrowHeight,
2098
+ arrowWidth,
2099
+ requestedArrowOffset,
2100
+ radii
2101
+ });
2102
+ const stroke = getStrokeConfig(surfaceComputedStyle);
2103
+ const nextMetrics = {
2104
+ ...surface,
2105
+ ...stroke
2106
+ };
2107
+ setMetrics((current) => {
2108
+ if (current.width === nextMetrics.width && current.height === nextMetrics.height && current.left === nextMetrics.left && current.top === nextMetrics.top && current.path === nextMetrics.path && current.strokeWidth === nextMetrics.strokeWidth && current.strokeColor === nextMetrics.strokeColor && current.strokeDasharray === nextMetrics.strokeDasharray && current.strokeLinecap === nextMetrics.strokeLinecap) {
2109
+ return current;
2110
+ }
2111
+ return nextMetrics;
2112
+ });
2113
+ };
2114
+ update();
2115
+ const resizeObserver = new ResizeObserver(update);
2116
+ resizeObserver.observe(body);
2117
+ window.addEventListener("resize", update);
2118
+ return () => {
2119
+ resizeObserver.disconnect();
2120
+ window.removeEventListener("resize", update);
2121
+ };
2122
+ }, [arrowOffset, bodyRef, placement, surfaceStyle]);
2123
+ const maskImage = metrics.path ? createMaskImage(metrics.width, metrics.height, metrics.path) : void 0;
2124
+ const resolvedFillStyle = {
2125
+ ...fillStyle,
2126
+ maskImage,
2127
+ maskPosition: "0 0",
2128
+ maskRepeat: "no-repeat",
2129
+ maskSize: "100% 100%",
2130
+ WebkitMaskImage: maskImage,
2131
+ WebkitMaskPosition: "0 0",
2132
+ WebkitMaskRepeat: "no-repeat",
2133
+ WebkitMaskSize: "100% 100%"
2134
+ };
2135
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2136
+ /* @__PURE__ */ jsx2(
2137
+ "div",
2138
+ {
2139
+ ref: surfaceProbeRef,
2140
+ className: "tooltip-surface-probe",
2141
+ style: surfaceStyle
2142
+ }
2143
+ ),
2144
+ /* @__PURE__ */ jsx2("div", { ref: arrowProbeRef, className: "tooltip-arrow-probe" }),
2145
+ metrics.path ? /* @__PURE__ */ jsxs(
2146
+ "div",
2147
+ {
2148
+ className: "tooltip-surface",
2149
+ style: {
2150
+ width: metrics.width,
2151
+ height: metrics.height,
2152
+ left: metrics.left,
2153
+ top: metrics.top,
2154
+ filter
2155
+ },
2156
+ "aria-hidden": "true",
2157
+ children: [
2158
+ /* @__PURE__ */ jsx2(
2159
+ "div",
2160
+ {
2161
+ className: "tooltip-surface__fill",
2162
+ style: resolvedFillStyle
2163
+ }
2164
+ ),
2165
+ metrics.strokeWidth > 0 ? /* @__PURE__ */ jsx2(
2166
+ "svg",
2167
+ {
2168
+ className: "tooltip-surface__stroke",
2169
+ width: metrics.width,
2170
+ height: metrics.height,
2171
+ viewBox: `0 0 ${metrics.width} ${metrics.height}`,
2172
+ children: /* @__PURE__ */ jsx2(
2173
+ "path",
2174
+ {
2175
+ d: metrics.path,
2176
+ fill: "none",
2177
+ stroke: metrics.strokeColor,
2178
+ strokeWidth: metrics.strokeWidth,
2179
+ strokeDasharray: metrics.strokeDasharray,
2180
+ strokeLinecap: metrics.strokeLinecap,
2181
+ strokeLinejoin: "round",
2182
+ vectorEffect: "non-scaling-stroke"
2183
+ }
2184
+ )
2185
+ }
2186
+ ) : null
2187
+ ]
2188
+ }
2189
+ ) : null
2190
+ ] });
2191
+ };
2192
+
2193
+ // src/components/Tooltip.tsx
2194
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
2195
+ var DEFAULT_SHOW_ANIMATION = "slide";
2196
+ var DEFAULT_HIDE_ANIMATION = "fade";
2197
+ var assignRef = (ref, value) => {
2198
+ if (typeof ref === "function") {
2199
+ ref(value);
2200
+ return;
2201
+ }
2202
+ if (ref) {
2203
+ ref.current = value;
2204
+ }
2205
+ };
2206
+ var Tooltip = ({
2207
+ content,
2208
+ children,
2209
+ position,
2210
+ selectTheme,
2211
+ customTheme,
2212
+ animation,
2213
+ disabled = false,
2214
+ interactive = false,
2215
+ hideDelay
2216
+ }) => {
2217
+ const defaults = useTooltipDefaults();
2218
+ const markerRef = useRef3(null);
2219
+ const [anchor, setAnchor] = useState3(null);
2220
+ const trigger = children ? Children.only(children) : null;
2221
+ const triggerRef = trigger?.props.ref;
2222
+ const setTriggerRef = useCallback2(
2223
+ (node) => {
2224
+ assignRef(triggerRef, node);
2225
+ setAnchor(node);
2226
+ },
2227
+ [triggerRef]
2228
+ );
2229
+ useLayoutEffect3(() => {
2230
+ if (trigger) {
2231
+ return;
2232
+ }
2233
+ const marker = markerRef.current;
2234
+ const parent = marker?.parentElement ?? null;
2235
+ setAnchor(parent);
2236
+ return () => {
2237
+ setAnchor(null);
2238
+ };
2239
+ }, [trigger]);
2240
+ const inheritedTheme = useMemo2(() => {
2241
+ return mergeThemes(presets[defaults.selectTheme], defaults.customTheme);
2242
+ }, [defaults.customTheme, defaults.selectTheme]);
2243
+ const theme = useMemo2(() => {
2244
+ if (selectTheme) {
2245
+ return mergeThemes(presets[selectTheme], customTheme);
2246
+ }
2247
+ return mergeThemes(inheritedTheme, customTheme);
2248
+ }, [customTheme, inheritedTheme, selectTheme]);
2249
+ const resolvedThemeStyles = useMemo2(() => {
2250
+ return resolveThemeStyles(theme);
2251
+ }, [theme]);
2252
+ const localThemeAnimation = selectTheme ? theme.animation : customTheme?.animation;
2253
+ const showAnimation = animation?.show ?? localThemeAnimation?.show ?? defaults.animation?.show ?? inheritedTheme.animation?.show ?? DEFAULT_SHOW_ANIMATION;
2254
+ const hideAnimation = animation?.hide ?? localThemeAnimation?.hide ?? defaults.animation?.hide ?? inheritedTheme.animation?.hide ?? DEFAULT_HIDE_ANIMATION;
2255
+ const animationSpeed = animation?.speed ?? localThemeAnimation?.speed ?? defaults.animation?.speed ?? inheritedTheme.animation?.speed ?? "120ms";
2256
+ const animationEasing = animation?.easing ?? localThemeAnimation?.easing ?? defaults.animation?.easing ?? inheritedTheme.animation?.easing ?? "ease-in-out";
2257
+ const preferredPlacement = position ?? defaults.defaultRenderPosition;
2258
+ const {
2259
+ shouldRender,
2260
+ phase,
2261
+ placement,
2262
+ position: tooltipPosition,
2263
+ tooltipRef,
2264
+ bodyRef,
2265
+ onAnimationEnd
2266
+ } = useTooltip({
2267
+ anchor,
2268
+ preferredPlacement,
2269
+ disabled: disabled || content === null || content === void 0,
2270
+ interactive,
2271
+ hideDelay
2272
+ });
2273
+ const arrowSize = theme.arrow?.size ?? "6px";
2274
+ const arrowWidth = theme.arrow?.width ?? `calc(${arrowSize} * 2)`;
2275
+ const containerStyle = {
2276
+ "--tooltip-bg": resolvedThemeStyles.background,
2277
+ "--tooltip-color": resolvedThemeStyles.color,
2278
+ "--tooltip-arrow-size": arrowSize,
2279
+ "--tooltip-arrow-width": arrowWidth,
2280
+ "--tooltip-animation-speed": animationSpeed,
2281
+ "--tooltip-animation-easing": animationEasing,
2282
+ ...tooltipPosition
2283
+ };
2284
+ const arrowOffset = String(
2285
+ tooltipPosition["--tooltip-arrow-offset"] ?? "50%"
2286
+ );
2287
+ const handleAnimationEnd = (event) => {
2288
+ if (event.target !== event.currentTarget) {
2289
+ return;
2290
+ }
2291
+ onAnimationEnd();
2292
+ };
2293
+ const triggerElement = trigger ? cloneElement(trigger, {
2294
+ ref: setTriggerRef
2295
+ }) : /* @__PURE__ */ jsx3("span", { ref: markerRef, hidden: true, "aria-hidden": "true" });
2296
+ const portal = shouldRender && typeof document !== "undefined" ? createPortal(
2297
+ /* @__PURE__ */ jsx3(
2298
+ "div",
2299
+ {
2300
+ ref: tooltipRef,
2301
+ className: [
2302
+ "tooltip-container",
2303
+ `tooltip-container--${placement}`,
2304
+ `tooltip-container--phase-${phase}`,
2305
+ `tooltip-container--show-${showAnimation}`,
2306
+ `tooltip-container--hide-${hideAnimation}`,
2307
+ interactive ? "tooltip-container--interactive" : null
2308
+ ].filter(Boolean).join(" "),
2309
+ style: containerStyle,
2310
+ children: /* @__PURE__ */ jsxs2(
2311
+ "div",
2312
+ {
2313
+ ref: bodyRef,
2314
+ className: "tooltip-body",
2315
+ onAnimationEnd: handleAnimationEnd,
2316
+ children: [
2317
+ /* @__PURE__ */ jsx3(
2318
+ TooltipSurface,
2319
+ {
2320
+ bodyRef,
2321
+ placement,
2322
+ arrowOffset,
2323
+ surfaceStyle: resolvedThemeStyles.surfaceStyle,
2324
+ fillStyle: resolvedThemeStyles.fillStyle,
2325
+ filter: resolvedThemeStyles.filter
2326
+ }
2327
+ ),
2328
+ /* @__PURE__ */ jsx3(
2329
+ "div",
2330
+ {
2331
+ className: [
2332
+ "tooltip-body__content",
2333
+ theme.body?.className
2334
+ ].filter(Boolean).join(" "),
2335
+ style: resolvedThemeStyles.contentStyle,
2336
+ children: content
2337
+ }
2338
+ )
2339
+ ]
2340
+ }
2341
+ )
2342
+ }
2343
+ ),
2344
+ document.body
2345
+ ) : null;
2346
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
2347
+ triggerElement,
2348
+ portal
2349
+ ] });
2350
+ };
2351
+ export {
2352
+ Tooltip,
2353
+ TooltipProvider
2354
+ };
2355
+ //# sourceMappingURL=index.mjs.map