@flikk/ui 1.0.0-beta.30 → 1.0.0-beta.31
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/CHANGELOG.md +97 -0
- package/dist/components/ai/AgentStatus/AgentStatus.d.ts +3 -0
- package/dist/components/ai/AgentStatus/AgentStatus.js +144 -0
- package/dist/components/ai/AgentStatus/AgentStatus.theme.d.ts +2 -0
- package/dist/components/ai/AgentStatus/AgentStatus.theme.js +37 -0
- package/dist/components/ai/AgentStatus/AgentStatus.types.d.ts +116 -0
- package/dist/components/ai/AgentStatus/index.d.ts +3 -0
- package/dist/components/ai/CodeBlock/CodeBlock.js +3 -3
- package/dist/components/ai/CodeBlock/CodeBlock.theme.js +1 -1
- package/dist/components/ai/PromptInput/PromptInput.js +13 -14
- package/dist/components/ai/PromptInput/PromptInput.theme.js +1 -1
- package/dist/components/ai/PromptInput/VoiceRecorder.js +3 -3
- package/dist/components/ai/Reasoning/Reasoning.d.ts +5 -0
- package/dist/components/ai/Reasoning/Reasoning.js +16 -0
- package/dist/components/ai/Reasoning/Reasoning.types.d.ts +20 -0
- package/dist/components/ai/Reasoning/index.d.ts +2 -0
- package/dist/components/ai/SourceCitation/SourceCitation.d.ts +4 -0
- package/dist/components/ai/SourceCitation/SourceCitation.js +29 -0
- package/dist/components/ai/SourceCitation/SourceCitation.theme.d.ts +2 -0
- package/dist/components/ai/SourceCitation/SourceCitation.theme.js +23 -0
- package/dist/components/ai/SourceCitation/SourceCitation.types.d.ts +55 -0
- package/dist/components/ai/SourceCitation/index.d.ts +3 -0
- package/dist/components/ai/StreamingResponse/ErrorDisplay.js +2 -2
- package/dist/components/ai/StreamingResponse/StreamingResponse.js +1 -3
- package/dist/components/ai/StreamingResponse/StreamingResponse.theme.js +3 -1
- package/dist/components/ai/TokenCounter/TokenCounter.js +2 -2
- package/dist/components/ai/index.d.ts +3 -0
- package/dist/components/ai/index.js +6 -3
- package/dist/components/ai/shared/StatusIndicator.d.ts +8 -0
- package/dist/components/ai/shared/StatusIndicator.js +34 -0
- package/dist/components/canvas/CanvasToolbar.js +2 -2
- package/dist/components/canvas/NodeControls.js +2 -2
- package/dist/components/canvas/NodeRenderer.js +2 -2
- package/dist/components/charts/ActivityRings/ActivityRings.js +2 -2
- package/dist/components/charts/AreaChart/AreaChart.js +21 -32
- package/dist/components/charts/AreaChart/AreaChart.theme.d.ts +1 -6
- package/dist/components/charts/AreaChart/AreaChart.theme.js +7 -19
- package/dist/components/charts/AreaChart/AreaChart.types.d.ts +18 -11
- package/dist/components/charts/AreaChart/AreaChart.types.js +10 -3
- package/dist/components/charts/AreaChart/index.d.ts +1 -1
- package/dist/components/charts/BarChart/BarChart.js +9 -28
- package/dist/components/charts/BarChart/BarChart.types.d.ts +20 -16
- package/dist/components/charts/BarChart/BarChart.types.js +11 -4
- package/dist/components/charts/ComboChart/BarRenderer.js +8 -5
- package/dist/components/charts/ComboChart/ComboChart.js +11 -24
- package/dist/components/charts/ComboChart/ComboChart.types.d.ts +15 -13
- package/dist/components/charts/ComboChart/ComboChart.types.js +14 -2
- package/dist/components/charts/ComboChart/LineRenderer.js +15 -10
- package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.d.ts +16 -0
- package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.js +237 -0
- package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.types.d.ts +62 -0
- package/dist/components/charts/HorizontalBarChart/HorizontalBarChart.types.js +21 -0
- package/dist/components/charts/HorizontalBarChart/index.d.ts +3 -0
- package/dist/components/charts/LineChart/LineChart.js +9 -26
- package/dist/components/charts/LineChart/LineChart.types.d.ts +11 -14
- package/dist/components/charts/LineChart/LineChart.types.js +11 -3
- package/dist/components/charts/LollipopChart/LollipopChart.d.ts +3 -0
- package/dist/components/charts/LollipopChart/LollipopChart.js +361 -0
- package/dist/components/charts/LollipopChart/LollipopChart.types.d.ts +42 -0
- package/dist/components/charts/LollipopChart/LollipopChart.types.js +12 -0
- package/dist/components/charts/LollipopChart/index.d.ts +3 -0
- package/dist/components/charts/ScatterPlot/ScatterPlot.js +5 -4
- package/dist/components/charts/ScatterPlot/ScatterPlot.types.d.ts +14 -19
- package/dist/components/charts/ScatterPlot/ScatterPlot.types.js +9 -2
- package/dist/components/charts/StackedBarChart/StackedBarChart.js +150 -132
- package/dist/components/charts/StackedBarChart/StackedBarChart.types.d.ts +20 -18
- package/dist/components/charts/StackedBarChart/StackedBarChart.types.js +10 -4
- package/dist/components/charts/hooks/useChartAccessibility.d.ts +1 -1
- package/dist/components/charts/hooks/useChartAccessibility.js +3 -0
- package/dist/components/charts/hooks/useTooltipPosition.js +18 -6
- package/dist/components/charts/index.d.ts +6 -0
- package/dist/components/charts/index.js +6 -0
- package/dist/components/charts/shared/ChartAxis/CategoryYAxis.d.ts +14 -0
- package/dist/components/charts/shared/ChartAxis/CategoryYAxis.js +35 -0
- package/dist/components/charts/shared/ChartAxis/ChartAxis.types.d.ts +69 -8
- package/dist/components/charts/shared/ChartAxis/ValueXAxis.d.ts +14 -0
- package/dist/components/charts/shared/ChartAxis/ValueXAxis.js +64 -0
- package/dist/components/charts/shared/ChartAxis/XAxis.js +1 -1
- package/dist/components/charts/shared/ChartAxis/YAxis.js +2 -2
- package/dist/components/charts/shared/ChartAxis/index.d.ts +3 -1
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.d.ts +0 -2
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +1 -1
- package/dist/components/charts/shared/ChartGrid/VerticalGrid.d.ts +29 -0
- package/dist/components/charts/shared/ChartGrid/VerticalGrid.js +26 -0
- package/dist/components/charts/shared/ChartGrid/index.d.ts +2 -0
- package/dist/components/charts/shared/ChartMarker/ChartMarker.js +7 -1
- package/dist/components/charts/theme/chart.theme.js +18 -23
- package/dist/components/charts/types/chart.types.d.ts +9 -5
- package/dist/components/charts/types/chart.types.js +1 -7
- package/dist/components/charts/utils/animation-utils.js +1 -3
- package/dist/components/charts/utils/bar-emphasis.d.ts +32 -3
- package/dist/components/charts/utils/bar-emphasis.js +24 -8
- package/dist/components/charts/utils/index.d.ts +1 -0
- package/dist/components/charts/utils/series-color.d.ts +7 -0
- package/dist/components/charts/utils/series-color.js +20 -0
- package/dist/components/core/Accordion/Accordion.theme.js +2 -2
- package/dist/components/core/Accordion/AccordionTrigger.js +2 -2
- package/dist/components/core/Alert/Alert.animations.d.ts +2 -1
- package/dist/components/core/Alert/Alert.animations.js +21 -6
- package/dist/components/core/Alert/Alert.js +7 -7
- package/dist/components/core/Avatar/Avatar.js +50 -42
- package/dist/components/core/Avatar/Avatar.theme.d.ts +8 -4
- package/dist/components/core/Avatar/Avatar.theme.js +64 -8
- package/dist/components/core/Avatar/Avatar.types.d.ts +13 -2
- package/dist/components/core/Avatar/index.d.ts +1 -1
- package/dist/components/core/AvatarGroup/AvatarGroup.js +6 -8
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.d.ts +1 -2
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +2 -6
- package/dist/components/core/AvatarGroup/AvatarGroup.types.d.ts +0 -6
- package/dist/components/core/AvatarGroup/index.d.ts +1 -1
- package/dist/components/core/Badge/Badge.animations.js +4 -2
- package/dist/components/core/Badge/Badge.js +9 -4
- package/dist/components/core/Badge/Badge.theme.js +18 -12
- package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.d.ts +1 -4
- package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +2 -2
- package/dist/components/core/Button/Button.js +9 -17
- package/dist/components/core/Button/Button.ripple.js +2 -2
- package/dist/components/core/Button/Button.theme.d.ts +2 -0
- package/dist/components/core/Button/Button.theme.js +34 -21
- package/dist/components/core/Button/Button.types.d.ts +18 -1
- package/dist/components/core/Calendar/Calendar.js +20 -5
- package/dist/components/core/Calendar/Calendar.theme.js +14 -22
- package/dist/components/core/Calendar/Calendar.types.d.ts +0 -1
- package/dist/components/core/Calendar/CalendarMini/CalendarMini.js +3 -3
- package/dist/components/core/Card/Card.theme.js +12 -4
- package/dist/components/core/Card/CardBody.js +1 -1
- package/dist/components/core/Card/CardFooter.js +1 -1
- package/dist/components/core/Card/CardHeader.js +1 -1
- package/dist/components/core/Carousel/CarouselNext.js +2 -2
- package/dist/components/core/Carousel/CarouselPrevious.js +2 -2
- package/dist/components/core/CommandPalette/CommandPalette.js +5 -4
- package/dist/components/core/CommandPalette/CommandPalette.theme.js +3 -7
- package/dist/components/core/CommandPalette/CommandPalette.types.d.ts +2 -0
- package/dist/components/core/ContextMenu/ContextMenuItem.js +2 -2
- package/dist/components/core/ContextMenu/ContextMenuSubTrigger.js +2 -2
- package/dist/components/core/Drawer/Drawer.theme.js +7 -4
- package/dist/components/core/Drawer/DrawerHeader.js +2 -2
- package/dist/components/core/Dropdown/Dropdown.theme.js +3 -1
- package/dist/components/core/Dropdown/DropdownItem.js +2 -2
- package/dist/components/core/Dropdown/DropdownTrigger.js +16 -5
- package/dist/components/core/HeroCard/HeroCard.theme.js +5 -2
- package/dist/components/core/Kbd/Kbd.theme.js +4 -2
- package/dist/components/core/Link/Link.js +6 -4
- package/dist/components/core/Message/Message.js +2 -2
- package/dist/components/core/Message/Message.theme.js +5 -7
- package/dist/components/core/Message/MessageAudio.js +2 -2
- package/dist/components/core/Message/MessageFile.js +2 -2
- package/dist/components/core/Message/MessageLink.js +2 -2
- package/dist/components/core/Message/MessageStatusIndicator.js +5 -5
- package/dist/components/core/Modal/Modal.d.ts +1 -1
- package/dist/components/core/Modal/Modal.js +2 -2
- package/dist/components/core/Modal/Modal.theme.js +9 -4
- package/dist/components/core/Modal/ModalHeader.js +2 -2
- package/dist/components/core/ModalStack/ModalStackModal.js +2 -2
- package/dist/components/core/NavItem/NavItem.js +6 -6
- package/dist/components/core/OfflineIndicator/OfflineIndicator.animations.d.ts +22 -0
- package/dist/components/core/OfflineIndicator/OfflineIndicator.animations.js +54 -0
- package/dist/components/core/OfflineIndicator/OfflineIndicator.js +23 -24
- package/dist/components/core/OfflineIndicator/OfflineIndicator.theme.js +25 -6
- package/dist/components/core/OfflineIndicator/OfflineIndicator.types.d.ts +17 -0
- package/dist/components/core/PageHeading/PageHeading.theme.js +1 -1
- package/dist/components/core/PageHeading/PageHeadingBackButton.js +2 -2
- package/dist/components/core/Pagination/Pagination.js +3 -3
- package/dist/components/core/Pagination/Pagination.theme.js +3 -3
- package/dist/components/core/Pill/Pill.js +4 -2
- package/dist/components/core/Pill/Pill.theme.js +6 -4
- package/dist/components/core/Rating/Rating.js +4 -5
- package/dist/components/core/Rating/Rating.theme.js +1 -1
- package/dist/components/core/Segmented/Segmented.theme.js +9 -6
- package/dist/components/core/Sidebar/Sidebar.types.d.ts +4 -2
- package/dist/components/core/Sidebar/SidebarHeader.js +2 -2
- package/dist/components/core/Sidebar/SidebarMobileTrigger.js +2 -2
- package/dist/components/core/Sidebar/SidebarSearch.js +3 -3
- package/dist/components/core/Sidebar/SidebarToggle.js +3 -3
- package/dist/components/core/Sidebar/SidebarUserProfile.js +2 -2
- package/dist/components/core/Sortable/Sortable.js +2 -2
- package/dist/components/core/Tag/Tag.js +2 -2
- package/dist/components/core/Tag/Tag.theme.js +4 -2
- package/dist/components/core/Toast/Toast.js +3 -3
- package/dist/components/core/Toast/Toast.types.d.ts +1 -1
- package/dist/components/core/Toast/useToast.js +5 -5
- package/dist/components/core/Tooltip/Tooltip.d.ts +1 -1
- package/dist/components/core/Tooltip/Tooltip.js +42 -10
- package/dist/components/core/Tooltip/Tooltip.types.d.ts +25 -0
- package/dist/components/core/Tree/Tree.js +2 -2
- package/dist/components/core/shared/interaction.animations.d.ts +51 -0
- package/dist/components/core/shared/interaction.animations.js +59 -0
- package/dist/components/data-display/Feed/Feed.js +2 -2
- package/dist/components/data-display/GanttChart/GanttChart.theme.js +1 -1
- package/dist/components/data-display/GanttChart/GanttChartPanel.js +2 -2
- package/dist/components/data-display/GanttChart/GanttTableGroupRow.js +3 -3
- package/dist/components/data-display/GanttChart/GanttTaskContextMenu.js +2 -2
- package/dist/components/data-display/GanttChart/GanttToolbar.js +2 -2
- package/dist/components/data-display/KPI/KPI.js +2 -2
- package/dist/components/data-display/KPI/KPI.theme.js +4 -4
- package/dist/components/data-display/Metric/Metric.js +2 -2
- package/dist/components/data-display/Metric/Metric.theme.js +25 -8
- package/dist/components/data-display/Metric/Metric.types.d.ts +1 -1
- package/dist/components/data-display/Table/Table.theme.js +9 -9
- package/dist/components/data-display/Table/TableActions.js +2 -2
- package/dist/components/data-display/Table/TableActionsMenu.js +1 -1
- package/dist/components/data-display/Table/TableColumnManager.js +2 -2
- package/dist/components/data-display/Table/TableDeclarative.js +3 -3
- package/dist/components/data-display/Table/TableFilter.js +4 -4
- package/dist/components/data-display/Table/TableHeader.js +3 -3
- package/dist/components/data-display/Table/TableRow.js +2 -2
- package/dist/components/data-display/Table/TableSelectionHeader.js +3 -3
- package/dist/components/data-display/Timeline/TimelineMarker.js +2 -2
- package/dist/components/effects/CustomCursor/CustomCursor.js +2 -2
- package/dist/components/effects/CustomCursor/CustomCursor.theme.js +2 -2
- package/dist/components/effects/DotPattern/DotPattern.js +6 -0
- package/dist/components/effects/DotPattern/DotPattern.types.d.ts +4 -2
- package/dist/components/effects/MeshGradient/MeshGradient.utils.d.ts +1 -1
- package/dist/components/effects/MeshGradient/MeshGradient.utils.js +1 -1
- package/dist/components/forms/Checkbox/Checkbox.js +2 -1
- package/dist/components/forms/Checkbox/Checkbox.theme.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerEyeDropper.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerGradient.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerHeader.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerImage.js +3 -3
- package/dist/components/forms/ColorPicker/ColorPickerInput.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerPresets.js +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerSavedColors.js +2 -2
- package/dist/components/forms/Combobox/Combobox.js +3 -3
- package/dist/components/forms/Combobox/Combobox.theme.js +2 -2
- package/dist/components/forms/DatePicker/DatePicker.animations.js +16 -25
- package/dist/components/forms/DatePicker/DatePicker.theme.js +2 -2
- package/dist/components/forms/DatePicker/DatePickerBody.js +1 -1
- package/dist/components/forms/DatePicker/DatePickerTrigger.js +2 -2
- package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +3 -3
- package/dist/components/forms/DateRangePicker/DateRangePickerBody.js +1 -1
- package/dist/components/forms/DateRangePicker/DateRangePickerPresets.js +2 -2
- package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +2 -2
- package/dist/components/forms/FileUpload/FileUpload.js +4 -4
- package/dist/components/forms/FileUpload/FileUpload.theme.js +5 -1
- package/dist/components/forms/FileUpload/FileUploadProgress.js +7 -7
- package/dist/components/forms/Input/Input.js +6 -7
- package/dist/components/forms/Input/Input.theme.js +19 -15
- package/dist/components/forms/InputAddress/InputAddress.js +10 -3
- package/dist/components/forms/InputCounter/InputCounter.js +3 -3
- package/dist/components/forms/InputOTP/InputOTP.d.ts +3 -12
- package/dist/components/forms/InputOTP/InputOTP.js +140 -151
- package/dist/components/forms/InputOTP/InputOTP.theme.d.ts +5 -1
- package/dist/components/forms/InputOTP/InputOTP.theme.js +40 -5
- package/dist/components/forms/InputOTP/InputOTP.types.d.ts +45 -2
- package/dist/components/forms/InputOTP/index.d.ts +1 -1
- package/dist/components/forms/InputTag/InputTag.js +5 -5
- package/dist/components/forms/InputTag/InputTag.theme.js +1 -2
- package/dist/components/forms/Mention/Mention.theme.js +3 -5
- package/dist/components/forms/Radio/Radio.js +3 -2
- package/dist/components/forms/Radio/Radio.theme.js +2 -2
- package/dist/components/forms/RichTextEditor/RichTextEditor.js +22 -23
- package/dist/components/forms/Select/Select.d.ts +5 -1
- package/dist/components/forms/Select/Select.js +12 -11
- package/dist/components/forms/Select/Select.theme.js +4 -4
- package/dist/components/forms/Select/Select.types.d.ts +4 -1
- package/dist/components/forms/SelectableCard/SelectableCard.animations.d.ts +1 -2
- package/dist/components/forms/SelectableCard/SelectableCard.animations.js +6 -7
- package/dist/components/forms/SelectableCard/SelectableCard.js +1 -1
- package/dist/components/forms/Signature/Signature.js +1 -1
- package/dist/components/forms/Slider/Slider.js +24 -11
- package/dist/components/forms/Slider/Slider.theme.js +9 -3
- package/dist/components/forms/Switch/Switch.theme.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +6 -7
- package/dist/components/forms/TimePicker/TimePickerContent.js +1 -1
- package/dist/components/forms/TimePicker/TimePickerTrigger.js +3 -3
- package/dist/components/forms/forms.theme.js +23 -12
- package/dist/components/forms/index.js +1 -1
- package/dist/components/generative/registry.js +195 -2
- package/dist/components/generative/resolvers.js +16 -16
- package/dist/components/generative/schema.generated.js +2687 -379
- package/dist/components/layout/Section/Section.theme.js +1 -1
- package/dist/generative.schema.json +2687 -379
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/useElapsedTime.d.ts +28 -0
- package/dist/hooks/useElapsedTime.js +37 -0
- package/dist/hooks/useSelectPortal.d.ts +10 -2
- package/dist/hooks/useSelectPortal.js +6 -3
- package/dist/index.js +1 -1
- package/dist/registry.json +835 -261
- package/dist/shadcn-compat.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/theme.css +5 -1
- package/dist/themes/ember.css +131 -0
- package/dist/themes/iris.css +94 -0
- package/dist/themes/jade.css +139 -0
- package/dist/tools.json +2705 -361
- package/dist/utils/colorUtils.d.ts +6 -6
- package/dist/utils/colorUtils.js +8 -8
- package/package.json +9 -6
- package/src/global.scss +15 -4
- package/src/styles/theme.css +440 -152
- package/tailwind.preset.cjs +52 -34
- package/dist/components/core/Pill/Pill.animations.d.ts +0 -32
- package/dist/components/core/Pill/Pill.animations.js +0 -16
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { useState, useId,
|
|
2
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import { useState, useId, useRef, useMemo, useEffect } from 'react';
|
|
4
4
|
import { useReducedMotion, motion } from 'motion/react';
|
|
5
5
|
import { cn } from '../../../utils/cn.js';
|
|
6
6
|
import { useTooltipPosition } from '../hooks/useTooltipPosition.js';
|
|
@@ -15,8 +15,10 @@ import { ChartTooltip } from '../shared/ChartTooltip/ChartTooltip.js';
|
|
|
15
15
|
import { resolveLegendPosition, ChartLegend } from '../shared/ChartLegend/ChartLegend.js';
|
|
16
16
|
import { STACKED_BAR_CHART_DEFAULTS } from './StackedBarChart.types.js';
|
|
17
17
|
import { X_AXIS_MARGIN } from '../types/chart.types.js';
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
18
|
+
import { BAR_STACK_CATEGORY_DELAY, RISE_FROM_BASELINE, stackedSegmentTransition } from '../utils/animation-utils.js';
|
|
19
|
+
import { resolveSeriesColor } from '../utils/series-color.js';
|
|
20
|
+
import { chartTheme } from '../theme/chart.theme.js';
|
|
21
|
+
import { Warning } from '@phosphor-icons/react';
|
|
20
22
|
|
|
21
23
|
// Pure helper functions moved to module level to avoid recreation per render
|
|
22
24
|
const createRoundedTopBarPath = (x, y, width, height, radius) => {
|
|
@@ -61,42 +63,11 @@ className, title, description, enableKeyboardNavigation = STACKED_BAR_CHART_DEFA
|
|
|
61
63
|
const stackGradientId = (index) => `${rawId}-stack-gradient-${index}`;
|
|
62
64
|
const columnShadowId = `${rawId}-column-shadow`;
|
|
63
65
|
const columnGlowId = `${rawId}-column-glow`;
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
if (!shouldReduceMotion && showAnimation) {
|
|
66
|
-
setHasAnimated(true);
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
setHasAnimated(true);
|
|
70
|
-
}
|
|
71
|
-
}, [shouldReduceMotion, showAnimation]);
|
|
72
66
|
// Validate data and config with error handling
|
|
73
67
|
const { validation, sanitizedData, isValid, hasWarnings, safeScale, safeMath, } = useChartValidation(data, config, {
|
|
74
68
|
autoSanitize: true,
|
|
75
69
|
});
|
|
76
|
-
|
|
77
|
-
const getSeriesFillColor = (index, key) => {
|
|
78
|
-
var _a;
|
|
79
|
-
if (key && config && ((_a = config[key]) === null || _a === void 0 ? void 0 : _a.color)) {
|
|
80
|
-
const customColor = config[key].color;
|
|
81
|
-
if (!customColor.startsWith("var(") &&
|
|
82
|
-
!customColor.startsWith("#") &&
|
|
83
|
-
!customColor.startsWith("rgb") &&
|
|
84
|
-
!customColor.startsWith("hsl") &&
|
|
85
|
-
customColor.includes("-")) {
|
|
86
|
-
return `var(--color-${customColor})`;
|
|
87
|
-
}
|
|
88
|
-
return customColor;
|
|
89
|
-
}
|
|
90
|
-
const colorVars = [
|
|
91
|
-
"var(--color-primary)",
|
|
92
|
-
"var(--color-primary-400)",
|
|
93
|
-
"var(--color-primary-300)",
|
|
94
|
-
"var(--color-primary-200)",
|
|
95
|
-
"var(--color-warning)",
|
|
96
|
-
"var(--color-success)",
|
|
97
|
-
];
|
|
98
|
-
return colorVars[index % colorVars.length];
|
|
99
|
-
};
|
|
70
|
+
const getSeriesFillColor = (index, key) => resolveSeriesColor(index, key, config, chartTheme.baseStyle.colors.series);
|
|
100
71
|
const containerRef = useRef(null);
|
|
101
72
|
// `measured` gates bar mount so motion captures geometry in the real
|
|
102
73
|
// coordinate space, not the 600×400 fallback (cold-load below-baseline bug).
|
|
@@ -171,13 +142,34 @@ className, title, description, enableKeyboardNavigation = STACKED_BAR_CHART_DEFA
|
|
|
171
142
|
});
|
|
172
143
|
return max;
|
|
173
144
|
}, [sanitizedData, dataKeys]);
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (!shouldReduceMotion &&
|
|
147
|
+
showAnimation &&
|
|
148
|
+
sanitizedData.length > 0 &&
|
|
149
|
+
dataKeys.length > 0) {
|
|
150
|
+
const maxDelay = (sanitizedData.length - 1) * BAR_STACK_CATEGORY_DELAY +
|
|
151
|
+
(dataKeys.length - 1) * 0.4;
|
|
152
|
+
const timer = setTimeout(() => {
|
|
153
|
+
setHasAnimated(true);
|
|
154
|
+
}, (maxDelay + 0.4) * 1000);
|
|
155
|
+
return () => clearTimeout(timer);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
setHasAnimated(true);
|
|
159
|
+
}
|
|
160
|
+
}, [
|
|
161
|
+
shouldReduceMotion,
|
|
162
|
+
showAnimation,
|
|
163
|
+
sanitizedData.length,
|
|
164
|
+
dataKeys.length,
|
|
165
|
+
]);
|
|
174
166
|
// --- Every hook above this line runs unconditionally, every render, in the
|
|
175
167
|
// same order. Only NOW — after the last hook — do we branch on validity, so
|
|
176
168
|
// a chart going from populated → empty/invalid data (a common loading-state
|
|
177
169
|
// transition) never changes its hook count mid-lifetime. See BarChart.tsx.
|
|
178
170
|
// Early return for invalid data
|
|
179
171
|
if (!isValid) {
|
|
180
|
-
return (jsxs("div", { className: cn("chart-container flex flex-col items-center justify-center p-6 border border-border rounded-lg text-2xl", className), role: "alert", "aria-live": "polite", ...props, children: [jsxs("div", { className: "flex flex-col items-center gap-4 mb-1", children: [jsx(
|
|
172
|
+
return (jsxs("div", { className: cn("chart-container flex flex-col items-center justify-center p-6 border border-border rounded-lg text-2xl", className), role: "alert", "aria-live": "polite", ...props, children: [jsxs("div", { className: "flex flex-col items-center gap-4 mb-1", children: [jsx(Warning, { className: "size-6 text-[var(--color-danger)]" }), jsx("div", { className: "text-base font-semibold text-[var(--color-text-secondary)]", children: "Invalid Chart Data" })] }), jsx("p", { className: "text-base text-[var(--color-text-secondary)]/70 mb-2", children: ((_a = validation.errors[0]) === null || _a === void 0 ? void 0 : _a.message) ||
|
|
181
173
|
"Unable to render chart due to data validation errors" })] }));
|
|
182
174
|
}
|
|
183
175
|
// Early return for empty data
|
|
@@ -211,114 +203,140 @@ className, title, description, enableKeyboardNavigation = STACKED_BAR_CHART_DEFA
|
|
|
211
203
|
? isHovered
|
|
212
204
|
? `url(#${columnGlowId})`
|
|
213
205
|
: `url(#${columnShadowId})`
|
|
214
|
-
: undefined, style: isGradientVariant ? { overflow: "visible" } : undefined, children: dataKeys.map((key, keyIndex) => {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
206
|
+
: undefined, style: isGradientVariant ? { overflow: "visible" } : undefined, children: jsx("g", { clipPath: `url(#${rawId}-column-clip-${categoryIndex})`, children: dataKeys.map((key, keyIndex) => {
|
|
207
|
+
var _a;
|
|
208
|
+
const stackData = (_a = getStackedValues[key]) === null || _a === void 0 ? void 0 : _a[categoryIndex];
|
|
209
|
+
if (!stackData)
|
|
210
|
+
return null;
|
|
211
|
+
let baseValue = stackData.base;
|
|
212
|
+
let topValue = stackData.top;
|
|
213
|
+
// Apply expand offset (normalize to percentage)
|
|
214
|
+
if (stackOffset === "expand") {
|
|
215
|
+
const totalForCategory = dataKeys.reduce((sum, k) => {
|
|
216
|
+
const rawVal = item[k];
|
|
217
|
+
return (sum +
|
|
218
|
+
(typeof rawVal === "number" && isFinite(rawVal) ? rawVal : 0));
|
|
219
|
+
}, 0);
|
|
220
|
+
if (totalForCategory > 0) {
|
|
221
|
+
baseValue = (stackData.base / totalForCategory) * 100;
|
|
222
|
+
topValue = (stackData.top / totalForCategory) * 100;
|
|
223
|
+
}
|
|
231
224
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
:
|
|
259
|
-
?
|
|
260
|
-
:
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
:
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
225
|
+
const barHeight = range > 0
|
|
226
|
+
? safeMath.scale(topValue - baseValue, 0, range, 0, innerHeight)
|
|
227
|
+
: 0;
|
|
228
|
+
const barY = margin.top +
|
|
229
|
+
innerHeight -
|
|
230
|
+
safeMath.scale(topValue, minValue, maxValue, 0, innerHeight);
|
|
231
|
+
const segmentGap = 2;
|
|
232
|
+
const renderedHeight = Math.max(0, barHeight - segmentGap);
|
|
233
|
+
if (renderedHeight <= 0)
|
|
234
|
+
return null;
|
|
235
|
+
const renderedY = barY + segmentGap / 2;
|
|
236
|
+
const pathD = createRectPath(x, renderedY, barWidth, renderedHeight);
|
|
237
|
+
const fillColor = getSeriesFillColor(keyIndex, key);
|
|
238
|
+
const delay = categoryIndex * BAR_STACK_CATEGORY_DELAY +
|
|
239
|
+
keyIndex * 0.4;
|
|
240
|
+
return (jsx(motion.path, { d: pathD, initial: showAnimation && !shouldReduceMotion
|
|
241
|
+
? { scaleY: 0, opacity: 0 }
|
|
242
|
+
: { scaleY: 1, opacity: 1 }, animate: {
|
|
243
|
+
scaleY: 1,
|
|
244
|
+
// Hover dim lives in `animate` (not `style`): motion.path freezes
|
|
245
|
+
// plain style values at mount and ignores re-render changes.
|
|
246
|
+
opacity: shouldReduceOpacity ? (isGradientVariant ? 0.42 : 0.9) : 1,
|
|
247
|
+
}, transition: stackedSegmentTransition(delay, hasAnimated), className: cn(isGradientVariant
|
|
248
|
+
? "transition-all duration-300 ease-out cursor-pointer"
|
|
249
|
+
: "transition-colors duration-200 cursor-pointer", isFocused && "stroke-2"), style: {
|
|
250
|
+
...RISE_FROM_BASELINE,
|
|
251
|
+
fill: isGradientVariant
|
|
252
|
+
? `url(#${stackGradientId(keyIndex)})`
|
|
253
|
+
: shouldReduceOpacity
|
|
254
|
+
? "var(--color-surface-sunken)"
|
|
255
|
+
: fillColor,
|
|
256
|
+
// Hairline stroke on keyboard focus only; 2px gap handles segment separation.
|
|
257
|
+
stroke: isFocused ? "var(--color-primary)" : "none",
|
|
258
|
+
strokeWidth: isFocused ? 2 : undefined,
|
|
259
|
+
vectorEffect: "non-scaling-stroke",
|
|
260
|
+
}, onMouseEnter: (e) => {
|
|
261
|
+
setHoveredCategory(categoryIndex);
|
|
262
|
+
// Create tooltip content with all series
|
|
263
|
+
const series = dataKeys.map((dataKey, idx) => {
|
|
264
|
+
var _a;
|
|
265
|
+
const rawValue = item[dataKey];
|
|
266
|
+
const value = typeof rawValue === "number" && isFinite(rawValue)
|
|
267
|
+
? rawValue
|
|
268
|
+
: 0;
|
|
269
|
+
return {
|
|
270
|
+
key: dataKey,
|
|
271
|
+
label: ((_a = config[dataKey]) === null || _a === void 0 ? void 0 : _a.label) || dataKey,
|
|
272
|
+
value,
|
|
273
|
+
color: getSeriesFillColor(idx, dataKey),
|
|
274
|
+
};
|
|
275
|
+
});
|
|
276
|
+
// Calculate total
|
|
277
|
+
const total = series.reduce((sum, s) => sum + s.value, 0);
|
|
278
|
+
const content = {
|
|
279
|
+
category: item.name || `Category ${categoryIndex + 1}`,
|
|
280
|
+
series,
|
|
281
|
+
total,
|
|
283
282
|
};
|
|
284
|
-
});
|
|
285
|
-
// Calculate total
|
|
286
|
-
const total = series.reduce((sum, s) => sum + s.value, 0);
|
|
287
|
-
const content = {
|
|
288
|
-
category: item.name || `Category ${categoryIndex + 1}`,
|
|
289
|
-
series,
|
|
290
|
-
total,
|
|
291
|
-
};
|
|
292
|
-
const svgCoordinates = {
|
|
293
|
-
x: x + barWidth / 2,
|
|
294
|
-
y: barY,
|
|
295
|
-
dimensions,
|
|
296
|
-
};
|
|
297
|
-
handleMouseEnter(e, content, svgCoordinates);
|
|
298
|
-
}, onMouseMove: (e) => {
|
|
299
|
-
if (hoveredCategory === categoryIndex) {
|
|
300
283
|
const svgCoordinates = {
|
|
301
284
|
x: x + barWidth / 2,
|
|
302
285
|
y: barY,
|
|
303
286
|
dimensions,
|
|
304
287
|
};
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
288
|
+
handleMouseEnter(e, content, svgCoordinates);
|
|
289
|
+
}, onMouseMove: (e) => {
|
|
290
|
+
if (hoveredCategory === categoryIndex) {
|
|
291
|
+
const svgCoordinates = {
|
|
292
|
+
x: x + barWidth / 2,
|
|
293
|
+
y: barY,
|
|
294
|
+
dimensions,
|
|
295
|
+
};
|
|
296
|
+
handleMouseMove(e, svgCoordinates);
|
|
297
|
+
}
|
|
298
|
+
}, onMouseLeave: () => {
|
|
299
|
+
setHoveredCategory(null);
|
|
300
|
+
handleMouseLeave();
|
|
301
|
+
} }, key));
|
|
302
|
+
}) }) }, categoryIndex));
|
|
312
303
|
};
|
|
313
304
|
return (jsx(ChartErrorBoundary, { className: className, showErrorDetails: process.env.NODE_ENV === "development", children: jsxs("div", { ref: containerRef, className: cn("chart-container w-full h-full flex flex-col", className), style: {
|
|
314
305
|
width: width !== undefined ? (typeof width === "number" ? `${width}px` : width) : undefined,
|
|
315
306
|
height: height !== undefined ? (typeof height === "number" ? `${height}px` : height) : undefined,
|
|
316
307
|
}, ...chartAccessibilityProps, onMouseEnter: handleMouseInteraction, onMouseMove: handleMouseInteraction, ...props, children: [resolvedLegendPosition === "top" && (jsx(ChartLegend, { items: legendItems, className: "shrink-0 pb-2" })), descriptionProps && jsx("div", { ...descriptionProps }), showValidationWarnings && hasWarnings && (jsxs("div", { className: "absolute top-2 left-2 right-2 z-10 p-2 bg-[var(--color-warning-50)] border border-[var(--color-warning-200)] rounded text-sm text-[var(--color-warning)] shadow-sm", children: [jsx("strong", { children: "Chart Warnings:" }), jsx("ul", { className: "mt-1", children: validation.warnings.map((warning, index) => (jsxs("li", { children: ["\u2022 ", warning.message] }, index))) })] })), jsx("div", { className: "relative flex-1 min-h-0", children: jsxs("svg", { width: "100%", height: "100%", viewBox: `0 0 ${dimensions.width} ${dimensions.height}`,
|
|
317
308
|
// Let the column lift shadow / hover glow paint past the plot edges.
|
|
318
|
-
className: isGradientVariant ? "overflow-visible" : undefined, children: [isGradientVariant && (jsxs(
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
309
|
+
className: isGradientVariant ? "overflow-visible" : undefined, children: [jsxs("defs", { children: [isGradientVariant && (jsxs(Fragment, { children: [dataKeys.map((key, index) => {
|
|
310
|
+
const color = getSeriesFillColor(index, key);
|
|
311
|
+
return (jsxs("linearGradient", { id: stackGradientId(index), x1: "0", y1: "0", x2: "0", y2: "1", children: [jsx("stop", { offset: "0%", stopColor: color, stopOpacity: "0.92" }), jsx("stop", { offset: "45%", stopColor: color, stopOpacity: "1" }), jsx("stop", { offset: "100%", stopColor: color, stopOpacity: "0.84" })] }, key));
|
|
312
|
+
}), jsx("filter", { id: columnShadowId, x: "-40%", y: "-25%", width: "180%", height: "160%", colorInterpolationFilters: "sRGB", children: jsx("feDropShadow", { dx: "0", dy: "10", stdDeviation: "9", floodColor: "var(--color-mono-950)", floodOpacity: "0.16" }) }), jsxs("filter", { id: columnGlowId, x: "-50%", y: "-45%", width: "200%", height: "200%", colorInterpolationFilters: "sRGB", children: [jsx("feDropShadow", { dx: "0", dy: "0", stdDeviation: "5", floodColor: getSeriesFillColor(0, dataKeys[0]), floodOpacity: "0.4" }), jsx("feDropShadow", { dx: "0", dy: "10", stdDeviation: "9", floodColor: "var(--color-mono-950)", floodOpacity: "0.14" })] })] })), measured &&
|
|
313
|
+
sanitizedData.map((item, categoryIndex) => {
|
|
314
|
+
var _a;
|
|
315
|
+
const x = margin.left + categoryIndex * (barWidth + categoryGap);
|
|
316
|
+
const topSegmentKey = dataKeys[dataKeys.length - 1];
|
|
317
|
+
const topStackData = (_a = getStackedValues[topSegmentKey]) === null || _a === void 0 ? void 0 : _a[categoryIndex];
|
|
318
|
+
let maxVal = topStackData ? topStackData.top : 0;
|
|
319
|
+
if (stackOffset === "expand") {
|
|
320
|
+
const totalForCategory = dataKeys.reduce((sum, k) => {
|
|
321
|
+
const rawVal = item[k];
|
|
322
|
+
return (sum +
|
|
323
|
+
(typeof rawVal === "number" && isFinite(rawVal) ? rawVal : 0));
|
|
324
|
+
}, 0);
|
|
325
|
+
if (totalForCategory > 0) {
|
|
326
|
+
maxVal = 100;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
const range = maxValue - minValue;
|
|
330
|
+
const columnTopY = range > 0
|
|
331
|
+
? margin.top +
|
|
332
|
+
innerHeight -
|
|
333
|
+
safeMath.scale(maxVal, minValue, maxValue, 0, innerHeight)
|
|
334
|
+
: margin.top + innerHeight;
|
|
335
|
+
const zeroY = margin.top + innerHeight;
|
|
336
|
+
const columnHeight = Math.max(0, zeroY - columnTopY);
|
|
337
|
+
const columnPathD = createRoundedTopBarPath(x, columnTopY, barWidth, columnHeight, barRadius);
|
|
338
|
+
return (jsx("clipPath", { id: `${rawId}-column-clip-${categoryIndex}`, children: jsx("path", { d: columnPathD }) }, categoryIndex));
|
|
339
|
+
})] }), jsx(HorizontalGrid, { show: showGrid, x: margin.left, y: margin.top, width: innerWidth, height: innerHeight, lineCount: 5 }), jsx(YAxis, { show: showYAxis, min: minValue, max: maxValue, x: margin.left, y: margin.top, height: innerHeight, showGrid: false, gridWidth: innerWidth, tickFormatter: (value) => {
|
|
322
340
|
if (stackOffset === "expand")
|
|
323
341
|
return `${value}%`;
|
|
324
342
|
if (Math.abs(value) >= 1000)
|
|
@@ -1,34 +1,36 @@
|
|
|
1
1
|
import { BaseChartProps, StandardChartDisplayProps, StandardVisualProps, BarChartSpecificProps, ChartVariant } from "../types/chart.types";
|
|
2
2
|
export type StackOffset = "none" | "expand" | "wiggle" | "silhouette";
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Visual props that actually apply to a stacked bar chart.
|
|
5
|
+
*
|
|
6
|
+
* 🔴 Narrowed with `Omit` on purpose — see the note on `StandardVisualProps`.
|
|
7
|
+
* Kept: `barRadius` only.
|
|
8
|
+
* Dropped: dot/cell radii, stroke width, the line/area-only props, `gap` (segment
|
|
9
|
+
* separation is a fixed hairline, not a tunable), and `stacked` (this chart always is).
|
|
10
|
+
*/
|
|
11
|
+
export type StackedBarVisualProps = Omit<StandardVisualProps, "dotRadius" | "radius" | "strokeWidth" | "gap" | "curved" | "curveType" | "showDots" | "fillOpacity" | "showStroke" | "stacked">;
|
|
12
|
+
export interface StackedBarChartProps extends BaseChartProps, StandardChartDisplayProps, StackedBarVisualProps, BarChartSpecificProps {
|
|
4
13
|
barRadius?: number;
|
|
5
|
-
gap?: number;
|
|
6
14
|
categoryGap?: number;
|
|
7
15
|
stackOffset?: StackOffset;
|
|
8
16
|
showAnimation?: boolean;
|
|
9
17
|
showValidationWarnings?: boolean;
|
|
10
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Default values using centralized defaults.
|
|
21
|
+
*
|
|
22
|
+
* 🔴 Picks explicitly rather than spreading `...CHART_DEFAULTS` — see the note on
|
|
23
|
+
* `BAR_CHART_DEFAULTS`.
|
|
24
|
+
*/
|
|
11
25
|
export declare const STACKED_BAR_CHART_DEFAULTS: {
|
|
26
|
+
readonly showGrid: true;
|
|
27
|
+
readonly showXAxis: true;
|
|
28
|
+
readonly showYAxis: true;
|
|
29
|
+
readonly enableKeyboardNavigation: true;
|
|
12
30
|
readonly barRadius: 32;
|
|
13
|
-
readonly gap: 4;
|
|
14
31
|
readonly categoryGap: 16;
|
|
15
|
-
readonly orientation: "horizontal" | "vertical";
|
|
16
32
|
readonly stackOffset: StackOffset;
|
|
17
33
|
readonly showAnimation: true;
|
|
18
34
|
readonly variant: ChartVariant;
|
|
19
|
-
readonly showGrid: true;
|
|
20
|
-
readonly showXAxis: true;
|
|
21
|
-
readonly showYAxis: true;
|
|
22
|
-
readonly dotRadius: 3;
|
|
23
|
-
readonly cellRadius: 4;
|
|
24
|
-
readonly radius: 20;
|
|
25
|
-
readonly strokeWidth: 2;
|
|
26
|
-
readonly curved: true;
|
|
27
|
-
readonly curveType: import("..").CurveType;
|
|
28
|
-
readonly fillOpacity: 0.3;
|
|
29
|
-
readonly showStroke: true;
|
|
30
|
-
readonly showDots: false;
|
|
31
|
-
readonly stacked: false;
|
|
32
|
-
readonly enableKeyboardNavigation: true;
|
|
33
35
|
};
|
|
34
36
|
export type StackedBarChartData = BaseChartProps["data"][0];
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { CHART_DEFAULTS } from '../types/chart.types.js';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Default values using centralized defaults.
|
|
5
|
+
*
|
|
6
|
+
* 🔴 Picks explicitly rather than spreading `...CHART_DEFAULTS` — see the note on
|
|
7
|
+
* `BAR_CHART_DEFAULTS`.
|
|
8
|
+
*/
|
|
4
9
|
const STACKED_BAR_CHART_DEFAULTS = {
|
|
5
|
-
|
|
10
|
+
showGrid: CHART_DEFAULTS.showGrid,
|
|
11
|
+
showXAxis: CHART_DEFAULTS.showXAxis,
|
|
12
|
+
showYAxis: CHART_DEFAULTS.showYAxis,
|
|
13
|
+
enableKeyboardNavigation: CHART_DEFAULTS.enableKeyboardNavigation,
|
|
6
14
|
barRadius: CHART_DEFAULTS.barRadius,
|
|
7
|
-
gap: CHART_DEFAULTS.gap,
|
|
8
15
|
categoryGap: CHART_DEFAULTS.categoryGap,
|
|
9
|
-
orientation: CHART_DEFAULTS.orientation,
|
|
10
16
|
stackOffset: "none",
|
|
11
17
|
showAnimation: true,
|
|
12
18
|
// Premium look by default (per-segment gradient + lift shadow + hover glow),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ChartDataPoint, ChartConfig } from '../types/chart.types';
|
|
2
2
|
export interface UseChartAccessibilityOptions {
|
|
3
3
|
/** Chart type for ARIA descriptions */
|
|
4
|
-
chartType: 'bar' | 'line' | 'area' | 'heatmap' | 'combo' | 'scatter';
|
|
4
|
+
chartType: 'bar' | 'line' | 'area' | 'heatmap' | 'combo' | 'scatter' | 'lollipop';
|
|
5
5
|
/** Chart data for generating descriptions */
|
|
6
6
|
data: ChartDataPoint[];
|
|
7
7
|
/** Chart configuration */
|
|
@@ -16,6 +16,9 @@ function useChartAccessibility({ chartType, data, config, title, description, en
|
|
|
16
16
|
case 'bar':
|
|
17
17
|
summary = `Bar chart with ${dataCount} categories`;
|
|
18
18
|
break;
|
|
19
|
+
case 'lollipop':
|
|
20
|
+
summary = `Lollipop chart with ${dataCount} categories`;
|
|
21
|
+
break;
|
|
19
22
|
case 'line':
|
|
20
23
|
summary = `Line chart with ${dataCount} data points`;
|
|
21
24
|
break;
|
|
@@ -112,11 +112,23 @@ function useTooltipPosition({ containerRef, padding = 10, offset = 15, isMobile
|
|
|
112
112
|
* Get tooltip position for SVG elements (mobile/touch)
|
|
113
113
|
*/
|
|
114
114
|
const getSVGTooltipPosition = useCallback((event, svgX, svgY, actualDimensions) => {
|
|
115
|
-
var _a, _b;
|
|
115
|
+
var _a, _b, _c, _d, _e;
|
|
116
116
|
try {
|
|
117
|
-
|
|
117
|
+
// Keyboard-driven callers have no real mouse event and synthesise one, whose
|
|
118
|
+
// `currentTarget` is null — the DOM only populates it during dispatch. Only the
|
|
119
|
+
// <svg> is wanted here, and `containerRef` already reaches it, so don't make
|
|
120
|
+
// finding it depend on the event: reading `.closest` off a null currentTarget
|
|
121
|
+
// threw on every keyboard focus move, and the catch below quietly swallowed it
|
|
122
|
+
// into a mouse-coordinate fallback.
|
|
123
|
+
const svgElement = (_b = (_a = event.currentTarget) === null || _a === void 0 ? void 0 : _a.closest('svg')) !== null && _b !== void 0 ? _b : (_c = containerRef.current) === null || _c === void 0 ? void 0 : _c.querySelector('svg');
|
|
118
124
|
const svgRect = svgElement === null || svgElement === void 0 ? void 0 : svgElement.getBoundingClientRect();
|
|
119
|
-
|
|
125
|
+
// A zero-sized rect is as unusable as a missing one: the scale factors below
|
|
126
|
+
// divide by it, so a not-yet-laid-out <svg> would collapse every coordinate
|
|
127
|
+
// onto its origin rather than fail loudly. Fall back to mouse coordinates.
|
|
128
|
+
if (!(svgRect === null || svgRect === void 0 ? void 0 : svgRect.width) ||
|
|
129
|
+
!svgRect.height ||
|
|
130
|
+
!actualDimensions.width ||
|
|
131
|
+
!actualDimensions.height) {
|
|
120
132
|
if (process.env.NODE_ENV !== 'production') {
|
|
121
133
|
console.warn('[useTooltipPosition]: SVG positioning fallback: missing SVG rect or dimensions');
|
|
122
134
|
}
|
|
@@ -130,8 +142,8 @@ function useTooltipPosition({ containerRef, padding = 10, offset = 15, isMobile
|
|
|
130
142
|
const screenY = svgRect.top + svgY * scaleY;
|
|
131
143
|
const x = screenX;
|
|
132
144
|
const y = screenY - offset;
|
|
133
|
-
const tooltipWidth = ((
|
|
134
|
-
const tooltipHeight = ((
|
|
145
|
+
const tooltipWidth = ((_d = tooltipRef.current) === null || _d === void 0 ? void 0 : _d.offsetWidth) || 200;
|
|
146
|
+
const tooltipHeight = ((_e = tooltipRef.current) === null || _e === void 0 ? void 0 : _e.offsetHeight) || 60;
|
|
135
147
|
return calculateBoundedPosition(x, y, tooltipWidth, tooltipHeight);
|
|
136
148
|
}
|
|
137
149
|
catch (error) {
|
|
@@ -140,7 +152,7 @@ function useTooltipPosition({ containerRef, padding = 10, offset = 15, isMobile
|
|
|
140
152
|
}
|
|
141
153
|
return getMouseTooltipPosition(event);
|
|
142
154
|
}
|
|
143
|
-
}, [calculateBoundedPosition, getMouseTooltipPosition, offset]);
|
|
155
|
+
}, [calculateBoundedPosition, getMouseTooltipPosition, offset, containerRef]);
|
|
144
156
|
/**
|
|
145
157
|
* Show tooltip with content and position
|
|
146
158
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { ChartContainer } from "./ChartContainer";
|
|
2
2
|
export { BarChart } from "./BarChart";
|
|
3
|
+
export { HorizontalBarChart } from "./HorizontalBarChart";
|
|
3
4
|
export { StackedBarChart } from "./StackedBarChart";
|
|
4
5
|
export { LineChart } from "./LineChart";
|
|
5
6
|
export { AreaChart } from "./AreaChart";
|
|
@@ -11,6 +12,7 @@ export { ScatterPlot } from "./ScatterPlot";
|
|
|
11
12
|
export { RadarChart } from "./RadarChart";
|
|
12
13
|
export { ComboChart } from "./ComboChart";
|
|
13
14
|
export { ActivityRings } from "./ActivityRings";
|
|
15
|
+
export { LollipopChart } from "./LollipopChart";
|
|
14
16
|
export { ChartTooltip } from "./shared/ChartTooltip";
|
|
15
17
|
export { ChartLegend } from "./shared/ChartLegend";
|
|
16
18
|
export { XAxis, YAxis } from "./shared/ChartAxis";
|
|
@@ -33,6 +35,7 @@ export type { ChartMarkerProps, ChartMarkerTheme, } from "./shared/ChartMarker/C
|
|
|
33
35
|
export type { ChartCrosshairProps, ChartCrosshairTheme, } from "./shared/ChartCrosshair/ChartCrosshair.types";
|
|
34
36
|
export type { HorizontalGridProps } from "./shared/ChartGrid";
|
|
35
37
|
export type { BarChartProps } from "./BarChart/BarChart.types";
|
|
38
|
+
export type { HorizontalBarChartProps, HorizontalBarVisualProps, } from "./HorizontalBarChart/HorizontalBarChart.types";
|
|
36
39
|
export type { StackedBarChartProps, StackOffset, } from "./StackedBarChart/StackedBarChart.types";
|
|
37
40
|
export type { LineChartProps } from "./LineChart/LineChart.types";
|
|
38
41
|
export type { AreaChartProps } from "./AreaChart/AreaChart.types";
|
|
@@ -44,11 +47,14 @@ export type { ScatterPlotProps, ScatterPlotDataPoint, } from "./ScatterPlot/Scat
|
|
|
44
47
|
export type { RadarChartProps, RadarChartSeries, } from "./RadarChart/RadarChart.types";
|
|
45
48
|
export type { ComboChartProps, ComboChartConfig, SeriesType, } from "./ComboChart/ComboChart.types";
|
|
46
49
|
export type { ActivityRingsProps, RingData, ActivityRingsThemeOverrides, } from "./ActivityRings/ActivityRings.types";
|
|
50
|
+
export type { LollipopChartProps, LollipopChartData } from "./LollipopChart/LollipopChart.types";
|
|
47
51
|
export { chartTheme } from "./theme/chart.theme";
|
|
48
52
|
export { extractFillClass, extractStrokeClass, colorClassToVariable, combineClasses, createColorClass, generateSeriesColors, DEFAULT_CHART_COLORS, EXTENDED_CHART_COLORS, MINIMAL_CHART_COLORS, } from "./utils/color-utils";
|
|
49
53
|
export { validateChart, validateChartData, validateChartConfig, sanitizeChartData, calculateSafeScaleRange, niceNum, generateNiceTicks, SafeMath, } from "./utils/chart-validation";
|
|
50
54
|
export { BAR_CHART_DEFAULTS } from "./BarChart/BarChart.types";
|
|
55
|
+
export { HORIZONTAL_BAR_CHART_DEFAULTS } from "./HorizontalBarChart/HorizontalBarChart.types";
|
|
51
56
|
export { STACKED_BAR_CHART_DEFAULTS } from "./StackedBarChart/StackedBarChart.types";
|
|
52
57
|
export { LINE_CHART_DEFAULTS } from "./LineChart/LineChart.types";
|
|
53
58
|
export { AREA_CHART_DEFAULTS } from "./AreaChart/AreaChart.types";
|
|
59
|
+
export { LOLLIPOP_CHART_DEFAULTS } from "./LollipopChart/LollipopChart.types";
|
|
54
60
|
export { ChartErrorBoundary } from "./shared/ChartErrorBoundary";
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { ChartContainer } from './ChartContainer.js';
|
|
2
2
|
export { BarChart } from './BarChart/BarChart.js';
|
|
3
|
+
export { HorizontalBarChart } from './HorizontalBarChart/HorizontalBarChart.js';
|
|
4
|
+
export { HORIZONTAL_BAR_CHART_DEFAULTS } from './HorizontalBarChart/HorizontalBarChart.types.js';
|
|
3
5
|
export { StackedBarChart } from './StackedBarChart/StackedBarChart.js';
|
|
4
6
|
export { STACKED_BAR_CHART_DEFAULTS } from './StackedBarChart/StackedBarChart.types.js';
|
|
5
7
|
export { LineChart } from './LineChart/LineChart.js';
|
|
@@ -16,10 +18,14 @@ export { ScatterPlot } from './ScatterPlot/ScatterPlot.js';
|
|
|
16
18
|
export { RadarChart } from './RadarChart/RadarChart.js';
|
|
17
19
|
export { ComboChart } from './ComboChart/ComboChart.js';
|
|
18
20
|
export { ActivityRings } from './ActivityRings/ActivityRings.js';
|
|
21
|
+
export { LollipopChart } from './LollipopChart/LollipopChart.js';
|
|
22
|
+
export { LOLLIPOP_CHART_DEFAULTS } from './LollipopChart/LollipopChart.types.js';
|
|
19
23
|
export { ChartTooltip } from './shared/ChartTooltip/ChartTooltip.js';
|
|
20
24
|
export { ChartLegend } from './shared/ChartLegend/ChartLegend.js';
|
|
21
25
|
export { XAxis } from './shared/ChartAxis/XAxis.js';
|
|
22
26
|
export { YAxis } from './shared/ChartAxis/YAxis.js';
|
|
27
|
+
import './shared/ChartAxis/ValueXAxis.js';
|
|
28
|
+
import './shared/ChartAxis/CategoryYAxis.js';
|
|
23
29
|
export { ChartText } from './shared/ChartText/ChartText.js';
|
|
24
30
|
export { ChartMarker } from './shared/ChartMarker/ChartMarker.js';
|
|
25
31
|
export { ChartCrosshair } from './shared/ChartCrosshair/ChartCrosshair.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { CategoryYAxisProps } from "./ChartAxis.types";
|
|
3
|
+
/**
|
|
4
|
+
* CategoryYAxis component for charts
|
|
5
|
+
* Renders a vertical CATEGORY axis: one label per category down the left, with
|
|
6
|
+
* optional tick marks.
|
|
7
|
+
*
|
|
8
|
+
* This is `XAxis` rotated. Labels sit to the LEFT of the axis line and are
|
|
9
|
+
* end-anchored, so a ragged set of category names ("United Kingdom", "Italy") stays
|
|
10
|
+
* flush against the plot — the caller is responsible for reserving enough left margin,
|
|
11
|
+
* since unlike a bottom axis there is no shared constant that can know how wide a
|
|
12
|
+
* category name will be.
|
|
13
|
+
*/
|
|
14
|
+
export declare const CategoryYAxis: React.FC<CategoryYAxisProps>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { cn } from '../../../../utils/cn.js';
|
|
4
|
+
import { ChartText } from '../ChartText/ChartText.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* CategoryYAxis component for charts
|
|
8
|
+
* Renders a vertical CATEGORY axis: one label per category down the left, with
|
|
9
|
+
* optional tick marks.
|
|
10
|
+
*
|
|
11
|
+
* This is `XAxis` rotated. Labels sit to the LEFT of the axis line and are
|
|
12
|
+
* end-anchored, so a ragged set of category names ("United Kingdom", "Italy") stays
|
|
13
|
+
* flush against the plot — the caller is responsible for reserving enough left margin,
|
|
14
|
+
* since unlike a bottom axis there is no shared constant that can know how wide a
|
|
15
|
+
* category name will be.
|
|
16
|
+
*/
|
|
17
|
+
const CategoryYAxis = React__default.memo(({ data, x, y, height, categoryHeight, categoryGap = 0, show = true, className, showTicks = true, tickLength = 6, tickPadding = 8, textAnchor = "end", labelFormatter, maxLabelWidth = 100, }) => {
|
|
18
|
+
if (!show)
|
|
19
|
+
return null;
|
|
20
|
+
const formatLabel = (item, index) => {
|
|
21
|
+
if (labelFormatter) {
|
|
22
|
+
return labelFormatter(item, index);
|
|
23
|
+
}
|
|
24
|
+
return item.name || item.label || String(index);
|
|
25
|
+
};
|
|
26
|
+
const getTickY = (index) => y + index * (categoryHeight + categoryGap) + categoryHeight / 2;
|
|
27
|
+
return (jsxs("g", { className: cn("chart-category-y-axis", className), children: [jsx("line", { x1: x, y1: y, x2: x, y2: y + height, className: "stroke-[var(--color-border)]", strokeWidth: 1 }), data.map((item, index) => {
|
|
28
|
+
const tickY = getTickY(index);
|
|
29
|
+
const label = formatLabel(item, index);
|
|
30
|
+
return (jsxs("g", { children: [showTicks && (jsx("line", { x1: x - tickLength, y1: tickY, x2: x, y2: tickY, className: "stroke-[var(--color-border)]", strokeWidth: 1 })), jsx(ChartText, { x: x - tickLength - tickPadding, y: tickY, textAnchor: textAnchor, dominantBaseline: "middle", maxWidth: maxLabelWidth, truncate: !!maxLabelWidth, children: label })] }, index));
|
|
31
|
+
})] }));
|
|
32
|
+
});
|
|
33
|
+
CategoryYAxis.displayName = "CategoryYAxis";
|
|
34
|
+
|
|
35
|
+
export { CategoryYAxis };
|