@vunset/vue 1.0.0-rc.3 → 1.0.0-rc.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/chart.d.ts +1 -1
  2. package/dist/chart.js +1 -1
  3. package/dist/components/accordion/AccordionRoot.vue.d.ts +1 -1
  4. package/dist/components/button/Button.vue.d.ts +1 -1
  5. package/dist/components/calendar/CalendarRoot.vue.d.ts +2 -2
  6. package/dist/components/chart/ChartArea.vue.d.ts +6 -0
  7. package/dist/components/chart/ChartArea.vue_vue_type_script_setup_true_lang.js +9 -1
  8. package/dist/components/chart/ChartAxis.vue.d.ts +9 -1
  9. package/dist/components/chart/ChartAxis.vue_vue_type_script_setup_true_lang.js +8 -2
  10. package/dist/components/chart/ChartDonut.vue.d.ts +12 -5
  11. package/dist/components/chart/ChartDonut.vue_vue_type_script_setup_true_lang.js +22 -6
  12. package/dist/components/chart/ChartFrame.vue.d.ts +4 -3
  13. package/dist/components/chart/ChartFrame.vue_vue_type_script_setup_true_lang.js +47 -28
  14. package/dist/components/chart/ChartLegend.vue.d.ts +52 -22
  15. package/dist/components/chart/ChartLegend.vue_vue_type_script_setup_true_lang.js +22 -6
  16. package/dist/components/chart/ChartRoot.vue.d.ts +20 -1
  17. package/dist/components/chart/ChartRoot.vue_vue_type_script_setup_true_lang.js +75 -33
  18. package/dist/components/chart/ChartTooltip.vue.d.ts +12 -1
  19. package/dist/components/chart/ChartTooltip.vue_vue_type_script_setup_true_lang.js +13 -1
  20. package/dist/components/chart/chart-scales.d.ts +10 -0
  21. package/dist/components/chart/chart-scales.js +14 -2
  22. package/dist/components/chart/use-chart-series.d.ts +2 -0
  23. package/dist/components/chart/use-chart-series.js +1 -1
  24. package/dist/components/combobox/ComboboxRoot.vue.d.ts +3 -3
  25. package/dist/components/datepicker/DatepickerRoot.vue.d.ts +3 -3
  26. package/dist/components/field/FieldRoot.vue.d.ts +1 -1
  27. package/dist/components/group/Group.vue.d.ts +1 -1
  28. package/dist/components/range/RangeRoot.vue.d.ts +1 -1
  29. package/dist/components/scroll-area/ScrollArea.vue.d.ts +1 -1
  30. package/dist/components/select/SelectRoot.vue.d.ts +1 -1
  31. package/dist/components/tabs/TabsRoot.vue.d.ts +1 -1
  32. package/dist/components/timepicker/TimepickerRoot.vue.d.ts +2 -2
  33. package/dist/components/toggle/ToggleGroup.vue.d.ts +2 -2
  34. package/package.json +2 -2
package/dist/chart.d.ts CHANGED
@@ -6,6 +6,6 @@ export { default as ChartAxis } from './components/chart/ChartAxis.vue';
6
6
  export { default as ChartGrid } from './components/chart/ChartGrid.vue';
7
7
  export { default as ChartCrosshair } from './components/chart/ChartCrosshair.vue';
8
8
  export { default as ChartTooltip } from './components/chart/ChartTooltip.vue';
9
- export { default as ChartLegend } from './components/chart/ChartLegend.vue';
9
+ export { default as ChartLegend, type ChartLegendItem } from './components/chart/ChartLegend.vue';
10
10
  export { default as ChartDonut } from './components/chart/ChartDonut.vue';
11
11
  export { type ChartSeries } from './components/chart/use-chart-series';
package/dist/chart.js CHANGED
@@ -1,3 +1,4 @@
1
+ import ChartLegend_default from "./components/chart/ChartLegend.js";
1
2
  import ChartRoot_default from "./components/chart/ChartRoot.js";
2
3
  import ChartArea_default from "./components/chart/ChartArea.js";
3
4
  import ChartLine_default from "./components/chart/ChartLine.js";
@@ -6,6 +7,5 @@ import ChartAxis_default from "./components/chart/ChartAxis.js";
6
7
  import ChartGrid_default from "./components/chart/ChartGrid.js";
7
8
  import ChartCrosshair_default from "./components/chart/ChartCrosshair.js";
8
9
  import ChartTooltip_default from "./components/chart/ChartTooltip.js";
9
- import ChartLegend_default from "./components/chart/ChartLegend.js";
10
10
  import ChartDonut_default from "./components/chart/ChartDonut.js";
11
11
  export { ChartArea_default as ChartArea, ChartAxis_default as ChartAxis, ChartBar_default as ChartBar, ChartCrosshair_default as ChartCrosshair, ChartDonut_default as ChartDonut, ChartGrid_default as ChartGrid, ChartLegend_default as ChartLegend, ChartLine_default as ChartLine, ChartRoot_default as ChartRoot, ChartTooltip_default as ChartTooltip };
