ezfw-core 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.
Files changed (154) hide show
  1. package/components/EzBaseComponent.ts +648 -0
  2. package/components/EzComponent.ts +89 -0
  3. package/components/EzInput.module.scss +183 -0
  4. package/components/EzInput.ts +104 -0
  5. package/components/EzLabel.ts +22 -0
  6. package/components/EzOutlet.ts +181 -0
  7. package/components/HtmlWrapper.ts +305 -0
  8. package/components/avatar/EzAvatar.module.scss +200 -0
  9. package/components/avatar/EzAvatar.ts +130 -0
  10. package/components/badge/EzBadge.module.scss +202 -0
  11. package/components/badge/EzBadge.ts +77 -0
  12. package/components/button/EzButton.module.scss +402 -0
  13. package/components/button/EzButton.ts +175 -0
  14. package/components/button/EzButtonGroup.ts +48 -0
  15. package/components/card/EzCard.module.scss +71 -0
  16. package/components/card/EzCard.ts +120 -0
  17. package/components/chart/EzBarChart.ts +47 -0
  18. package/components/chart/EzChart.module.scss +14 -0
  19. package/components/chart/EzChart.ts +279 -0
  20. package/components/chart/EzDoughnutChart.ts +47 -0
  21. package/components/chart/EzLineChart.ts +53 -0
  22. package/components/checkbox/EzCheckbox.module.scss +145 -0
  23. package/components/checkbox/EzCheckbox.ts +115 -0
  24. package/components/dataview/EzDataView.module.scss +115 -0
  25. package/components/dataview/EzDataView.ts +355 -0
  26. package/components/dataview/modes/EzDataViewCards.ts +322 -0
  27. package/components/dataview/modes/EzDataViewGrid.ts +76 -0
  28. package/components/datepicker/EzDatePicker.module.scss +348 -0
  29. package/components/datepicker/EzDatePicker.ts +519 -0
  30. package/components/dialog/EzDialog.module.scss +180 -0
  31. package/components/dropdown/EzDropdown.module.scss +107 -0
  32. package/components/dropdown/EzDropdown.ts +235 -0
  33. package/components/feed/EzActivityFeed.module.scss +90 -0
  34. package/components/feed/EzActivityFeed.ts +78 -0
  35. package/components/form/EzForm.ts +364 -0
  36. package/components/form/EzValidators.test.js +421 -0
  37. package/components/form/EzValidators.ts +202 -0
  38. package/components/grid/EzGrid.scss +88 -0
  39. package/components/grid/EzGrid.ts +1085 -0
  40. package/components/grid/EzGridContainer.ts +104 -0
  41. package/components/grid/body/EzGridBody.scss +283 -0
  42. package/components/grid/body/EzGridBody.ts +549 -0
  43. package/components/grid/body/EzGridCell.ts +211 -0
  44. package/components/grid/body/EzGridRow.ts +196 -0
  45. package/components/grid/filter/EzGridFilters.scss +78 -0
  46. package/components/grid/filter/EzGridFilters.ts +285 -0
  47. package/components/grid/footer/EzGridFooter.scss +136 -0
  48. package/components/grid/footer/EzGridFooter.ts +448 -0
  49. package/components/grid/header/EzGridHeader.scss +199 -0
  50. package/components/grid/header/EzGridHeader.ts +430 -0
  51. package/components/grid/query/EzGridQuery.ts +81 -0
  52. package/components/grid/state/EzGridColumns.ts +155 -0
  53. package/components/grid/state/EzGridController.ts +470 -0
  54. package/components/grid/state/EzGridLifecycle.ts +136 -0
  55. package/components/grid/state/EzGridNormalizers.test.js +273 -0
  56. package/components/grid/state/EzGridNormalizers.ts +162 -0
  57. package/components/grid/state/EzGridParts.ts +233 -0
  58. package/components/grid/state/EzGridPersistence.ts +140 -0
  59. package/components/grid/state/EzGridRemote.test.js +573 -0
  60. package/components/grid/state/EzGridRemote.ts +335 -0
  61. package/components/grid/state/EzGridSelection.ts +231 -0
  62. package/components/grid/state/EzGridSort.ts +286 -0
  63. package/components/grid/title/EzGridActionBar.ts +98 -0
  64. package/components/grid/title/EzGridTitle.ts +114 -0
  65. package/components/grid/title/EzGridTitleBar.scss +65 -0
  66. package/components/grid/title/EzGridTitleBar.ts +87 -0
  67. package/components/grid/types.ts +607 -0
  68. package/components/panel/EzPanel.module.scss +133 -0
  69. package/components/panel/EzPanel.ts +147 -0
  70. package/components/radio/EzRadio.module.scss +190 -0
  71. package/components/radio/EzRadio.ts +149 -0
  72. package/components/select/EzSelect.module.scss +153 -0
  73. package/components/select/EzSelect.ts +238 -0
  74. package/components/skeleton/EzSkeleton.module.scss +95 -0
  75. package/components/skeleton/EzSkeleton.ts +70 -0
  76. package/components/store/EzStore.ts +344 -0
  77. package/components/switch/EzSwitch.module.scss +164 -0
  78. package/components/switch/EzSwitch.ts +117 -0
  79. package/components/tabs/EzTabPanel.module.scss +181 -0
  80. package/components/tabs/EzTabPanel.ts +402 -0
  81. package/components/textarea/EzTextarea.module.scss +131 -0
  82. package/components/textarea/EzTextarea.ts +161 -0
  83. package/components/timepicker/EzTimePicker.module.scss +282 -0
  84. package/components/timepicker/EzTimePicker.ts +540 -0
  85. package/components/toast/EzToast.module.scss +291 -0
  86. package/components/tooltip/EzTooltip.module.scss +124 -0
  87. package/components/tooltip/EzTooltip.ts +153 -0
  88. package/core/EzComponentTypes.ts +693 -0
  89. package/core/EzError.ts +63 -0
  90. package/core/EzModel.ts +268 -0
  91. package/core/EzTypes.ts +328 -0
  92. package/core/eventBus.ts +284 -0
  93. package/core/ez.ts +617 -0
  94. package/core/loader.ts +725 -0
  95. package/core/renderer.ts +1010 -0
  96. package/core/router.ts +490 -0
  97. package/core/services.ts +124 -0
  98. package/core/state.ts +142 -0
  99. package/core/utils.ts +81 -0
  100. package/package.json +51 -0
  101. package/services/RouteUI.js +17 -0
  102. package/services/crypto.js +64 -0
  103. package/services/dialog.js +222 -0
  104. package/services/fetchApi.js +63 -0
  105. package/services/firebase.js +30 -0
  106. package/services/toast.js +214 -0
  107. package/template/doc/EzDocs.js +15 -0
  108. package/template/doc/EzDocs.module.scss +627 -0
  109. package/template/doc/EzDocsController.js +164 -0
  110. package/template/doc/data/activityfeed/EzActivityFeedDoc.js +42 -0
  111. package/template/doc/data/avatar/EzAvatarDoc.js +71 -0
  112. package/template/doc/data/badge/EzBadgeDoc.js +92 -0
  113. package/template/doc/data/button/EzButtonDoc.js +77 -0
  114. package/template/doc/data/buttongroup/EzButtonGroupDoc.js +102 -0
  115. package/template/doc/data/card/EzCardDoc.js +39 -0
  116. package/template/doc/data/chart/EzChartDoc.js +60 -0
  117. package/template/doc/data/checkbox/EzCheckboxDoc.js +67 -0
  118. package/template/doc/data/component/EzComponentDoc.js +34 -0
  119. package/template/doc/data/cssmodules/CSSModulesDoc.js +70 -0
  120. package/template/doc/data/datepicker/EzDatePickerDoc.js +126 -0
  121. package/template/doc/data/dialog/EzDialogDoc.js +217 -0
  122. package/template/doc/data/dropdown/EzDropdownDoc.js +178 -0
  123. package/template/doc/data/form/EzFormDoc.js +90 -0
  124. package/template/doc/data/grid/EzGridDoc.js +99 -0
  125. package/template/doc/data/input/EzInputDoc.js +92 -0
  126. package/template/doc/data/label/EzLabelDoc.js +40 -0
  127. package/template/doc/data/model/EzModelDoc.js +53 -0
  128. package/template/doc/data/outlet/EzOutletDoc.js +63 -0
  129. package/template/doc/data/panel/EzPanelDoc.js +214 -0
  130. package/template/doc/data/radio/EzRadioDoc.js +174 -0
  131. package/template/doc/data/router/EzRouterDoc.js +75 -0
  132. package/template/doc/data/select/EzSelectDoc.js +37 -0
  133. package/template/doc/data/skeleton/EzSkeletonDoc.js +149 -0
  134. package/template/doc/data/switch/EzSwitchDoc.js +82 -0
  135. package/template/doc/data/tabpanel/EzTabPanelDoc.js +44 -0
  136. package/template/doc/data/textarea/EzTextareaDoc.js +131 -0
  137. package/template/doc/data/timepicker/EzTimePickerDoc.js +107 -0
  138. package/template/doc/data/tooltip/EzTooltipDoc.js +193 -0
  139. package/template/doc/data/validators/EzValidatorsDoc.js +37 -0
  140. package/template/doc/sidebar/EzDocsSidebar.js +32 -0
  141. package/template/doc/sidebar/category/EzDocsCategory.js +33 -0
  142. package/template/doc/sidebar/item/EzDocsComponentItem.js +24 -0
  143. package/template/doc/viewer/EzDocsViewer.js +18 -0
  144. package/template/doc/viewer/codepanel/EzDocsCodePanel.js +51 -0
  145. package/template/doc/viewer/content/EzDocsContent.js +315 -0
  146. package/template/doc/viewer/header/EzDocsViewerHeader.js +46 -0
  147. package/template/doc/viewer/showcase/EzDocsShowcase.js +59 -0
  148. package/template/doc/viewer/showcase/EzDocsShowcaseSection.js +25 -0
  149. package/template/doc/viewer/showcase/EzDocsVariantItem.js +29 -0
  150. package/template/doc/welcome/EzDocsWelcome.js +48 -0
  151. package/themes/ez-theme.scss +179 -0
  152. package/themes/nature-fresh.scss +169 -0
  153. package/types/global.d.ts +21 -0
  154. package/utils/cssModules.js +81 -0
