flikkui 0.1.0-beta.4 → 0.1.0-beta.5

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 (146) hide show
  1. package/dist/components/charts/AreaChart/AreaChart.js +434 -0
  2. package/dist/components/charts/AreaChart/AreaChart.types.js +7 -0
  3. package/dist/components/charts/BarChart/BarChart.js +402 -0
  4. package/dist/components/charts/BarChart/BarChart.types.js +7 -0
  5. package/dist/components/charts/ChartContainer.js +38 -0
  6. package/dist/components/charts/Heatmap/Heatmap.js +153 -0
  7. package/dist/components/charts/Heatmap/HeatmapCell.js +100 -0
  8. package/dist/components/charts/Heatmap/HeatmapLegend.js +20 -0
  9. package/dist/components/charts/Heatmap/utils/heatmapUtils.js +174 -0
  10. package/dist/components/charts/LineChart/LineChart.js +396 -0
  11. package/dist/components/charts/LineChart/LineChart.types.js +7 -0
  12. package/dist/components/charts/hooks/useChartAccessibility.js +127 -0
  13. package/dist/components/charts/hooks/useChartTheme.js +86 -0
  14. package/dist/components/charts/hooks/useChartValidation.js +59 -0
  15. package/dist/components/charts/hooks/useTooltipPosition.js +292 -0
  16. package/dist/components/charts/shared/ChartAxis/XAxis.js +30 -0
  17. package/dist/components/charts/shared/ChartAxis/YAxis.js +97 -0
  18. package/dist/components/charts/shared/ChartCrosshair/ChartCrosshair.js +35 -0
  19. package/dist/components/charts/shared/ChartCrosshair/ChartCrosshair.theme.js +11 -0
  20. package/dist/components/charts/shared/ChartErrorBoundary/ChartErrorBoundary.js +66 -0
  21. package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +22 -0
  22. package/dist/components/charts/shared/ChartLegend/ChartLegend.js +30 -0
  23. package/dist/components/charts/shared/ChartLegend/ChartLegendContent.js +22 -0
  24. package/dist/components/charts/shared/ChartMarker/ChartMarker.js +25 -0
  25. package/dist/components/charts/shared/ChartMarker/ChartMarker.theme.js +9 -0
  26. package/dist/components/charts/shared/ChartText/ChartText.js +33 -0
  27. package/dist/components/charts/shared/ChartText/ChartText.theme.js +9 -0
  28. package/dist/components/charts/shared/ChartTooltip/ChartTooltip.js +62 -0
  29. package/dist/components/charts/theme/chart.theme.js +73 -0
  30. package/dist/components/charts/types/chart.types.js +29 -0
  31. package/dist/components/charts/utils/chart-validation.js +292 -0
  32. package/dist/components/charts/utils/color-utils.js +175 -0
  33. package/dist/components/core/Accordion/Accordion.animations.js +45 -0
  34. package/dist/components/core/Accordion/Accordion.js +52 -0
  35. package/dist/components/core/Accordion/Accordion.theme.js +8 -0
  36. package/dist/components/core/Accordion/AccordionContent.js +25 -0
  37. package/dist/components/core/Accordion/AccordionItem.js +56 -0
  38. package/dist/components/core/Accordion/AccordionTrigger.js +32 -0
  39. package/dist/components/core/Accordion/index.js +5 -0
  40. package/dist/components/core/Avatar/Avatar.js +94 -0
  41. package/dist/components/core/Avatar/Avatar.theme.js +25 -0
  42. package/dist/components/core/AvatarGroup/AvatarGroup.animations.js +79 -0
  43. package/dist/components/core/AvatarGroup/AvatarGroup.js +67 -0
  44. package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +23 -0
  45. package/dist/components/core/Badge/Badge.animations.js +109 -0
  46. package/dist/components/core/Badge/Badge.js +101 -0
  47. package/dist/components/core/Badge/Badge.theme.js +41 -0
  48. package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +8 -8
  49. package/dist/components/core/Button/Button.theme.js +5 -5
  50. package/dist/components/core/Card/Card.js +46 -0
  51. package/dist/components/core/Card/Card.theme.js +5 -0
  52. package/dist/components/core/Divider/Divider.js +21 -0
  53. package/dist/components/core/Divider/Divider.theme.js +19 -0
  54. package/dist/components/core/Pagination/Pagination.js +113 -0
  55. package/dist/components/core/Pagination/Pagination.theme.js +27 -0
  56. package/dist/components/core/Segmented/Segmented.js +69 -0
  57. package/dist/components/core/Segmented/Segmented.theme.js +40 -0
  58. package/dist/components/core/Segmented/SegmentedContext.js +8 -0
  59. package/dist/components/core/Segmented/SegmentedItem.js +30 -0
  60. package/dist/components/core/Stepper/Stepper.js +57 -0
  61. package/dist/components/core/Stepper/Stepper.theme.js +9 -0
  62. package/dist/components/core/Stepper/components/ConnectorLine.js +42 -0
  63. package/dist/components/core/Stepper/components/IconCircle.js +44 -0
  64. package/dist/components/core/Stepper/components/ProgressIndicator.js +12 -0
  65. package/dist/components/core/Stepper/components/StepContent.js +36 -0
  66. package/dist/components/core/Stepper/components/StepperItem.js +22 -0
  67. package/dist/components/core/Tabs/Tabs.theme.js +2 -2
  68. package/dist/components/core/Tooltip/Tooltip.animations.js +46 -0
  69. package/dist/components/core/Tooltip/Tooltip.js +85 -0
  70. package/dist/components/core/Tooltip/Tooltip.theme.js +11 -0
  71. package/dist/components/core/Tooltip/useTooltipPositioning.js +59 -0
  72. package/dist/components/core/Tree/Tree.animations.js +38 -0
  73. package/dist/components/core/Tree/Tree.js +177 -0
  74. package/dist/components/core/Tree/Tree.theme.js +11 -0
  75. package/dist/components/data-display/Table/Table.js +177 -0
  76. package/dist/components/data-display/Table/Table.theme.js +28 -0
  77. package/dist/components/data-display/Table/Table.utils.js +28 -0
  78. package/dist/components/data-display/Table/components/DeclarativeComponents.js +123 -0
  79. package/dist/components/data-display/Table/components/TableActions/TableActions.js +56 -0
  80. package/dist/components/data-display/Table/components/TableActions/TableActionsMenu.js +29 -0
  81. package/dist/components/data-display/Table/components/TableColumnManager/TableColumnManager.js +85 -0
  82. package/dist/components/data-display/Table/components/TableColumnManager/TableColumnManager.theme.js +21 -0
  83. package/dist/components/data-display/Table/components/TablePagination/TablePagination.js +51 -0
  84. package/dist/components/data-display/Table/components/TableSelectionHeader/TableSelectionHeader.js +29 -0
  85. package/dist/components/data-display/Table/components/core/TableBody.js +32 -0
  86. package/dist/components/data-display/Table/components/core/TableCell.js +47 -0
  87. package/dist/components/data-display/Table/components/core/TableHeader.js +77 -0
  88. package/dist/components/data-display/Table/components/core/TableRow.js +46 -0
  89. package/dist/components/data-display/Table/index.js +20 -0
  90. package/dist/components/feedback/Alert/Alert.js +36 -0
  91. package/dist/components/feedback/Alert/Alert.theme.js +17 -0
  92. package/dist/components/feedback/ChatMessage/ChatMessage.js +26 -0
  93. package/dist/components/feedback/ChatMessage/ChatMessage.theme.js +16 -0
  94. package/dist/components/feedback/Empty/Empty.js +26 -0
  95. package/dist/components/feedback/Empty/Empty.theme.js +13 -0
  96. package/dist/components/feedback/Notification/Notification.js +41 -0
  97. package/dist/components/feedback/Notification/Notification.theme.js +49 -0
  98. package/dist/components/feedback/Spinner/Spinner.theme.js +3 -3
  99. package/dist/components/feedback/Toast/Toast.animations.js +58 -0
  100. package/dist/components/feedback/Toast/Toast.js +67 -0
  101. package/dist/components/feedback/Toast/Toast.theme.js +18 -0
  102. package/dist/components/feedback/Toast/ToastProvider.js +73 -0
  103. package/dist/components/feedback/Toast/useToast.js +91 -0
  104. package/dist/components/forms/Checkbox/Checkbox.theme.js +1 -1
  105. package/dist/components/forms/FormLabel/FormLabel.theme.js +2 -2
  106. package/dist/components/forms/Input/Input.theme.js +4 -4
  107. package/dist/components/forms/Radio/Radio.theme.js +2 -2
  108. package/dist/components/forms/Select/Select.js +1 -1
  109. package/dist/components/forms/Select/Select.theme.js +5 -5
  110. package/dist/components/forms/Switch/Switch.theme.js +1 -1
  111. package/dist/components/forms/TimePicker/TimePicker.theme.js +19 -19
  112. package/dist/components/forms/forms.theme.js +8 -8
  113. package/dist/components/navigation/NavItem/NavItem.js +93 -0
  114. package/dist/components/navigation/NavItem/NavItem.theme.js +27 -0
  115. package/dist/components/navigation/Sidebar/Sidebar.js +28 -0
  116. package/dist/components/navigation/Sidebar/Sidebar.theme.js +16 -0
  117. package/dist/components/navigation/Sidebar/SidebarContent.js +12 -0
  118. package/dist/components/navigation/Sidebar/SidebarContext.js +38 -0
  119. package/dist/components/navigation/Sidebar/SidebarFooter.js +11 -0
  120. package/dist/components/navigation/Sidebar/SidebarHeader.js +22 -0
  121. package/dist/components/navigation/Sidebar/SidebarNav.js +11 -0
  122. package/dist/components/navigation/Sidebar/SidebarNavGroup.js +19 -0
  123. package/dist/components/navigation/Sidebar/SidebarToggle.js +26 -0
  124. package/dist/icons/core/TickIcon.js +3 -1
  125. package/dist/index.d.ts +29 -4
  126. package/dist/index.js +64 -4
  127. package/dist/node_modules/@heroicons/react/20/solid/esm/ChevronDownIcon.js +26 -0
  128. package/dist/node_modules/@heroicons/react/24/outline/esm/ChevronDoubleLeftIcon.js +28 -0
  129. package/dist/node_modules/@heroicons/react/24/outline/esm/ChevronDoubleRightIcon.js +28 -0
  130. package/dist/node_modules/@heroicons/react/24/outline/esm/ChevronLeftIcon.js +28 -0
  131. package/dist/node_modules/@heroicons/react/24/outline/esm/Cog6ToothIcon.js +32 -0
  132. package/dist/node_modules/@heroicons/react/24/outline/esm/DocumentIcon.js +28 -0
  133. package/dist/node_modules/@heroicons/react/24/outline/esm/EllipsisVerticalIcon.js +28 -0
  134. package/dist/node_modules/@heroicons/react/24/outline/esm/PlusIcon.js +28 -0
  135. package/dist/node_modules/@heroicons/react/24/solid/esm/ArrowPathIcon.js +26 -0
  136. package/dist/node_modules/@heroicons/react/24/solid/esm/BellIcon.js +26 -0
  137. package/dist/node_modules/@heroicons/react/24/solid/esm/CheckCircleIcon.js +26 -0
  138. package/dist/node_modules/@heroicons/react/24/solid/esm/ExclamationTriangleIcon.js +26 -0
  139. package/dist/node_modules/@heroicons/react/24/solid/esm/InformationCircleIcon.js +26 -0
  140. package/dist/node_modules/@heroicons/react/24/solid/esm/XCircleIcon.js +26 -0
  141. package/dist/node_modules/@heroicons/react/24/solid/esm/XMarkIcon.js +26 -0
  142. package/dist/node_modules/tslib/tslib.es6.js +15 -1
  143. package/dist/utils/dateUtils.js +32 -0
  144. package/dist/utils/debounce.js +21 -0
  145. package/package.json +1 -1
  146. package/dist/styles.css +0 -2
