kitzo 2.1.29 → 2.2.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.
@@ -1,859 +0,0 @@
1
- import React, { useRef, useLayoutEffect, useState, useEffect } from 'react';
2
-
3
- const toastStyles = `.toast-content,
4
- .toast-content-bottom {
5
- font-size: 0.925rem;
6
- }
7
- .toast-content,
8
- .toast-content-bottom {
9
- pointer-events: all;
10
- }
11
-
12
- .pre-styled {
13
- padding-inline: 0.825rem;
14
- padding-block: 0.625rem;
15
- display: flex;
16
- align-items: center;
17
- gap: 0.5rem;
18
- background-color: white;
19
- border-radius: 0.5525rem;
20
- box-shadow: 0 2px 8px -3px rgba(0, 0, 0, 0.3);
21
- }
22
-
23
- .toast-content {
24
- animation: slide-in 230ms forwards;
25
- }
26
- .toast-content.exit {
27
- animation: slide-out 110ms forwards;
28
- }
29
-
30
- .toast-content-bottom {
31
- animation: bottom-slide-in 230ms forwards;
32
- }
33
- .toast-content-bottom.exit {
34
- animation: bottom-slide-out 110ms forwards;
35
- }
36
-
37
- @keyframes slide-in {
38
- from {
39
- opacity: 0;
40
- translate: 0 -100%;
41
- scale: 0.7;
42
- }
43
- to {
44
- opacity: 1;
45
- translate: 0 0;
46
- scale: 1;
47
- }
48
- }
49
-
50
- @keyframes slide-out {
51
- from {
52
- opacity: 1;
53
- translate: 0 0;
54
- scale: 1;
55
- }
56
- to {
57
- opacity: 0;
58
- translate: 0 -100%;
59
- scale: 0.7;
60
- }
61
- }
62
-
63
- @keyframes bottom-slide-in {
64
- from {
65
- opacity: 0;
66
- translate: 0 100%;
67
- scale: 0.7;
68
- }
69
- to {
70
- opacity: 1;
71
- translate: 0 0;
72
- scale: 1;
73
- }
74
- }
75
-
76
- @keyframes bottom-slide-out {
77
- from {
78
- opacity: 1;
79
- translate: 0 0;
80
- scale: 1;
81
- }
82
- to {
83
- opacity: 0;
84
- translate: 0 100%;
85
- scale: 0.7;
86
- }
87
- }
88
-
89
- .svg-container {
90
- display: grid;
91
- place-items: center;
92
- border-radius: 10rem;
93
- background-color: #61d345;
94
- color: white;
95
- height: 20px;
96
- width: 20px;
97
- position: relative;
98
- overflow: hidden;
99
-
100
- scale: 1.1;
101
- animation: svg-container-animation 400ms ease-in-out forwards;
102
-
103
- svg {
104
- width: 14px;
105
- height: 14px;
106
- stroke-width: 4px;
107
- display: inline-block;
108
- }
109
- }
110
-
111
- .svg-container.success {
112
- background-color: #61d345;
113
- }
114
- .svg-container.error {
115
- background-color: #ff4b4b;
116
-
117
- svg {
118
- scale: 0;
119
- animation: error-svg-zoom-in 170ms 130ms forwards;
120
- }
121
- }
122
-
123
- .svg-container.success::before {
124
- content: '';
125
- position: absolute;
126
- inset: 0;
127
- z-index: 5;
128
- border-radius: 10rem;
129
- background-color: #61d345;
130
- animation: success-container-before-animation 250ms 150ms forwards;
131
- }
132
-
133
- @keyframes svg-container-animation {
134
- 0% {
135
- scale: 1;
136
- }
137
- 50% {
138
- scale: 1.15;
139
- }
140
- 100% {
141
- scale: 1;
142
- }
143
- }
144
-
145
- @keyframes success-container-before-animation {
146
- from {
147
- translate: 0 0;
148
- }
149
- to {
150
- translate: 100% -50%;
151
- }
152
- }
153
-
154
- @keyframes error-svg-zoom-in {
155
- from {
156
- scale: 0;
157
- }
158
- to {
159
- scale: 1;
160
- }
161
- }
162
-
163
- .promise-svg-container {
164
- width: 20px;
165
- height: 20px;
166
- display: grid;
167
- place-items: center;
168
- color: #474747;
169
-
170
- svg {
171
- width: 14px;
172
- height: 14px;
173
- stroke-width: 3px;
174
- display: inline-block;
175
- animation: rotate-infinity 1000ms infinite linear;
176
- }
177
- }
178
-
179
- @keyframes rotate-infinity {
180
- to {
181
- rotate: 360deg;
182
- }
183
- }
184
- `;
185
- const listeners = new Set();
186
- function addToast(toast) {
187
- listeners.forEach(callback => {
188
- callback(toast);
189
- });
190
- }
191
- function subscribe(callback) {
192
- if (!document.getElementById('kitzo-react-toast-styles')) {
193
- const styleTag = document.createElement('style');
194
- styleTag.id = 'kitzo-react-toast-styles';
195
- styleTag.textContent = toastStyles;
196
- document.head.appendChild(styleTag);
197
- }
198
- listeners.add(callback);
199
- return () => listeners.delete(callback);
200
- }
201
- function toast(text = 'Toast message', options = {}) {
202
- const id = Date.now();
203
- options = Object.assign({
204
- duration: 2800,
205
- id,
206
- style: {},
207
- showIcon: false
208
- }, options);
209
- addToast({
210
- type: 'success',
211
- text,
212
- options
213
- });
214
- }
215
- toast.success = (text = 'Toast success', options = {}) => {
216
- const id = Date.now();
217
- options = Object.assign({
218
- duration: 2800,
219
- id,
220
- style: {},
221
- showIcon: true
222
- }, options);
223
- addToast({
224
- type: 'success',
225
- text,
226
- options
227
- });
228
- };
229
- toast.error = (text = 'Toast denied', options = {}) => {
230
- const id = Date.now();
231
- options = Object.assign({
232
- duration: 2800,
233
- id,
234
- style: {},
235
- showIcon: true
236
- }, options);
237
- addToast({
238
- type: 'error',
239
- text,
240
- options
241
- });
242
- };
243
- toast.promise = (callback, msgs = {}, options = {}) => {
244
- const id = Date.now();
245
- options = Object.assign({
246
- duration: 2800,
247
- id,
248
- style: {},
249
- showIcon: true
250
- }, options);
251
- msgs = Object.assign({
252
- loading: 'Saving...',
253
- success: 'Success',
254
- error: 'Something went wrong'
255
- }, msgs);
256
- addToast({
257
- type: 'loading',
258
- text: msgs.loading,
259
- options: {
260
- ...options,
261
- duration: Infinity,
262
- id
263
- }
264
- });
265
- callback.then(res => {
266
- const successMsg = typeof msgs.success === 'function' ? msgs.success(res) : msgs.success;
267
- addToast({
268
- type: 'success',
269
- text: successMsg,
270
- options
271
- });
272
- return res;
273
- }).catch(err => {
274
- const normalizedError = err instanceof Error ? err : new Error(String(err));
275
- const errorMsg = typeof msgs.error === 'function' ? msgs.error(normalizedError) : msgs.error;
276
- addToast({
277
- type: 'error',
278
- text: errorMsg,
279
- options
280
- });
281
- return Promise.reject(normalizedError);
282
- });
283
- };
284
- toast.custom = (render, options = {}) => {
285
- const id = Date.now();
286
- options = Object.assign({
287
- duration: 3000,
288
- id,
289
- exitDelay: 50
290
- }, options);
291
- addToast({
292
- type: 'custom',
293
- render,
294
- options
295
- });
296
- return id;
297
- };
298
- function dismiss(id, exitDelay) {
299
- addToast({
300
- type: 'dismiss',
301
- id,
302
- exitDelay
303
- });
304
- }
305
-
306
- function SuccessSvg() {
307
- return /*#__PURE__*/React.createElement("div", {
308
- className: "svg-container success"
309
- }, /*#__PURE__*/React.createElement("svg", {
310
- xmlns: "http://www.w3.org/2000/svg",
311
- width: "24",
312
- height: "24",
313
- viewBox: "0 0 24 24",
314
- fill: "none",
315
- stroke: "currentColor",
316
- strokeWidth: "2",
317
- strokeLinecap: "round",
318
- strokeLinejoin: "round"
319
- }, /*#__PURE__*/React.createElement("path", {
320
- d: "M20 6 9 17l-5-5"
321
- })));
322
- }
323
- function ErrorSvg() {
324
- return /*#__PURE__*/React.createElement("div", {
325
- className: "svg-container error"
326
- }, /*#__PURE__*/React.createElement("svg", {
327
- xmlns: "http://www.w3.org/2000/svg",
328
- width: "24",
329
- height: "24",
330
- viewBox: "0 0 24 24",
331
- fill: "none",
332
- stroke: "currentColor",
333
- strokeWidth: "2",
334
- strokeLinecap: "round",
335
- strokeLinejoin: "round"
336
- }, /*#__PURE__*/React.createElement("path", {
337
- d: "M18 6 6 18"
338
- }), /*#__PURE__*/React.createElement("path", {
339
- d: "m6 6 12 12"
340
- })));
341
- }
342
- function LoadingSvg() {
343
- return /*#__PURE__*/React.createElement("div", {
344
- className: "promise-svg-container"
345
- }, /*#__PURE__*/React.createElement("svg", {
346
- xmlns: "http://www.w3.org/2000/svg",
347
- width: "24",
348
- height: "24",
349
- viewBox: "0 0 24 24",
350
- fill: "none",
351
- stroke: "currentColor",
352
- strokeWidth: "2",
353
- strokeLinecap: "round",
354
- strokeLinejoin: "round"
355
- }, /*#__PURE__*/React.createElement("path", {
356
- d: "M21 12a9 9 0 1 1-6.219-8.56"
357
- })));
358
- }
359
-
360
- function Toast({
361
- toast,
362
- setToasts,
363
- position,
364
- gap
365
- }) {
366
- const {
367
- id,
368
- leaving,
369
- offset,
370
- text,
371
- type,
372
- options
373
- } = toast;
374
- const {
375
- style,
376
- showIcon
377
- } = options;
378
- const ref = useRef(null);
379
- useLayoutEffect(() => {
380
- if (!ref.current) return;
381
- const height = ref.current.getBoundingClientRect().height;
382
- const totalHeight = height + gap;
383
- setToasts(prev => prev.map(t => t.id === id ? {
384
- ...t,
385
- height: totalHeight
386
- } : t));
387
- }, []);
388
- const transformY = position.includes('bottom') ? `translateY(-${offset || 0}px)` : `translateY(${offset || 0}px)`;
389
- function renderCustomContent() {
390
- const render = toast.render;
391
- if (typeof render === 'function') {
392
- return render(() => dismiss(toast.id, toast.options.exitDelay));
393
- }
394
- if (typeof render === 'string') {
395
- return /*#__PURE__*/React.createElement("span", null, render);
396
- }
397
- return render;
398
- }
399
- return /*#__PURE__*/React.createElement("div", {
400
- ref: ref,
401
- style: {
402
- maxHeight: 'fit-content',
403
- transform: transformY,
404
- ...getToastPosition(position)
405
- }
406
- }, /*#__PURE__*/React.createElement("div", {
407
- className: `toast-content${position.includes('bottom') ? '-bottom' : ''} ${leaving ? 'exit' : ''}`
408
- }, type === 'custom' ? renderCustomContent() : /*#__PURE__*/React.createElement("div", {
409
- style: {
410
- ...style
411
- },
412
- className: "pre-styled"
413
- }, showIcon && /*#__PURE__*/React.createElement(React.Fragment, null, type === 'loading' && /*#__PURE__*/React.createElement(LoadingSvg, null), type === 'success' && /*#__PURE__*/React.createElement(SuccessSvg, null), type === 'error' && /*#__PURE__*/React.createElement(ErrorSvg, null)), /*#__PURE__*/React.createElement("span", null, text))));
414
- }
415
- function getToastPosition(position) {
416
- const isLeft = position.includes('left');
417
- const isRight = position.includes('right');
418
- const styles = {
419
- position: 'absolute',
420
- width: '100%',
421
- pointerEvents: 'none',
422
- transition: 'transform 230ms',
423
- display: 'flex'
424
- };
425
- if (position.includes('top')) {
426
- styles.top = '0';
427
- styles.justifyContent = isLeft ? 'flex-start' : isRight ? 'flex-end' : 'center';
428
- }
429
- if (position.includes('bottom')) {
430
- styles.bottom = '0';
431
- styles.justifyContent = isLeft ? 'flex-start' : isRight ? 'flex-end' : 'center';
432
- }
433
- return styles;
434
- }
435
-
436
- function ToastContainer(props) {
437
- props = Object.assign({
438
- position: 'top-center',
439
- gap: 8
440
- }, props);
441
- const {
442
- gap
443
- } = props;
444
- const position = props.position;
445
- const [toasts, setToasts] = useState([]);
446
-
447
- // event listener
448
- useEffect(() => {
449
- const unsub = subscribe(toast => {
450
- if (toast.type === 'dismiss') {
451
- setTimeout(() => {
452
- setToasts(prev => prev.map(t => t.options.id === toast.id ? {
453
- ...t,
454
- leaving: true
455
- } : t));
456
- }, Math.max(0, Number(toast.exitDelay)));
457
- setTimeout(() => {
458
- setToasts(prev => prev.filter(t => t.options.id !== toast.id));
459
- }, Math.max(0, Number(toast.exitDelay) + 300));
460
- return;
461
- }
462
- const duration = toast.options.duration;
463
- const id = toast.options.id;
464
- setToasts(prev => {
465
- const exists = prev.some(t => t.options.id === id);
466
- if (exists) {
467
- return prev.map(t => t.options.id === id ? {
468
- ...t,
469
- ...toast
470
- } : t);
471
- }
472
- return [{
473
- id,
474
- ...toast,
475
- offset: 0,
476
- height: 0,
477
- leaving: false
478
- }, ...prev];
479
- });
480
- if (toast.type !== 'loading' && isFinite(duration)) {
481
- setTimeout(() => {
482
- setToasts(prev => prev.map(t => t.options.id === id ? {
483
- ...t,
484
- leaving: true
485
- } : t));
486
- }, Math.max(0, duration - 300));
487
- setTimeout(() => {
488
- setToasts(prev => prev.filter(t => t.options.id !== id));
489
- }, duration);
490
- }
491
- });
492
- return () => unsub();
493
- }, []);
494
-
495
- // measue height and offset for each toast
496
- useLayoutEffect(() => {
497
- const grouped = toasts.reduce((acc, t) => {
498
- const pos = t.options.position || position || 'top-center';
499
- (acc[pos] ||= []).push(t);
500
- return acc;
501
- }, {});
502
- let hasChanged = false;
503
- const updated = toasts.map(toast => {
504
- const pos = toast.options.position || position || 'top-center';
505
- const group = grouped[pos];
506
- const index = group.findIndex(t => t.id === toast.id);
507
- const offset = group.slice(0, index).reduce((acc, t) => acc + (t.height || 0), 0);
508
- if (offset !== toast.offset) {
509
- hasChanged = true;
510
- }
511
- return {
512
- ...toast,
513
- offset
514
- };
515
- });
516
- if (hasChanged) {
517
- setToasts(updated);
518
- }
519
- }, [toasts]);
520
- const positions = ['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'];
521
- return /*#__PURE__*/React.createElement("div", {
522
- style: {
523
- position: 'fixed',
524
- inset: 0,
525
- zIndex: 100000000,
526
- pointerEvents: 'none',
527
- fontFamily: 'inherit',
528
- boxSizing: 'border-box'
529
- }
530
- }, positions.map(pos => {
531
- const group = toasts.filter(t => (t.options.position || position || 'top-center') === pos);
532
- if (!group.length) return null;
533
- return /*#__PURE__*/React.createElement("div", {
534
- key: pos,
535
- style: {
536
- position: 'absolute',
537
- inset: 0,
538
- display: 'grid',
539
- padding: '1rem'
540
- }
541
- }, /*#__PURE__*/React.createElement("div", {
542
- style: {
543
- position: 'relative'
544
- }
545
- }, group.map(toast => /*#__PURE__*/React.createElement(Toast, {
546
- key: toast.options.id,
547
- toast: toast,
548
- setToasts: setToasts,
549
- position: pos,
550
- gap: typeof gap === 'string' ? isNaN(+gap) ? 8 : +gap : gap
551
- }))));
552
- }));
553
- }
554
-
555
- // import './style.css';
556
- const tooltipStyles = `/* Default styling */
557
- .kitzo-react-tooltip-root {
558
- --bg-clr: hsl(0, 0%, 15%);
559
- --text-clr: hsl(0, 0%, 95%);
560
-
561
- @media (prefers-color-scheme: dark) {
562
- --bg-clr: hsl(0, 0%, 95%);
563
- --text-clr: hsl(0, 0%, 15%);
564
- }
565
- }
566
-
567
- .kitzo-react-tooltip-content-default-style {
568
- font-family:
569
- inherit,
570
- system-ui,
571
- -apple-system,
572
- BlinkMacSystemFont,
573
- 'Segoe UI',
574
- Roboto,
575
- Oxygen,
576
- Ubuntu,
577
- Cantarell,
578
- 'Open Sans',
579
- 'Helvetica Neue',
580
- sans-serif;
581
- font-size: 0.875rem;
582
- background-color: var(--bg-clr);
583
- color: var(--text-clr);
584
- padding-block: 0.25rem;
585
- padding-inline: 0.5rem;
586
- border-radius: 0.325rem;
587
- }
588
-
589
- /* Tooltip positioning */
590
- .kitzo-react-tooltip-wrapper {
591
- --tooltip-offset: calc(var(--offset) * 1px + 1px);
592
- }
593
- /* Top */
594
- .kitzo-react-tooltip-wrapper.top {
595
- bottom: 100%;
596
- padding-block-end: var(--tooltip-offset);
597
- }
598
- .kitzo-react-tooltip-wrapper.top {
599
- left: 50%;
600
- translate: -50% 0;
601
- }
602
- .kitzo-react-tooltip-wrapper.top.start {
603
- left: 0;
604
- translate: 0 0;
605
- }
606
- .kitzo-react-tooltip-wrapper.top.end {
607
- right: 0;
608
- translate: 0 0;
609
- }
610
-
611
- /* Right */
612
- .kitzo-react-tooltip-wrapper.right {
613
- left: 100%;
614
- padding-inline-start: var(--tooltip-offset);
615
- }
616
- .kitzo-react-tooltip-wrapper.right {
617
- top: 50%;
618
- translate: 0 -50%;
619
- }
620
- .kitzo-react-tooltip-wrapper.right.start {
621
- top: 0;
622
- translate: 0 0;
623
- }
624
- .kitzo-react-tooltip-wrapper.right.end {
625
- top: 100%;
626
- translate: 0 -100%;
627
- }
628
-
629
- /* Bottom */
630
- .kitzo-react-tooltip-wrapper.bottom {
631
- top: 100%;
632
- padding-block-start: var(--tooltip-offset);
633
- }
634
- .kitzo-react-tooltip-wrapper.bottom {
635
- left: 50%;
636
- translate: -50% 0;
637
- }
638
- .kitzo-react-tooltip-wrapper.bottom.start {
639
- left: 0;
640
- translate: 0 0;
641
- }
642
- .kitzo-react-tooltip-wrapper.bottom.end {
643
- left: 100%;
644
- translate: -100% 0;
645
- }
646
-
647
- /* Left */
648
- .kitzo-react-tooltip-wrapper.left {
649
- right: 100%;
650
- padding-inline-end: var(--tooltip-offset);
651
- }
652
- .kitzo-react-tooltip-wrapper.left {
653
- top: 50%;
654
- translate: 0 -50%;
655
- }
656
- .kitzo-react-tooltip-wrapper.left.start {
657
- top: 0;
658
- translate: 0 0;
659
- }
660
- .kitzo-react-tooltip-wrapper.left.end {
661
- top: 100%;
662
- translate: 0 -100%;
663
- }
664
-
665
- /* Tooltip transitions */
666
- .kitzo-react-tooltip-root.animate-tooltip {
667
- --transition-startDuration: calc(var(--startDuration) * 1ms);
668
- --transition-endDuration: calc(var(--endDuration) * 1ms);
669
- --transition-startDelay: calc(var(--startDelay) * 1ms);
670
- --transition-endDelay: calc(var(--endDelay) * 1ms);
671
-
672
- .kitzo-react-tooltip-content {
673
- transition:
674
- transform var(--transition-endDuration) var(--transition-endDelay),
675
- opacity var(--transition-endDuration) var(--transition-endDelay);
676
- }
677
- }
678
-
679
- .kitzo-react-tooltip-content {
680
- transform: scale(0.8);
681
- opacity: 0;
682
- }
683
-
684
- .kitzo-react-tooltip-content.top {
685
- transform-origin: bottom;
686
- }
687
- .kitzo-react-tooltip-content.right {
688
- transform-origin: left;
689
- }
690
- .kitzo-react-tooltip-content.bottom {
691
- transform-origin: top;
692
- }
693
- .kitzo-react-tooltip-content.left {
694
- transform-origin: right;
695
- }
696
-
697
- .kitzo-react-tooltip-root.animate-tooltip:hover {
698
- .kitzo-react-tooltip-content {
699
- transition:
700
- transform var(--transition-startDuration) var(--transition-startDelay),
701
- opacity var(--transition-startDuration) var(--transition-startDelay);
702
- }
703
- }
704
- .kitzo-react-tooltip-root:hover {
705
- .kitzo-react-tooltip-content {
706
- transform: scale(1);
707
- opacity: 1;
708
- }
709
- }
710
-
711
- /* smart hover persistence feature */
712
- .kitzo-react-tooltip-root {
713
- .kitzo-react-tooltip-wrapper {
714
- pointer-events: none;
715
- }
716
- }
717
- .kitzo-react-tooltip-root.smart-hover:hover {
718
- .kitzo-react-tooltip-wrapper {
719
- pointer-events: all;
720
- }
721
- }
722
-
723
- /* Arrow */
724
- .kitzo-react-tooltip-content.tooltip-arrow {
725
- --effective-size: calc(var(--arrow-size, 6) * 1px);
726
- --effective-color: var(--arrow-color, var(--bg-clr));
727
-
728
- position: relative;
729
- }
730
- .kitzo-react-tooltip-content.tooltip-arrow::before {
731
- content: '';
732
- position: absolute;
733
- z-index: -1;
734
- border: var(--effective-size) solid transparent;
735
- }
736
- .kitzo-react-tooltip-content.tooltip-arrow.top::before {
737
- left: 50%;
738
- translate: -50% 0;
739
- top: calc(100% - 1px);
740
- border-top: var(--effective-size) solid var(--effective-color);
741
- }
742
- .kitzo-react-tooltip-content.tooltip-arrow.right::before {
743
- top: 50%;
744
- translate: 0 -50%;
745
- right: calc(100% - 1px);
746
- border-right: var(--effective-size) solid var(--effective-color);
747
- }
748
- .kitzo-react-tooltip-content.tooltip-arrow.bottom::before {
749
- left: 50%;
750
- translate: -50% 0;
751
- bottom: calc(100% - 1px);
752
- border-bottom: var(--effective-size) solid var(--effective-color);
753
- }
754
- .kitzo-react-tooltip-content.tooltip-arrow.left::before {
755
- top: 50%;
756
- translate: 0 -50%;
757
- left: calc(100% - 1px);
758
- border-left: var(--effective-size) solid var(--effective-color);
759
- }`;
760
- (() => {
761
- if (!document.getElementById('kitzo-react-tooltip-styles')) {
762
- const styleTag = document.createElement('style');
763
- styleTag.id = 'kitzo-react-tooltip-styles';
764
- styleTag.textContent = tooltipStyles;
765
- document.head.appendChild(styleTag);
766
- }
767
- })();
768
- const allowedPositions = ['top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-start', 'bottom', 'bottom-end', 'left-start', 'left', 'left-end'];
769
- function getPositionClass(position = '') {
770
- const allowedPos = allowedPositions.find(p => p === position);
771
- if (!allowedPos) return 'top';
772
- if (allowedPos.includes('-')) {
773
- const [dir, state] = allowedPos.split('-');
774
- return `${dir} ${state}`;
775
- } else {
776
- return allowedPos;
777
- }
778
- }
779
- function getAnimationProperties(animation) {
780
- const effectiveStartDelay = animation?.startDelay;
781
- const effectiveEndDelay = animation?.endDelay;
782
- const effectiveDelay = animation?.delay ?? 0;
783
- const effectiveStartDuration = animation?.startDuration;
784
- const effectiveEndDuration = animation?.endDuration;
785
- const effectiveDuration = animation?.duration ?? 110;
786
- return {
787
- startDelay: effectiveStartDelay ?? effectiveDelay,
788
- endDelay: effectiveEndDelay ?? effectiveDelay,
789
- startDuration: effectiveStartDuration ?? effectiveDuration,
790
- endDuration: effectiveEndDuration ?? effectiveDuration
791
- };
792
- }
793
- function Tooltip({
794
- content,
795
- tooltipOptions = {},
796
- animation = true,
797
- style = {},
798
- isHidden = false,
799
- children
800
- }) {
801
- if (typeof isHidden === 'boolean' && isHidden) return children;
802
- if (typeof content === 'string') {
803
- if (!content.trim()) throw new Error('kitzo/react: tooltip content is required');
804
- } else if (!content) {
805
- throw new Error('kitzo/react: tooltip content is required');
806
- }
807
- // Define options
808
- const {
809
- position = 'top',
810
- offset = 8,
811
- hideOnTouch = true,
812
- arrow = false,
813
- smartHover = true
814
- } = tooltipOptions ?? {};
815
- const finalOptions = {
816
- position: typeof position === 'string' ? position.trim().toLowerCase() : 'top',
817
- offset: !isNaN(Number(offset)) ? Number(offset) : 8,
818
- arrow: typeof arrow === 'boolean' ? arrow : false,
819
- smartHover: typeof smartHover === 'boolean' ? smartHover : true,
820
- hideOnTouch: typeof hideOnTouch === 'boolean' ? hideOnTouch : true
821
- };
822
-
823
- // Hide on touch device
824
- const isTouch = window.matchMedia('(pointer: coarse)').matches;
825
- if (isTouch && finalOptions.hideOnTouch) return children;
826
- const positionClass = getPositionClass(finalOptions.position);
827
-
828
- // Define animations
829
- const animationEnabled = animation ? true : false;
830
- const animationObj = animation === true ? {} : animation;
831
- const finalAnimationProperties = getAnimationProperties(animationObj);
832
- return /*#__PURE__*/React.createElement("div", {
833
- style: {
834
- position: 'relative',
835
- width: 'fit-content',
836
- '--offset': Math.max(0, finalOptions.offset),
837
- '--startDuration': Math.max(0, finalAnimationProperties.startDuration),
838
- '--endDuration': Math.max(0, finalAnimationProperties.endDuration),
839
- '--startDelay': Math.max(0, finalAnimationProperties.startDelay),
840
- '--endDelay': Math.max(0, finalAnimationProperties.endDelay),
841
- '--arrow-color': style?.['--arrow-color'],
842
- '--arrow-size': style?.['--arrow-size']
843
- },
844
- className: `kitzo-react-tooltip-root ${finalOptions.smartHover ? 'smart-hover' : ''} ${animationEnabled ? 'animate-tooltip' : ''}`
845
- }, children, /*#__PURE__*/React.createElement("div", {
846
- style: {
847
- position: 'absolute',
848
- whiteSpace: typeof content === 'string' ? 'nowrap' : 'normal'
849
- },
850
- tabIndex: -1,
851
- className: `kitzo-react-tooltip-wrapper ${positionClass}`
852
- }, /*#__PURE__*/React.createElement("div", {
853
- className: `kitzo-react-tooltip-content ${positionClass} ${finalOptions.arrow ? 'tooltip-arrow' : ''}`
854
- }, typeof content === 'string' || typeof content === 'number' ? /*#__PURE__*/React.createElement("div", {
855
- className: "kitzo-react-tooltip-content-default-style"
856
- }, content) : /*#__PURE__*/React.createElement(React.Fragment, null, content))));
857
- }
858
-
859
- export { ToastContainer, Tooltip, toast };