nuxt-charts 2.2.1 → 3.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +80 -79
  3. package/dist/module.d.mts +4 -4
  4. package/dist/module.json +1 -1
  5. package/dist/module.mjs +64 -95
  6. package/dist/runtime/assets/components.css +1 -0
  7. package/dist/runtime/assets/theme.css +1 -0
  8. package/dist/runtime/components/AreaChart.d.vue.ts +19 -0
  9. package/dist/runtime/components/AreaChart.vue +149 -0
  10. package/dist/runtime/components/AreaChart.vue.d.ts +19 -0
  11. package/dist/runtime/components/BarChart.d.vue.ts +19 -0
  12. package/dist/runtime/components/BarChart.vue +175 -0
  13. package/dist/runtime/components/BarChart.vue.d.ts +19 -0
  14. package/dist/runtime/components/BubbleChart.d.vue.ts +19 -0
  15. package/dist/runtime/components/BubbleChart.vue +213 -0
  16. package/dist/runtime/components/BubbleChart.vue.d.ts +19 -0
  17. package/dist/runtime/components/CandlestickChart.d.vue.ts +19 -0
  18. package/dist/runtime/components/CandlestickChart.vue +329 -0
  19. package/dist/runtime/components/CandlestickChart.vue.d.ts +19 -0
  20. package/dist/runtime/components/DonutChart.d.vue.ts +21 -0
  21. package/dist/runtime/components/DonutChart.vue +116 -0
  22. package/dist/runtime/components/DonutChart.vue.d.ts +21 -0
  23. package/dist/runtime/components/FunnelChart.d.vue.ts +19 -0
  24. package/dist/runtime/components/FunnelChart.vue +152 -0
  25. package/dist/runtime/components/FunnelChart.vue.d.ts +19 -0
  26. package/dist/runtime/components/LineChart.d.vue.ts +19 -0
  27. package/dist/runtime/components/LineChart.vue +84 -0
  28. package/dist/runtime/components/LineChart.vue.d.ts +19 -0
  29. package/dist/runtime/components/RadarChart.d.vue.ts +19 -0
  30. package/dist/runtime/components/RadarChart.vue +90 -0
  31. package/dist/runtime/components/RadarChart.vue.d.ts +19 -0
  32. package/dist/runtime/components/RadialBarChart.d.vue.ts +19 -0
  33. package/dist/runtime/components/RadialBarChart.vue +81 -0
  34. package/dist/runtime/components/RadialBarChart.vue.d.ts +19 -0
  35. package/dist/runtime/components/StatusTrackerChart.d.vue.ts +19 -0
  36. package/dist/runtime/components/StatusTrackerChart.vue +147 -0
  37. package/dist/runtime/components/StatusTrackerChart.vue.d.ts +19 -0
  38. package/dist/runtime/components/internal/CandlestickTooltip.d.vue.ts +17 -0
  39. package/dist/runtime/components/internal/CandlestickTooltip.vue +38 -0
  40. package/dist/runtime/components/internal/CandlestickTooltip.vue.d.ts +17 -0
  41. package/dist/runtime/components/internal/CartesianFrame.d.vue.ts +40 -0
  42. package/dist/runtime/components/internal/CartesianFrame.vue +321 -0
  43. package/dist/runtime/components/internal/CartesianFrame.vue.d.ts +40 -0
  44. package/dist/runtime/components/internal/ChartLegend.d.vue.ts +11 -0
  45. package/dist/runtime/components/internal/ChartLegend.vue +22 -0
  46. package/dist/runtime/components/internal/ChartLegend.vue.d.ts +11 -0
  47. package/dist/runtime/components/internal/ChartTooltip.d.vue.ts +3 -0
  48. package/dist/runtime/components/internal/ChartTooltip.vue +39 -0
  49. package/dist/runtime/components/internal/ChartTooltip.vue.d.ts +3 -0
  50. package/dist/runtime/components/internal/CubeBarShape.d.vue.ts +28 -0
  51. package/dist/runtime/components/internal/CubeBarShape.vue +69 -0
  52. package/dist/runtime/components/internal/CubeBarShape.vue.d.ts +28 -0
  53. package/dist/runtime/components/internal/DitherDefs.d.ts +98 -0
  54. package/dist/runtime/components/internal/DitherDefs.js +158 -0
  55. package/dist/runtime/components/internal/FunnelLayeredShape.d.vue.ts +42 -0
  56. package/dist/runtime/components/internal/FunnelLayeredShape.vue +124 -0
  57. package/dist/runtime/components/internal/FunnelLayeredShape.vue.d.ts +42 -0
  58. package/dist/runtime/components/internal/GradientDefs.d.ts +46 -0
  59. package/dist/runtime/components/internal/GradientDefs.js +38 -0
  60. package/dist/runtime/enums.d.ts +65 -0
  61. package/dist/runtime/enums.js +40 -0
  62. package/dist/runtime/types/charts.d.ts +642 -0
  63. package/dist/runtime/types/charts.js +0 -0
  64. package/dist/runtime/types/shared.d.ts +202 -0
  65. package/dist/runtime/types/shared.js +0 -0
  66. package/dist/runtime/types.d.ts +8 -0
  67. package/dist/runtime/types.js +0 -0
  68. package/dist/runtime/utils/axis.d.ts +132 -0
  69. package/dist/runtime/utils/axis.js +93 -0
  70. package/dist/runtime/utils/categories.d.ts +36 -0
  71. package/dist/runtime/utils/categories.js +18 -0
  72. package/dist/runtime/utils/cubes.d.ts +100 -0
  73. package/dist/runtime/utils/cubes.js +73 -0
  74. package/dist/runtime/utils/curve.d.ts +12 -0
  75. package/dist/runtime/utils/curve.js +26 -0
  76. package/dist/runtime/utils/dither.d.ts +55 -0
  77. package/dist/runtime/utils/dither.js +45 -0
  78. package/dist/runtime/utils/gradient.d.ts +12 -0
  79. package/dist/runtime/utils/gradient.js +8 -0
  80. package/dist/runtime/utils/index.d.ts +6 -0
  81. package/dist/runtime/utils/index.js +6 -0
  82. package/dist/runtime/utils/legend.d.ts +27 -0
  83. package/dist/runtime/utils/legend.js +19 -0
  84. package/dist/runtime/utils/marker.d.ts +20 -0
  85. package/dist/runtime/utils/marker.js +21 -0
  86. package/dist/runtime/utils/style.d.ts +14 -0
  87. package/dist/runtime/utils/style.js +10 -0
  88. package/dist/runtime/utils/theme.d.ts +36 -0
  89. package/dist/runtime/utils/theme.js +45 -0
  90. package/package.json +56 -12
  91. package/dist/runtime/vue-chrts.d.ts +0 -1
  92. package/dist/runtime/vue-chrts.js +0 -13
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Shared config types, preserved from `nuxt-charts` v2.
3
+ *
4
+ * Kept structurally identical to the v2 (`vue-chrts`) types so existing
5
+ * templates keep type-checking after the engine swap to `vccs`. Types that
6
+ * were Unovis-specific and have no `vccs` analog are retained as inert
7
+ * shapes and marked `@deprecated` — passing them is a no-op, not an error.
8
+ */
9
+ /**
10
+ * Describes one category / series in a chart's legend: its label, colour, and
11
+ * visibility. Keyed by the data property it represents in a `categories` record.
12
+ */
13
+ export interface BulletLegendItemInterface {
14
+ name: string | number;
15
+ /** Series colour. An array is accepted for v2 compatibility; the first entry is used. */
16
+ color?: string | Array<string>;
17
+ className?: string;
18
+ inactive?: boolean;
19
+ hidden?: boolean;
20
+ pointer?: boolean;
21
+ /**
22
+ * Id of the y-axis this series is plotted against. Series sharing an id share
23
+ * a scale. Defaults to the primary axis, so charts that omit it are unchanged.
24
+ */
25
+ yAxis?: AxisId;
26
+ }
27
+ /** Identifies one y-axis. Series and axis configs are matched by this value. */
28
+ export type AxisId = string | number;
29
+ /**
30
+ * Configuration for one y-axis in a multi-axis chart, keyed by {@link AxisId}
31
+ * in the `yAxes` prop.
32
+ */
33
+ export interface YAxisConfig extends AxisConfig {
34
+ /** Which side of the plot area the axis is drawn on. Default `left`. */
35
+ orientation?: "left" | "right";
36
+ /** Axis label. */
37
+ label?: string;
38
+ /** Fixed domain as `[min, max]`. */
39
+ domain?: [number | undefined, number | undefined];
40
+ /** Desired number of ticks. */
41
+ numTicks?: number;
42
+ /** Formats this axis' ticks. */
43
+ formatter?: axisFormatter;
44
+ /** Hide the axis while still plotting its series. */
45
+ hide?: boolean;
46
+ }
47
+ /**
48
+ * Formats an axis tick value into a display string.
49
+ * Mapped onto the `vccs` axis `tickFormatter(value, index)`.
50
+ */
51
+ export type axisFormatter = ((tick: number, i?: number, ticks?: number[]) => string) | ((tick: Date, i?: number, ticks?: Date[]) => string);
52
+ /**
53
+ * Fine-grained axis appearance options.
54
+ *
55
+ * Only the fields with a `vccs` equivalent are applied (`tickFormatter`,
56
+ * `tickLine`). The remaining text-layout fields are retained for v2
57
+ * template compatibility and currently have no effect.
58
+ */
59
+ export interface AxisConfig {
60
+ tickLine?: boolean;
61
+ tickFormat?: axisFormatter;
62
+ /** Tick label font size, applied as the tick `<text>` `font-size`. */
63
+ tickTextFontSize?: string;
64
+ /** Tick label colour, applied as the tick `<text>` `fill`. */
65
+ tickTextColor?: string;
66
+ /** Tick label horizontal anchor (`left`→`start`, `right`→`end`, `center`→`middle`). */
67
+ tickTextAlign?: "left" | "right" | "center";
68
+ /** @deprecated No `vccs` equivalent; retained for v2 compatibility. */
69
+ tickTextAngle?: number;
70
+ /** @deprecated No `vccs` equivalent; retained for v2 compatibility. */
71
+ tickTextWidth?: number;
72
+ /** @deprecated No `vccs` equivalent; retained for v2 compatibility. */
73
+ tickTextFitMode?: "wrap" | "trim";
74
+ /** @deprecated No `vccs` equivalent; retained for v2 compatibility. */
75
+ tickTextTrimType?: "start" | "middle" | "end";
76
+ /** @deprecated No `vccs` equivalent; retained for v2 compatibility. */
77
+ tickTextForceWordBreak?: boolean;
78
+ /** @deprecated No `vccs` equivalent; retained for v2 compatibility. */
79
+ tickTextSeparator?: string | readonly string[];
80
+ minMaxTicksOnly?: boolean;
81
+ /** @deprecated No `vccs` equivalent; retained for v2 compatibility. */
82
+ minMaxTicksOnlyShowGridLines?: boolean;
83
+ tickValues?: readonly number[] | readonly Date[];
84
+ }
85
+ /**
86
+ * Tooltip behaviour options. Mapped onto `vccs` `<Tooltip>`.
87
+ */
88
+ export interface TooltipConfig {
89
+ /** Hide delay in milliseconds. */
90
+ hideDelay?: number;
91
+ /** Show delay in milliseconds. */
92
+ showDelay?: number;
93
+ /** If `true`, the tooltip follows the cursor. */
94
+ followCursor?: boolean;
95
+ }
96
+ /**
97
+ * @deprecated Unovis-only. `vccs` has no crosshair primitive; retained as an
98
+ * inert type so v2 templates keep type-checking. Has no effect.
99
+ */
100
+ export interface CrosshairConfig<T> {
101
+ color?: string | ((d: T, i: number) => string | undefined);
102
+ strokeColor?: string;
103
+ strokeWidth?: number;
104
+ template?: (d: T) => string;
105
+ }
106
+ /**
107
+ * @deprecated Unovis-only. `vccs` has no custom marker primitive; retained as
108
+ * an inert type so v2 templates keep type-checking. Has no effect.
109
+ */
110
+ /** Per-series marker (dot) options. */
111
+ export type MarkerSeriesConfig = {
112
+ type?: "circle" | "square" | "triangle" | "diamond";
113
+ size?: number;
114
+ strokeWidth?: number;
115
+ color?: string;
116
+ strokeColor?: string;
117
+ };
118
+ /**
119
+ * Marker configuration keyed by series (category) key, matching the v2 docs
120
+ * usage: `:marker-config="{ desktop: { type: 'circle', size: 6 } }"`.
121
+ *
122
+ * The legacy `{ id, config }` wrapper shape is still accepted for back-compat;
123
+ * the adapter reads `config` when present, else treats the value as the flat map.
124
+ */
125
+ export type MarkerConfig = Record<string, MarkerSeriesConfig> | {
126
+ id?: string;
127
+ config: Record<string, MarkerSeriesConfig>;
128
+ };
129
+ /** Per-side chart padding in pixels. */
130
+ export interface ChartPadding {
131
+ top: number;
132
+ right: number;
133
+ bottom: number;
134
+ left: number;
135
+ }
136
+ /**
137
+ * Per-chart appearance overrides. Every field maps onto a `--vc-*` CSS token
138
+ * (`runtime/assets/theme.css` for SVG + tokens, `runtime/assets/components.css`
139
+ * for HTML chrome) written inline on the chart root. Set `theme.legend.size` to
140
+ * scale legend, axis ticks, axis titles, and radar labels together.
141
+ */
142
+ export interface ChartTheme {
143
+ /** Grid + axis (domain) lines. */
144
+ grid?: {
145
+ /** Line colour. Token: `--vc-grid-color`. */
146
+ color?: string;
147
+ /** SVG dash pattern, e.g. `"3 3"` (solid: `"0"`). Token: `--vc-grid-dash`. */
148
+ dash?: string;
149
+ /** Line width in pixels. Token: `--vc-grid-width`. */
150
+ width?: number;
151
+ };
152
+ /** Axis ticks + labels. */
153
+ axis?: {
154
+ /** Tick label colour. Token: `--vc-tick-color`. */
155
+ tickColor?: string;
156
+ /** Tick label size. Defaults to `--vc-legend-size`. Token: `--vc-tick-size`. */
157
+ tickSize?: string;
158
+ /** Tick label weight. Token: `--vc-tick-weight`. */
159
+ tickWeight?: number | string;
160
+ /** Axis title colour. Token: `--vc-axis-label-color`. */
161
+ labelColor?: string;
162
+ /** Axis title size. Defaults to `--vc-legend-size`. Token: `--vc-axis-label-size`. */
163
+ labelSize?: string;
164
+ /** Domain (axis) line colour. Token: `--vc-axis-line-color`. */
165
+ lineColor?: string;
166
+ };
167
+ /** Legend text + spacing. */
168
+ legend?: {
169
+ /** Text colour. Token: `--vc-legend-color`. */
170
+ color?: string;
171
+ /** Font size for legend and all chart labels. Token: `--vc-legend-size`. */
172
+ size?: string;
173
+ /** Font weight. Token: `--vc-legend-weight`. */
174
+ weight?: number | string;
175
+ /** Gap between items, e.g. `"0.75rem"`. Token: `--vc-legend-gap`. */
176
+ gap?: string;
177
+ /** Gap between plot and legend, e.g. `"0.75rem"`. Token: `--vc-legend-inset`. */
178
+ inset?: string;
179
+ };
180
+ /** Hover cursor (the band/rect behind the hovered point). */
181
+ hover?: {
182
+ /** Fill colour. Token: `--vc-hover-fill`. */
183
+ fill?: string;
184
+ /** Stroke colour. Token: `--vc-hover-stroke`. */
185
+ stroke?: string;
186
+ /** Corner radius in pixels. Token: `--vc-hover-radius`. */
187
+ radius?: number;
188
+ /** Set `false` to hide the hover cursor entirely (tooltip still shows). */
189
+ visible?: boolean;
190
+ };
191
+ /** Tooltip container. */
192
+ tooltip?: {
193
+ /** Background colour. Token: `--vc-tooltip-bg`. */
194
+ bg?: string;
195
+ /** Text colour. Token: `--vc-tooltip-fg`. */
196
+ fg?: string;
197
+ /** Border colour. Token: `--vc-tooltip-border`. */
198
+ border?: string;
199
+ /** Corner radius, e.g. `"0.5rem"`. Token: `--vc-tooltip-radius`. */
200
+ radius?: string;
201
+ };
202
+ }
File without changes
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Public type surface for `nuxt-charts`.
3
+ *
4
+ * Re-exported via the module's `addImportsSources` so these auto-import in
5
+ * consumer code (`from "nuxt-charts/types"`).
6
+ */
7
+ export type * from "./types/shared";
8
+ export type * from "./types/charts";
File without changes
@@ -0,0 +1,132 @@
1
+ import type { AxisConfig, AxisId, axisFormatter, YAxisConfig } from "../types/shared.js";
2
+ import { type SeriesDescriptor } from "./categories.js";
3
+ /** `vccs` axis `tickFormatter` signature. */
4
+ export type VccsTickFormatter = (value: unknown, index: number) => string;
5
+ /** A `vccs` axis tick value (numbers for value axes, strings for category axes). */
6
+ export type VccsAxisTick = number | string;
7
+ /** `vccs` axis `interval` values we use. */
8
+ export type VccsAxisInterval = number | "preserveStartEnd";
9
+ /**
10
+ * Axis slot sizing tuned for gallery / dashboard charts. vccs defaults (Y width
11
+ * 60, X height 30, tickMargin 2) leave the value Y-axis too far from the plot
12
+ * and X tick labels hugging the bottom edge.
13
+ */
14
+ export declare const AXIS_SLOT: {
15
+ readonly numericYWidth: 40;
16
+ readonly categoryYWidth: 72;
17
+ readonly titledYWidth: 72;
18
+ readonly defaultXHeight: 38;
19
+ readonly titledXHeight: 52;
20
+ };
21
+ export declare function resolveYAxisWidth(options: {
22
+ hasTitle: boolean;
23
+ isCategoryAxis: boolean;
24
+ }): number;
25
+ export declare function resolveXAxisHeight(options: {
26
+ hasTitle: boolean;
27
+ }): number;
28
+ /**
29
+ * Gap (in px) between an axis line and its tick labels, passed to the native
30
+ * `vccs` `tickMargin` prop. vccs positions labels in SVG space from this value
31
+ * (X labels hang below the axis, Y labels are right-aligned toward the plot and
32
+ * vertically centred on each gridline), so we let it own positioning instead of
33
+ * nudging with CSS transforms. vccs's own default (2) leaves labels cramped.
34
+ */
35
+ export declare const AXIS_TICK_MARGIN: {
36
+ /** Between the x-axis line and the tick label below it. */
37
+ readonly x: 8;
38
+ /** Between the plot edge and the right-aligned y tick label. */
39
+ readonly y: 8;
40
+ };
41
+ /**
42
+ * The native `vccs` `tick` prop value for an axis. vccs accepts `true` (default
43
+ * SVG presentation, with per-orientation `textAnchor` / `verticalAnchor`) or an
44
+ * object of SVG attrs that override those defaults. We only ever override the
45
+ * horizontal anchor (from `AxisConfig.tickTextAlign`); colour / size / weight
46
+ * are themed via CSS variables on `.v-charts-cartesian-axis-tick-value`.
47
+ */
48
+ export declare function toTickProp(tick: Record<string, unknown> | undefined): true | {
49
+ textAnchor: string;
50
+ };
51
+ /**
52
+ * Resolved subset of `vccs` axis props derived from the v2 config API. Centralises
53
+ * the mapping for the props that *do* have a `vccs` equivalent (explicit ticks,
54
+ * min/max-only) so both axes in {@link CartesianFrame} stay consistent.
55
+ */
56
+ export interface ResolvedAxisProps {
57
+ /** Explicit tick values (`xExplicitTicks` / `tickValues`). */
58
+ ticks: VccsAxisTick[] | undefined;
59
+ /** Tick thinning. `preserveStartEnd` approximates v2 `minMaxTicksOnly`. */
60
+ interval: VccsAxisInterval | undefined;
61
+ /** Per-tick SVG presentation attributes (colour / font-size) from `AxisConfig`. */
62
+ tick: Record<string, unknown> | undefined;
63
+ }
64
+ /**
65
+ * Build `vccs` axis presentation props from the v2 explicit-tick props and
66
+ * {@link AxisConfig}. `explicitTicks` is the standalone `xExplicitTicks` /
67
+ * `yExplicitTicks` prop; `AxisConfig.tickValues` is the equivalent nested form
68
+ * and takes precedence when both are set.
69
+ *
70
+ * `minMaxTicksOnly` (top-level or in `AxisConfig`) maps onto
71
+ * `interval="preserveStartEnd"`, the closest `vccs` analog of "first & last only".
72
+ */
73
+ export declare function resolveAxisProps(explicitTicks: ReadonlyArray<number | string | Date> | undefined, config: AxisConfig | undefined, minMaxTicksOnly: boolean | undefined): ResolvedAxisProps;
74
+ /** One resolved y-axis, ready to render as a `vccs` `<YAxis>`. */
75
+ export interface ResolvedYAxis extends ResolvedAxisProps {
76
+ id: AxisId;
77
+ orientation: "left" | "right";
78
+ label: string | undefined;
79
+ domain: readonly [number, number] | undefined;
80
+ tickCount: number | undefined;
81
+ tickFormatter: VccsTickFormatter | undefined;
82
+ tickLine: boolean;
83
+ hide: boolean;
84
+ }
85
+ /**
86
+ * Build the list of y-axes to render.
87
+ *
88
+ * The primary axis (id {@link PRIMARY_Y_AXIS_ID}) is always present and driven
89
+ * by the top-level `yLabel` / `yDomain` / `yAxisConfig` props, so single-axis
90
+ * charts are unaffected. Each additional id referenced by a series' `yAxis` — or
91
+ * declared in `yAxes` — becomes its own axis, falling back to the primary axis'
92
+ * settings for anything its {@link YAxisConfig} leaves unset.
93
+ *
94
+ * Axes are emitted in `yAxes` declaration order (primary first) so the render
95
+ * order is stable and predictable when several share a side.
96
+ */
97
+ export declare function resolveYAxes(options: {
98
+ series: readonly SeriesDescriptor[];
99
+ yAxes: Record<AxisId, YAxisConfig> | undefined;
100
+ primary: Omit<ResolvedYAxis, "id" | "orientation">;
101
+ minMaxTicksOnly: boolean | undefined;
102
+ }): ResolvedYAxis[];
103
+ /**
104
+ * Adapt a v2 {@link axisFormatter} to the `vccs` `tickFormatter(value, index)`
105
+ * signature. Returns `undefined` when no formatter is supplied so the axis
106
+ * falls back to `vccs`'s default rendering.
107
+ *
108
+ * The v2 union accepts either a number- or Date-typed tick; both are forwarded
109
+ * as-is, matching how Unovis called them.
110
+ */
111
+ export declare function toTickFormatter(formatter: axisFormatter | undefined): VccsTickFormatter | undefined;
112
+ /** `vccs` axis title config (string labels default to the axis centre and overlap ticks). */
113
+ export type VccsAxisLabel = {
114
+ value: string;
115
+ position: "insideBottom" | "insideLeft" | "insideRight";
116
+ offset: number;
117
+ angle?: number;
118
+ textAnchor?: "start" | "middle" | "end";
119
+ fill: string;
120
+ fontSize: string;
121
+ fontWeight: string | number;
122
+ };
123
+ /**
124
+ * Build a positioned axis title for `vccs` cartesian axes.
125
+ *
126
+ * Plain strings land at the axis midpoint; `insideBottom` / `insideLeft` keep
127
+ * titles clear of tick values and inside the reserved axis slot.
128
+ */
129
+ export declare function toAxisLabel(text: string | undefined, position: "insideBottom" | "insideLeft" | "insideRight", options?: {
130
+ angle?: number;
131
+ offset?: number;
132
+ }): VccsAxisLabel | undefined;
@@ -0,0 +1,93 @@
1
+ import { PRIMARY_Y_AXIS_ID, normalizeAxisId } from "./categories.js";
2
+ import { toAxisDomain } from "./style.js";
3
+ export const AXIS_SLOT = {
4
+ numericYWidth: 40,
5
+ categoryYWidth: 72,
6
+ titledYWidth: 72,
7
+ defaultXHeight: 38,
8
+ titledXHeight: 52
9
+ };
10
+ export function resolveYAxisWidth(options) {
11
+ if (options.hasTitle) return AXIS_SLOT.titledYWidth;
12
+ if (options.isCategoryAxis) return AXIS_SLOT.categoryYWidth;
13
+ return AXIS_SLOT.numericYWidth;
14
+ }
15
+ export function resolveXAxisHeight(options) {
16
+ return options.hasTitle ? AXIS_SLOT.titledXHeight : AXIS_SLOT.defaultXHeight;
17
+ }
18
+ export const AXIS_TICK_MARGIN = {
19
+ /** Between the x-axis line and the tick label below it. */
20
+ x: 8,
21
+ /** Between the plot edge and the right-aligned y tick label. */
22
+ y: 8
23
+ };
24
+ export function toTickProp(tick) {
25
+ if (tick && typeof tick.textAnchor === "string") return { textAnchor: tick.textAnchor };
26
+ return true;
27
+ }
28
+ function toAxisTicks(values) {
29
+ if (!values || values.length === 0) return void 0;
30
+ return values.map((v) => v instanceof Date ? v.getTime() : v);
31
+ }
32
+ export function resolveAxisProps(explicitTicks, config, minMaxTicksOnly) {
33
+ const ticks = toAxisTicks(config?.tickValues ?? explicitTicks);
34
+ const minMax = minMaxTicksOnly ?? config?.minMaxTicksOnly ?? false;
35
+ const tickAttrs = {};
36
+ if (config?.tickTextColor) tickAttrs.fill = config.tickTextColor;
37
+ if (config?.tickTextFontSize) tickAttrs.fontSize = config.tickTextFontSize;
38
+ if (config?.tickTextAlign) {
39
+ tickAttrs.textAnchor = config.tickTextAlign === "left" ? "start" : config.tickTextAlign === "right" ? "end" : "middle";
40
+ }
41
+ return {
42
+ ticks,
43
+ interval: minMax ? "preserveStartEnd" : void 0,
44
+ tick: Object.keys(tickAttrs).length ? tickAttrs : void 0
45
+ };
46
+ }
47
+ export function resolveYAxes(options) {
48
+ const { series, yAxes, primary, minMaxTicksOnly } = options;
49
+ const ids = [PRIMARY_Y_AXIS_ID];
50
+ const seen = /* @__PURE__ */ new Set([PRIMARY_Y_AXIS_ID]);
51
+ for (const raw of [...Object.keys(yAxes ?? {}), ...series.map((s) => s.yAxisId)]) {
52
+ const id = normalizeAxisId(raw);
53
+ if (seen.has(id)) continue;
54
+ seen.add(id);
55
+ ids.push(id);
56
+ }
57
+ const DEFAULT_ORIENTATION = "left";
58
+ return ids.map((id) => {
59
+ const config = yAxes?.[id] ?? yAxes?.[String(id)];
60
+ if (!config) return { ...primary, id, orientation: DEFAULT_ORIENTATION };
61
+ const resolved = resolveAxisProps(void 0, config, config.minMaxTicksOnly ?? minMaxTicksOnly);
62
+ return {
63
+ ...primary,
64
+ ...resolved,
65
+ id,
66
+ orientation: config.orientation ?? DEFAULT_ORIENTATION,
67
+ label: config.label ?? (id === PRIMARY_Y_AXIS_ID ? primary.label : void 0),
68
+ domain: toAxisDomain(config.domain) ?? primary.domain,
69
+ tickCount: config.numTicks ?? primary.tickCount,
70
+ tickFormatter: toTickFormatter(config.formatter ?? config.tickFormat) ?? primary.tickFormatter,
71
+ tickLine: config.tickLine ?? primary.tickLine,
72
+ hide: config.hide ?? false
73
+ };
74
+ });
75
+ }
76
+ export function toTickFormatter(formatter) {
77
+ if (!formatter) return void 0;
78
+ return (value, index) => formatter(value, index);
79
+ }
80
+ export function toAxisLabel(text, position, options) {
81
+ if (!text) return void 0;
82
+ const isVertical = position === "insideLeft" || position === "insideRight";
83
+ return {
84
+ value: text,
85
+ position,
86
+ offset: options?.offset ?? (isVertical ? 8 : 4),
87
+ ...options?.angle !== void 0 ? { angle: options.angle } : {},
88
+ ...isVertical && options?.angle !== void 0 ? { textAnchor: "middle" } : {},
89
+ fill: "var(--vc-axis-label-color)",
90
+ fontSize: "var(--vc-axis-label-size)",
91
+ fontWeight: "var(--vc-axis-label-weight)"
92
+ };
93
+ }
@@ -0,0 +1,36 @@
1
+ import type { AxisId, BulletLegendItemInterface } from "../types/shared.js";
2
+ /** Id of the implicit primary y-axis, matching the `vccs` default. */
3
+ export declare const PRIMARY_Y_AXIS_ID = 0;
4
+ /**
5
+ * Canonicalise an axis id to the form `vccs` will match on.
6
+ *
7
+ * `vccs` binds a series to its axis with strict equality (`item.yAxisId === axisId`),
8
+ * so `"1"` and `1` are two different axes as far as the engine is concerned. Object
9
+ * keys are always strings, which means a numeric id declared in `yAxes` would never
10
+ * match the same id written as a number on a category. Ids that look like integers
11
+ * are normalised to numbers so both spellings — including `yAxis: "0"` for the
12
+ * primary axis — land on one axis.
13
+ */
14
+ export declare function normalizeAxisId(id: AxisId): AxisId;
15
+ /**
16
+ * A single resolved series, derived from one entry in a `categories` record.
17
+ * Drives one `<Area>` / `<Bar>` / `<Line>` / `<Scatter>` child in the adapters.
18
+ */
19
+ export interface SeriesDescriptor {
20
+ /** The data property this series plots (the `categories` record key). */
21
+ dataKey: string;
22
+ /** Display name shown in legend / tooltip. */
23
+ name: string;
24
+ /** Resolved colour. Falls back to `var(--chart-color-N)` for CSS-var theming. */
25
+ color: string;
26
+ /** Whether the series is hidden. */
27
+ hidden: boolean;
28
+ /** Id of the y-axis this series is plotted against. */
29
+ yAxisId: AxisId;
30
+ }
31
+ /**
32
+ * Convert a `categories` record into an ordered list of {@link SeriesDescriptor}s.
33
+ * Hidden categories are kept (so the legend can still show them) — callers that
34
+ * want only visible series can filter on `hidden`.
35
+ */
36
+ export declare function categoriesToSeries(categories: Record<string, BulletLegendItemInterface>): SeriesDescriptor[];
@@ -0,0 +1,18 @@
1
+ export const PRIMARY_Y_AXIS_ID = 0;
2
+ export function normalizeAxisId(id) {
3
+ if (typeof id === "number") return id;
4
+ return /^-?\d+$/.test(id) ? Number(id) : id;
5
+ }
6
+ function resolveColor(color, index) {
7
+ if (Array.isArray(color)) return color[0] ?? `var(--chart-color-${index})`;
8
+ return color ?? `var(--chart-color-${index})`;
9
+ }
10
+ export function categoriesToSeries(categories) {
11
+ return Object.entries(categories).map(([dataKey, item], index) => ({
12
+ dataKey,
13
+ name: String(item.name ?? dataKey),
14
+ color: resolveColor(item.color, index),
15
+ hidden: item.hidden ?? false,
16
+ yAxisId: item.yAxis == null ? PRIMARY_Y_AXIS_ID : normalizeAxisId(item.yAxis)
17
+ }));
18
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Cube-grid bar geometry.
3
+ *
4
+ * Turns a column band + value segment into a vertical stack of square cells
5
+ * (GitHub-contribution / Lego style). Pure functions — no Vue — so layout can
6
+ * be unit-tested and shared across single, grouped, and stacked series.
7
+ */
8
+ /** One square in a cube column. */
9
+ export interface CubeRect {
10
+ x: number;
11
+ y: number;
12
+ size: number;
13
+ radius: number;
14
+ /** 0–1 fill opacity. Tapers with size when `minSize` is set. */
15
+ opacity: number;
16
+ /** True when this cell represents the data value. */
17
+ filled: boolean;
18
+ }
19
+ /** Full-column band from the plot top to the baseline (`vccs` bar `background`). */
20
+ export interface CubeColumnBand {
21
+ x: number;
22
+ y: number;
23
+ width: number;
24
+ height: number;
25
+ }
26
+ export interface LayoutCubeColumnInput {
27
+ column: CubeColumnBand;
28
+ /** Already-scaled segment height in px. */
29
+ valueHeight: number;
30
+ /**
31
+ * SVG y of the segment top. When omitted, the segment sits on the baseline
32
+ * (`valueHeight` tall). Stacked series pass the real bar `y` here so each
33
+ * layer owns a contiguous cube range.
34
+ */
35
+ segmentY?: number;
36
+ /**
37
+ * Draw ghost cubes for unfilled rows. For stacked bars only the first series
38
+ * should do this; later series paint fills only. Default `true`.
39
+ */
40
+ includeEmpty?: boolean;
41
+ /** Gap between cubes in px. Default 2. */
42
+ gap?: number;
43
+ /** Corner radius per cube. Default 2. */
44
+ radius?: number;
45
+ /**
46
+ * Preferred cube edge length. Clamped to the band width so each column stays
47
+ * a straight, centered stack. Default 10.
48
+ */
49
+ preferredSize?: number;
50
+ /**
51
+ * When set below `preferredSize`, cube edge length tapers from preferred at
52
+ * the top of the plot down to this size at the baseline. Size is based on
53
+ * absolute row position so every horizontal line shares one cube size.
54
+ * Grid stride stays based on preferred size; each square is centered in its cell.
55
+ * Opacity also tapers top → bottom (see `minOpacity`).
56
+ */
57
+ minSize?: number;
58
+ /**
59
+ * Floor opacity when size-tapering (top stays 1). Default 0.05 — nearly
60
+ * invisible at the baseline. Ignored unless `minSize` enables taper.
61
+ */
62
+ minOpacity?: number;
63
+ }
64
+ export declare const DEFAULT_CUBE_GAP = 2;
65
+ export declare const DEFAULT_CUBE_RADIUS = 2;
66
+ export declare const DEFAULT_CUBE_SIZE = 10;
67
+ export declare const DEFAULT_CUBE_EMPTY_COLOR = "rgba(128, 128, 128, 0.14)";
68
+ /** Baseline opacity when size-tapering — almost invisible at the bottom. */
69
+ export declare const DEFAULT_CUBE_MIN_OPACITY = 0.05;
70
+ /**
71
+ * Map a value height onto an integer cube count.
72
+ * `valueHeight / columnHeight` mirrors the y-scale without needing yMax.
73
+ */
74
+ export declare function valueToCubeCount(valueHeight: number, columnHeight: number, rows: number): number;
75
+ /** Resolve cube size + row count for a column band. */
76
+ export declare function resolveCubeGrid(column: CubeColumnBand, gap?: number, preferredSize?: number): {
77
+ size: number;
78
+ rows: number;
79
+ stride: number;
80
+ originX: number;
81
+ originY: number;
82
+ } | null;
83
+ /**
84
+ * Edge length for a row when tapering from `maxSize` (top) to `minSize` (bottom).
85
+ * `rowFromTop` is 0 at the top of the column.
86
+ */
87
+ export declare function cubeSizeAtRow(rowFromTop: number, rows: number, maxSize: number, minSize: number): number;
88
+ /**
89
+ * Fill opacity for a row when tapering from 1 (top) to `minOpacity` (bottom).
90
+ * Uses a ease-in curve so the washout accelerates toward the baseline.
91
+ */
92
+ export declare function cubeOpacityAtRow(rowFromTop: number, rows: number, minOpacity?: number): number;
93
+ /**
94
+ * Lay out cubes for one series segment within a category column.
95
+ *
96
+ * - Single / grouped: omit `segmentY`, `includeEmpty: true` (default).
97
+ * - Stacked: pass each layer's bar `y` as `segmentY`; only the first series
98
+ * should set `includeEmpty: true` so the ghost tower is drawn once.
99
+ */
100
+ export declare function layoutCubeColumn(input: LayoutCubeColumnInput): CubeRect[];
@@ -0,0 +1,73 @@
1
+ export const DEFAULT_CUBE_GAP = 2;
2
+ export const DEFAULT_CUBE_RADIUS = 2;
3
+ export const DEFAULT_CUBE_SIZE = 10;
4
+ export const DEFAULT_CUBE_EMPTY_COLOR = "rgba(128, 128, 128, 0.14)";
5
+ export const DEFAULT_CUBE_MIN_OPACITY = 0.05;
6
+ export function valueToCubeCount(valueHeight, columnHeight, rows) {
7
+ if (rows <= 0 || columnHeight <= 0 || valueHeight <= 0) return 0;
8
+ return Math.min(rows, Math.max(0, Math.round(valueHeight / columnHeight * rows)));
9
+ }
10
+ export function resolveCubeGrid(column, gap = DEFAULT_CUBE_GAP, preferredSize = DEFAULT_CUBE_SIZE) {
11
+ const { x, y, width, height } = column;
12
+ if (!(width > 0) || !(height > 0)) return null;
13
+ const size = Math.max(1, Math.min(width, preferredSize));
14
+ const stride = size + gap;
15
+ const rows = Math.max(1, Math.floor((height + gap) / stride));
16
+ const stackHeight = rows * size + (rows - 1) * gap;
17
+ return {
18
+ size,
19
+ rows,
20
+ stride,
21
+ originX: x + (width - size) / 2,
22
+ originY: y + height - stackHeight
23
+ };
24
+ }
25
+ export function cubeSizeAtRow(rowFromTop, rows, maxSize, minSize) {
26
+ if (rows <= 1 || minSize >= maxSize) return maxSize;
27
+ const t = rowFromTop / (rows - 1);
28
+ return maxSize + (minSize - maxSize) * t;
29
+ }
30
+ export function cubeOpacityAtRow(rowFromTop, rows, minOpacity = DEFAULT_CUBE_MIN_OPACITY) {
31
+ if (rows <= 1) return 1;
32
+ const t = rowFromTop / (rows - 1);
33
+ const eased = t * t;
34
+ return 1 + (Math.min(1, Math.max(0, minOpacity)) - 1) * eased;
35
+ }
36
+ export function layoutCubeColumn(input) {
37
+ const gap = input.gap ?? DEFAULT_CUBE_GAP;
38
+ const radius = input.radius ?? DEFAULT_CUBE_RADIUS;
39
+ const preferred = input.preferredSize ?? DEFAULT_CUBE_SIZE;
40
+ const includeEmpty = input.includeEmpty !== false;
41
+ const { column } = input;
42
+ const grid = resolveCubeGrid(column, gap, preferred);
43
+ if (!grid) return [];
44
+ const { size, rows, stride, originX, originY } = grid;
45
+ const rawMin = input.minSize;
46
+ const taper = typeof rawMin === "number" && Number.isFinite(rawMin) && rawMin > 0 && rawMin < size;
47
+ const minSize = taper ? Math.max(1, rawMin) : size;
48
+ const minOpacity = typeof input.minOpacity === "number" && Number.isFinite(input.minOpacity) ? Math.min(1, Math.max(0, input.minOpacity)) : DEFAULT_CUBE_MIN_OPACITY;
49
+ const baseline = column.y + column.height;
50
+ const segH = Math.max(0, input.valueHeight);
51
+ const segTop = input.segmentY ?? baseline - segH;
52
+ const segBottom = segTop + segH;
53
+ const startIdx = valueToCubeCount(Math.max(0, baseline - segBottom), column.height, rows);
54
+ const endIdx = valueToCubeCount(Math.max(0, baseline - segTop), column.height, rows);
55
+ const rects = [];
56
+ for (let i = 0; i < rows; i++) {
57
+ const filled = i >= startIdx && i < endIdx;
58
+ if (!filled && !includeEmpty) continue;
59
+ const rowFromTop = rows - 1 - i;
60
+ const cubeSize = taper ? cubeSizeAtRow(rowFromTop, rows, size, minSize) : size;
61
+ const opacity = taper ? cubeOpacityAtRow(rowFromTop, rows, minOpacity) : 1;
62
+ const inset = (size - cubeSize) / 2;
63
+ rects.push({
64
+ x: originX + inset,
65
+ y: originY + rowFromTop * stride + inset,
66
+ size: cubeSize,
67
+ radius: Math.min(radius, cubeSize / 2),
68
+ opacity,
69
+ filled
70
+ });
71
+ }
72
+ return rects;
73
+ }