@@ -0,0 +1,291 @@
1
+ .toastContainer {
2
+ position: fixed;
3
+ z-index: 10000;
4
+ display: flex;
5
+ flex-direction: column;
6
+ gap: 8px;
7
+ pointer-events: none;
8
+ max-width: 420px;
9
+ width: 100%;
10
+ padding: 16px;
11
+ }
12
+
13
+ // Position classes (standalone for CSS modules)
14
+ .topRight {
15
+ top: 0;
16
+ right: 0;
17
+ }
18
+
19
+ .topLeft {
20
+ top: 0;
21
+ left: 0;
22
+ }
23
+
24
+ .topCenter {
25
+ top: 0;
26
+ left: 50%;
27
+ transform: translateX(-50%);
28
+ }
29
+
30
+ .bottomRight {
31
+ bottom: 0;
32
+ right: 0;
33
+ flex-direction: column-reverse;
34
+ }
35
+
36
+ .bottomLeft {
37
+ bottom: 0;
38
+ left: 0;
39
+ flex-direction: column-reverse;
40
+ }
41
+
42
+ .bottomCenter {
43
+ bottom: 0;
44
+ left: 50%;
45
+ transform: translateX(-50%);
46
+ flex-direction: column-reverse;
47
+ }
48
+
49
+ .toast {
50
+ display: flex;
51
+ align-items: flex-start;
52
+ gap: 12px;
53
+
54
+ position: relative;
55
+ overflow: hidden;
56
+
57
+ background: var(--ez-surface-secondary, #ffffff);
58
+ border: 1px solid var(--ez-border, #e2e8f0);
59
+ border-radius: var(--ez-radius-lg, 8px);
60
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
61
+
62
+ padding: 14px 16px;
63
+ pointer-events: auto;
64
+
65
+ opacity: 0;
66
+ transform: translateX(100%);
67
+ transition: all 0.3s ease;
68
+
69
+ // Left border accent
70
+ &::before {
71
+ content: '';
72
+ position: absolute;
73
+ left: 0;
74
+ top: 0;
75
+ bottom: 0;
76
+ width: 4px;
77
+ background: var(--toast-color);
78
+ }
79
+ }
80
+
81
+ .toastVisible {
82
+ opacity: 1;
83
+ transform: translateX(0);
84
+ }
85
+
86
+ .toastExiting {
87
+ opacity: 0;
88
+ transform: translateX(100%);
89
+ }
90
+
91
+ // Variants
92
+ .success {
93
+ --toast-color: var(--ez-success, #10b981);
94
+
95
+ .toastIcon {
96
+ color: var(--ez-success, #10b981);
97
+ }
98
+ }
99
+
100
+ .error {
101
+ --toast-color: var(--ez-danger, #ef4444);
102
+
103
+ .toastIcon {
104
+ color: var(--ez-danger, #ef4444);
105
+ }
106
+ }
107
+
108
+ .warning {
109
+ --toast-color: var(--ez-warning, #f59e0b);
110
+
111
+ .toastIcon {
112
+ color: var(--ez-warning, #f59e0b);
113
+ }
114
+ }
115
+
116
+ .info {
117
+ --toast-color: var(--ez-primary, #2563eb);
118
+
119
+ .toastIcon {
120
+ color: var(--ez-primary, #2563eb);
121
+ }
122
+ }
123
+
124
+ .toastIcon {
125
+ font-size: 18px;
126
+ flex-shrink: 0;
127
+ margin-top: 1px;
128
+ }
129
+
130
+ .toastContent {
131
+ flex: 1;
132
+ min-width: 0;
133
+ }
134
+
135
+ .toastTitle {
136
+ font-size: 14px;
137
+ font-weight: 600;
138
+ color: var(--ez-text-primary, #1e293b);
139
+ margin-bottom: 2px;
140
+ }
141
+
142
+ .toastMessage {
143
+ font-size: 13px;
144
+ color: var(--ez-text-secondary, #64748b);
145
+ line-height: 1.4;
146
+ }
147
+
148
+ .toastAction {
149
+ flex-shrink: 0;
150
+ align-self: center;
151
+
152
+ padding: 6px 12px;
153
+
154
+ font-size: 12px;
155
+ font-weight: 600;
156
+ color: var(--toast-color);
157
+
158
+ background: transparent;
159
+ border: 1px solid var(--toast-color);
160
+ border-radius: var(--ez-radius-sm, 4px);
161
+
162
+ cursor: pointer;
163
+ transition: all 0.15s ease;
164
+
165
+ &:hover {
166
+ background: var(--toast-color);
167
+ color: #ffffff;
168
+ }
169
+ }
170
+
171
+ .toastClose {
172
+ flex-shrink: 0;
173
+ align-self: flex-start;
174
+
175
+ display: flex;
176
+ align-items: center;
177
+ justify-content: center;
178
+
179
+ width: 24px;
180
+ height: 24px;
181
+ padding: 0;
182
+ margin: -4px -4px -4px 0;
183
+
184
+ font-size: 14px;
185
+ color: var(--ez-text-tertiary, #94a3b8);
186
+
187
+ background: transparent;
188
+ border: none;
189
+ border-radius: var(--ez-radius-sm, 4px);
190
+
191
+ cursor: pointer;
192
+ transition: all 0.15s ease;
193
+
194
+ &:hover {
195
+ background: var(--ez-surface-primary, #f1f5f9);
196
+ color: var(--ez-text-secondary, #64748b);
197
+ }
198
+ }
199
+
200
+ .toastProgress {
201
+ position: absolute;
202
+ bottom: 0;
203
+ left: 0;
204
+ right: 0;
205
+ height: 3px;
206
+
207
+ background: var(--toast-color);
208
+ opacity: 0.3;
209
+
210
+ transform-origin: left;
211
+ animation: toastProgress linear forwards;
212
+ }
213
+
214
+ @keyframes toastProgress {
215
+ from {
216
+ transform: scaleX(1);
217
+ }
218
+ to {
219
+ transform: scaleX(0);
220
+ }
221
+ }
222
+
223
+ // Position variants for animation direction
224
+ .topLeft,
225
+ .bottomLeft {
226
+ .toast {
227
+ transform: translateX(-100%);
228
+ }
229
+
230
+ .toastVisible {
231
+ transform: translateX(0);
232
+ }
233
+
234
+ .toastExiting {
235
+ transform: translateX(-100%);
236
+ }
237
+ }
238
+
239
+ .topCenter,
240
+ .bottomCenter {
241
+ .toast {
242
+ transform: translateY(-20px);
243
+ }
244
+
245
+ .toastVisible {
246
+ transform: translateY(0);
247
+ }
248
+
249
+ .toastExiting {
250
+ transform: translateY(-20px);
251
+ opacity: 0;
252
+ }
253
+ }
254
+
255
+ .bottomRight,
256
+ .bottomLeft,
257
+ .bottomCenter {
258
+ .toast {
259
+ transform: translateY(20px);
260
+ }
261
+
262
+ .toastVisible {
263
+ transform: translateY(0);
264
+ }
265
+
266
+ .toastExiting {
267
+ transform: translateY(20px);
268
+ opacity: 0;
269
+ }
270
+ }
271
+
272
+ // Override for left positions
273
+ .bottomLeft {
274
+ .toast {
275
+ transform: translateX(-100%);
276
+ }
277
+
278
+ .toastExiting {
279
+ transform: translateX(-100%);
280
+ }
281
+ }
282
+
283
+ .bottomRight {
284
+ .toast {
285
+ transform: translateX(100%);
286
+ }
287
+
288
+ .toastExiting {
289
+ transform: translateX(100%);
290
+ }
291
+ }
@@ -0,0 +1,124 @@
1
+ .tooltipWrapper {
2
+ display: inline-flex;
3
+ }
4
+
5
+ .tooltip {
6
+ position: fixed;
7
+ z-index: 10001;
8
+
9
+ max-width: 250px;
10
+ padding: 6px 10px;
11
+
12
+ font-size: 12px;
13
+ font-weight: 500;
14
+ line-height: 1.4;
15
+ text-align: center;
16
+ white-space: normal;
17
+ word-wrap: break-word;
18
+
19
+ border-radius: var(--ez-radius-sm, 4px);
20
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
21
+
22
+ pointer-events: none;
23
+ transition: opacity 0.15s ease, visibility 0.15s ease;
24
+ }
25
+
26
+ .arrow {
27
+ position: absolute;
28
+ width: 8px;
29
+ height: 8px;
30
+ background: inherit;
31
+ transform: rotate(45deg);
32
+ }
33
+
34
+ // Dark variant (default)
35
+ .dark {
36
+ background: var(--ez-text-primary, #1e293b);
37
+ color: #ffffff;
38
+
39
+ .arrow {
40
+ background: var(--ez-text-primary, #1e293b);
41
+ }
42
+ }
43
+
44
+ // Light variant
45
+ .light {
46
+ background: #ffffff;
47
+ color: var(--ez-text-primary, #1e293b);
48
+ border: 1px solid var(--ez-border, #e2e8f0);
49
+
50
+ .arrow {
51
+ background: #ffffff;
52
+ border: 1px solid var(--ez-border, #e2e8f0);
53
+ border-top: none;
54
+ border-left: none;
55
+ }
56
+ }
57
+
58
+ // Primary variant
59
+ .primary {
60
+ background: var(--ez-primary, #2563eb);
61
+ color: #ffffff;
62
+
63
+ .arrow {
64
+ background: var(--ez-primary, #2563eb);
65
+ }
66
+ }
67
+
68
+ // Position-based arrow placement
69
+ .top {
70
+ .arrow {
71
+ bottom: -4px;
72
+ left: 50%;
73
+ margin-left: -4px;
74
+ }
75
+ }
76
+
77
+ .bottom {
78
+ .arrow {
79
+ top: -4px;
80
+ left: 50%;
81
+ margin-left: -4px;
82
+ }
83
+ }
84
+
85
+ .left {
86
+ .arrow {
87
+ right: -4px;
88
+ top: 50%;
89
+ margin-top: -4px;
90
+ }
91
+ }
92
+
93
+ .right {
94
+ .arrow {
95
+ left: -4px;
96
+ top: 50%;
97
+ margin-top: -4px;
98
+ }
99
+ }
100
+
101
+ // Light variant arrow fixes for borders
102
+ .light.top .arrow {
103
+ border: 1px solid var(--ez-border, #e2e8f0);
104
+ border-top: none;
105
+ border-left: none;
106
+ }
107
+
108
+ .light.bottom .arrow {
109
+ border: 1px solid var(--ez-border, #e2e8f0);
110
+ border-bottom: none;
111
+ border-right: none;
112
+ }
113
+
114
+ .light.left .arrow {
115
+ border: 1px solid var(--ez-border, #e2e8f0);
116
+ border-bottom: none;
117
+ border-left: none;
118
+ }
119
+
120
+ .light.right .arrow {
121
+ border: 1px solid var(--ez-border, #e2e8f0);
122
+ border-top: none;
123
+ border-right: none;
124
+ }
@@ -0,0 +1,153 @@
1
+ import styles from './EzTooltip.module.scss';
2
+ import { cx } from '../../utils/cssModules.js';
3
+ import { EzBaseComponent, EzBaseComponentConfig } from '../EzBaseComponent.js';
4
+
5
+ declare const ez: {
6
+ _createChildElements(items: unknown[], controller: string | null, state: unknown): Promise<Node[]>;
7
+ };
8
+
9
+ const cls = cx(styles);
10
+
11
+ type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
12
+
13
+ export interface EzTooltipConfig extends EzBaseComponentConfig {
14
+ text?: string;
15
+ position?: TooltipPosition;
16
+ variant?: 'dark' | 'light';
17
+ delay?: number;
18
+ hideDelay?: number;
19
+ items?: unknown[];
20
+ }
21
+
22
+ export class EzTooltip extends EzBaseComponent {
23
+ declare config: EzTooltipConfig;
24
+
25
+ private _wrapper: HTMLElement | null = null;
26
+ private _tooltipEl: HTMLElement | null = null;
27
+ private _position: TooltipPosition = 'top';
28
+ private _delay: number = 200;
29
+ private _hideDelay: number = 0;
30
+ private _showTimeout: ReturnType<typeof setTimeout> | null = null;
31
+ private _hideTimeout: ReturnType<typeof setTimeout> | null = null;
32
+
33
+ async render(): Promise<HTMLElement> {
34
+ const cfg = this.config;
35
+
36
+ const wrapper = document.createElement('div');
37
+ wrapper.className = cls('tooltipWrapper');
38
+
39
+ if (cfg.items && cfg.items.length > 0) {
40
+ const children = await ez._createChildElements(
41
+ cfg.items,
42
+ this.config.controller || null,
43
+ null
44
+ );
45
+ for (const child of children) {
46
+ if (child instanceof Node) {
47
+ wrapper.appendChild(child);
48
+ }
49
+ }
50
+ }
51
+
52
+ const tooltip = document.createElement('div');
53
+ tooltip.className = cls(
54
+ 'tooltip',
55
+ cfg.variant || 'dark'
56
+ );
57
+ tooltip.textContent = cfg.text || '';
58
+ tooltip.style.opacity = '0';
59
+ tooltip.style.visibility = 'hidden';
60
+
61
+ const arrow = document.createElement('div');
62
+ arrow.className = cls('arrow');
63
+ tooltip.appendChild(arrow);
64
+
65
+ document.body.appendChild(tooltip);
66
+
67
+ this._wrapper = wrapper;
68
+ this._tooltipEl = tooltip;
69
+ this._position = cfg.position || 'top';
70
+ this._delay = cfg.delay ?? 200;
71
+ this._hideDelay = cfg.hideDelay ?? 0;
72
+
73
+ wrapper.addEventListener('mouseenter', () => this._scheduleShow());
74
+ wrapper.addEventListener('mouseleave', () => this._scheduleHide());
75
+ wrapper.addEventListener('focus', () => this._scheduleShow(), true);
76
+ wrapper.addEventListener('blur', () => this._scheduleHide(), true);
77
+
78
+ return wrapper;
79
+ }
80
+
81
+ private _scheduleShow(): void {
82
+ if (this._hideTimeout) clearTimeout(this._hideTimeout);
83
+ this._showTimeout = setTimeout(() => this._show(), this._delay);
84
+ }
85
+
86
+ private _scheduleHide(): void {
87
+ if (this._showTimeout) clearTimeout(this._showTimeout);
88
+ this._hideTimeout = setTimeout(() => this._hide(), this._hideDelay);
89
+ }
90
+
91
+ private _show(): void {
92
+ if (!this._wrapper || !this._tooltipEl) return;
93
+
94
+ const rect = this._wrapper.getBoundingClientRect();
95
+ const tooltipRect = this._tooltipEl.getBoundingClientRect();
96
+ const position = this._position;
97
+
98
+ let top: number, left: number;
99
+
100
+ switch (position) {
101
+ case 'top':
102
+ top = rect.top - tooltipRect.height - 8;
103
+ left = rect.left + (rect.width - tooltipRect.width) / 2;
104
+ break;
105
+ case 'bottom':
106
+ top = rect.bottom + 8;
107
+ left = rect.left + (rect.width - tooltipRect.width) / 2;
108
+ break;
109
+ case 'left':
110
+ top = rect.top + (rect.height - tooltipRect.height) / 2;
111
+ left = rect.left - tooltipRect.width - 8;
112
+ break;
113
+ case 'right':
114
+ top = rect.top + (rect.height - tooltipRect.height) / 2;
115
+ left = rect.right + 8;
116
+ break;
117
+ default:
118
+ top = rect.top - tooltipRect.height - 8;
119
+ left = rect.left + (rect.width - tooltipRect.width) / 2;
120
+ }
121
+
122
+ const padding = 8;
123
+ if (left < padding) left = padding;
124
+ if (left + tooltipRect.width > window.innerWidth - padding) {
125
+ left = window.innerWidth - tooltipRect.width - padding;
126
+ }
127
+ if (top < padding) top = padding;
128
+ if (top + tooltipRect.height > window.innerHeight - padding) {
129
+ top = window.innerHeight - tooltipRect.height - padding;
130
+ }
131
+
132
+ this._tooltipEl.style.top = `${top + window.scrollY}px`;
133
+ this._tooltipEl.style.left = `${left + window.scrollX}px`;
134
+ this._tooltipEl.className = cls('tooltip', this.config.variant || 'dark', position);
135
+ this._tooltipEl.style.opacity = '1';
136
+ this._tooltipEl.style.visibility = 'visible';
137
+ }
138
+
139
+ private _hide(): void {
140
+ if (this._tooltipEl) {
141
+ this._tooltipEl.style.opacity = '0';
142
+ this._tooltipEl.style.visibility = 'hidden';
143
+ }
144
+ }
145
+
146
+ destroy(): void {
147
+ if (this._showTimeout) clearTimeout(this._showTimeout);
148
+ if (this._hideTimeout) clearTimeout(this._hideTimeout);
149
+ if (this._tooltipEl && this._tooltipEl.parentNode) {
150
+ this._tooltipEl.parentNode.removeChild(this._tooltipEl);
151
+ }
152
+ }
153
+ }