@@ -31,9 +31,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, import("./u
31
31
  "onUpdate:modelValue"?: ((value: AccordionValue[]) => any) | undefined;
32
32
  }>, {
33
33
  defaultValue: AccordionValue[];
34
- orientation: Orientation;
35
34
  as: string | object;
36
35
  modelValue: AccordionValue[];
36
+ orientation: Orientation;
37
37
  disabled: boolean;
38
38
  loop: boolean;
39
39
  multiple: boolean;
@@ -15,8 +15,8 @@ type __VLS_Slots = {} & {
15
15
  default?: (props: typeof __VLS_8) => any;
16
16
  };
17
17
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, import("./use-button").UseButtonReturn, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
18
- type: "button" | "submit" | "reset";
19
18
  as: string | object;
19
+ type: "button" | "submit" | "reset";
20
20
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
21
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
22
22
  declare const _default: typeof __VLS_export;
@@ -73,10 +73,10 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, import("./u
73
73
  onChange?: ((value: CalendarValue) => any) | undefined;
74
74
  "onUpdate:modelValue"?: ((value: CalendarModelValue | undefined) => any) | undefined;
75
75
  }>, {
76
- required: boolean;
77
- invalid: boolean;
78
76
  mode: CalendarSelectionMode;
77
+ invalid: boolean;
79
78
  as: string | object;
79
+ required: boolean;
80
80
  disabled: boolean;
81
81
  readOnly: boolean;
82
82
  maxToday: boolean;
@@ -14,10 +14,16 @@ type __VLS_Props = {
14
14
  curve?: ChartCurve;
15
15
  /** Mark each row with a dot. */
16
16
  points?: boolean;
17
+ /** Draw the line along the band's top. Without it, the band alone takes the focus. @default true */
18
+ line?: boolean;
19
+ /** Fade the band towards the axis, or fill it evenly. @default true */
20
+ gradient?: boolean;
17
21
  };
18
22
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
23
+ line: boolean;
19
24
  curve: ChartCurve;
20
25
  scale: string;
26
+ gradient: boolean;
21
27
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
28
  declare const _default: typeof __VLS_export;
23
29
  export default _default;
@@ -11,7 +11,15 @@ var ChartArea_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
11
11
  scale: { default: "y" },
12
12
  format: {},
13
13
  curve: { default: "smooth" },
14
- points: { type: Boolean }
14
+ points: { type: Boolean },
15
+ line: {
16
+ type: Boolean,
17
+ default: true
18
+ },
19
+ gradient: {
20
+ type: Boolean,
21
+ default: true
22
+ }
15
23
  },
16
24
  setup(__props) {
17
25
  const props = __props;
@@ -12,7 +12,15 @@ type __VLS_Props = {
12
12
  numTicks?: number;
13
13
  /** Cut long row labels rather than dropping the ones that would collide. */
14
14
  trimLabels?: boolean;
15
+ /** A title along the axis, such as its unit. */
16
+ label?: string;
17
+ /** Draw the axis' own line along the plot's edge. */
18
+ line?: boolean;
19
+ /** The short mark at each label. @default true */
20
+ tickMarks?: boolean;
15
21
  };
16
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
23
+ tickMarks: boolean;
24
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
17
25
  declare const _default: typeof __VLS_export;
18
26
  export default _default;
@@ -8,9 +8,15 @@ var ChartAxis_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
8
8
  type: {},
9
9
  scale: {},
10
10
  side: {},
11
- format: { type: Function },
11
+ format: {},
12
12
  numTicks: {},
13
- trimLabels: { type: Boolean }
13
+ trimLabels: { type: Boolean },
14
+ label: {},
15
+ line: { type: Boolean },
16
+ tickMarks: {
17
+ type: Boolean,
18
+ default: true
19
+ }
14
20
  },
15
21
  setup(__props) {
16
22
  const props = __props;
@@ -13,20 +13,27 @@ declare const __VLS_export: <T extends Record<string, any>>(__VLS_props: NonNull
13
13
  labelFormat?: (category: string) => string;
14
14
  /** One per slice. Defaults to `var(--chart-color-N)`. */
15
15
  colors?: string[];
16
+ /** How many `--chart-color-N` the theme defines: series past it start over at the first. @default 8 */
17
+ paletteSize?: number;
16
18
  /** Slices not drawn. `v-model:hidden` pairs it with a `ChartLegend`. */
17
19
  hidden?: string[];
18
20
  /** A number means pixels. @default '20rem' */
19
21
  height?: number | string;
20
- /** Gap between slices, in radians. @default 0.04 */
22
+ /** Gap between slices, in radians: a wedge, widening towards the edge. @default 0.04 */
21
23
  padAngle?: number;
24
+ /**
25
+ * Gap between slices, in pixels, the same width from the center to the edge; `0` for none. Replaces
26
+ * `pad-angle`. It's drawn as a line in `--chart-gap-color`, the page's background by default.
27
+ */
28
+ gap?: number;
22
29
  /** The radius of each slice's corners, in pixels. @default 6 */
23
30
  cornerRadius?: number;
24
31
  /** How thick the ring is. `0` fills it in, making a pie. @default 12 */
25
32
  arcWidth?: number;
26
- /** Defaults to the total of what is showing. Empty string for nothing. */
27
- centralLabel?: string;
28
- /** The line under the central label. @default 'Total' */
29
- centralSubLabel?: string;
33
+ /** Defaults to the total of what is showing; a pie, with no middle, shows none. `false` for nothing. */
34
+ centralLabel?: string | false;
35
+ /** The line under the central label. Defaults to 'Total', or none on a pie. `false` for nothing. */
36
+ centralSubLabel?: string | false;
30
37
  /** Shows the slice under the pointer. @default true */
31
38
  tooltip?: boolean;
32
39
  /** A class for the tooltip's box. */
@@ -31,13 +31,21 @@ var ChartDonut_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
31
31
  valueFormat: {},
32
32
  labelFormat: {},
33
33
  colors: {},
34
+ paletteSize: {},
34
35
  hidden: {},
35
36
  height: { default: "20rem" },
36
37
  padAngle: { default: .04 },
38
+ gap: {},
37
39
  cornerRadius: { default: 6 },
38
40
  arcWidth: { default: 12 },
39
- centralLabel: { default: void 0 },
40
- centralSubLabel: { default: void 0 },
41
+ centralLabel: {
42
+ type: [String, Boolean],
43
+ default: void 0
44
+ },
45
+ centralSubLabel: {
46
+ type: [String, Boolean],
47
+ default: void 0
48
+ },
41
49
  tooltip: {
42
50
  type: Boolean,
43
51
  default: void 0
@@ -62,6 +70,7 @@ var ChartDonut_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
62
70
  const { visible } = useChartSeries({
63
71
  categories: () => slices.value.map((slice) => slice.category),
64
72
  colors: () => props.colors,
73
+ paletteSize: () => props.paletteSize,
65
74
  hidden: () => props.hidden,
66
75
  onHiddenChange: (next) => emit("update:hidden", next)
67
76
  });
@@ -82,16 +91,22 @@ var ChartDonut_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
82
91
  const definition = computed(() => {
83
92
  const width = props.arcWidth;
84
93
  const cornerRadius = props.cornerRadius;
94
+ const gap = props.gap;
85
95
  return defineChart({
96
+ svgAnimation: false,
86
97
  marks: [polar({
87
98
  marks: [radialArc(pie(shown.value, {
88
99
  value: "size",
89
- gapAngle: props.padAngle
100
+ gapAngle: gap === void 0 ? props.padAngle : 0
90
101
  }), {
91
102
  color: "category",
92
103
  key: "category",
93
104
  innerRadius: ({ radius }) => width > 0 ? Math.max(radius - width, 0) : 0,
94
- cornerRadius
105
+ cornerRadius,
106
+ ...gap !== void 0 && gap > 0 && {
107
+ stroke: "var(--chart-gap-color, Canvas)",
108
+ strokeWidth: gap
109
+ }
95
110
  })],
96
111
  scales: {
97
112
  angle: null,
@@ -116,8 +131,9 @@ var ChartDonut_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
116
131
  }
117
132
  });
118
133
  });
119
- const centralLabel = computed(() => props.centralLabel ?? format(total.value));
120
- const centralSubLabel = computed(() => props.centralSubLabel ?? "Total");
134
+ const filled = computed(() => props.arcWidth <= 0);
135
+ const centralLabel = computed(() => props.centralLabel ?? (filled.value ? false : format(total.value)));
136
+ const centralSubLabel = computed(() => props.centralSubLabel ?? (filled.value ? false : "Total"));
121
137
  const ariaLabel = computed(() => props.label ?? chartName(shown.value.map((slice) => slice.category), props.labelFormat, "Donut chart"));
122
138
  return (_ctx, _cache) => {
123
139
  return openBlock(), createBlock(ChartFrame_default, mergeProps({
@@ -30,8 +30,8 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
30
30
  /** `--chart-tick-font-size` in px, for the chart's definition. */
31
31
  tickSize?: number;
32
32
  }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
33
- "update:tickSize": (value: number | undefined) => any;
34
33
  render: (context: ChartRender) => any;
34
+ "update:tickSize": (value: number | undefined) => any;
35
35
  }, string, import("vue").PublicProps, Readonly<{
36
36
  /** Which chart this is, for `data-chart`. */
37
37
  kind?: string;
@@ -47,14 +47,15 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
47
47
  /** `--chart-tick-font-size` in px, for the chart's definition. */
48
48
  tickSize?: number;
49
49
  }> & Readonly<{
50
- "onUpdate:tickSize"?: ((value: number | undefined) => any) | undefined;
51
50
  onRender?: ((context: ChartRender) => any) | undefined;
51
+ "onUpdate:tickSize"?: ((value: number | undefined) => any) | undefined;
52
52
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
53
53
  /** Content before the drawing, such as a `ChartLegend`. */
54
54
  default(): unknown;
55
- /** The tooltip's content, for the point in focus. */
55
+ /** The tooltip's content, for the point in focus; `pinned` once a click holds it. */
56
56
  tooltip(props: {
57
57
  point: ChartPoint<any>;
58
+ pinned: boolean;
58
59
  }): unknown;
59
60
  /** Content laid over the plot, centered on it. */
60
61
  center?(): unknown;
@@ -1,4 +1,5 @@
1
- import { computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, h, mergeModels, mergeProps, normalizeStyle, onMounted, openBlock, renderSlot, shallowRef, unref, useModel, useSlots, useTemplateRef } from "vue";
1
+ import ChartLegend_default from "./ChartLegend.js";
2
+ import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, h, mergeModels, mergeProps, normalizeStyle, onMounted, openBlock, renderSlot, shallowRef, unref, useModel, useSlots, useTemplateRef } from "vue";
2
3
  import { Chart } from "@tanstack/charts/vue";
3
4
  //#region src/components/chart/ChartFrame.vue?vue&type=script&setup=true&lang.ts
4
5
  var _hoisted_1 = ["data-chart"];
@@ -49,7 +50,21 @@ var ChartFrame_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
49
50
  emit("render", context);
50
51
  }
51
52
  const height = computed(() => typeof props.height === "number" ? `${props.height}px` : props.height);
52
- const tooltipBody = ({ primaryPoint }) => primaryPoint ? h("div", mergeProps({ "data-part": "chart-tooltip" }, props.tooltipAttrs?.() ?? {}), [h("div", { "data-part": "tooltip" }, slots.tooltip({ point: primaryPoint }))]) : null;
53
+ const tooltipBody = ({ primaryPoint, pinned }) => primaryPoint ? h("div", mergeProps({
54
+ "data-part": "chart-tooltip",
55
+ "data-pinned": pinned ? "" : void 0
56
+ }, props.tooltipAttrs?.() ?? {}), [h("div", { "data-part": "tooltip" }, slots.tooltip({
57
+ point: primaryPoint,
58
+ pinned
59
+ }))]) : null;
60
+ const below = (node) => node.type === ChartLegend_default && node.props?.placement === "bottom";
61
+ function flat(nodes) {
62
+ return nodes.flatMap((node) => node.type === Fragment && Array.isArray(node.children) ? flat(node.children) : [node]);
63
+ }
64
+ const Content = (own) => {
65
+ return flat(slots.default?.() ?? []).filter((node) => below(node) === (own.bottom ?? false));
66
+ };
67
+ Content.props = { bottom: Boolean };
53
68
  const Drawing = defineComponent({
54
69
  name: "ChartDrawing",
55
70
  setup: () => () => h(Chart, {
@@ -63,32 +78,36 @@ var ChartFrame_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
63
78
  return openBlock(), createElementBlock("div", {
64
79
  "data-part": "chart",
65
80
  "data-chart": props.kind
66
- }, [renderSlot(_ctx.$slots, "default"), createElementVNode("div", _hoisted_2, [
67
- createElementVNode("span", {
68
- ref_key: "probe",
69
- ref: probe,
70
- "aria-hidden": "true",
71
- style: {
72
- position: "absolute",
73
- visibility: "hidden",
74
- fontSize: "var(--chart-tick-font-size, 0px)"
75
- }
76
- }, null, 512),
77
- createVNode(unref(Drawing)),
78
- slots.center && plot.value ? (openBlock(), createElementBlock("div", {
79
- key: 0,
80
- "data-part": "chart-center",
81
- style: normalizeStyle({
82
- position: "absolute",
83
- ...plot.value,
84
- display: "flex",
85
- flexDirection: "column",
86
- alignItems: "center",
87
- justifyContent: "center",
88
- pointerEvents: "none"
89
- })
90
- }, [renderSlot(_ctx.$slots, "center")], 4)) : createCommentVNode("", true)
91
- ])], 8, _hoisted_1);
81
+ }, [
82
+ createVNode(Content),
83
+ createElementVNode("div", _hoisted_2, [
84
+ createElementVNode("span", {
85
+ ref_key: "probe",
86
+ ref: probe,
87
+ "aria-hidden": "true",
88
+ style: {
89
+ position: "absolute",
90
+ visibility: "hidden",
91
+ fontSize: "var(--chart-tick-font-size, 0px)"
92
+ }
93
+ }, null, 512),
94
+ createVNode(unref(Drawing)),
95
+ slots.center && plot.value ? (openBlock(), createElementBlock("div", {
96
+ key: 0,
97
+ "data-part": "chart-center",
98
+ style: normalizeStyle({
99
+ position: "absolute",
100
+ ...plot.value,
101
+ display: "flex",
102
+ flexDirection: "column",
103
+ alignItems: "center",
104
+ justifyContent: "center",
105
+ pointerEvents: "none"
106
+ })
107
+ }, [renderSlot(_ctx.$slots, "center")], 4)) : createCommentVNode("", true)
108
+ ]),
109
+ createVNode(Content, { bottom: "" })
110
+ ], 8, _hoisted_1);
92
111
  };
93
112
  }
94
113
  });
@@ -1,44 +1,74 @@
1
- type __VLS_Props = {
1
+ import { type HTMLAttributes } from 'vue';
2
+ /** One entry in a legend. */
3
+ export interface ChartLegendItem {
4
+ category: string;
5
+ label: string;
6
+ color: string;
7
+ /** Its series isn't drawn. */
8
+ hidden: boolean;
9
+ /** Hides it, or shows it again. */
10
+ toggle: () => void;
11
+ }
12
+ declare const _default: typeof __VLS_export;
13
+ export default _default;
14
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
2
15
  /** The hidden categories, bound with `v-model`, for a legend beside a chart rather than inside it. */
3
16
  modelValue?: string[];
4
17
  /** Taken from the chart this sits inside, when it sits inside one. */
5
18
  categories?: string[];
6
19
  /** One per category; taken from the chart this sits inside, or `var(--chart-color-N)`. */
7
20
  colors?: string[];
21
+ /** How many `--chart-color-N` the theme defines: series past it start over at the first. @default 8 */
22
+ paletteSize?: number;
8
23
  /** Renames a category for the reader. Inside a chart, each series' `label` already does. */
9
24
  labelFormat?: (category: string) => string;
25
+ /** Inside a chart: above the drawing, or below it. @default 'top' */
26
+ placement?: "top" | "bottom";
27
+ /** A class for each button, beside its `data-part="legend-item"`. */
28
+ itemClass?: HTMLAttributes["class"];
10
29
  /** Element or component to render. */
11
30
  as?: string | object;
12
- };
13
- type __VLS_Slots = {
31
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
32
+ "update:modelValue": (hidden: string[]) => any;
33
+ }, string, import("vue").PublicProps, Readonly<{
34
+ /** The hidden categories, bound with `v-model`, for a legend beside a chart rather than inside it. */
35
+ modelValue?: string[];
36
+ /** Taken from the chart this sits inside, when it sits inside one. */
37
+ categories?: string[];
38
+ /** One per category; taken from the chart this sits inside, or `var(--chart-color-N)`. */
39
+ colors?: string[];
40
+ /** How many `--chart-color-N` the theme defines: series past it start over at the first. @default 8 */
41
+ paletteSize?: number;
42
+ /** Renames a category for the reader. Inside a chart, each series' `label` already does. */
43
+ labelFormat?: (category: string) => string;
44
+ /** Inside a chart: above the drawing, or below it. @default 'top' */
45
+ placement?: "top" | "bottom";
46
+ /** A class for each button, beside its `data-part="legend-item"`. */
47
+ itemClass?: HTMLAttributes["class"];
48
+ /** Element or component to render. */
49
+ as?: string | object;
50
+ }> & Readonly<{
51
+ "onUpdate:modelValue"?: ((hidden: string[]) => any) | undefined;
52
+ }>, {
53
+ as: string | object;
54
+ modelValue: string[];
55
+ placement: "top" | "bottom";
56
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
14
57
  /**
15
58
  * Replaces the buttons.
16
59
  * @slotOnly The element carries only `data-part="legend"`.
17
60
  */
18
61
  default(props: {
19
62
  /** One per category, with its `category`, `label`, `color`, whether it is `hidden`, and a `toggle()`. */
20
- items: {
21
- category: string;
22
- label: string;
23
- color: string;
24
- hidden: boolean;
25
- toggle: () => void;
26
- }[];
63
+ items: ChartLegendItem[];
27
64
  /** The hidden categories. */
28
65
  hidden: string[];
29
66
  }): unknown;
30
- };
31
- declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
32
- "update:modelValue": (hidden: string[]) => any;
33
- }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
34
- "onUpdate:modelValue"?: ((hidden: string[]) => any) | undefined;
35
- }>, {
36
- as: string | object;
37
- modelValue: string[];
38
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
39
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
40
- declare const _default: typeof __VLS_export;
41
- export default _default;
67
+ /** Replaces what each button shows, a swatch and the label; the button and its toggling stay. */
68
+ item?(props: ChartLegendItem & {
69
+ index: number;
70
+ }): unknown;
71
+ }>;
42
72
  type __VLS_WithSlots<T, S> = T & {
43
73
  new (): {
44
74
  $slots: S;
@@ -2,7 +2,7 @@ import { mergeProps as mergeProps$1 } from "../../shared/merge-props.js";
2
2
  import { Part } from "../../shared/part.js";
3
3
  import { useControlled } from "../../shared/use-controlled.js";
4
4
  import { useOptionalChartContext } from "./use-chart-series.js";
5
- import { Fragment, computed, createBlock, createElementBlock, createElementVNode, defineComponent, guardReactiveProps, mergeProps, normalizeProps, normalizeStyle, openBlock, renderList, renderSlot, toDisplayString, unref, useAttrs, withCtx } from "vue";
5
+ import { Fragment, computed, createBlock, createElementBlock, createElementVNode, defineComponent, guardReactiveProps, mergeProps, normalizeClass, normalizeProps, normalizeStyle, openBlock, renderList, renderSlot, toDisplayString, unref, useAttrs, withCtx } from "vue";
6
6
  import { chartColors } from "@vunset/utils";
7
7
  //#region src/components/chart/ChartLegend.vue?vue&type=script&setup=true&lang.ts
8
8
  var _hoisted_1 = [
@@ -19,7 +19,16 @@ var ChartLegend_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
19
19
  modelValue: { default: void 0 },
20
20
  categories: {},
21
21
  colors: {},
22
+ paletteSize: {},
22
23
  labelFormat: {},
24
+ placement: { default: "top" },
25
+ itemClass: { type: [
26
+ Boolean,
27
+ null,
28
+ String,
29
+ Object,
30
+ Array
31
+ ] },
23
32
  as: { default: "div" }
24
33
  },
25
34
  emits: ["update:modelValue"],
@@ -36,7 +45,7 @@ var ChartLegend_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
36
45
  label: "modelValue"
37
46
  });
38
47
  const categories = computed(() => props.categories ?? chart?.categories.value ?? []);
39
- const colors = computed(() => props.colors ?? chart?.colors.value ?? chartColors(categories.value.length));
48
+ const colors = computed(() => props.colors ?? chart?.colors.value ?? chartColors(categories.value.length, void 0, void 0, props.paletteSize));
40
49
  const hidden = computed(() => driven ? chart.hidden.value : own.value);
41
50
  function toggle(category) {
42
51
  if (driven) {
@@ -53,24 +62,31 @@ var ChartLegend_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
53
62
  toggle: () => toggle(category)
54
63
  })));
55
64
  const attrs = useAttrs();
56
- const merged = computed(() => mergeProps$1({ "data-part": "legend" }, attrs));
65
+ const merged = computed(() => mergeProps$1({
66
+ "data-part": "legend",
67
+ "data-placement": props.placement
68
+ }, attrs));
57
69
  return (_ctx, _cache) => {
58
70
  return openBlock(), createBlock(unref(Part), mergeProps({ as: props.as }, merged.value), {
59
71
  default: withCtx(() => [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps({
60
72
  items: items.value,
61
73
  hidden: hidden.value
62
- })), () => [(openBlock(true), createElementBlock(Fragment, null, renderList(items.value, (item) => {
74
+ })), () => [(openBlock(true), createElementBlock(Fragment, null, renderList(items.value, (item, index) => {
63
75
  return openBlock(), createElementBlock("button", {
64
76
  key: item.category,
65
77
  type: "button",
66
78
  "data-part": "legend-item",
79
+ class: normalizeClass(props.itemClass),
67
80
  "data-hidden": item.hidden ? "" : void 0,
68
81
  "aria-pressed": !item.hidden,
69
82
  onClick: ($event) => item.toggle()
70
- }, [createElementVNode("span", {
83
+ }, [renderSlot(_ctx.$slots, "item", mergeProps({ ref_for: true }, {
84
+ ...item,
85
+ index
86
+ }), () => [createElementVNode("span", {
71
87
  "data-part": "legend-swatch",
72
88
  style: normalizeStyle({ background: item.color })
73
- }, null, 4), createElementVNode("span", _hoisted_2, toDisplayString(item.label), 1)], 8, _hoisted_1);
89
+ }, null, 4), createElementVNode("span", _hoisted_2, toDisplayString(item.label), 1)])], 10, _hoisted_1);
74
90
  }), 128))])]),
75
91
  _: 3
76
92
  }, 16, ["as"]);
@@ -12,6 +12,8 @@ export interface ChartSeriesPart {
12
12
  curve?: ChartCurve;
13
13
  points?: boolean;
14
14
  gradient?: boolean;
15
+ /** Areas only: the line along the band's top. */
16
+ line?: boolean;
15
17
  roundedCorners?: number;
16
18
  padding?: number;
17
19
  }
@@ -22,6 +24,9 @@ export interface ChartAxisPart {
22
24
  format?: (value: any) => string;
23
25
  numTicks?: number;
24
26
  trimLabels?: boolean;
27
+ label?: string;
28
+ line?: boolean;
29
+ tickMarks?: boolean;
25
30
  }
26
31
  export interface ChartGridPart {
27
32
  type: 'x' | 'y';
@@ -42,12 +47,17 @@ export interface ChartTooltipSlotProps<T = Record<string, any>> {
42
47
  row: T;
43
48
  /** Its `x-key` value, through the x axis' formatter. */
44
49
  heading: string;
45
- /** The series showing, in order. */
50
+ /** The series showing, in order; in `point` mode, only the point's. */
46
51
  series: ChartTooltipSeries[];
52
+ /** Pinned in place by a click, Enter or Space. */
53
+ pinned: boolean;
47
54
  }
48
55
  export interface ChartTooltipPart {
49
56
  attrs: Record<string, unknown>;
50
57
  slot?: (props: ChartTooltipSlotProps) => unknown;
58
+ mode: 'row' | 'point';
59
+ sticky: boolean;
60
+ headingFormat?: (value: any) => string;
51
61
  }
52
62
  interface Parts {
53
63
  series: ChartSeriesPart;
@@ -83,6 +93,13 @@ declare const __VLS_export: <T extends Record<string, any>>(__VLS_props: NonNull
83
93
  data: T[];
84
94
  /** The key naming each row, along the x axis. */
85
95
  xKey: keyof T & string;
96
+ /**
97
+ * Where the rows sit along the x axis. `category` spaces them evenly, in
98
+ * order; `linear` places them by their `x-key` number; or pass a scale
99
+ * factory, such as d3-scale's `scaleUtc` for dates. Bars need `category`.
100
+ * @default 'category'
101
+ */
102
+ xScale?: "category" | "linear" | (() => unknown);
86
103
  /** A number means pixels. @default '20rem' */
87
104
  height?: number | string;
88
105
  /** Which way the bars grow, and so which way the rows run. @default 'vertical' */
@@ -93,6 +110,8 @@ declare const __VLS_export: <T extends Record<string, any>>(__VLS_props: NonNull
93
110
  hidden?: string[];
94
111
  /** The chart's accessible name. Defaults to its series. */
95
112
  label?: string;
113
+ /** How many `--chart-color-N` the theme defines: series past it start over at the first. @default 8 */
114
+ paletteSize?: number;
96
115
  } & {
97
116
  "onUpdate:hidden"?: ((hidden: string[]) => any) | undefined;
98
117
  }> & (typeof globalThis extends {
@@ -1,6 +1,6 @@
1
1
  import { createContext } from "../../shared/context.js";
2
2
  import { useChartSeries } from "./use-chart-series.js";
3
- import { curveOf, plotted, rowFocus, rowLabel, rowTicks, tickLabels, valueLabel } from "./chart-scales.js";
3
+ import { SVG_ANIMATION, curveOf, plotted, pointFocus, rowFocus, rowLabel, rowTicks, tickLabels, valueLabel } from "./chart-scales.js";
4
4
  import ChartFrame_default from "./ChartFrame.js";
5
5
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, getCurrentInstance, mergeProps, normalizeStyle, onBeforeUnmount, onMounted, openBlock, renderList, renderSlot, shallowRef, toDisplayString, unref, withCtx } from "vue";
6
6
  import { chartColors, formatNumber } from "@vunset/utils";
@@ -53,11 +53,16 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
53
53
  props: {
54
54
  data: {},
55
55
  xKey: {},
56
+ xScale: {
57
+ type: [String, Function],
58
+ default: "category"
59
+ },
56
60
  height: { default: "20rem" },
57
61
  orientation: { default: "vertical" },
58
62
  stacked: { type: Boolean },
59
63
  hidden: { default: void 0 },
60
- label: {}
64
+ label: {},
65
+ paletteSize: {}
61
66
  },
62
67
  emits: ["update:hidden"],
63
68
  setup(__props, { emit: __emit }) {
@@ -88,7 +93,7 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
88
93
  const { colors, visible } = useChartSeries({
89
94
  categories: () => keys.value,
90
95
  colors: () => {
91
- const palette = chartColors(keys.value.length);
96
+ const palette = chartColors(keys.value.length, void 0, void 0, props.paletteSize);
92
97
  return keys.value.map((key, index) => series.value.find((entry) => entry.yKey === key && entry.color)?.color ?? palette[index]);
93
98
  },
94
99
  labels: () => keys.value.map(labelOf),
@@ -97,6 +102,7 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
97
102
  onHiddenChange: (next) => emit("update:hidden", next)
98
103
  });
99
104
  const horizontal = computed(() => props.orientation === "horizontal");
105
+ const continuous = computed(() => props.xScale !== "category");
100
106
  const shownKeys = computed(() => visible.value.map((entry) => entry.category));
101
107
  const shownColors = computed(() => visible.value.map((entry) => entry.color));
102
108
  const shown = computed(() => series.value.filter((entry) => shownKeys.value.includes(entry.yKey)));
@@ -120,9 +126,12 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
120
126
  });
121
127
  const formatOf = (entry) => entry?.format ?? axisOf(entry?.scale ?? "y")?.format;
122
128
  const xText = (row) => rowLabel(row, props.xKey, xAxis.value?.format);
123
- /** The row's series for the tooltip, one per key showing. */
124
- function tooltipSeries(row) {
125
- return shownKeys.value.map((key, index) => {
129
+ const headingText = (row) => rowLabel(row, props.xKey, tooltips.value[0]?.headingFormat ?? xAxis.value?.format);
130
+ const tooltip$1 = computed(() => tooltips.value[0]);
131
+ const pointMode = computed(() => tooltip$1.value?.mode === "point");
132
+ /** The row's series for the tooltip, one per key showing; in `point` mode, only `key`'s. */
133
+ function tooltipSeries(row, only) {
134
+ const list = shownKeys.value.map((key, index) => {
126
135
  const value = row[key];
127
136
  const format = formatOf(series.value.find((entry) => entry.yKey === key));
128
137
  return {
@@ -133,21 +142,25 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
133
142
  text: format ? format(value) : formatNumber(Number(value) || 0)
134
143
  };
135
144
  });
145
+ return pointMode.value && only !== void 0 ? list.filter((entry) => entry.key === only) : list;
136
146
  }
137
- const tooltipProps = (row) => ({
138
- row,
139
- heading: xText(row),
140
- series: tooltipSeries(row)
147
+ const tooltipProps = (point, pinned) => ({
148
+ row: point.datum.row,
149
+ heading: headingText(point.datum.row),
150
+ series: tooltipSeries(point.datum.row, point.datum.category),
151
+ pinned
141
152
  });
142
153
  const band = shallowRef();
143
154
  const tickSize = shallowRef();
144
- const fits = computed(() => xAxis.value?.trimLabels && !horizontal.value && band.value !== void 0 ? Math.max(1, Math.floor(band.value / ((tickSize.value ?? 11) * .6))) : void 0);
155
+ const fits = computed(() => xAxis.value?.trimLabels && !horizontal.value && !continuous.value && band.value !== void 0 ? Math.max(1, Math.floor(band.value / ((tickSize.value ?? 11) * .6))) : void 0);
145
156
  const trim = (label, fits) => fits !== void 0 && label.length > fits ? `${label.slice(0, Math.max(1, fits - 1))}…` : label;
146
157
  const areaGradient = (key) => `area-${colorIndex(key)}`;
147
158
  const barGradient = (key) => `bar-${colorIndex(key)}`;
159
+ const at = (row, index) => continuous.value ? row[props.xKey] : index;
148
160
  const pointsOf = (key, fill) => props.data.map((row, index) => ({
149
161
  row,
150
162
  index,
163
+ at: at(row, index),
151
164
  category: key,
152
165
  value: plotted(row[key]),
153
166
  fill
@@ -159,6 +172,7 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
159
172
  const data = props.data.flatMap((row, index) => bars.map((entry) => ({
160
173
  row,
161
174
  index,
175
+ at: index,
162
176
  category: entry.yKey,
163
177
  value: plotted(row[entry.yKey]),
164
178
  fill: entry.gradient ? `url(#${barGradient(entry.yKey)})` : void 0
@@ -176,11 +190,11 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
176
190
  return horizontal.value ? barX(data, {
177
191
  ...options,
178
192
  x: "value",
179
- y: "index",
193
+ y: "at",
180
194
  xScale: valueId(first.scale)
181
195
  }) : barY(data, {
182
196
  ...options,
183
- x: "index",
197
+ x: "at",
184
198
  y: "value",
185
199
  yScale: valueId(first.scale)
186
200
  });
@@ -190,10 +204,10 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
190
204
  const channels = {
191
205
  ...horizontal.value ? {
192
206
  x: "value",
193
- y: "index",
207
+ y: "at",
194
208
  xScale: valueId(entry.scale)
195
209
  } : {
196
- x: "index",
210
+ x: "at",
197
211
  y: "value",
198
212
  yScale: valueId(entry.scale)
199
213
  },
@@ -209,10 +223,15 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
209
223
  if (entry.kind === "line") return [line];
210
224
  const area = (horizontal.value ? areaX : areaY)(points, {
211
225
  ...channels,
212
- fill: `url(#${areaGradient(entry.yKey)})`,
213
- fillOpacity: 1
226
+ ...entry.gradient === false ? {
227
+ fill: colors.value[colorIndex(entry.yKey)],
228
+ fillOpacity: .25
229
+ } : {
230
+ fill: `url(#${areaGradient(entry.yKey)})`,
231
+ fillOpacity: 1
232
+ }
214
233
  });
215
- return [decorative(area), line];
234
+ return entry.line === false ? [area] : [decorative(area), line];
216
235
  }
217
236
  const fade = computed(() => horizontal.value ? {
218
237
  x1: 1,
@@ -229,7 +248,7 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
229
248
  const found = /* @__PURE__ */ new Map();
230
249
  for (const entry of shown.value) {
231
250
  const color = colors.value[colorIndex(entry.yKey)];
232
- if (entry.kind === "area") found.set(areaGradient(entry.yKey), {
251
+ if (entry.kind === "area" && entry.gradient !== false) found.set(areaGradient(entry.yKey), {
233
252
  id: areaGradient(entry.yKey),
234
253
  x1: 0,
235
254
  y1: 0,
@@ -264,7 +283,10 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
264
283
  const marks = [];
265
284
  let bars = false;
266
285
  for (const entry of shown.value) if (entry.kind !== "bar") marks.push(...seriesMarks(entry));
267
- else if (!bars) {
286
+ else if (continuous.value) {
287
+ if (process.env.NODE_ENV !== "production" && !bars) console.warn("[vunset] ChartBar needs `x-scale=\"category\"`: bars are left out on a continuous x axis.");
288
+ bars = true;
289
+ } else if (!bars) {
268
290
  marks.push(barMark());
269
291
  bars = true;
270
292
  }
@@ -278,15 +300,32 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
278
300
  const budget = fits.value;
279
301
  const x = xAxis.value;
280
302
  const firstBar = series.value.find((entry) => entry.kind === "bar");
281
- const rowScale = {
303
+ const titled = (axis) => axis?.label ? { label: axis.label } : {};
304
+ const stubs = (axis) => axis.tickMarks === false ? { line: false } : {};
305
+ const rowScale = continuous.value ? {
306
+ scale: props.xScale === "linear" ? scaleLinear : props.xScale,
307
+ grid: grids.value.some((entry) => entry.type === "x"),
308
+ axis: x ? {
309
+ line: x.line === true,
310
+ ...tickLabels(tickSize.value),
311
+ ...titled(x),
312
+ ticks: {
313
+ ...x.format && { format: x.format },
314
+ ...x.numTicks !== void 0 && { count: x.numTicks },
315
+ ...stubs(x)
316
+ }
317
+ } : false
318
+ } : {
282
319
  scale: firstBar ? () => scaleBand().padding(firstBar.padding ?? .1) : () => scalePoint().padding(0),
283
320
  grid: grids.value.some((entry) => entry.type === "x"),
284
321
  axis: x ? {
285
- line: false,
322
+ line: x.line === true,
286
323
  ...tickLabels(tickSize.value),
324
+ ...titled(x),
287
325
  ticks: {
288
326
  format: (index) => trim(xText(props.data[index]), budget),
289
- values: rowTicks(props.data.length, x.numTicks)
327
+ values: shown.value.length ? rowTicks(props.data.length, x.numTicks) : void 0,
328
+ ...stubs(x)
290
329
  }
291
330
  } : false
292
331
  };
@@ -301,16 +340,19 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
301
340
  nice: true,
302
341
  grid: valueGrid.value === scale,
303
342
  axis: axis && axisShown(scale) ? {
304
- line: false,
343
+ line: axis.line === true,
305
344
  ...tickLabels(tickSize.value),
345
+ ...titled(axis),
306
346
  ticks: {
307
347
  format: (raw) => valueLabel(raw, axis.format),
308
- ...axis.numTicks !== void 0 && { count: axis.numTicks }
348
+ ...axis.numTicks !== void 0 && { count: axis.numTicks },
349
+ ...stubs(axis)
309
350
  }
310
351
  } : false
311
352
  }];
312
353
  }));
313
354
  return defineChart({
355
+ svgAnimation: SVG_ANIMATION,
314
356
  marks,
315
357
  scales: {
316
358
  [rowId.value]: rowScale,
@@ -318,15 +360,16 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
318
360
  },
319
361
  color: { scale: scaleOrdinal().domain(shownKeys.value).range(shownColors.value) },
320
362
  gradients: gradients(),
321
- ...rowFocus(horizontal.value),
322
- tooltip: tooltips.value.length > 0 && {
363
+ ...pointMode.value ? pointFocus : rowFocus(horizontal.value),
364
+ tooltip: tooltip$1.value && {
323
365
  use: tooltip,
366
+ sticky: tooltip$1.value.sticky,
324
367
  content: (points) => {
325
368
  const row = points[0]?.datum.row;
326
369
  if (!row) return { rows: [] };
327
370
  return {
328
- title: row[props.xKey] !== void 0 ? xText(row) : void 0,
329
- rows: tooltipSeries(row).map((entry) => ({
371
+ title: row[props.xKey] !== void 0 ? headingText(row) : void 0,
372
+ rows: tooltipSeries(row, points[0].datum.category).map((entry) => ({
330
373
  label: entry.label,
331
374
  value: entry.text,
332
375
  color: entry.color
@@ -348,7 +391,6 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
348
391
  for (const label of svg.querySelectorAll(`text[data-ts-key^="${valueId(scale)}-tick-label"]`)) label.setAttribute("fill", color);
349
392
  }
350
393
  }
351
- const tooltip$1 = computed(() => tooltips.value[0]);
352
394
  const Render = (own) => own.render();
353
395
  return (_ctx, _cache) => {
354
396
  return openBlock(), createBlock(ChartFrame_default, mergeProps({
@@ -361,10 +403,10 @@ var ChartRoot_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
361
403
  "tick-size": tickSize.value,
362
404
  "onUpdate:tickSize": _cache[0] || (_cache[0] = ($event) => tickSize.value = $event)
363
405
  }, _ctx.$attrs, { onRender }), {
364
- tooltip: withCtx(({ point }) => [tooltip$1.value?.slot ? (openBlock(), createBlock(Render, {
406
+ tooltip: withCtx(({ point, pinned }) => [tooltip$1.value?.slot ? (openBlock(), createBlock(Render, {
365
407
  key: 0,
366
- render: () => tooltip$1.value.slot(tooltipProps(point.datum.row))
367
- }, null, 8, ["render"])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [point.datum.row[props.xKey] !== void 0 ? (openBlock(), createElementBlock("div", _hoisted_1, toDisplayString(xText(point.datum.row)), 1)) : createCommentVNode("", true), createElementVNode("div", _hoisted_2, [(openBlock(true), createElementBlock(Fragment, null, renderList(tooltipSeries(point.datum.row), (entry) => {
408
+ render: () => tooltip$1.value.slot(tooltipProps(point, pinned))
409
+ }, null, 8, ["render"])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [point.datum.row[props.xKey] !== void 0 ? (openBlock(), createElementBlock("div", _hoisted_1, toDisplayString(headingText(point.datum.row)), 1)) : createCommentVNode("", true), createElementVNode("div", _hoisted_2, [(openBlock(true), createElementBlock(Fragment, null, renderList(tooltipSeries(point.datum.row, point.datum.category), (entry) => {
368
410
  return openBlock(), createElementBlock("div", {
369
411
  key: entry.key,
370
412
  "data-part": "tooltip-row"
@@ -1,9 +1,20 @@
1
1
  import { type ChartTooltipSlotProps } from './ChartRoot.vue';
2
+ type __VLS_Props = {
3
+ /** `row`: every series at the row under the pointer. `point`: the one point nearest it. @default 'row' */
4
+ mode?: 'row' | 'point';
5
+ /** A click, Enter or Space pins it in place; another, or Escape, lets it go. @default true */
6
+ sticky?: boolean;
7
+ /** Formats the heading from the row's `x-key` value, apart from the x axis' ticks. Defaults to the x axis' `format`. */
8
+ headingFormat?: (value: any) => string;
9
+ };
2
10
  type __VLS_Slots = {
3
11
  /** Replaces the content: a heading, then a row per series. */
4
12
  default?(props: ChartTooltipSlotProps): unknown;
5
13
  };
6
- declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
14
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
15
+ mode: "row" | "point";
16
+ sticky: boolean;
17
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
18
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
8
19
  declare const _default: typeof __VLS_export;
9
20
  export default _default;
@@ -5,12 +5,24 @@ var ChartTooltip_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ def
5
5
  name: "ChartTooltip",
6
6
  inheritAttrs: false,
7
7
  __name: "ChartTooltip",
8
+ props: {
9
+ mode: { default: "row" },
10
+ sticky: {
11
+ type: Boolean,
12
+ default: true
13
+ },
14
+ headingFormat: {}
15
+ },
8
16
  setup(__props) {
17
+ const props = __props;
9
18
  const slots = useSlots();
10
19
  const attrs = useAttrs();
11
20
  useChartPart("tooltip", () => ({
12
21
  attrs,
13
- slot: slots.default
22
+ slot: slots.default,
23
+ mode: props.mode,
24
+ sticky: props.sticky,
25
+ headingFormat: props.headingFormat
14
26
  }));
15
27
  return (_ctx, _cache) => {
16
28
  return null;
@@ -6,6 +6,11 @@ import type { ChartCurve } from '@tanstack/charts';
6
6
  export declare function rowTicks(length: number, count: number | undefined): number[] | undefined;
7
7
  /** TanStack's own tick label size, in px, until `--chart-tick-font-size` sets one. */
8
8
  export declare const TICK_FONT_SIZE = 11;
9
+ /** Tweens a cartesian chart's redraw for new data or a toggled series; off under reduced motion, never on resize. */
10
+ export declare const SVG_ANIMATION: {
11
+ readonly duration: 240;
12
+ readonly easing: "ease-out";
13
+ };
9
14
  /** An axis' tick labels at `size` px; TanStack lays the axis out for it. */
10
15
  export declare const tickLabels: (size: number | undefined) => {
11
16
  tickLabels?: undefined;
@@ -28,6 +33,11 @@ export declare const rowFocus: (horizontal?: boolean) => {
28
33
  focus: "group-y" | "group-x";
29
34
  maxFocusDistance: number;
30
35
  };
36
+ /** The one point nearest the pointer, however far. */
37
+ export declare const pointFocus: {
38
+ focus: "nearest";
39
+ maxFocusDistance: number;
40
+ };
31
41
  /** A chart's accessible name: what it plots, in the reader's words. */
32
42
  export declare const chartName: (categories: string[], labelFormat: ((category: string) => string) | undefined, fallback: string) => string;
33
43
  /** A line's run between its points: bending through them, or straight. TanStack draws straight by default. */
@@ -10,12 +10,19 @@ function rowTicks(length, count) {
10
10
  const step = Math.max(1, Math.ceil(length / Math.max(1, count)));
11
11
  return Array.from({ length }, (_, index) => index).filter((index) => index % step === 0);
12
12
  }
13
+ /** Tweens a cartesian chart's redraw for new data or a toggled series; off under reduced motion, never on resize. */
14
+ var SVG_ANIMATION = {
15
+ duration: 240,
16
+ easing: "ease-out"
17
+ };
13
18
  /** An axis' tick labels at `size` px; TanStack lays the axis out for it. */
14
19
  var tickLabels = (size) => size === void 0 ? {} : { tickLabels: { fontSize: size } };
15
20
  /** A row's `xKey` value as its axis label. */
16
21
  function rowLabel(row, xKey, format) {
17
22
  const raw = row?.[xKey];
18
- return raw === void 0 ? "" : format ? format(raw) : String(raw);
23
+ if (raw === void 0) return "";
24
+ if (format) return format(raw);
25
+ return raw instanceof Date ? raw.toLocaleString() : String(raw);
19
26
  }
20
27
  /** A value axis label: the caller's formatter, or a grouped number. */
21
28
  var valueLabel = (raw, format) => format ? format(raw) : formatNumber(raw);
@@ -29,6 +36,11 @@ var rowFocus = (horizontal = false) => ({
29
36
  focus: horizontal ? "group-y" : "group-x",
30
37
  maxFocusDistance: Number.POSITIVE_INFINITY
31
38
  });
39
+ /** The one point nearest the pointer, however far. */
40
+ var pointFocus = {
41
+ focus: "nearest",
42
+ maxFocusDistance: Number.POSITIVE_INFINITY
43
+ };
32
44
  /** A chart's accessible name: what it plots, in the reader's words. */
33
45
  var chartName = (categories, labelFormat, fallback) => categories.map((category) => labelFormat ? labelFormat(category) : category).join(", ") || fallback;
34
46
  var SMOOTH = {
@@ -38,4 +50,4 @@ var SMOOTH = {
38
50
  /** A line's run between its points: bending through them, or straight. TanStack draws straight by default. */
39
51
  var curveOf = (curve) => curve === "smooth" ? SMOOTH : void 0;
40
52
  //#endregion
41
- export { chartName, curveOf, plotted, rowFocus, rowLabel, rowTicks, tickLabels, valueLabel };
53
+ export { SVG_ANIMATION, chartName, curveOf, plotted, pointFocus, rowFocus, rowLabel, rowTicks, tickLabels, valueLabel };
@@ -24,6 +24,8 @@ export declare const provideChartContext: (value: ChartContext) => ChartContext,
24
24
  export interface UseChartSeriesOptions {
25
25
  categories: () => string[];
26
26
  colors: () => string[] | undefined;
27
+ /** How many palette colors the default cycles through. */
28
+ paletteSize?: () => number | undefined;
27
29
  labels?: () => string[];
28
30
  /** Supplying this makes the hidden list controlled. */
29
31
  hidden: () => string[] | undefined;
@@ -18,7 +18,7 @@ var { provideContext: provideChartContext, useContext: useChartContext, useOptio
18
18
  * happens to be showing.
19
19
  */
20
20
  function useChartSeries(options) {
21
- const colors = computed(() => options.colors() ?? chartColors(options.categories().length));
21
+ const colors = computed(() => options.colors() ?? chartColors(options.categories().length, void 0, void 0, options.paletteSize?.()));
22
22
  const hidden = useControlled({
23
23
  value: options.hidden,
24
24
  defaultValue: () => [],
@@ -82,18 +82,18 @@ type __VLS_Slots = {} & {
82
82
  default?: (props: typeof __VLS_8) => any;
83
83
  };
84
84
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
85
- create: (value: string) => any;
86
85
  "update:modelValue": (value: ListboxOptionValue | ListboxOptionValue[] | null | undefined) => any;
86
+ create: (value: string) => any;
87
87
  "update:open": (open: boolean) => any;
88
88
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
89
- onCreate?: ((value: string) => any) | undefined;
90
89
  "onUpdate:modelValue"?: ((value: ListboxOptionValue | ListboxOptionValue[] | null | undefined) => any) | undefined;
90
+ onCreate?: ((value: string) => any) | undefined;
91
91
  "onUpdate:open"?: ((open: boolean) => any) | undefined;
92
92
  }>, {
93
- required: boolean;
94
93
  invalid: boolean;
95
94
  as: string | object;
96
95
  modelValue: ListboxOptionValue | ListboxOptionValue[] | null;
96
+ required: boolean;
97
97
  options: ListboxItem[];
98
98
  disabled: boolean;
99
99
  open: boolean;
@@ -147,11 +147,11 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
147
147
  "onUpdate:modelValue"?: ((value: CalendarModelValue | undefined) => any) | undefined;
148
148
  "onUpdate:open"?: ((open: boolean) => any) | undefined;
149
149
  }>, {
150
- required: boolean;
151
- invalid: boolean;
152
150
  mode: CalendarSelectionMode;
153
- side: Side;
151
+ invalid: boolean;
154
152
  as: string | object;
153
+ required: boolean;
154
+ side: Side;
155
155
  disabled: boolean;
156
156
  open: boolean;
157
157
  align: Align;
@@ -29,9 +29,9 @@ type __VLS_Slots = {
29
29
  custom(props: UseFieldReturn): unknown;
30
30
  };
31
31
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, UseFieldReturn, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
32
- required: boolean;
33
32
  invalid: boolean;
34
33
  as: string | object;
34
+ required: boolean;
35
35
  disabled: boolean;
36
36
  readOnly: boolean;
37
37
  touched: boolean;
@@ -42,8 +42,8 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
42
42
  /** Element or component to render. */
43
43
  as?: string | object;
44
44
  }> & Readonly<{}>, {
45
- orientation: Orientation;
46
45
  as: string | object;
46
+ orientation: Orientation;
47
47
  variant: GroupVariant;
48
48
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
49
49
  default?: (props: {
@@ -63,9 +63,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, import("./u
63
63
  }>, {
64
64
  defaultValue: number | number[];
65
65
  invalid: boolean;
66
- orientation: RangeOrientation;
67
66
  as: string | object;
68
67
  modelValue: number | number[];
68
+ orientation: RangeOrientation;
69
69
  disabled: boolean;
70
70
  min: number;
71
71
  max: number;
@@ -80,8 +80,8 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
80
80
  /** Element or component to render. */
81
81
  as?: string | object;
82
82
  }> & Readonly<{}>, {
83
- axis: ScrollAreaAxis;
84
83
  as: string | object;
84
+ axis: ScrollAreaAxis;
85
85
  fade: ScrollAreaFade;
86
86
  overflowThreshold: number;
87
87
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
@@ -90,10 +90,10 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
90
90
  "onUpdate:modelValue"?: ((value: ListboxOptionValue | ListboxOptionValue[] | null | undefined) => any) | undefined;
91
91
  "onUpdate:open"?: ((open: boolean) => any) | undefined;
92
92
  }>, {
93
- required: boolean;
94
93
  invalid: boolean;
95
94
  as: string | object;
96
95
  modelValue: ListboxOptionValue | ListboxOptionValue[] | null;
96
+ required: boolean;
97
97
  options: ListboxItem[];
98
98
  disabled: boolean;
99
99
  open: boolean;
@@ -28,9 +28,9 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, import("./u
28
28
  "onUpdate:modelValue"?: ((value: TabValue) => any) | undefined;
29
29
  }>, {
30
30
  defaultValue: TabValue;
31
- orientation: TabsOrientation;
32
31
  as: string | object;
33
32
  modelValue: TabValue;
33
+ orientation: TabsOrientation;
34
34
  loop: boolean;
35
35
  activateOnFocus: boolean;
36
36
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -58,10 +58,10 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
58
58
  "onUpdate:modelValue"?: ((value: string | null | undefined) => any) | undefined;
59
59
  "onUpdate:open"?: ((open: boolean) => any) | undefined;
60
60
  }>, {
61
- required: boolean;
62
61
  invalid: boolean;
63
- side: Side;
64
62
  as: string | object;
63
+ required: boolean;
64
+ side: Side;
65
65
  disabled: boolean;
66
66
  open: boolean;
67
67
  align: Align;
@@ -45,11 +45,11 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, import("./u
45
45
  "onUpdate:modelValue"?: ((value: ToggleGroupValue | undefined) => any) | undefined;
46
46
  }>, {
47
47
  defaultValue: ToggleGroupValue;
48
- required: boolean;
49
48
  invalid: boolean;
50
- orientation: Orientation;
51
49
  as: string | object;
52
50
  modelValue: ToggleGroupValue;
51
+ required: boolean;
52
+ orientation: Orientation;
53
53
  disabled: boolean;
54
54
  loop: boolean;
55
55
  multiple: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vunset/vue",
3
- "version": "1.0.0-rc.3",
3
+ "version": "1.0.0-rc.5",
4
4
  "description": "Headless, unstyled Vue 3 components: keyboard, focus and ARIA handled, the look left to you.",
5
5
  "keywords": [
6
6
  "vue",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@floating-ui/vue": "^2.0.1",
50
- "@vunset/utils": "1.0.0-rc.3"
50
+ "@vunset/utils": "1.0.0-rc.5"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@tanstack/charts": "^1.1.0",