@@ -0,0 +1,59 @@
1
+ import { useMemo, useCallback } from 'react';
2
+ import { validateChart, sanitizeChartData, calculateSafeScaleRange, SafeMath } from '../utils/chart-validation.js';
3
+
4
+ /**
5
+ * Hook for comprehensive chart validation and error handling
6
+ */
7
+ function useChartValidation(data, config, options) {
8
+ if (options === void 0) { options = {}; }
9
+ var _a = options.autoSanitize, autoSanitize = _a === void 0 ? true : _a, _b = options.logWarnings, logWarnings = _b === void 0 ? process.env.NODE_ENV === 'development' : _b, onValidationError = options.onValidationError, onValidationWarning = options.onValidationWarning;
10
+ // Memoized validation result
11
+ var validation = useMemo(function () {
12
+ var result = validateChart(data, config);
13
+ // Handle errors
14
+ if (result.errors.length > 0 && onValidationError) {
15
+ onValidationError(result.errors);
16
+ }
17
+ // Handle warnings
18
+ if (result.warnings.length > 0) {
19
+ if (logWarnings) {
20
+ console.warn('Chart validation warnings:', result.warnings);
21
+ }
22
+ if (onValidationWarning) {
23
+ onValidationWarning(result.warnings);
24
+ }
25
+ }
26
+ return result;
27
+ }, [data, config, onValidationError, onValidationWarning, logWarnings]);
28
+ // Sanitized data
29
+ var sanitizedData = useMemo(function () {
30
+ if (!autoSanitize || !Array.isArray(data)) {
31
+ return Array.isArray(data) ? data : [];
32
+ }
33
+ return sanitizeChartData(data);
34
+ }, [data, autoSanitize]);
35
+ // Safe scale calculation
36
+ var safeScale = useMemo(function () { return ({
37
+ calculateRange: function (options) {
38
+ var validData = autoSanitize ? sanitizedData : (Array.isArray(data) ? data : []);
39
+ var validConfig = (config && typeof config === 'object') ? config : {};
40
+ return calculateSafeScaleRange(validData, validConfig, options);
41
+ }
42
+ }); }, [sanitizedData, data, config, autoSanitize]);
43
+ // Manual revalidation trigger
44
+ var revalidate = useCallback(function () {
45
+ // This will trigger re-computation of the validation memoized value
46
+ // by updating a dependency (though in this case, we rely on the data/config changes)
47
+ }, []);
48
+ return {
49
+ validation: validation,
50
+ sanitizedData: sanitizedData,
51
+ isValid: validation.isValid,
52
+ hasWarnings: validation.warnings.length > 0,
53
+ safeScale: safeScale,
54
+ safeMath: SafeMath,
55
+ revalidate: revalidate,
56
+ };
57
+ }
58
+
59
+ export { useChartValidation };
@@ -0,0 +1,292 @@
1
+ import { __assign } from '../../../node_modules/tslib/tslib.es6.js';
2
+ import { useState, useRef, useEffect, useCallback } from 'react';
3
+
4
+ // Optimized animation frame throttle for smooth movement
5
+ function rafThrottle(func) {
6
+ var rafId = null;
7
+ var latestArgs = null;
8
+ var throttledFn = function () {
9
+ var args = [];
10
+ for (var _i = 0; _i < arguments.length; _i++) {
11
+ args[_i] = arguments[_i];
12
+ }
13
+ latestArgs = args;
14
+ if (rafId === null) {
15
+ rafId = requestAnimationFrame(function () {
16
+ if (latestArgs) {
17
+ func.apply(void 0, latestArgs);
18
+ }
19
+ rafId = null;
20
+ latestArgs = null;
21
+ });
22
+ }
23
+ };
24
+ // Add cleanup method
25
+ throttledFn.cancel = function () {
26
+ if (rafId !== null) {
27
+ cancelAnimationFrame(rafId);
28
+ rafId = null;
29
+ latestArgs = null;
30
+ }
31
+ };
32
+ return throttledFn;
33
+ }
34
+ function useTooltipPosition(_a) {
35
+ var containerRef = _a.containerRef, _b = _a.padding, padding = _b === void 0 ? 10 : _b, _c = _a.offset, offset = _c === void 0 ? 15 : _c, _d = _a.isMobile, isMobile = _d === void 0 ? false : _d, _e = _a.animation, animation = _e === void 0 ? {
36
+ duration: 0.08,
37
+ ease: "easeOut",
38
+ enabled: true,
39
+ } : _e;
40
+ var _f = useState(null), tooltipData = _f[0], setTooltipData = _f[1];
41
+ var tooltipRef = useRef(null);
42
+ var isUnmountedRef = useRef(false);
43
+ // Track component mount status to prevent state updates after unmount
44
+ useEffect(function () {
45
+ isUnmountedRef.current = false;
46
+ return function () {
47
+ isUnmountedRef.current = true;
48
+ };
49
+ }, []);
50
+ /**
51
+ * Safe state setter that checks if component is still mounted
52
+ * Supports both direct values and function updates like React.setState
53
+ */
54
+ var safeSetTooltipData = useCallback(function (data) {
55
+ if (!isUnmountedRef.current) {
56
+ setTooltipData(function (prevData) {
57
+ if (typeof data === 'function') {
58
+ return data(prevData);
59
+ }
60
+ return data;
61
+ });
62
+ }
63
+ }, []);
64
+ /**
65
+ * Calculate bounded position within container with simplified logic
66
+ */
67
+ var calculateBoundedPosition = useCallback(function (x, y, tooltipWidth, tooltipHeight) {
68
+ if (tooltipWidth === void 0) { tooltipWidth = 0; }
69
+ if (tooltipHeight === void 0) { tooltipHeight = 0; }
70
+ if (!containerRef.current)
71
+ return { x: x, y: y };
72
+ try {
73
+ var containerRect = containerRef.current.getBoundingClientRect();
74
+ var viewportWidth = window.innerWidth;
75
+ var viewportHeight = window.innerHeight;
76
+ var boundedX = x;
77
+ var boundedY = y;
78
+ // Simple X positioning: try right, then left, then clamp
79
+ if (boundedX + tooltipWidth + padding > Math.min(containerRect.right, viewportWidth)) {
80
+ // Try positioning to the left of cursor
81
+ boundedX = x - tooltipWidth - offset;
82
+ }
83
+ // Ensure it doesn't go off the left edge
84
+ boundedX = Math.max(Math.max(containerRect.left, 0) + padding, boundedX);
85
+ // Final clamp to viewport
86
+ boundedX = Math.min(boundedX, viewportWidth - tooltipWidth - padding);
87
+ // Simple Y positioning: try below, then above, then clamp
88
+ if (boundedY + tooltipHeight + padding > Math.min(containerRect.bottom, viewportHeight)) {
89
+ // Try positioning above cursor
90
+ boundedY = y - tooltipHeight - offset;
91
+ }
92
+ // Ensure it doesn't go off the top edge
93
+ boundedY = Math.max(Math.max(containerRect.top, 0) + padding, boundedY);
94
+ // Final clamp to viewport
95
+ boundedY = Math.min(boundedY, viewportHeight - tooltipHeight - padding);
96
+ return { x: boundedX, y: boundedY };
97
+ }
98
+ catch (error) {
99
+ console.warn('Error calculating tooltip position:', error);
100
+ return { x: x, y: y };
101
+ }
102
+ }, [containerRef, padding, offset]);
103
+ /**
104
+ * Get tooltip position for mouse events with stable positioning
105
+ */
106
+ var getMouseTooltipPosition = useCallback(function (event) {
107
+ var _a, _b;
108
+ // Use page coordinates to avoid scroll issues
109
+ var x = event.clientX;
110
+ var y = event.clientY - offset;
111
+ // Get current tooltip dimensions or use estimated defaults
112
+ var tooltipWidth = ((_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 200; // reasonable default
113
+ var tooltipHeight = ((_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.offsetHeight) || 60; // reasonable default
114
+ return calculateBoundedPosition(x, y, tooltipWidth, tooltipHeight);
115
+ }, [calculateBoundedPosition, offset]);
116
+ /**
117
+ * Get tooltip position for SVG elements (mobile/touch)
118
+ */
119
+ var getSVGTooltipPosition = useCallback(function (event, svgX, svgY, actualDimensions) {
120
+ var _a, _b;
121
+ try {
122
+ var svgElement = event.currentTarget.closest('svg');
123
+ var svgRect = svgElement === null || svgElement === void 0 ? void 0 : svgElement.getBoundingClientRect();
124
+ if (!svgRect || !actualDimensions.width || !actualDimensions.height) {
125
+ console.warn('SVG positioning fallback: missing SVG rect or dimensions');
126
+ return getMouseTooltipPosition(event);
127
+ }
128
+ // Calculate scale factors using actual dimensions
129
+ var scaleX = svgRect.width / actualDimensions.width;
130
+ var scaleY = svgRect.height / actualDimensions.height;
131
+ // Convert SVG coordinates to screen coordinates
132
+ var screenX_1 = svgRect.left + svgX * scaleX;
133
+ var screenY_1 = svgRect.top + svgY * scaleY;
134
+ var x = screenX_1;
135
+ var y = screenY_1 - offset;
136
+ var tooltipWidth = ((_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 200;
137
+ var tooltipHeight = ((_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.offsetHeight) || 60;
138
+ return calculateBoundedPosition(x, y, tooltipWidth, tooltipHeight);
139
+ }
140
+ catch (error) {
141
+ console.warn('Error in SVG tooltip positioning:', error);
142
+ return getMouseTooltipPosition(event);
143
+ }
144
+ }, [calculateBoundedPosition, getMouseTooltipPosition, offset]);
145
+ /**
146
+ * Show tooltip with content and position
147
+ */
148
+ var showTooltip = useCallback(function (content, position) {
149
+ safeSetTooltipData({
150
+ x: position.x,
151
+ y: position.y,
152
+ content: content,
153
+ });
154
+ }, [safeSetTooltipData]);
155
+ /**
156
+ * Update tooltip position (for mouse move events)
157
+ */
158
+ var updateTooltipPosition = useCallback(function (position) {
159
+ safeSetTooltipData(function (prev) {
160
+ return prev ? __assign(__assign({}, prev), { x: position.x, y: position.y }) : null;
161
+ });
162
+ }, [safeSetTooltipData]);
163
+ // Create RAF-throttled version of updateTooltipPosition for smooth movement
164
+ var rafThrottledUpdateRef = useRef(null);
165
+ var rafThrottledUpdate = useCallback(function (position) {
166
+ if (!isUnmountedRef.current) {
167
+ updateTooltipPosition(position);
168
+ }
169
+ }, [updateTooltipPosition]);
170
+ // Initialize RAF throttling
171
+ useEffect(function () {
172
+ rafThrottledUpdateRef.current = rafThrottle(rafThrottledUpdate);
173
+ return function () {
174
+ var _a;
175
+ if ((_a = rafThrottledUpdateRef.current) === null || _a === void 0 ? void 0 : _a.cancel) {
176
+ rafThrottledUpdateRef.current.cancel();
177
+ }
178
+ };
179
+ }, [rafThrottledUpdate]);
180
+ /**
181
+ * Hide tooltip and cancel any pending updates
182
+ */
183
+ var hideTooltip = useCallback(function () {
184
+ var _a;
185
+ // Cancel any pending RAF updates
186
+ if ((_a = rafThrottledUpdateRef.current) === null || _a === void 0 ? void 0 : _a.cancel) {
187
+ rafThrottledUpdateRef.current.cancel();
188
+ }
189
+ safeSetTooltipData(null);
190
+ }, [safeSetTooltipData]);
191
+ /**
192
+ * Handle mouse enter for chart elements
193
+ */
194
+ var handleMouseEnter = useCallback(function (event, content, svgCoordinates) {
195
+ try {
196
+ var position = void 0;
197
+ if (isMobile && svgCoordinates) {
198
+ position = getSVGTooltipPosition(event, svgCoordinates.x, svgCoordinates.y, svgCoordinates.dimensions);
199
+ }
200
+ else {
201
+ position = getMouseTooltipPosition(event);
202
+ }
203
+ showTooltip(content, position);
204
+ }
205
+ catch (error) {
206
+ console.warn('Error handling mouse enter:', error);
207
+ }
208
+ }, [isMobile, getSVGTooltipPosition, getMouseTooltipPosition, showTooltip]);
209
+ /**
210
+ * Handle mouse move with optimized RAF throttling for smooth movement
211
+ */
212
+ var handleMouseMove = useCallback(function (event, svgCoordinates) {
213
+ if (!tooltipData)
214
+ return;
215
+ try {
216
+ // Always use mouse position for consistent movement
217
+ var position = getMouseTooltipPosition(event);
218
+ if (rafThrottledUpdateRef.current) {
219
+ rafThrottledUpdateRef.current(position);
220
+ }
221
+ else {
222
+ // Fallback to direct update
223
+ updateTooltipPosition(position);
224
+ }
225
+ }
226
+ catch (error) {
227
+ console.warn('Error handling mouse move:', error);
228
+ }
229
+ }, [tooltipData, getMouseTooltipPosition, updateTooltipPosition]);
230
+ /**
231
+ * Handle mouse leave for chart elements
232
+ */
233
+ var handleMouseLeave = useCallback(function () {
234
+ hideTooltip();
235
+ }, [hideTooltip]);
236
+ // Update tooltip position when container resizes (simplified)
237
+ useEffect(function () {
238
+ if (!tooltipData || !containerRef.current)
239
+ return;
240
+ var handleResize = function () {
241
+ if (tooltipData && tooltipRef.current && !isUnmountedRef.current) {
242
+ try {
243
+ var tooltipWidth = tooltipRef.current.offsetWidth;
244
+ var tooltipHeight = tooltipRef.current.offsetHeight;
245
+ var newPosition = calculateBoundedPosition(tooltipData.x, tooltipData.y, tooltipWidth, tooltipHeight);
246
+ // Use direct update for resize, not RAF throttled
247
+ updateTooltipPosition(newPosition);
248
+ }
249
+ catch (error) {
250
+ console.warn('Error updating tooltip position on resize:', error);
251
+ }
252
+ }
253
+ };
254
+ // Use window resize instead of ResizeObserver for better performance
255
+ window.addEventListener('resize', handleResize);
256
+ return function () {
257
+ window.removeEventListener('resize', handleResize);
258
+ };
259
+ }, [tooltipData, containerRef, calculateBoundedPosition, updateTooltipPosition]);
260
+ return {
261
+ tooltipData: tooltipData,
262
+ tooltipRef: tooltipRef,
263
+ showTooltip: showTooltip,
264
+ hideTooltip: hideTooltip,
265
+ updateTooltipPosition: updateTooltipPosition,
266
+ handleMouseEnter: handleMouseEnter,
267
+ handleMouseMove: handleMouseMove,
268
+ handleMouseLeave: handleMouseLeave,
269
+ getMouseTooltipPosition: getMouseTooltipPosition,
270
+ getSVGTooltipPosition: getSVGTooltipPosition,
271
+ // Animation configuration for the consuming component
272
+ animationConfig: {
273
+ animate: tooltipData ? { x: tooltipData.x, y: tooltipData.y, opacity: 1 } : { opacity: 0 },
274
+ transition: animation.enabled ? {
275
+ duration: animation.duration,
276
+ ease: animation.ease,
277
+ // Reduce layout thrashing by using transform instead of changing x/y directly
278
+ type: "tween",
279
+ } : { duration: 0 },
280
+ initial: { opacity: 0 },
281
+ style: tooltipData ? {
282
+ position: 'fixed',
283
+ left: 0,
284
+ top: 0,
285
+ transform: "translate(".concat(tooltipData.x, "px, ").concat(tooltipData.y, "px)"),
286
+ willChange: 'transform, opacity', // Optimize for animations
287
+ } : {},
288
+ },
289
+ };
290
+ }
291
+
292
+ export { useTooltipPosition };
@@ -0,0 +1,30 @@
1
+ import React__default from 'react';
2
+ import { cn } from '../../../../utils/cn.js';
3
+ import { ChartText } from '../ChartText/ChartText.js';
4
+
5
+ /**
6
+ * XAxis component for charts
7
+ * Renders horizontal axis with labels and optional tick marks
8
+ */
9
+ var XAxis = function (_a) {
10
+ var data = _a.data, x = _a.x, y = _a.y, width = _a.width, categoryWidth = _a.categoryWidth, _b = _a.categoryGap, categoryGap = _b === void 0 ? 0 : _b, _c = _a.show, show = _c === void 0 ? true : _c, className = _a.className, _d = _a.color, color = _d === void 0 ? 'currentColor' : _d, _e = _a.showTicks, showTicks = _e === void 0 ? true : _e, _f = _a.tickLength, tickLength = _f === void 0 ? 6 : _f, _g = _a.tickPadding, tickPadding = _g === void 0 ? 12 : _g, _h = _a.textAnchor, textAnchor = _h === void 0 ? 'middle' : _h, _j = _a.labelRotation, labelRotation = _j === void 0 ? 0 : _j, labelFormatter = _a.labelFormatter, _k = _a.maxLabelWidth, maxLabelWidth = _k === void 0 ? 100 : _k;
11
+ if (!show)
12
+ return null;
13
+ var formatLabel = function (item, index) {
14
+ if (labelFormatter) {
15
+ return labelFormatter(item, index);
16
+ }
17
+ return item.name || item.label || String(index);
18
+ };
19
+ return (React__default.createElement("g", { className: cn('chart-x-axis', className) },
20
+ React__default.createElement("line", { x1: x, y1: y, x2: x + width, y2: y, stroke: color, className: "opacity-20", strokeWidth: 1 }),
21
+ data.map(function (item, index) {
22
+ var tickX = x + index * (categoryWidth + categoryGap) + categoryWidth / 2;
23
+ var label = formatLabel(item, index);
24
+ return (React__default.createElement("g", { key: index },
25
+ showTicks && (React__default.createElement("line", { x1: tickX, y1: y, x2: tickX, y2: y + tickLength, stroke: color, className: "opacity-40", strokeWidth: 1 })),
26
+ React__default.createElement(ChartText, { x: tickX, y: y + tickLength + tickPadding, textAnchor: textAnchor, maxWidth: maxLabelWidth, truncate: !!maxLabelWidth, rotation: labelRotation }, label)));
27
+ })));
28
+ };
29
+
30
+ export { XAxis };
@@ -0,0 +1,97 @@
1
+ import React__default from 'react';
2
+ import { cn } from '../../../../utils/cn.js';
3
+ import { ChartText } from '../ChartText/ChartText.js';
4
+
5
+ /**
6
+ * YAxis component for charts
7
+ * Renders vertical axis with labels, optional tick marks, and grid lines
8
+ */
9
+ var YAxis = function (_a) {
10
+ var min = _a.min, max = _a.max, _b = _a.tickCount, tickCount = _b === void 0 ? 5 : _b, x = _a.x, y = _a.y, height = _a.height, _c = _a.show, show = _c === void 0 ? true : _c, className = _a.className, _d = _a.color, color = _d === void 0 ? 'currentColor' : _d, _e = _a.showTicks, showTicks = _e === void 0 ? true : _e, _f = _a.tickLength, tickLength = _f === void 0 ? 6 : _f, _g = _a.tickPadding, tickPadding = _g === void 0 ? 8 : _g, _h = _a.textAnchor, textAnchor = _h === void 0 ? 'end' : _h, tickFormatter = _a.tickFormatter, _j = _a.showGrid, showGrid = _j === void 0 ? false : _j, _k = _a.gridWidth, gridWidth = _k === void 0 ? 0 : _k, customTicks = _a.ticks;
11
+ if (!show)
12
+ return null;
13
+ // Generate tick values
14
+ var generateTicks = function () {
15
+ if (customTicks)
16
+ return customTicks;
17
+ if (tickCount <= 1)
18
+ return [min];
19
+ var range = max - min;
20
+ // For small ranges (like 0-100), use round numbers
21
+ if (range <= 100) {
22
+ var step_1 = Math.ceil(range / (tickCount - 1) / 5) * 5; // Round to nearest 5
23
+ var ticks_1 = [];
24
+ for (var i = 0; i < tickCount; i++) {
25
+ var value = min + i * step_1;
26
+ if (value <= max) {
27
+ ticks_1.push(value);
28
+ }
29
+ }
30
+ // Always include max if it's not already included
31
+ if (ticks_1[ticks_1.length - 1] < max) {
32
+ ticks_1.push(max);
33
+ }
34
+ return ticks_1;
35
+ }
36
+ // For larger ranges, use smarter step calculation
37
+ var roughStep = range / (tickCount - 1);
38
+ var step;
39
+ if (roughStep >= 1000) {
40
+ step = Math.ceil(roughStep / 1000) * 1000;
41
+ }
42
+ else if (roughStep >= 100) {
43
+ step = Math.ceil(roughStep / 100) * 100;
44
+ }
45
+ else if (roughStep >= 10) {
46
+ step = Math.ceil(roughStep / 10) * 10;
47
+ }
48
+ else {
49
+ step = Math.ceil(roughStep);
50
+ }
51
+ var ticks = [];
52
+ for (var i = 0; i <= tickCount; i++) {
53
+ var value = min + i * step;
54
+ if (value <= max) {
55
+ ticks.push(value);
56
+ }
57
+ }
58
+ return ticks;
59
+ };
60
+ var ticks = generateTicks();
61
+ var formatTick = function (value) {
62
+ if (tickFormatter) {
63
+ return tickFormatter(value);
64
+ }
65
+ // Default formatting - prioritize whole numbers
66
+ if (Math.abs(value) >= 1000000) {
67
+ return "".concat(Math.round(value / 1000000), "M");
68
+ }
69
+ else if (Math.abs(value) >= 1000) {
70
+ return "".concat(Math.round(value / 1000), "K");
71
+ }
72
+ else if (Number.isInteger(value) || Math.abs(value - Math.round(value)) < 0.01) {
73
+ return Math.round(value).toString();
74
+ }
75
+ else {
76
+ return value.toFixed(1);
77
+ }
78
+ };
79
+ var getTickY = function (value) {
80
+ if (max === min) {
81
+ return y + height / 2; // Center position when no range
82
+ }
83
+ var ratio = (value - min) / (max - min);
84
+ return y + height - (ratio * height);
85
+ };
86
+ return (React__default.createElement("g", { className: cn('chart-y-axis', className) },
87
+ React__default.createElement("line", { x1: x, y1: y, x2: x, y2: y + height, stroke: color, className: "opacity-10", strokeWidth: 1 }),
88
+ ticks.map(function (tick, index) {
89
+ var tickY = getTickY(tick);
90
+ return (React__default.createElement("g", { key: index },
91
+ showGrid && gridWidth > 0 && (React__default.createElement("line", { x1: x, y1: tickY, x2: x + gridWidth, y2: tickY, stroke: color, className: "opacity-10", strokeWidth: 1 })),
92
+ showTicks && (React__default.createElement("line", { x1: x - tickLength, y1: tickY, x2: x, y2: tickY, stroke: color, className: "opacity-40", strokeWidth: 1 })),
93
+ React__default.createElement(ChartText, { x: x - tickLength - tickPadding, y: tickY, textAnchor: textAnchor, dominantBaseline: "middle" }, formatTick(tick))));
94
+ })));
95
+ };
96
+
97
+ export { YAxis };
@@ -0,0 +1,35 @@
1
+ import React__default from 'react';
2
+ import { cn } from '../../../../utils/cn.js';
3
+ import { chartCrosshairTheme } from './ChartCrosshair.theme.js';
4
+ import { AnimatePresence } from '../../../../node_modules/framer-motion/dist/es/components/AnimatePresence/index.js';
5
+ import { motion } from '../../../../node_modules/framer-motion/dist/es/render/components/motion/proxy.js';
6
+
7
+ /**
8
+ * ChartCrosshair component for rendering crosshair lines in charts
9
+ * Supports both vertical and horizontal lines with smooth Framer Motion transitions
10
+ */
11
+ var ChartCrosshair = function (_a) {
12
+ var show = _a.show, x = _a.x, y = _a.y, margin = _a.margin, innerWidth = _a.innerWidth, innerHeight = _a.innerHeight, _b = _a.showHorizontal, showHorizontal = _b === void 0 ? false : _b, _c = _a.strokeColor, strokeColor = _c === void 0 ? "#6b7280" : _c, _d = _a.strokeWidth, strokeWidth = _d === void 0 ? 1 : _d, _e = _a.strokeDasharray, strokeDasharray = _e === void 0 ? "4 4" : _e, _f = _a.opacity, opacity = _f === void 0 ? 0.4 : _f, className = _a.className;
13
+ var theme = chartCrosshairTheme;
14
+ var baseClasses = cn(theme.baseStyle, className);
15
+ return (React__default.createElement(AnimatePresence, null, show && (React__default.createElement(motion.g, { className: "chart-crosshair", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: {
16
+ duration: 0.3,
17
+ ease: "easeInOut"
18
+ } },
19
+ React__default.createElement(motion.line, { x1: x, y1: margin.top, x2: x, y2: margin.top + innerHeight, stroke: strokeColor, strokeWidth: strokeWidth, strokeDasharray: strokeDasharray, opacity: opacity, className: cn(baseClasses, theme.verticalLine), animate: {
20
+ x1: x,
21
+ x2: x
22
+ }, transition: {
23
+ duration: 0.2,
24
+ ease: "easeOut"
25
+ } }),
26
+ showHorizontal && y !== undefined && (React__default.createElement(motion.line, { x1: margin.left, y1: y, x2: margin.left + innerWidth, y2: y, stroke: strokeColor, strokeWidth: strokeWidth, strokeDasharray: strokeDasharray, opacity: opacity, className: cn(baseClasses, theme.horizontalLine), animate: {
27
+ y1: y,
28
+ y2: y
29
+ }, transition: {
30
+ duration: 0.2,
31
+ ease: "easeOut"
32
+ } }))))));
33
+ };
34
+
35
+ export { ChartCrosshair };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Default theme for ChartCrosshair component
3
+ * Provides consistent styling for chart crosshair lines with Framer Motion animations
4
+ */
5
+ var chartCrosshairTheme = {
6
+ baseStyle: "pointer-events-none",
7
+ verticalLine: "stroke-gray-500",
8
+ horizontalLine: "stroke-gray-500",
9
+ };
10
+
11
+ export { chartCrosshairTheme };
@@ -0,0 +1,66 @@
1
+ import { __extends } from '../../../../node_modules/tslib/tslib.es6.js';
2
+ import React__default, { Component } from 'react';
3
+ import { cn } from '../../../../utils/cn.js';
4
+
5
+ /**
6
+ * Error boundary specifically designed for chart components
7
+ * Provides graceful error handling and fallback UI
8
+ */
9
+ var ChartErrorBoundary = /** @class */ (function (_super) {
10
+ __extends(ChartErrorBoundary, _super);
11
+ function ChartErrorBoundary(props) {
12
+ var _this = _super.call(this, props) || this;
13
+ _this.state = { hasError: false };
14
+ return _this;
15
+ }
16
+ ChartErrorBoundary.getDerivedStateFromError = function (error) {
17
+ return {
18
+ hasError: true,
19
+ error: error,
20
+ };
21
+ };
22
+ ChartErrorBoundary.prototype.componentDidCatch = function (error, errorInfo) {
23
+ this.setState({
24
+ error: error,
25
+ errorInfo: errorInfo,
26
+ });
27
+ // Call optional error handler
28
+ if (this.props.onError) {
29
+ this.props.onError(error, errorInfo);
30
+ }
31
+ // Log error in development
32
+ if (process.env.NODE_ENV === 'development') {
33
+ console.error('Chart Error Boundary caught an error:', error, errorInfo);
34
+ }
35
+ };
36
+ ChartErrorBoundary.prototype.render = function () {
37
+ var _this = this;
38
+ var _a;
39
+ if (this.state.hasError) {
40
+ // Use custom fallback if provided
41
+ if (this.props.fallback) {
42
+ return this.props.fallback;
43
+ }
44
+ // Default error UI
45
+ return (React__default.createElement("div", { className: cn("flex flex-col items-center justify-center p-6 border border-danger-200 bg-danger-50 rounded-lg text-center", this.props.className), role: "alert", "aria-live": "polite" },
46
+ React__default.createElement("div", { className: "flex items-center gap-2 mb-2" },
47
+ React__default.createElement("svg", { className: "w-5 h-5 text-danger-500", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" },
48
+ React__default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" })),
49
+ React__default.createElement("h3", { className: "text-sm font-medium text-danger-800" }, "Chart Error")),
50
+ React__default.createElement("p", { className: "text-sm text-danger-600 mb-3" }, "Unable to render chart due to an error"),
51
+ this.props.showErrorDetails && this.state.error && (React__default.createElement("details", { className: "w-full" },
52
+ React__default.createElement("summary", { className: "text-xs text-danger-500 cursor-pointer hover:text-danger-700 mb-2" }, "Show error details"),
53
+ React__default.createElement("div", { className: "text-left bg-danger-100 p-3 rounded border text-xs font-mono text-danger-800 overflow-auto max-h-32" },
54
+ React__default.createElement("div", { className: "font-semibold mb-1" }, "Error:"),
55
+ React__default.createElement("div", { className: "mb-2" }, this.state.error.message),
56
+ ((_a = this.state.errorInfo) === null || _a === void 0 ? void 0 : _a.componentStack) && (React__default.createElement(React__default.Fragment, null,
57
+ React__default.createElement("div", { className: "font-semibold mb-1" }, "Component Stack:"),
58
+ React__default.createElement("pre", { className: "whitespace-pre-wrap text-xs" }, this.state.errorInfo.componentStack)))))),
59
+ React__default.createElement("button", { onClick: function () { return _this.setState({ hasError: false, error: undefined, errorInfo: undefined }); }, className: "mt-3 px-3 py-1 text-xs bg-danger-600 text-white rounded hover:bg-danger-700 transition-colors" }, "Try Again")));
60
+ }
61
+ return this.props.children;
62
+ };
63
+ return ChartErrorBoundary;
64
+ }(Component));
65
+
66
+ export { ChartErrorBoundary };
@@ -0,0 +1,22 @@
1
+ import React__default from 'react';
2
+ import { cn } from '../../../../utils/cn.js';
3
+
4
+ /**
5
+ * HorizontalGrid component for charts
6
+ * Renders horizontal grid lines at specified intervals
7
+ */
8
+ var HorizontalGrid = function (_a) {
9
+ var x = _a.x, y = _a.y, width = _a.width, height = _a.height, _b = _a.lineCount, lineCount = _b === void 0 ? 5 : _b, _c = _a.show, show = _c === void 0 ? true : _c, _d = _a.color, color = _d === void 0 ? 'currentColor' : _d, className = _a.className, tickPositions = _a.tickPositions;
10
+ if (!show)
11
+ return null;
12
+ // Generate grid line positions
13
+ var positions = tickPositions ||
14
+ Array.from({ length: lineCount }, function (_, i) {
15
+ if (lineCount <= 1)
16
+ return y;
17
+ return y + (i * height) / (lineCount - 1);
18
+ });
19
+ return (React__default.createElement("g", { className: cn('chart-horizontal-grid', className) }, positions.map(function (lineY, index) { return (React__default.createElement("line", { key: index, x1: x, y1: lineY, x2: x + width, y2: lineY, stroke: color, className: "opacity-10", strokeWidth: 1 })); })));
20
+ };
21
+
22
+ export { HorizontalGrid };
@@ -0,0 +1,30 @@
1
+ import { __rest, __assign } from '../../../../node_modules/tslib/tslib.es6.js';
2
+ import React__default from 'react';
3
+
4
+ /**
5
+ * Basic ChartLegend component - minimal implementation
6
+ * TODO: Enhance with full legend functionality when needed
7
+ */
8
+ var ChartLegend = function (_a) {
9
+ var content = _a.content, className = _a.className, wrapperStyle = _a.wrapperStyle, _b = _a.layout, layout = _b === void 0 ? 'horizontal' : _b, _c = _a.align, align = _c === void 0 ? 'center' : _c, _d = _a.verticalAlign, verticalAlign = _d === void 0 ? 'bottom' : _d, props = __rest(_a, ["content", "className", "wrapperStyle", "layout", "align", "verticalAlign"]);
10
+ if (!content) {
11
+ return null;
12
+ }
13
+ var alignClasses = {
14
+ left: 'justify-start',
15
+ center: 'justify-center',
16
+ right: 'justify-end',
17
+ };
18
+ var verticalAlignClasses = {
19
+ top: 'items-start',
20
+ middle: 'items-center',
21
+ bottom: 'items-end',
22
+ };
23
+ var layoutClasses = {
24
+ horizontal: 'flex-row',
25
+ vertical: 'flex-col',
26
+ };
27
+ return (React__default.createElement("div", __assign({ className: "flex ".concat(layoutClasses[layout], " ").concat(alignClasses[align], " ").concat(verticalAlignClasses[verticalAlign], " ").concat(className || ''), style: wrapperStyle }, props), content));
28
+ };
29
+
30
+ export { ChartLegend };