@acronis-platform/ui-react 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ui/accordion-container/accordion-container.js +14 -14
- package/dist/components/ui/accordion-container/accordion-container.js.map +1 -1
- package/dist/components/ui/app-shell-chat/app-shell-chat.js.map +1 -1
- package/dist/components/ui/area-chart/area-chart.js +141 -139
- package/dist/components/ui/area-chart/area-chart.js.map +1 -1
- package/dist/components/ui/bar-chart/bar-chart.js +295 -293
- package/dist/components/ui/bar-chart/bar-chart.js.map +1 -1
- package/dist/components/ui/category-bar/category-bar.js +109 -93
- package/dist/components/ui/category-bar/category-bar.js.map +1 -1
- package/dist/components/ui/chart/chart-palette.js +113 -0
- package/dist/components/ui/chart/chart-palette.js.map +1 -0
- package/dist/components/ui/chart/chart.js +176 -129
- package/dist/components/ui/chart/chart.js.map +1 -1
- package/dist/components/ui/chart-state/chart-state-illustrations.js +310 -0
- package/dist/components/ui/chart-state/chart-state-illustrations.js.map +1 -0
- package/dist/components/ui/chart-state/chart-state.js +48 -34
- package/dist/components/ui/chart-state/chart-state.js.map +1 -1
- package/dist/components/ui/chart-widget/chart-widget.js +87 -0
- package/dist/components/ui/chart-widget/chart-widget.js.map +1 -0
- package/dist/components/ui/composed-chart/composed-chart.js +117 -115
- package/dist/components/ui/composed-chart/composed-chart.js.map +1 -1
- package/dist/components/ui/confidence-cone/confidence-cone.js +166 -158
- package/dist/components/ui/confidence-cone/confidence-cone.js.map +1 -1
- package/dist/components/ui/funnel-chart/funnel-chart.js +162 -161
- package/dist/components/ui/funnel-chart/funnel-chart.js.map +1 -1
- package/dist/components/ui/histogram/histogram.js +94 -92
- package/dist/components/ui/histogram/histogram.js.map +1 -1
- package/dist/components/ui/input/input.js.map +1 -1
- package/dist/components/ui/label/label.js +2 -9
- package/dist/components/ui/label/label.js.map +1 -1
- package/dist/components/ui/line-chart/line-chart.js +143 -141
- package/dist/components/ui/line-chart/line-chart.js.map +1 -1
- package/dist/components/ui/metric/metric.js +74 -185
- package/dist/components/ui/metric/metric.js.map +1 -1
- package/dist/components/ui/page-content/page-content.js.map +1 -1
- package/dist/components/ui/pie-chart/pie-chart.js +201 -195
- package/dist/components/ui/pie-chart/pie-chart.js.map +1 -1
- package/dist/components/ui/radar-chart/radar-chart.js +133 -131
- package/dist/components/ui/radar-chart/radar-chart.js.map +1 -1
- package/dist/components/ui/radial-bar-chart/radial-bar-chart.js +297 -265
- package/dist/components/ui/radial-bar-chart/radial-bar-chart.js.map +1 -1
- package/dist/components/ui/sankey-chart/sankey-chart.js +123 -101
- package/dist/components/ui/sankey-chart/sankey-chart.js.map +1 -1
- package/dist/components/ui/scatter-chart/scatter-chart.js +76 -74
- package/dist/components/ui/scatter-chart/scatter-chart.js.map +1 -1
- package/dist/components/ui/section/section.js +157 -31
- package/dist/components/ui/section/section.js.map +1 -1
- package/dist/components/ui/stepper/stepper.js +24 -24
- package/dist/components/ui/stepper/stepper.js.map +1 -1
- package/dist/components/ui/stepper-item/stepper-item.js +43 -24
- package/dist/components/ui/stepper-item/stepper-item.js.map +1 -1
- package/dist/components/ui/treemap/treemap.js +133 -124
- package/dist/components/ui/treemap/treemap.js.map +1 -1
- package/dist/components/ui/trend-indicator/trend-indicator.js +34 -69
- package/dist/components/ui/trend-indicator/trend-indicator.js.map +1 -1
- package/dist/components/ui/wizard/wizard.js +59 -0
- package/dist/components/ui/wizard/wizard.js.map +1 -0
- package/dist/hooks/use-wizard.js +75 -0
- package/dist/hooks/use-wizard.js.map +1 -0
- package/dist/index.js +502 -497
- package/dist/index.js.map +1 -1
- package/dist/llms/accordion-container.md +181 -0
- package/dist/llms/accordion.md +124 -0
- package/dist/llms/alert.md +225 -0
- package/dist/llms/app-shell-chat.md +415 -0
- package/dist/llms/area-chart.md +355 -0
- package/dist/llms/avatar.md +208 -0
- package/dist/llms/bar-chart.md +406 -0
- package/dist/llms/breadcrumb.md +326 -0
- package/dist/llms/button-group.md +298 -0
- package/dist/llms/button-icon-input.md +142 -0
- package/dist/llms/button-icon-menu.md +209 -0
- package/dist/llms/button-icon.md +128 -0
- package/dist/llms/button-menu.md +172 -0
- package/dist/llms/button.md +185 -0
- package/dist/llms/calendar-panel.md +733 -0
- package/dist/llms/calendar.md +188 -0
- package/dist/llms/card-filter.md +214 -0
- package/dist/llms/card-section.md +293 -0
- package/dist/llms/card.md +447 -0
- package/dist/llms/carousel-dialog.md +156 -0
- package/dist/llms/category-bar.md +193 -0
- package/dist/llms/chart-state.md +190 -0
- package/dist/llms/chart-widget.md +209 -0
- package/dist/llms/chart.md +182 -0
- package/dist/llms/checkbox.md +257 -0
- package/dist/llms/chip.md +195 -0
- package/dist/llms/combobox.md +164 -0
- package/dist/llms/composed-chart.md +508 -0
- package/dist/llms/confidence-cone.md +277 -0
- package/dist/llms/data-table.md +474 -0
- package/dist/llms/date-range-picker.md +272 -0
- package/dist/llms/description-list.md +131 -0
- package/dist/llms/dialog-footer-carousel.md +147 -0
- package/dist/llms/dialog-footer-default.md +142 -0
- package/dist/llms/dialog-root.md +246 -0
- package/dist/llms/dialog-welcome.md +223 -0
- package/dist/llms/dialog.md +403 -0
- package/dist/llms/dropdown-menu.md +193 -0
- package/dist/llms/empty-overlay.md +146 -0
- package/dist/llms/empty.md +156 -0
- package/dist/llms/field.md +185 -0
- package/dist/llms/filter-cards.md +157 -0
- package/dist/llms/filter-chips.md +323 -0
- package/dist/llms/filter-search.md +512 -0
- package/dist/llms/form.md +154 -0
- package/dist/llms/funnel-chart.md +333 -0
- package/dist/llms/grid.md +80 -0
- package/dist/llms/histogram.md +190 -0
- package/dist/llms/input-date-picker.md +203 -0
- package/dist/llms/input-otp.md +173 -0
- package/dist/llms/input-password.md +197 -0
- package/dist/llms/input-search.md +170 -0
- package/dist/llms/input-select.md +278 -0
- package/dist/llms/input-text-area.md +271 -0
- package/dist/llms/input-text.md +192 -0
- package/dist/llms/line-chart.md +369 -0
- package/dist/llms/link.md +209 -0
- package/dist/llms/loading.md +130 -0
- package/dist/llms/meter.md +177 -0
- package/dist/llms/metric.md +204 -0
- package/dist/llms/number-field.md +122 -0
- package/dist/llms/page-content.md +69 -0
- package/dist/llms/page-header.md +182 -0
- package/dist/llms/pagination.md +133 -0
- package/dist/llms/pie-chart.md +307 -0
- package/dist/llms/popover.md +252 -0
- package/dist/llms/progress-circle.md +126 -0
- package/dist/llms/progress.md +111 -0
- package/dist/llms/radar-chart.md +316 -0
- package/dist/llms/radial-bar-chart.md +319 -0
- package/dist/llms/radio.md +255 -0
- package/dist/llms/resizable.md +195 -0
- package/dist/llms/sankey-chart.md +208 -0
- package/dist/llms/scatter-chart.md +239 -0
- package/dist/llms/scroll-area.md +183 -0
- package/dist/llms/section.md +401 -0
- package/dist/llms/select.md +210 -0
- package/dist/llms/separator.md +87 -0
- package/dist/llms/sheet.md +202 -0
- package/dist/llms/sidebar-primary.md +360 -0
- package/dist/llms/sidebar-secondary.md +417 -0
- package/dist/llms/skeleton.md +81 -0
- package/dist/llms/slider.md +97 -0
- package/dist/llms/spinner.md +100 -0
- package/dist/llms/stack.md +80 -0
- package/dist/llms/stepper-item.md +309 -0
- package/dist/llms/stepper.md +251 -0
- package/dist/llms/switch.md +140 -0
- package/dist/llms/table.md +436 -0
- package/dist/llms/tabs.md +197 -0
- package/dist/llms/tag.md +139 -0
- package/dist/llms/timeline.md +361 -0
- package/dist/llms/timer.md +259 -0
- package/dist/llms/toast.md +241 -0
- package/dist/llms/toggle-group.md +121 -0
- package/dist/llms/toolbar.md +453 -0
- package/dist/llms/tooltip.md +164 -0
- package/dist/llms/treemap.md +254 -0
- package/dist/llms/trend-indicator.md +132 -0
- package/dist/llms/widget-placeholder.md +169 -0
- package/dist/llms/wizard.md +412 -0
- package/dist/llms.txt +142 -0
- package/dist/react.js +502 -497
- package/dist/react.js.map +1 -1
- package/dist/src/components/ui/area-chart/area-chart.d.ts +9 -4
- package/dist/src/components/ui/avatar/avatar.d.ts +1 -1
- package/dist/src/components/ui/bar-chart/bar-chart.d.ts +9 -4
- package/dist/src/components/ui/category-bar/category-bar.d.ts +10 -4
- package/dist/src/components/ui/chart/__stories__/palette-control.d.ts +48 -0
- package/dist/src/components/ui/chart/__tests__/chart-palette.test.d.ts +1 -0
- package/dist/src/components/ui/chart/chart-palette.d.ts +128 -0
- package/dist/src/components/ui/chart/chart.d.ts +66 -15
- package/dist/src/components/ui/chart/index.d.ts +4 -2
- package/dist/src/components/ui/chart-state/chart-state-illustrations.d.ts +6 -0
- package/dist/src/components/ui/chart-state/chart-state.d.ts +13 -2
- package/dist/src/components/ui/chart-state/index.d.ts +1 -0
- package/dist/src/components/ui/chart-widget/chart-widget.d.ts +64 -0
- package/dist/src/components/ui/chart-widget/index.d.ts +1 -0
- package/dist/src/components/ui/composed-chart/composed-chart.d.ts +12 -7
- package/dist/src/components/ui/confidence-cone/confidence-cone.d.ts +10 -5
- package/dist/src/components/ui/empty-overlay/empty-overlay.d.ts +1 -1
- package/dist/src/components/ui/funnel-chart/funnel-chart.d.ts +11 -5
- package/dist/src/components/ui/histogram/histogram.d.ts +10 -4
- package/dist/src/components/ui/label/index.d.ts +1 -1
- package/dist/src/components/ui/label/label.d.ts +1 -5
- package/dist/src/components/ui/line-chart/line-chart.d.ts +9 -4
- package/dist/src/components/ui/metric/metric.d.ts +13 -14
- package/dist/src/components/ui/pie-chart/pie-chart.d.ts +17 -8
- package/dist/src/components/ui/radar-chart/radar-chart.d.ts +10 -5
- package/dist/src/components/ui/radial-bar-chart/radial-bar-chart.d.ts +17 -6
- package/dist/src/components/ui/sankey-chart/sankey-chart.d.ts +10 -5
- package/dist/src/components/ui/scatter-chart/scatter-chart.d.ts +10 -5
- package/dist/src/components/ui/section/index.d.ts +1 -1
- package/dist/src/components/ui/section/section.d.ts +75 -6
- package/dist/src/components/ui/stepper-item/stepper-item.d.ts +6 -5
- package/dist/src/components/ui/tag/tag.d.ts +1 -1
- package/dist/src/components/ui/treemap/treemap.d.ts +11 -5
- package/dist/src/components/ui/trend-indicator/trend-indicator.d.ts +3 -7
- package/dist/src/components/ui/wizard/index.d.ts +1 -0
- package/dist/src/components/ui/wizard/wizard.d.ts +6 -0
- package/dist/src/hooks/index.d.ts +1 -0
- package/dist/src/hooks/use-wizard.d.ts +80 -0
- package/dist/src/index.d.ts +2 -3
- package/dist/ui-react.css +1 -1
- package/package.json +9 -3
- package/dist/components/ui/app-shell/app-shell.js +0 -75
- package/dist/components/ui/app-shell/app-shell.js.map +0 -1
- package/dist/components/ui/auth-layout/auth-layout.js +0 -56
- package/dist/components/ui/auth-layout/auth-layout.js.map +0 -1
- package/dist/components/ui/collapsible/collapsible.js +0 -22
- package/dist/components/ui/collapsible/collapsible.js.map +0 -1
- package/dist/src/components/ui/app-shell/app-shell.d.ts +0 -8
- package/dist/src/components/ui/app-shell/index.d.ts +0 -1
- package/dist/src/components/ui/auth-layout/auth-layout.d.ts +0 -6
- package/dist/src/components/ui/auth-layout/index.d.ts +0 -1
- package/dist/src/components/ui/collapsible/collapsible.d.ts +0 -5
- package/dist/src/components/ui/collapsible/index.d.ts +0 -1
- package/dist/src/components/ui/label/label.docs.d.ts +0 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"category-bar.js","sources":["../../../../src/components/ui/category-bar/category-bar.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\nimport { ChartStyle, type ChartConfig } from '../chart';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip';\n\n// A category bar: a single horizontal bar split into proportional colored\n// segments — one part-to-whole across a handful of categories, in one row\n// (onboarding stages, certification status, a rating scale). Unlike `Meter`\n// (one value per row, stacked into a bar list), all segments share the same bar.\n// It's a plain flex composition, not a recharts chart: each segment's width is\n// `value / total`, so exact proportions and the count/% legend are direct DOM,\n// with no axes/grid to hide. Segment colors are caller-supplied via `config`\n// (existing semantic `--ui-*` tokens); there is no chart palette tier yet.\n//\n// Colors are consumed through the same `--color-<key>` bridge the recharts\n// charts use: `ChartStyle` emits one custom property per config entry, so a\n// `theme: { light, dark }` entry works as well as a flat `color` — reading\n// `config[key].color` directly would render a themed config colorless. The\n// tooltip is portaled out of the bar's DOM, so its popup carries its own\n// `data-chart` scope + `ChartStyle` to keep the bridge resolvable there.\n\nconst defaultFormat = (value: number) => value.toLocaleString();\n\n// Track height only — the flex/rounded/overflow chrome is static.\nconst categoryBarVariants = cva('flex w-full overflow-hidden rounded-full bg-input', {\n variants: {\n size: {\n sm: 'h-1.5',\n md: 'h-2.5',\n lg: 'h-4',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\nexport interface CategoryBarSegment {\n /** Key into `config` for this segment's label + color. */\n key: string;\n /** The segment's value — its width is this over the sum of all values. */\n value: number;\n}\n\n/** The resolved segment passed to a custom `tooltipContent` renderer. */\nexport interface CategoryBarTooltipContext extends CategoryBarSegment {\n /** Resolved `config` label (falls back to the key); may be any `ReactNode`. */\n label: React.ReactNode;\n /** Share of the total as a rounded percentage (0–100). */\n percent: number;\n /**\n * CSS color reference for the segment — the `var(--color-<key>)` bridge, which\n * resolves the config entry's `color` or its per-theme `theme` value. Usable\n * anywhere a CSS color is (e.g. a `style` background); not a literal value.\n */\n color: string;\n}\n\nexport interface CategoryBarProps\n extends Omit<React.ComponentProps<'div'>, 'children'>,\n VariantProps<typeof categoryBarVariants> {\n /** Ordered segments (left → right). Widths are proportional to `value`. */\n data: ReadonlyArray<CategoryBarSegment>;\n /** Maps each segment `key` to a `label` and `color` (an existing `--ui-*` token). */\n config: ChartConfig;\n /** Show the legend below the bar (color dot + label + value + %). */\n showLegend?: boolean;\n /** Show a hover tooltip per segment (dot + label + value + %). */\n showTooltip?: boolean;\n /**\n * Custom tooltip content per segment — replaces the default (dot + label +\n * `value · %`) inside the same card. Ignored when `showTooltip` is false.\n */\n tooltipContent?: (segment: CategoryBarTooltipContext) => React.ReactNode;\n /** Format the numeric value (legend + tooltip). Defaults to `toLocaleString()`. */\n valueFormatter?: (value: number) => string;\n /** Render the tooltip for this segment index initially open (VR/testing). */\n defaultOpenIndex?: number;\n /**\n * Accessible summary of the whole bar. Defaults to a `label value` list built\n * from the data; pass a fuller sentence for screen readers if you have one.\n */\n 'aria-label'?: string;\n}\n\n/**\n * One segment's hover card.\n *\n * It re-declares `data-chart` and re-renders `ChartStyle` because the popup is\n * portaled out of the bar: outside that subtree the `--color-*` bridge the\n * swatch reads has nothing to resolve against.\n */\nfunction CategoryBarSegmentTooltip({\n chartId,\n config,\n color,\n label,\n percent,\n segmentKey,\n value,\n valueFormatter,\n renderContent,\n}: {\n chartId: string;\n config: ChartConfig;\n color: string;\n label: React.ReactNode;\n percent: number;\n segmentKey: string;\n value: number;\n valueFormatter: (value: number) => string;\n // Not named `render`: in this package that name is reserved for Base UI's\n // polymorphic composition prop (see `<TooltipTrigger render={…} />` below).\n renderContent?: (segment: CategoryBarTooltipContext) => React.ReactNode;\n}) {\n return (\n <TooltipContent\n data-chart={chartId}\n className={cn(\n 'border border-border bg-background text-foreground shadow-md',\n !renderContent && 'flex items-center gap-2'\n )}\n >\n <ChartStyle id={chartId} config={config} />\n {renderContent ? (\n renderContent({ key: segmentKey, value, label, percent, color })\n ) : (\n <>\n <span\n className=\"size-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: color }}\n />\n <span className=\"font-semibold\">{label}</span>\n <span className=\"text-muted-foreground tabular-nums\">\n {valueFormatter(value)} · {percent}%\n </span>\n </>\n )}\n </TooltipContent>\n );\n}\n\nconst CategoryBar = React.forwardRef<HTMLDivElement, CategoryBarProps>(\n (\n {\n className,\n data,\n config,\n size,\n showLegend = false,\n showTooltip = true,\n tooltipContent,\n valueFormatter = defaultFormat,\n defaultOpenIndex,\n 'aria-label': ariaLabel,\n ...props\n },\n ref\n ) => {\n const uniqueId = React.useId();\n const chartId = `chart-${uniqueId.replace(/:/g, '')}`;\n\n const total = data.reduce((sum, seg) => sum + seg.value, 0);\n const labelFor = (key: string): React.ReactNode => config[key]?.label ?? key;\n // The aria-label has to be a plain string, so a rich (element) label can't\n // be used there — fall back to the key rather than stringifying it into\n // \"[object Object]\".\n const labelTextFor = (key: string) => {\n const label = config[key]?.label;\n return typeof label === 'string' || typeof label === 'number'\n ? String(label)\n : key;\n };\n const colorOf = (key: string) => `var(--color-${key})`;\n const pctOf = (value: number) =>\n total > 0 ? Math.round((value / total) * 100) : 0;\n\n // A locale-neutral fallback: \"<label> <value>\" pairs. Consumers can pass a\n // fuller `aria-label` sentence.\n const summary =\n ariaLabel ??\n data\n .map((seg) => `${labelTextFor(seg.key)} ${valueFormatter(seg.value)}`)\n .join(', ');\n\n return (\n <div\n ref={ref}\n data-chart={chartId}\n className={cn('flex w-full flex-col gap-3', className)}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <div className={categoryBarVariants({ size })} role=\"img\" aria-label={summary}>\n {data.map((seg, index) => {\n const color = colorOf(seg.key);\n // flex-grow proportional to value with a zero basis → widths are\n // exactly value/total; a zero-value segment collapses.\n const segment = (\n <div\n key={seg.key}\n className=\"h-full min-w-0\"\n style={{ flex: `${seg.value} 0 0%`, backgroundColor: color }}\n />\n );\n\n if (!showTooltip) return segment;\n\n return (\n <Tooltip key={seg.key} defaultOpen={index === defaultOpenIndex}>\n <TooltipTrigger render={segment} />\n <CategoryBarSegmentTooltip\n chartId={chartId}\n config={config}\n color={color}\n label={labelFor(seg.key)}\n percent={pctOf(seg.value)}\n segmentKey={seg.key}\n value={seg.value}\n valueFormatter={valueFormatter}\n renderContent={tooltipContent}\n />\n </Tooltip>\n );\n })}\n </div>\n\n {showLegend && (\n <ul className=\"flex flex-wrap justify-between gap-x-6 gap-y-3\">\n {data.map((seg) => (\n <li key={seg.key} className=\"flex flex-col gap-1.5\">\n <span className=\"flex items-center gap-1.5 text-sm leading-none text-muted-foreground\">\n <span\n className=\"size-2.5 shrink-0 rounded-sm\"\n style={{ backgroundColor: colorOf(seg.key) }}\n />\n {labelFor(seg.key)}\n </span>\n <span className=\"flex items-baseline gap-1.5 leading-none tabular-nums\">\n <span className=\"text-base font-semibold text-foreground\">\n {valueFormatter(seg.value)}\n </span>\n <span className=\"text-sm text-muted-foreground\">\n {pctOf(seg.value)}%\n </span>\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n }\n);\nCategoryBar.displayName = 'CategoryBar';\n\nexport { CategoryBar, categoryBarVariants };\n"],"names":["defaultFormat","value","categoryBarVariants","cva","CategoryBarSegmentTooltip","chartId","config","color","label","percent","segmentKey","valueFormatter","renderContent","jsxs","TooltipContent","cn","jsx","ChartStyle","Fragment","CategoryBar","React","className","data","size","showLegend","showTooltip","tooltipContent","defaultOpenIndex","ariaLabel","props","ref","total","sum","seg","labelFor","key","_a","labelTextFor","colorOf","pctOf","summary","index","segment","Tooltip","TooltipTrigger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"category-bar.js","sources":["../../../../src/components/ui/category-bar/category-bar.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\nimport {\n CHART_DEFAULT_PALETTE,\n ChartStyle,\n resolveChartColors,\n type ChartConfig,\n type ChartPalette,\n type ResolvedChartConfig,\n} from '../chart';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip';\n\n// A category bar: a single horizontal bar split into proportional colored\n// segments — one part-to-whole across a handful of categories, in one row\n// (onboarding stages, certification status, a rating scale). Unlike `Meter`\n// (one value per row, stacked into a bar list), all segments share the same bar.\n// It's a plain flex composition, not a recharts chart: each segment's width is\n// `value / total`, so exact proportions and the count/% legend are direct DOM,\n// with no axes/grid to hide. Segment colors come from the `palette` prop, the\n// same dataviz palettes the recharts charts use.\n//\n// Colors are consumed through the same `--color-<key>` bridge the recharts\n// charts use: `ChartStyle` emits one custom property per config entry, so a\n// `theme: { light, dark }` entry works as well as a flat `color` — reading\n// `config[key].color` directly would render a themed config colorless. The\n// tooltip is portaled out of the bar's DOM, so its popup carries its own\n// `data-chart` scope + `ChartStyle` to keep the bridge resolvable there.\n\nconst defaultFormat = (value: number) => value.toLocaleString();\n\n// Track height only — the flex/rounded/overflow chrome is static.\nconst categoryBarVariants = cva(\n 'flex w-full overflow-hidden rounded-full bg-input',\n {\n variants: {\n size: {\n sm: 'h-1.5',\n md: 'h-2.5',\n lg: 'h-4',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\nexport interface CategoryBarSegment {\n /** Key into `config` for this segment's label + color. */\n key: string;\n /** The segment's value — its width is this over the sum of all values. */\n value: number;\n}\n\n/** The resolved segment passed to a custom `tooltipContent` renderer. */\nexport interface CategoryBarTooltipContext extends CategoryBarSegment {\n /** Resolved `config` label (falls back to the key); may be any `ReactNode`. */\n label: React.ReactNode;\n /** Share of the total as a rounded percentage (0–100). */\n percent: number;\n /**\n * CSS color reference for the segment — the `var(--color-<key>)` bridge, which\n * resolves the palette stop assigned to this segment. Usable anywhere a CSS\n * color is (e.g. a `style` background); not a literal value.\n */\n color: string;\n}\n\nexport interface CategoryBarProps\n extends\n Omit<React.ComponentProps<'div'>, 'children'>,\n VariantProps<typeof categoryBarVariants> {\n /** Ordered segments (left → right). Widths are proportional to `value`. */\n data: ReadonlyArray<CategoryBarSegment>;\n /** Maps each segment `key` to a `label` and, optionally, a palette `tone`. */\n config: ChartConfig;\n /**\n * The dataviz palette the segments are painted from. Segments take a stop of\n * it in the palette's defined order, or the one their `tone` names. Defaults\n * to `categorical`.\n */\n palette?: ChartPalette;\n /** Show the legend below the bar (color dot + label + value + %). */\n showLegend?: boolean;\n /** Show a hover tooltip per segment (dot + label + value + %). */\n showTooltip?: boolean;\n /**\n * Custom tooltip content per segment — replaces the default (dot + label +\n * `value · %`) inside the same card. Ignored when `showTooltip` is false.\n */\n tooltipContent?: (segment: CategoryBarTooltipContext) => React.ReactNode;\n /** Format the numeric value (legend + tooltip). Defaults to `toLocaleString()`. */\n valueFormatter?: (value: number) => string;\n /** Render the tooltip for this segment index initially open (VR/testing). */\n defaultOpenIndex?: number;\n /**\n * Accessible summary of the whole bar. Defaults to a `label value` list built\n * from the data; pass a fuller sentence for screen readers if you have one.\n */\n 'aria-label'?: string;\n}\n\n/**\n * One segment's hover card.\n *\n * It re-declares `data-chart` and re-renders `ChartStyle` because the popup is\n * portaled out of the bar: outside that subtree the `--color-*` bridge the\n * swatch reads has nothing to resolve against.\n */\nfunction CategoryBarSegmentTooltip({\n chartId,\n config,\n color,\n label,\n percent,\n segmentKey,\n value,\n valueFormatter,\n renderContent,\n}: {\n chartId: string;\n config: ResolvedChartConfig;\n color: string;\n label: React.ReactNode;\n percent: number;\n segmentKey: string;\n value: number;\n valueFormatter: (value: number) => string;\n // Not named `render`: in this package that name is reserved for Base UI's\n // polymorphic composition prop (see `<TooltipTrigger render={…} />` below).\n renderContent?: (segment: CategoryBarTooltipContext) => React.ReactNode;\n}) {\n return (\n <TooltipContent\n data-chart={chartId}\n className={cn(\n 'border border-border bg-background text-foreground shadow-md',\n !renderContent && 'flex items-center gap-2'\n )}\n >\n <ChartStyle id={chartId} config={config} />\n {renderContent ? (\n renderContent({ key: segmentKey, value, label, percent, color })\n ) : (\n <>\n <span\n className=\"size-2.5 shrink-0 rounded-full\"\n style={{ backgroundColor: color }}\n />\n <span className=\"font-semibold\">{label}</span>\n <span className=\"text-muted-foreground tabular-nums\">\n {valueFormatter(value)} · {percent}%\n </span>\n </>\n )}\n </TooltipContent>\n );\n}\n\nconst CategoryBar = React.forwardRef<HTMLDivElement, CategoryBarProps>(\n (\n {\n className,\n data,\n config,\n palette = CHART_DEFAULT_PALETTE,\n size,\n showLegend = false,\n showTooltip = true,\n tooltipContent,\n valueFormatter = defaultFormat,\n defaultOpenIndex,\n 'aria-label': ariaLabel,\n ...props\n },\n ref\n ) => {\n const uniqueId = React.useId();\n const chartId = `chart-${uniqueId.replace(/:/g, '')}`;\n // Resolved here rather than by a `ChartContainer`: this component paints\n // plain divs, not a recharts plot, so it owns the `--color-*` emission for\n // both the bar and its portaled per-segment tooltip.\n const resolvedConfig = React.useMemo(\n () => resolveChartColors(config, palette),\n [config, palette]\n );\n\n const total = data.reduce((sum, seg) => sum + seg.value, 0);\n const labelFor = (key: string): React.ReactNode =>\n config[key]?.label ?? key;\n // The aria-label has to be a plain string, so a rich (element) label can't\n // be used there — fall back to the key rather than stringifying it into\n // \"[object Object]\".\n const labelTextFor = (key: string) => {\n const label = config[key]?.label;\n return typeof label === 'string' || typeof label === 'number'\n ? String(label)\n : key;\n };\n const colorOf = (key: string) => `var(--color-${key})`;\n const pctOf = (value: number) =>\n total > 0 ? Math.round((value / total) * 100) : 0;\n\n // A locale-neutral fallback: \"<label> <value>\" pairs. Consumers can pass a\n // fuller `aria-label` sentence.\n const summary =\n ariaLabel ??\n data\n .map((seg) => `${labelTextFor(seg.key)} ${valueFormatter(seg.value)}`)\n .join(', ');\n\n return (\n <div\n ref={ref}\n data-chart={chartId}\n className={cn('flex w-full flex-col gap-3', className)}\n {...props}\n >\n <ChartStyle id={chartId} config={resolvedConfig} />\n <div\n className={categoryBarVariants({ size })}\n role=\"img\"\n aria-label={summary}\n >\n {data.map((seg, index) => {\n const color = colorOf(seg.key);\n // flex-grow proportional to value with a zero basis → widths are\n // exactly value/total; a zero-value segment collapses.\n const segment = (\n <div\n key={seg.key}\n className=\"h-full min-w-0\"\n style={{ flex: `${seg.value} 0 0%`, backgroundColor: color }}\n />\n );\n\n if (!showTooltip) return segment;\n\n return (\n <Tooltip key={seg.key} defaultOpen={index === defaultOpenIndex}>\n <TooltipTrigger render={segment} />\n <CategoryBarSegmentTooltip\n chartId={chartId}\n config={resolvedConfig}\n color={color}\n label={labelFor(seg.key)}\n percent={pctOf(seg.value)}\n segmentKey={seg.key}\n value={seg.value}\n valueFormatter={valueFormatter}\n renderContent={tooltipContent}\n />\n </Tooltip>\n );\n })}\n </div>\n\n {showLegend && (\n <ul className=\"flex flex-wrap justify-between gap-x-6 gap-y-3\">\n {data.map((seg) => (\n <li key={seg.key} className=\"flex flex-col gap-1.5\">\n <span className=\"flex items-center gap-1.5 text-sm leading-none text-muted-foreground\">\n <span\n className=\"size-2.5 shrink-0 rounded-sm\"\n style={{ backgroundColor: colorOf(seg.key) }}\n />\n {labelFor(seg.key)}\n </span>\n <span className=\"flex items-baseline gap-1.5 leading-none tabular-nums\">\n <span className=\"text-base font-semibold text-foreground\">\n {valueFormatter(seg.value)}\n </span>\n <span className=\"text-sm text-muted-foreground\">\n {pctOf(seg.value)}%\n </span>\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n }\n);\nCategoryBar.displayName = 'CategoryBar';\n\nexport { CategoryBar, categoryBarVariants };\n"],"names":["defaultFormat","value","categoryBarVariants","cva","CategoryBarSegmentTooltip","chartId","config","color","label","percent","segmentKey","valueFormatter","renderContent","jsxs","TooltipContent","cn","jsx","ChartStyle","Fragment","CategoryBar","React","className","data","palette","CHART_DEFAULT_PALETTE","size","showLegend","showTooltip","tooltipContent","defaultOpenIndex","ariaLabel","props","ref","resolvedConfig","resolveChartColors","total","sum","seg","labelFor","key","_a","labelTextFor","colorOf","pctOf","summary","index","segment","Tooltip","TooltipTrigger"],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const s = (e) => `var(--ui-dataviz-${e})`, f = Object.freeze(
|
|
2
|
+
Array.from({ length: 16 }, (e, t) => s(`categorical-${t + 1}`))
|
|
3
|
+
), h = Object.freeze({
|
|
4
|
+
blue: Object.freeze(
|
|
5
|
+
Array.from({ length: 8 }, (e, t) => s(`sequential-blue-${t + 1}`))
|
|
6
|
+
),
|
|
7
|
+
teal: Object.freeze(
|
|
8
|
+
Array.from({ length: 8 }, (e, t) => s(`sequential-teal-${t + 1}`))
|
|
9
|
+
),
|
|
10
|
+
orange: Object.freeze(
|
|
11
|
+
Array.from({ length: 8 }, (e, t) => s(`sequential-orange-${t + 1}`))
|
|
12
|
+
),
|
|
13
|
+
violet: Object.freeze(
|
|
14
|
+
Array.from({ length: 8 }, (e, t) => s(`sequential-violet-${t + 1}`))
|
|
15
|
+
)
|
|
16
|
+
}), g = (e) => Object.freeze([
|
|
17
|
+
s(`diverging-${e}-a3`),
|
|
18
|
+
s(`diverging-${e}-a2`),
|
|
19
|
+
s(`diverging-${e}-a1`),
|
|
20
|
+
s(`diverging-${e}-b1`),
|
|
21
|
+
s(`diverging-${e}-b2`),
|
|
22
|
+
s(`diverging-${e}-b3`)
|
|
23
|
+
]), b = Object.freeze({
|
|
24
|
+
"blue-orange": g("blue-orange"),
|
|
25
|
+
"teal-violet": g("teal-violet")
|
|
26
|
+
}), u = Object.freeze({
|
|
27
|
+
danger: s("meaningful-status-danger"),
|
|
28
|
+
critical: s("meaningful-status-critical"),
|
|
29
|
+
warning: s("meaningful-status-warning"),
|
|
30
|
+
success: s("meaningful-status-success"),
|
|
31
|
+
info: s("meaningful-status-info"),
|
|
32
|
+
neutral: s("meaningful-status-neutral")
|
|
33
|
+
}), p = Object.freeze({
|
|
34
|
+
type: "categorical"
|
|
35
|
+
});
|
|
36
|
+
function d(e) {
|
|
37
|
+
switch (e.type) {
|
|
38
|
+
case "categorical":
|
|
39
|
+
return f;
|
|
40
|
+
case "sequential":
|
|
41
|
+
return h[e.ramp];
|
|
42
|
+
case "diverging":
|
|
43
|
+
return b[e.pair];
|
|
44
|
+
case "status":
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function A(e) {
|
|
49
|
+
switch (e.type) {
|
|
50
|
+
case "status":
|
|
51
|
+
return Object.keys(u).map(
|
|
52
|
+
(t) => ({ status: t })
|
|
53
|
+
);
|
|
54
|
+
case "categorical":
|
|
55
|
+
return f.map((t, r) => ({ slot: r + 1 }));
|
|
56
|
+
default:
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function i(e) {
|
|
61
|
+
process.env.NODE_ENV !== "production" && console.warn(`[ui-react] ${e}`);
|
|
62
|
+
}
|
|
63
|
+
function m(e, t, r) {
|
|
64
|
+
const a = Math.round(e);
|
|
65
|
+
return !Number.isFinite(e) || a < 1 || a > t ? (i(
|
|
66
|
+
`Chart series slot ${e} is outside the "${r.type}" palette (1–${t}). Clamping.`
|
|
67
|
+
), Math.min(
|
|
68
|
+
Math.max(Number.isFinite(a) ? a : 1, 1),
|
|
69
|
+
t
|
|
70
|
+
)) : a;
|
|
71
|
+
}
|
|
72
|
+
function $(e, { index: t, tone: r }) {
|
|
73
|
+
if (e.type === "status")
|
|
74
|
+
return r != null && r.status ? u[r.status] : (i(
|
|
75
|
+
'A chart series has no `status` under the "status" palette. Falling back to neutral.'
|
|
76
|
+
), u.neutral);
|
|
77
|
+
const a = d(e);
|
|
78
|
+
if (r != null && r.status)
|
|
79
|
+
i(
|
|
80
|
+
`A chart series names a status ("${r.status}") under the "${e.type}" palette, which has no status tones. Ignoring.`
|
|
81
|
+
);
|
|
82
|
+
else if (typeof (r == null ? void 0 : r.slot) == "number") {
|
|
83
|
+
if (e.type === "categorical")
|
|
84
|
+
return a[m(r.slot, a.length, e) - 1];
|
|
85
|
+
i(
|
|
86
|
+
`A chart series pins slot ${r.slot} under the "${e.type}" palette, whose stops are a ramp and are not individually selectable. Ignoring.`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return a[t % a.length];
|
|
90
|
+
}
|
|
91
|
+
function v(e, t) {
|
|
92
|
+
var a, c;
|
|
93
|
+
const r = /* @__PURE__ */ new Map();
|
|
94
|
+
for (const [n, l] of Object.entries(e)) {
|
|
95
|
+
if ((c = (a = t == null ? void 0 : t[n]) == null ? void 0 : a.tone) != null && c.sameAs)
|
|
96
|
+
continue;
|
|
97
|
+
const o = r.get(l);
|
|
98
|
+
o ? o.push(n) : r.set(l, [n]);
|
|
99
|
+
}
|
|
100
|
+
return [...r.values()].filter((n) => n.length > 1);
|
|
101
|
+
}
|
|
102
|
+
export {
|
|
103
|
+
f as CHART_CATEGORICAL_TOKENS,
|
|
104
|
+
p as CHART_DEFAULT_PALETTE,
|
|
105
|
+
b as CHART_DIVERGING_TOKENS,
|
|
106
|
+
h as CHART_SEQUENTIAL_TOKENS,
|
|
107
|
+
u as CHART_STATUS_TOKENS,
|
|
108
|
+
v as findDuplicateTones,
|
|
109
|
+
A as listPaletteChoices,
|
|
110
|
+
d as listPaletteStops,
|
|
111
|
+
$ as resolveSeriesColor
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=chart-palette.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-palette.js","sources":["../../../../src/components/ui/chart/chart-palette.ts"],"sourcesContent":["// The dataviz palettes a chart paints its series from.\n//\n// Every color here resolves to a `--ui-dataviz-*` token from\n// `@acronis-platform/tokens-pd`'s semantic tier (already imported by\n// `styles/index.css`), so light/dark and brand overrides come for free — the\n// tokens are `light-dark()` pairs. There is deliberately no `--ui-chart-*`\n// component tier: these tokens are already semantic and shared across every\n// chart type, and a 1:1 alias layer would be pure indirection (see\n// `context/conventions.md`, \"bridge what's reused\").\n//\n// The four palettes mirror the product's widget editor, which offers exactly\n// this choice — Categorical / Sequential / Diverging / Status — and then, for\n// Categorical and Status only, a per-series color picker. Sequential and\n// Diverging expose the ramp/pair and nothing else, so how N series spread\n// across a ramp's stops is this module's decision, not the user's.\n\n/** A sequential ramp: one hue, eight stops from lightest to darkest. */\nexport type ChartSequentialRamp = 'blue' | 'teal' | 'orange' | 'violet';\n\n/** A diverging pair: two hues meeting at a pale midpoint. */\nexport type ChartDivergingPair = 'blue-orange' | 'teal-violet';\n\n/**\n * A semantic status tone. Ordered by severity in the product's picker:\n * danger (red) · critical (orange) · warning (yellow) · success (green) ·\n * info (blue) · neutral (gray). Note that `critical` is orange and ranks\n * *below* `danger` — that is what the tokens say, across the whole semantic\n * tier, not a typo here.\n */\nexport type ChartStatusTone =\n | 'danger'\n | 'critical'\n | 'warning'\n | 'success'\n | 'info'\n | 'neutral';\n\n/** Which palette a chart's series are painted from. */\nexport type ChartPalette =\n | { type: 'categorical' }\n | { type: 'sequential'; ramp: ChartSequentialRamp }\n | { type: 'diverging'; pair: ChartDivergingPair }\n | { type: 'status' };\n\n/**\n * How one series picks its color out of the active palette.\n *\n * Only the two palettes whose colors are independent of each other accept an\n * override:\n *\n * - `categorical` — `{ slot }` picks one of the 16 hues.\n * - `status` — `{ status }` names a tone.\n *\n * `sequential` and `diverging` accept none. Their stops are a *ramp*: the\n * colors mean something only in relation to each other, so letting one series\n * jump to an arbitrary stop would break the reading order the ramp exists to\n * convey. The product's widget editor agrees — it offers a ramp/pair picker\n * and no per-series control. An override passed under those palettes is\n * ignored, with a dev warning.\n *\n * Neither form can express a color from outside the palette — that is the point.\n */\nexport type ChartSeriesTone =\n | { slot: number; status?: never; sameAs?: never }\n | { slot?: never; status: ChartStatusTone; sameAs?: never }\n /**\n * Paint whatever the series under this key paints, under any palette. For a\n * twin series that is the *same* metric drawn differently — a forecast tail\n * continuing its actuals, a projection band behind its bars — where two hues\n * would read as two metrics. Resolved by `resolveChartColors`, which is the\n * only place the whole config is in view.\n */\n | { slot?: never; status?: never; sameAs: string };\n\nconst token = (name: string) => `var(--ui-dataviz-${name})`;\n\n/** The 16 categorical hues, in the order the product's picker lists them. */\nexport const CHART_CATEGORICAL_TOKENS = Object.freeze(\n Array.from({ length: 16 }, (_, i) => token(`categorical-${i + 1}`))\n);\n\n/** Each sequential ramp's eight stops, lightest (1) to darkest (8). */\nexport const CHART_SEQUENTIAL_TOKENS: Readonly<\n Record<ChartSequentialRamp, readonly string[]>\n> = Object.freeze({\n blue: Object.freeze(\n Array.from({ length: 8 }, (_, i) => token(`sequential-blue-${i + 1}`))\n ),\n teal: Object.freeze(\n Array.from({ length: 8 }, (_, i) => token(`sequential-teal-${i + 1}`))\n ),\n orange: Object.freeze(\n Array.from({ length: 8 }, (_, i) => token(`sequential-orange-${i + 1}`))\n ),\n violet: Object.freeze(\n Array.from({ length: 8 }, (_, i) => token(`sequential-violet-${i + 1}`))\n ),\n});\n\n// Ordered `a3 → a1` then `b1 → b3`: strongest of the first hue, through the two\n// pale midpoints, out to the strongest of the second. That is the order the\n// ChartTreeMap mockup paints its tiles in (Figma node 8999:72012), and it is\n// what makes a diverging palette read as a single gradient rather than two\n// unrelated ramps.\nconst divergingStops = (pair: string) =>\n Object.freeze([\n token(`diverging-${pair}-a3`),\n token(`diverging-${pair}-a2`),\n token(`diverging-${pair}-a1`),\n token(`diverging-${pair}-b1`),\n token(`diverging-${pair}-b2`),\n token(`diverging-${pair}-b3`),\n ]);\n\n/** Each diverging pair's six stops, one hue's strongest through to the other's. */\nexport const CHART_DIVERGING_TOKENS: Readonly<\n Record<ChartDivergingPair, readonly string[]>\n> = Object.freeze({\n 'blue-orange': divergingStops('blue-orange'),\n 'teal-violet': divergingStops('teal-violet'),\n});\n\n/** The six semantic status tones. */\nexport const CHART_STATUS_TOKENS: Readonly<Record<ChartStatusTone, string>> =\n Object.freeze({\n danger: token('meaningful-status-danger'),\n critical: token('meaningful-status-critical'),\n warning: token('meaningful-status-warning'),\n success: token('meaningful-status-success'),\n info: token('meaningful-status-info'),\n neutral: token('meaningful-status-neutral'),\n });\n\n/** The default palette — what a chart paints with when none is chosen. */\nexport const CHART_DEFAULT_PALETTE: ChartPalette = Object.freeze({\n type: 'categorical',\n});\n\n/**\n * The stops a palette offers, in picker order. `status` has named tones rather\n * than positional stops, so it returns an empty list — use\n * `CHART_STATUS_TOKENS` for those.\n */\nexport function listPaletteStops(palette: ChartPalette): readonly string[] {\n switch (palette.type) {\n case 'categorical':\n return CHART_CATEGORICAL_TOKENS;\n case 'sequential':\n return CHART_SEQUENTIAL_TOKENS[palette.ramp];\n case 'diverging':\n return CHART_DIVERGING_TOKENS[palette.pair];\n case 'status':\n return [];\n }\n}\n\n/**\n * Every choice a per-series picker may offer for this palette — what the\n * product's widget editor renders in its dropdown. Pure, so the form can build\n * its UI without re-deriving the palette.\n *\n * Empty for `sequential` and `diverging`: those have no per-series control, so\n * a form driven by this function renders no picker for them, which is exactly\n * the design.\n */\nexport function listPaletteChoices(\n palette: ChartPalette\n): readonly ChartSeriesTone[] {\n switch (palette.type) {\n case 'status':\n return (Object.keys(CHART_STATUS_TOKENS) as ChartStatusTone[]).map(\n (status) => ({ status })\n );\n case 'categorical':\n return CHART_CATEGORICAL_TOKENS.map((_, i) => ({ slot: i + 1 }));\n default:\n return [];\n }\n}\n\nfunction warn(message: string) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`[ui-react] ${message}`);\n }\n}\n\nfunction clampSlot(slot: number, length: number, palette: ChartPalette) {\n const rounded = Math.round(slot);\n\n if (!Number.isFinite(slot) || rounded < 1 || rounded > length) {\n warn(\n `Chart series slot ${slot} is outside the \"${palette.type}\" palette (1–${length}). Clamping.`\n );\n return Math.min(\n Math.max(Number.isFinite(rounded) ? rounded : 1, 1),\n length\n );\n }\n\n return rounded;\n}\n\nexport interface ResolveSeriesColorOptions {\n /** This series' position among the chart's series. */\n index: number;\n /** This series' explicit choice within the palette, if it may make one. */\n tone?: ChartSeriesTone;\n}\n\n/**\n * The color one series paints with.\n *\n * Series walk the palette **in its defined order** — series 1 takes stop 1,\n * series 2 takes stop 2, and so on, wrapping once the stops run out. The order\n * is the design's, not something derived here: no re-ordering, no spreading\n * across a ramp, no skipping stops.\n *\n * On top of that, `categorical` and `status` honour a per-series override\n * (see `ChartSeriesTone`); `sequential` and `diverging` do not.\n *\n * Always returns a token from the active palette. A `slot` out of range is\n * clamped (with a dev warning) rather than passed through, so switching\n * palettes can never leave a series painting off-palette.\n */\nexport function resolveSeriesColor(\n palette: ChartPalette,\n { index, tone }: ResolveSeriesColorOptions\n): string {\n if (palette.type === 'status') {\n if (tone?.status) {\n return CHART_STATUS_TOKENS[tone.status];\n }\n\n // Unlike the ordered palettes there is no meaningful \"next\" tone to fall\n // back to — status colors carry meaning, and inventing one would be worse\n // than reading gray.\n warn(\n 'A chart series has no `status` under the \"status\" palette. Falling back to neutral.'\n );\n return CHART_STATUS_TOKENS.neutral;\n }\n\n const stops = listPaletteStops(palette);\n\n if (tone?.status) {\n warn(\n `A chart series names a status (\"${tone.status}\") under the \"${palette.type}\" palette, which has no status tones. Ignoring.`\n );\n } else if (typeof tone?.slot === 'number') {\n if (palette.type === 'categorical') {\n return stops[clampSlot(tone.slot, stops.length, palette) - 1];\n }\n\n warn(\n `A chart series pins slot ${tone.slot} under the \"${palette.type}\" palette, whose stops are a ramp and are not individually selectable. Ignoring.`\n );\n }\n\n // Wraps rather than clamps once the stops run out: a chart with more series\n // than the palette has colors is unreadable either way, but wrapping keeps\n // each series distinguishable from its immediate neighbours.\n return stops[index % stops.length];\n}\n\n/**\n * Series that would paint the same color — what the widget editor's \"duplicate\n * color\" warning is keyed to. Returns one group per collision, each holding the\n * colliding series' keys in input order.\n *\n * Only series that named a `tone` can collide: automatic assignment is\n * injective by construction (up to `categorical`'s 16-series wrap).\n *\n * Pass the chart's `config` to exclude intentional aliases: a series with\n * `tone: { sameAs }` shares its target's colour on purpose, so it is not a\n * collision. Without the config every alias reads as a duplicate.\n */\nexport function findDuplicateTones(\n colors: Readonly<Record<string, string>>,\n config?: Readonly<Record<string, { tone?: { sameAs?: string } }>>\n): string[][] {\n const byColor = new Map<string, string[]>();\n\n for (const [key, color] of Object.entries(colors)) {\n if (config?.[key]?.tone?.sameAs) {\n continue;\n }\n const group = byColor.get(color);\n if (group) {\n group.push(key);\n } else {\n byColor.set(color, [key]);\n }\n }\n\n return [...byColor.values()].filter((group) => group.length > 1);\n}\n"],"names":["token","name","CHART_CATEGORICAL_TOKENS","_","i","CHART_SEQUENTIAL_TOKENS","divergingStops","pair","CHART_DIVERGING_TOKENS","CHART_STATUS_TOKENS","CHART_DEFAULT_PALETTE","listPaletteStops","palette","listPaletteChoices","status","warn","message","clampSlot","slot","length","rounded","resolveSeriesColor","index","tone","stops","findDuplicateTones","colors","config","_a","_b","byColor","key","color","group"],"mappings":"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"}
|
|
@@ -1,29 +1,64 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import * as
|
|
1
|
+
import { jsx as s, jsxs as p, Fragment as L } from "react/jsx-runtime";
|
|
2
|
+
import * as b from "react";
|
|
3
3
|
import * as j from "recharts";
|
|
4
|
-
import { cn as
|
|
5
|
-
|
|
6
|
-
function
|
|
7
|
-
|
|
4
|
+
import { cn as x } from "../../../lib/utils.js";
|
|
5
|
+
import { CHART_DEFAULT_PALETTE as $, resolveSeriesColor as C, CHART_STATUS_TOKENS as A } from "./chart-palette.js";
|
|
6
|
+
function S(e, r) {
|
|
7
|
+
var h;
|
|
8
|
+
const t = Object.entries(e), n = (c) => {
|
|
9
|
+
var l;
|
|
10
|
+
return !!((l = c.tone) != null && l.sameAs);
|
|
11
|
+
};
|
|
12
|
+
let o = 0;
|
|
13
|
+
const i = {};
|
|
14
|
+
for (const [c, l] of t)
|
|
15
|
+
n(l) || (i[c] = {
|
|
16
|
+
...l,
|
|
17
|
+
color: C(r, { index: o++, tone: l.tone })
|
|
18
|
+
});
|
|
19
|
+
const a = /* @__PURE__ */ new Map();
|
|
20
|
+
for (const [c, l] of t)
|
|
21
|
+
n(l) && a.set(c, l.tone.sameAs);
|
|
22
|
+
let f = !0;
|
|
23
|
+
for (; f && a.size > 0; ) {
|
|
24
|
+
f = !1;
|
|
25
|
+
for (const [c, l] of a) {
|
|
26
|
+
const v = (h = i[l]) == null ? void 0 : h.color;
|
|
27
|
+
v !== void 0 && (i[c] = { ...e[c], color: v }, a.delete(c), f = !0);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
for (const [c, l] of a)
|
|
31
|
+
process.env.NODE_ENV !== "production" && console.warn(
|
|
32
|
+
`[ui-react] Chart series "${c}" aliases "${l}", which is not a palette-assigned series in this config. Falling back to neutral.`
|
|
33
|
+
), i[c] = { ...e[c], color: A.neutral };
|
|
34
|
+
return Object.fromEntries(t.map(([c]) => [c, i[c]]));
|
|
35
|
+
}
|
|
36
|
+
const T = b.createContext(null);
|
|
37
|
+
function y() {
|
|
38
|
+
const e = b.useContext(T);
|
|
8
39
|
if (!e)
|
|
9
40
|
throw new Error("useChart must be used within a <ChartContainer />");
|
|
10
41
|
return e;
|
|
11
42
|
}
|
|
12
|
-
function
|
|
43
|
+
function H({
|
|
13
44
|
id: e,
|
|
14
45
|
className: r,
|
|
15
46
|
children: t,
|
|
16
47
|
config: n,
|
|
17
|
-
|
|
48
|
+
palette: o = $,
|
|
49
|
+
...i
|
|
18
50
|
}) {
|
|
19
|
-
const
|
|
20
|
-
|
|
51
|
+
const a = b.useId(), f = `chart-${e || a.replace(/:/g, "")}`, h = b.useMemo(
|
|
52
|
+
() => S(n, o),
|
|
53
|
+
[n, o]
|
|
54
|
+
);
|
|
55
|
+
return /* @__PURE__ */ s(T.Provider, { value: { config: h }, children: /* @__PURE__ */ p(
|
|
21
56
|
"div",
|
|
22
57
|
{
|
|
23
58
|
id: e,
|
|
24
59
|
"data-slot": "chart",
|
|
25
|
-
"data-chart":
|
|
26
|
-
className:
|
|
60
|
+
"data-chart": f,
|
|
61
|
+
className: x(
|
|
27
62
|
"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden [&_.recharts-trapezoid[stroke='#fff']]:stroke-transparent",
|
|
28
63
|
// A `<Brush>` traveller is the one `.recharts-layer` that is a real
|
|
29
64
|
// control (`role="slider"`, tabbable, arrow-key driven), so the blanket
|
|
@@ -52,216 +87,228 @@ function O({
|
|
|
52
87
|
"[&_.recharts-surface]:[direction:ltr] rtl:[&_.recharts-surface_foreignObject]:[direction:rtl]",
|
|
53
88
|
r
|
|
54
89
|
),
|
|
55
|
-
...
|
|
90
|
+
...i,
|
|
56
91
|
children: [
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
-
/* @__PURE__ */
|
|
92
|
+
/* @__PURE__ */ s(O, { id: f, config: h }),
|
|
93
|
+
/* @__PURE__ */ s(j.ResponsiveContainer, { children: t })
|
|
59
94
|
]
|
|
60
95
|
}
|
|
61
96
|
) });
|
|
62
97
|
}
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
${t.map(([l, c]) => {
|
|
71
|
-
var u;
|
|
72
|
-
const i = ((u = c.theme) == null ? void 0 : u[n]) || c.color;
|
|
73
|
-
return i ? ` --color-${l}: ${i};` : null;
|
|
74
|
-
}).join(`
|
|
98
|
+
const O = ({
|
|
99
|
+
id: e,
|
|
100
|
+
config: r
|
|
101
|
+
}) => {
|
|
102
|
+
const t = Object.entries(r);
|
|
103
|
+
return t.length ? /* @__PURE__ */ s("style", { children: `[data-chart=${e}] {
|
|
104
|
+
${t.map(([n, o]) => ` --color-${n}: ${o.color};`).join(`
|
|
75
105
|
`)}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
`) }) : null;
|
|
80
|
-
};
|
|
81
|
-
function y({
|
|
82
|
-
marker: e,
|
|
83
|
-
color: r,
|
|
84
|
-
className: t
|
|
85
|
-
}) {
|
|
86
|
-
return /* @__PURE__ */ o(
|
|
87
|
-
"div",
|
|
88
|
-
{
|
|
89
|
-
className: d(
|
|
90
|
-
"shrink-0",
|
|
91
|
-
e === "swatch" ? "h-2.5 w-2.5 rounded-sm" : "h-[3px] w-4 rounded-full",
|
|
92
|
-
t
|
|
93
|
-
),
|
|
94
|
-
style: e === "dashed" ? {
|
|
95
|
-
// A dashed stroke can't be drawn with a background color, so the
|
|
96
|
-
// dash pattern is painted as a gradient.
|
|
97
|
-
backgroundImage: `repeating-linear-gradient(90deg, ${r} 0 4px, transparent 4px 7px)`
|
|
98
|
-
} : { backgroundColor: r }
|
|
99
|
-
}
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
const K = j.Tooltip;
|
|
103
|
-
function I({
|
|
106
|
+
}` }) : null;
|
|
107
|
+
}, K = j.Tooltip;
|
|
108
|
+
function P({
|
|
104
109
|
item: e,
|
|
105
110
|
index: r,
|
|
106
111
|
payload: t,
|
|
107
112
|
itemConfig: n,
|
|
108
|
-
indicatorColor:
|
|
109
|
-
hideIndicator:
|
|
110
|
-
formatter:
|
|
113
|
+
indicatorColor: o,
|
|
114
|
+
hideIndicator: i,
|
|
115
|
+
formatter: a
|
|
111
116
|
}) {
|
|
112
|
-
return /* @__PURE__ */
|
|
113
|
-
n != null && n.icon ? /* @__PURE__ */
|
|
117
|
+
return /* @__PURE__ */ s("div", { className: "flex w-full flex-wrap items-center gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", children: a && (e == null ? void 0 : e.value) !== void 0 && e.name ? a(e.value, e.name, e, r, t) : /* @__PURE__ */ p(L, { children: [
|
|
118
|
+
n != null && n.icon ? /* @__PURE__ */ s(n.icon, {}) : !i && // A row is always dotted, whatever marker the legend
|
|
114
119
|
// gives that series.
|
|
115
|
-
/* @__PURE__ */
|
|
120
|
+
/* @__PURE__ */ s(
|
|
116
121
|
"div",
|
|
117
122
|
{
|
|
118
123
|
className: "h-2.5 w-2.5 shrink-0 rounded-full",
|
|
119
|
-
style: { backgroundColor:
|
|
124
|
+
style: { backgroundColor: o }
|
|
120
125
|
}
|
|
121
126
|
),
|
|
122
|
-
/* @__PURE__ */
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
-
e.value != null && /* @__PURE__ */
|
|
127
|
+
/* @__PURE__ */ p("div", { className: "flex flex-1 items-center justify-between gap-4 leading-none", children: [
|
|
128
|
+
/* @__PURE__ */ s("span", { className: "text-muted-foreground", children: (n == null ? void 0 : n.label) || e.name }),
|
|
129
|
+
e.value != null && /* @__PURE__ */ s("span", { className: "font-medium tabular-nums text-foreground", children: e.value.toLocaleString() })
|
|
125
130
|
] })
|
|
126
131
|
] }) });
|
|
127
132
|
}
|
|
128
|
-
function
|
|
133
|
+
function U({
|
|
129
134
|
active: e,
|
|
130
135
|
payload: r,
|
|
131
136
|
label: t,
|
|
132
137
|
className: n,
|
|
133
|
-
hideLabel:
|
|
134
|
-
hideIndicator:
|
|
135
|
-
labelFormatter:
|
|
136
|
-
formatter:
|
|
137
|
-
labelClassName:
|
|
138
|
-
color:
|
|
139
|
-
nameKey:
|
|
140
|
-
labelKey:
|
|
138
|
+
hideLabel: o = !1,
|
|
139
|
+
hideIndicator: i = !1,
|
|
140
|
+
labelFormatter: a,
|
|
141
|
+
formatter: f,
|
|
142
|
+
labelClassName: h,
|
|
143
|
+
color: c,
|
|
144
|
+
nameKey: l,
|
|
145
|
+
labelKey: v
|
|
141
146
|
}) {
|
|
142
|
-
const { config:
|
|
143
|
-
if (
|
|
147
|
+
const { config: u } = y(), _ = b.useMemo(() => {
|
|
148
|
+
if (o || !(r != null && r.length))
|
|
144
149
|
return null;
|
|
145
|
-
const [
|
|
146
|
-
var
|
|
147
|
-
const
|
|
148
|
-
return typeof
|
|
150
|
+
const [d] = r, k = `${v || (d == null ? void 0 : d.dataKey) || (d == null ? void 0 : d.name) || "value"}`, g = w(u, d, k), N = (() => {
|
|
151
|
+
var E;
|
|
152
|
+
const m = !v && typeof t == "string" ? ((E = u[t]) == null ? void 0 : E.label) ?? t : g == null ? void 0 : g.label;
|
|
153
|
+
return typeof m == "string" || typeof m == "number" ? m : void 0;
|
|
149
154
|
})();
|
|
150
|
-
return
|
|
155
|
+
return a ? /* @__PURE__ */ s("div", { className: x("font-medium", h), children: a(N, r) }) : N ? /* @__PURE__ */ s("div", { className: x("font-medium", h), children: N }) : null;
|
|
151
156
|
}, [
|
|
152
157
|
t,
|
|
153
|
-
|
|
158
|
+
a,
|
|
154
159
|
r,
|
|
155
|
-
|
|
160
|
+
o,
|
|
161
|
+
h,
|
|
156
162
|
u,
|
|
157
|
-
|
|
158
|
-
b
|
|
163
|
+
v
|
|
159
164
|
]);
|
|
160
|
-
return !e || !(r != null && r.length) ? null : /* @__PURE__ */
|
|
165
|
+
return !e || !(r != null && r.length) ? null : /* @__PURE__ */ p(
|
|
161
166
|
"div",
|
|
162
167
|
{
|
|
163
|
-
className:
|
|
168
|
+
className: x(
|
|
164
169
|
"grid min-w-[8rem] items-start gap-1.5 rounded-[var(--ui-tooltip-container-border-radius)] border border-border bg-background px-[var(--ui-tooltip-container-padding-x)] py-[var(--ui-tooltip-container-padding-y)] text-xs text-foreground shadow-md",
|
|
165
170
|
n
|
|
166
171
|
),
|
|
167
172
|
children: [
|
|
168
|
-
|
|
169
|
-
/* @__PURE__ */
|
|
170
|
-
const
|
|
171
|
-
return /* @__PURE__ */
|
|
172
|
-
|
|
173
|
+
_,
|
|
174
|
+
/* @__PURE__ */ s("div", { className: "grid gap-1.5", children: r.map((d, k) => {
|
|
175
|
+
const g = `${l || d.name || d.dataKey || "value"}`;
|
|
176
|
+
return /* @__PURE__ */ s(
|
|
177
|
+
P,
|
|
173
178
|
{
|
|
174
|
-
item:
|
|
175
|
-
index:
|
|
179
|
+
item: d,
|
|
180
|
+
index: k,
|
|
176
181
|
payload: r,
|
|
177
|
-
itemConfig:
|
|
178
|
-
indicatorColor:
|
|
179
|
-
hideIndicator:
|
|
180
|
-
formatter:
|
|
182
|
+
itemConfig: w(u, d, g),
|
|
183
|
+
indicatorColor: c || d.payload.fill || d.color,
|
|
184
|
+
hideIndicator: i,
|
|
185
|
+
formatter: f
|
|
181
186
|
},
|
|
182
|
-
|
|
187
|
+
g
|
|
183
188
|
);
|
|
184
189
|
}) })
|
|
185
190
|
]
|
|
186
191
|
}
|
|
187
192
|
);
|
|
188
193
|
}
|
|
189
|
-
const
|
|
194
|
+
const V = j.Legend;
|
|
190
195
|
function R({
|
|
196
|
+
item: e,
|
|
197
|
+
itemConfig: r,
|
|
198
|
+
valueKey: t,
|
|
199
|
+
valueFormatter: n
|
|
200
|
+
}) {
|
|
201
|
+
var a;
|
|
202
|
+
const o = t ? (a = e.payload) == null ? void 0 : a[t] : void 0, i = o != null ? n ? n(o) : String(o) : void 0;
|
|
203
|
+
return /* @__PURE__ */ p("div", { className: "flex w-full items-start gap-2 overflow-hidden", children: [
|
|
204
|
+
/* @__PURE__ */ p("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
205
|
+
r != null && r.icon ? /* @__PURE__ */ s(r.icon, {}) : /* @__PURE__ */ s(
|
|
206
|
+
"div",
|
|
207
|
+
{
|
|
208
|
+
className: "h-2.5 w-2.5 shrink-0 rounded-full",
|
|
209
|
+
style: { backgroundColor: e.color }
|
|
210
|
+
}
|
|
211
|
+
),
|
|
212
|
+
/* @__PURE__ */ s("span", { className: "min-w-0 flex-1 truncate text-xs text-foreground", children: (r == null ? void 0 : r.label) ?? e.value })
|
|
213
|
+
] }),
|
|
214
|
+
i != null && /* @__PURE__ */ s("span", { className: "shrink-0 text-xs font-semibold text-[var(--ui-text-on-surface-link-idle)]", children: i })
|
|
215
|
+
] });
|
|
216
|
+
}
|
|
217
|
+
function I({
|
|
191
218
|
item: e,
|
|
192
219
|
itemConfig: r,
|
|
193
220
|
hideIcon: t
|
|
194
221
|
}) {
|
|
195
|
-
|
|
196
|
-
const n = (l = e.payload) == null ? void 0 : l.strokeDasharray, s = e.type !== "line" ? "swatch" : n ? "dashed" : "line";
|
|
197
|
-
return /* @__PURE__ */ v(
|
|
222
|
+
return /* @__PURE__ */ p(
|
|
198
223
|
"div",
|
|
199
224
|
{
|
|
200
|
-
className:
|
|
225
|
+
className: x(
|
|
201
226
|
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
|
|
202
227
|
),
|
|
203
228
|
children: [
|
|
204
|
-
r != null && r.icon && !t ? /* @__PURE__ */
|
|
229
|
+
r != null && r.icon && !t ? /* @__PURE__ */ s(r.icon, {}) : /* @__PURE__ */ s(
|
|
230
|
+
"div",
|
|
231
|
+
{
|
|
232
|
+
className: "h-2.5 w-2.5 shrink-0 rounded-full",
|
|
233
|
+
style: { backgroundColor: e.color }
|
|
234
|
+
}
|
|
235
|
+
),
|
|
205
236
|
(r == null ? void 0 : r.label) ?? e.value
|
|
206
237
|
]
|
|
207
238
|
}
|
|
208
239
|
);
|
|
209
240
|
}
|
|
210
|
-
function
|
|
241
|
+
function q({
|
|
211
242
|
className: e,
|
|
212
243
|
hideIcon: r = !1,
|
|
213
244
|
payload: t,
|
|
214
245
|
verticalAlign: n = "bottom",
|
|
215
|
-
nameKey:
|
|
216
|
-
config:
|
|
246
|
+
nameKey: o,
|
|
247
|
+
config: i,
|
|
248
|
+
variant: a = "default",
|
|
249
|
+
valueKey: f,
|
|
250
|
+
valueFormatter: h
|
|
217
251
|
}) {
|
|
218
|
-
var
|
|
219
|
-
const c = (
|
|
220
|
-
if (!
|
|
252
|
+
var v;
|
|
253
|
+
const c = (v = b.useContext(T)) == null ? void 0 : v.config, l = i ?? c;
|
|
254
|
+
if (!l)
|
|
221
255
|
throw new Error(
|
|
222
256
|
"ChartLegendContent must be used within a <ChartContainer /> or given a `config` prop"
|
|
223
257
|
);
|
|
224
|
-
return t != null && t.length ? /* @__PURE__ */
|
|
258
|
+
return t != null && t.length ? a === "list" ? /* @__PURE__ */ s("div", { className: x("flex flex-col", e), children: t.map((u) => {
|
|
259
|
+
const _ = `${o || u.dataKey || "value"}`;
|
|
260
|
+
return /* @__PURE__ */ s(
|
|
261
|
+
R,
|
|
262
|
+
{
|
|
263
|
+
item: u,
|
|
264
|
+
itemConfig: w(l, u, _),
|
|
265
|
+
valueKey: f,
|
|
266
|
+
valueFormatter: h
|
|
267
|
+
},
|
|
268
|
+
u.value
|
|
269
|
+
);
|
|
270
|
+
}) }) : /* @__PURE__ */ s(
|
|
225
271
|
"div",
|
|
226
272
|
{
|
|
227
|
-
className:
|
|
273
|
+
className: x(
|
|
228
274
|
// Wraps rather than overflowing: a legend with many entries (a treemap's
|
|
229
275
|
// one-per-tile, a pie's one-per-slice) is wider than the chart on a narrow
|
|
230
276
|
// surface, and a row that can't wrap paints past the chart's edge. The
|
|
231
277
|
// column gap is unchanged, so a legend that already fits on one row keeps
|
|
232
278
|
// its exact layout.
|
|
233
|
-
"flex flex-wrap items-center justify-
|
|
279
|
+
"flex flex-wrap items-center justify-center gap-x-6 gap-y-2",
|
|
234
280
|
n === "top" ? "pb-3" : "pt-3",
|
|
235
281
|
e
|
|
236
282
|
),
|
|
237
|
-
children: t.map((
|
|
238
|
-
const
|
|
239
|
-
return /* @__PURE__ */
|
|
240
|
-
|
|
283
|
+
children: t.map((u) => {
|
|
284
|
+
const _ = `${o || u.dataKey || "value"}`;
|
|
285
|
+
return /* @__PURE__ */ s(
|
|
286
|
+
I,
|
|
241
287
|
{
|
|
242
|
-
item:
|
|
243
|
-
itemConfig:
|
|
288
|
+
item: u,
|
|
289
|
+
itemConfig: w(l, u, _),
|
|
244
290
|
hideIcon: r
|
|
245
291
|
},
|
|
246
|
-
|
|
292
|
+
u.value
|
|
247
293
|
);
|
|
248
294
|
})
|
|
249
295
|
}
|
|
250
296
|
) : null;
|
|
251
297
|
}
|
|
252
|
-
function
|
|
298
|
+
function w(e, r, t) {
|
|
253
299
|
if (typeof r != "object" || r === null)
|
|
254
300
|
return;
|
|
255
301
|
const n = "payload" in r && typeof r.payload == "object" && r.payload !== null ? r.payload : void 0;
|
|
256
|
-
let
|
|
257
|
-
return t in r && typeof r[t] == "string" ?
|
|
302
|
+
let o = t;
|
|
303
|
+
return t in r && typeof r[t] == "string" ? o = r[t] : n && t in n && typeof n[t] == "string" && (o = n[t]), o in e ? e[o] : e[t];
|
|
258
304
|
}
|
|
259
305
|
export {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
306
|
+
H as ChartContainer,
|
|
307
|
+
V as ChartLegend,
|
|
308
|
+
q as ChartLegendContent,
|
|
309
|
+
O as ChartStyle,
|
|
264
310
|
K as ChartTooltip,
|
|
265
|
-
|
|
311
|
+
U as ChartTooltipContent,
|
|
312
|
+
S as resolveChartColors
|
|
266
313
|
};
|
|
267
314
|
//# sourceMappingURL=chart.js.map
|