vccs 1.0.0-beta.1 → 1.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/README.md +11 -0
- package/dist/es/cartesian/bar/components/BarRectangles.mjs +1 -1
- package/dist/es/cartesian/brush/Brush.mjs +4 -0
- package/dist/es/cartesian/funnel/Funnel.mjs +1 -1
- package/dist/es/cartesian/scatter/Scatter.mjs +1 -1
- package/dist/es/chart/CellGridLayer.mjs +1 -1
- package/dist/es/chart/JourneySankey.mjs +1 -1
- package/dist/es/chart/Sankey.mjs +2 -2
- package/dist/es/chart/Sparkline.mjs +1 -1
- package/dist/es/chart/SunburstChart.mjs +1 -1
- package/dist/es/chart/Treemap.mjs +1 -1
- package/dist/es/events/sync.mjs +1 -2
- package/dist/es/events/usePointEvents.mjs +1 -1
- package/dist/es/model/tooltip.mjs +3 -5
- package/dist/es/polar/pie/Pie.mjs +1 -1
- package/dist/es/polar/radial-bar/RadialBar.mjs +1 -1
- package/dist/model/tooltip.d.ts +4 -18
- package/package.json +6 -2
- package/usage/catalog.json +235 -0
- package/usage/guides/charts/area-chart.md +56 -0
- package/usage/guides/charts/bar-chart.md +60 -0
- package/usage/guides/charts/bar-list.md +46 -0
- package/usage/guides/charts/calendar-heatmap.md +55 -0
- package/usage/guides/charts/cohort-chart.md +47 -0
- package/usage/guides/charts/composed-chart.md +70 -0
- package/usage/guides/charts/funnel-chart.md +58 -0
- package/usage/guides/charts/heatmap.md +51 -0
- package/usage/guides/charts/journey-sankey.md +49 -0
- package/usage/guides/charts/line-chart.md +60 -0
- package/usage/guides/charts/pie-chart.md +59 -0
- package/usage/guides/charts/radar-chart.md +69 -0
- package/usage/guides/charts/radial-bar-chart.md +54 -0
- package/usage/guides/charts/sankey.md +59 -0
- package/usage/guides/charts/scatter-chart.md +62 -0
- package/usage/guides/charts/sparkline.md +51 -0
- package/usage/guides/charts/sunburst-chart.md +66 -0
- package/usage/guides/charts/tracker.md +49 -0
- package/usage/guides/charts/treemap.md +68 -0
- package/usage/guides/core/installation.md +68 -0
- package/usage/guides/core/ssr-testing.md +50 -0
- package/usage/guides/core/typed-rows.md +47 -0
- package/usage/guides/core/vue-api.md +72 -0
- package/usage/vccs-usage.mjs +191 -0
package/README.md
CHANGED
|
@@ -76,6 +76,17 @@ export default defineConfig({
|
|
|
76
76
|
})
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
## Use vccs with an AI agent
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
npx skills add unovue/vue-charts # add -g to install for every project
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Then just ask for the chart — you run nothing yourself. Claude loads the skill when the request
|
|
86
|
+
matches it, or you can invoke it explicitly with `/vccs-usage`:
|
|
87
|
+
|
|
88
|
+
> add a card with weekly user retention by signup month
|
|
89
|
+
|
|
79
90
|
## Typed rows
|
|
80
91
|
|
|
81
92
|
`defineChartComponents` binds your row type to the components you pick. A wrong `data-key` is
|
|
@@ -148,7 +148,7 @@ var BarRectangles = /* @__PURE__ */ defineComponent({
|
|
|
148
148
|
emit("mouseenter", bar, index, event);
|
|
149
149
|
},
|
|
150
150
|
mouseleave: ({ bar, index }, _position, event) => {
|
|
151
|
-
tooltip.clear("hover");
|
|
151
|
+
tooltip.clear("hover", "item");
|
|
152
152
|
emit("mouseleave", bar, index, event);
|
|
153
153
|
}
|
|
154
154
|
});
|
|
@@ -55,8 +55,10 @@ var BrushView = /* @__PURE__ */ defineComponent({
|
|
|
55
55
|
const startIndex = computed(() => view.range?.startIndex ?? 0);
|
|
56
56
|
const endIndex = computed(() => view.range?.endIndex ?? Math.max(0, (chartData.value?.length ?? 0) - 1));
|
|
57
57
|
const calculatedY = computed(() => (y.value ?? 0) + (props.dy ?? 0));
|
|
58
|
+
let proposed;
|
|
58
59
|
function onChange(nextState) {
|
|
59
60
|
if (sameRange(nextState, view.range)) return;
|
|
61
|
+
proposed = nextState;
|
|
60
62
|
emit("update:range", nextState);
|
|
61
63
|
emit("change", nextState);
|
|
62
64
|
nextTick(restoreControlledPositions);
|
|
@@ -68,6 +70,8 @@ var BrushView = /* @__PURE__ */ defineComponent({
|
|
|
68
70
|
});
|
|
69
71
|
function restoreControlledPositions() {
|
|
70
72
|
if (!view.controlled()) return;
|
|
73
|
+
if (sameRange(view.range, proposed ?? null)) return;
|
|
74
|
+
proposed = void 0;
|
|
71
75
|
brushState.value.startX = brushState.value.scale?.(startIndex.value);
|
|
72
76
|
brushState.value.endX = brushState.value.scale?.(endIndex.value);
|
|
73
77
|
}
|
|
@@ -125,7 +125,7 @@ var ScatterView = /* @__PURE__ */ defineComponent({
|
|
|
125
125
|
});
|
|
126
126
|
};
|
|
127
127
|
const onMouseLeaveSymbol = () => {
|
|
128
|
-
tooltip.clear("hover");
|
|
128
|
+
tooltip.clear("hover", "item");
|
|
129
129
|
};
|
|
130
130
|
let symbolData = [];
|
|
131
131
|
const listeners = delegateItemEvents((index) => symbolData[index], {
|
|
@@ -203,7 +203,7 @@ var CellGridLayer = /* @__PURE__ */ defineComponent({
|
|
|
203
203
|
coordinate: void 0,
|
|
204
204
|
active: false
|
|
205
205
|
});
|
|
206
|
-
else tooltip.clear("hover");
|
|
206
|
+
else tooltip.clear("hover", "item");
|
|
207
207
|
}
|
|
208
208
|
function onEnter(cell, index, event) {
|
|
209
209
|
keyboard.value = false;
|
package/dist/es/chart/Sankey.mjs
CHANGED
|
@@ -292,11 +292,11 @@ function useSankey(props, slots, emit) {
|
|
|
292
292
|
emit("link-mouseenter", link, index, e);
|
|
293
293
|
}
|
|
294
294
|
function handleNodeMouseLeave(node, index, e) {
|
|
295
|
-
tooltip.clear("hover");
|
|
295
|
+
tooltip.clear("hover", "item");
|
|
296
296
|
emit("node-mouseleave", node, index, e);
|
|
297
297
|
}
|
|
298
298
|
function handleLinkMouseLeave(link, index, e) {
|
|
299
|
-
tooltip.clear("hover");
|
|
299
|
+
tooltip.clear("hover", "item");
|
|
300
300
|
emit("link-mouseleave", link, index, e);
|
|
301
301
|
}
|
|
302
302
|
function handleNodeClick(node, index, e) {
|
|
@@ -247,7 +247,7 @@ function useSparkline(props, emit) {
|
|
|
247
247
|
function setActive(index, keyboard = false) {
|
|
248
248
|
const point = index === null ? void 0 : points.value[index];
|
|
249
249
|
if (!point && !keyboard) {
|
|
250
|
-
tooltip.clear("hover");
|
|
250
|
+
tooltip.clear("hover", "item");
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
253
|
const action = {
|
|
@@ -201,7 +201,7 @@ function useSunburst(props, slots, emit) {
|
|
|
201
201
|
});
|
|
202
202
|
}
|
|
203
203
|
function handleMouseLeave(node, e) {
|
|
204
|
-
tooltip.clear("hover");
|
|
204
|
+
tooltip.clear("hover", "item");
|
|
205
205
|
emit("node-mouseleave", node, indexOf(node), e);
|
|
206
206
|
}
|
|
207
207
|
function handleClick(node, e) {
|
|
@@ -278,7 +278,7 @@ function useTreemap(props, slots, emit) {
|
|
|
278
278
|
emit("node-mouseenter", node, index, e);
|
|
279
279
|
}
|
|
280
280
|
function handleNodeMouseLeave(node, index, e) {
|
|
281
|
-
tooltip.clear("hover");
|
|
281
|
+
tooltip.clear("hover", "item");
|
|
282
282
|
emit("node-mouseleave", node, index, e);
|
|
283
283
|
}
|
|
284
284
|
function handleNodeClick(node, index, e) {
|
package/dist/es/events/sync.mjs
CHANGED
|
@@ -10,8 +10,7 @@ function useTooltipChartSynchronisation(source, enabled) {
|
|
|
10
10
|
const activeDataKey = computed(() => tooltip.target.value?.entry?.value?.settings.dataKey);
|
|
11
11
|
const eventEmitterSymbol = presentation.emitter;
|
|
12
12
|
const syncId = presentation.syncId;
|
|
13
|
-
const
|
|
14
|
-
const isReceivingSynchronisation = computed(() => tooltipState.value?.active);
|
|
13
|
+
const isReceivingSynchronisation = computed(() => tooltip.receivingSynchronisation.value);
|
|
15
14
|
watchEffect(() => {
|
|
16
15
|
if (!enabled()) return;
|
|
17
16
|
if (isReceivingSynchronisation.value) return;
|
|
@@ -286,8 +286,9 @@ function createTooltip(inputs) {
|
|
|
286
286
|
coordinate: input.coordinate
|
|
287
287
|
};
|
|
288
288
|
}
|
|
289
|
-
function clear(channel) {
|
|
289
|
+
function clear(channel, scope) {
|
|
290
290
|
if (channel === "hover" && settings.value.trigger !== "hover") return;
|
|
291
|
+
if (scope === "item" && selection.value?.target.entry === void 0) return;
|
|
291
292
|
request(null);
|
|
292
293
|
if (channel === "keyboard") {
|
|
293
294
|
selection.value = null;
|
|
@@ -371,10 +372,7 @@ function createTooltip(inputs) {
|
|
|
371
372
|
index: selection.value.requestedIndex,
|
|
372
373
|
active: selection.value.active
|
|
373
374
|
} : noInteraction),
|
|
374
|
-
|
|
375
|
-
...selection.value?.channel === "sync" ? interaction.value : noInteraction,
|
|
376
|
-
label: label.value
|
|
377
|
-
})),
|
|
375
|
+
receivingSynchronisation: computed(() => selection.value?.channel === "sync"),
|
|
378
376
|
activeIndexFor,
|
|
379
377
|
coordinateFor,
|
|
380
378
|
activate,
|
|
@@ -139,7 +139,7 @@ var PieView = /* @__PURE__ */ defineComponent({
|
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
141
|
function handleSectorLeave() {
|
|
142
|
-
tooltip.clear("hover");
|
|
142
|
+
tooltip.clear("hover", "item");
|
|
143
143
|
}
|
|
144
144
|
let sectorList = items.value;
|
|
145
145
|
const listeners = delegateItemEvents((position) => sectorList[position]?.value, {
|
|
@@ -217,7 +217,7 @@ var RadialBarView = /* @__PURE__ */ defineComponent({
|
|
|
217
217
|
emit("mouseenter", sector, sector.index, event);
|
|
218
218
|
};
|
|
219
219
|
const onMouseleave = (event) => {
|
|
220
|
-
tooltip.clear("hover");
|
|
220
|
+
tooltip.clear("hover", "item");
|
|
221
221
|
emit("mouseleave", sector, sector.index, event);
|
|
222
222
|
};
|
|
223
223
|
if (slots.shape) return createVNode("g", mergeProps({ "key": items.value[i].key }, { [DATA_ITEM_INDEX_ATTRIBUTE_NAME]: sector.index }, {
|
package/dist/model/tooltip.d.ts
CHANGED
|
@@ -228,18 +228,11 @@ export declare function useTooltipController(): {
|
|
|
228
228
|
entries: import('./registry.js').Registry<TooltipPayloadConfiguration>;
|
|
229
229
|
announcement: import('vue').ShallowRef<string, string>;
|
|
230
230
|
keyboardInteraction: ComputedRef<TooltipInteraction>;
|
|
231
|
-
|
|
232
|
-
label: string | undefined;
|
|
233
|
-
configuration?: TooltipPayloadConfiguration;
|
|
234
|
-
active: boolean;
|
|
235
|
-
index: TooltipActiveIndex;
|
|
236
|
-
dataKey: import('../types/base.js').ChartDataKey | undefined;
|
|
237
|
-
coordinate: Coordinate | undefined;
|
|
238
|
-
}>;
|
|
231
|
+
receivingSynchronisation: ComputedRef<boolean>;
|
|
239
232
|
activeIndexFor: (entry: Entry) => ComputedRef<number | null>;
|
|
240
233
|
coordinateFor: (candidate: Target | undefined, fallback?: Coordinate) => Coordinate | undefined;
|
|
241
234
|
activate: (channel: Channel, input: TooltipTargetRequest) => void;
|
|
242
|
-
clear: (channel: Channel) => void;
|
|
235
|
+
clear: (channel: Channel, scope?: "item") => void;
|
|
243
236
|
};
|
|
244
237
|
export declare function useTooltipSource(): TooltipSource;
|
|
245
238
|
export declare function provideTooltipEntry(entry: Entry): void;
|
|
@@ -435,17 +428,10 @@ export declare function createTooltip(inputs: TooltipInputs): {
|
|
|
435
428
|
entries: import('./registry.js').Registry<TooltipPayloadConfiguration>;
|
|
436
429
|
announcement: import('vue').ShallowRef<string, string>;
|
|
437
430
|
keyboardInteraction: ComputedRef<TooltipInteraction>;
|
|
438
|
-
|
|
439
|
-
label: string | undefined;
|
|
440
|
-
configuration?: TooltipPayloadConfiguration;
|
|
441
|
-
active: boolean;
|
|
442
|
-
index: TooltipActiveIndex;
|
|
443
|
-
dataKey: import('../types/base.js').ChartDataKey | undefined;
|
|
444
|
-
coordinate: Coordinate | undefined;
|
|
445
|
-
}>;
|
|
431
|
+
receivingSynchronisation: ComputedRef<boolean>;
|
|
446
432
|
activeIndexFor: (entry: Entry) => ComputedRef<number | null>;
|
|
447
433
|
coordinateFor: (candidate: Target | undefined, fallback?: Coordinate) => Coordinate | undefined;
|
|
448
434
|
activate: (channel: Channel, input: TooltipTargetRequest) => void;
|
|
449
|
-
clear: (channel: Channel) => void;
|
|
435
|
+
clear: (channel: Channel, scope?: "item") => void;
|
|
450
436
|
};
|
|
451
437
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vccs",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"description": "Composable charting components for Vue 3 — an unofficial port of Recharts",
|
|
6
6
|
"author": "rick-hup",
|
|
7
7
|
"license": "MIT",
|
|
@@ -51,11 +51,15 @@
|
|
|
51
51
|
]
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
|
+
"bin": {
|
|
55
|
+
"vccs-usage": "./usage/vccs-usage.mjs"
|
|
56
|
+
},
|
|
54
57
|
"files": [
|
|
55
58
|
"./LICENSE",
|
|
56
59
|
"./README.md",
|
|
57
60
|
"./dist/**/*.d.ts",
|
|
58
|
-
"./dist/**/*.mjs"
|
|
61
|
+
"./dist/**/*.mjs",
|
|
62
|
+
"./usage"
|
|
59
63
|
],
|
|
60
64
|
"peerDependencies": {
|
|
61
65
|
"@nuxt/kit": "^4.0.0",
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"guides": [
|
|
4
|
+
{
|
|
5
|
+
"id": "installation",
|
|
6
|
+
"title": "Installation and registration",
|
|
7
|
+
"description": "Install vccs in Vite or Nuxt 4, use explicit imports, auto-imports, or the Nuxt module.",
|
|
8
|
+
"category": "core",
|
|
9
|
+
"path": "guides/core/installation.md",
|
|
10
|
+
"components": [],
|
|
11
|
+
"useCases": ["Set up a new Vue or Nuxt chart", "Configure VccsResolver or vccs/nuxt"],
|
|
12
|
+
"keywords": ["install", "setup", "vite", "nuxt", "resolver", "auto-import", "安装", "自动导入"]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "vue-api",
|
|
16
|
+
"title": "Vue API rules",
|
|
17
|
+
"description": "Use slots, events, Vue models, responsive sizing, data keys, and CSS theme variables correctly.",
|
|
18
|
+
"category": "core",
|
|
19
|
+
"path": "guides/core/vue-api.md",
|
|
20
|
+
"components": ["Tooltip", "Brush", "Legend"],
|
|
21
|
+
"useCases": ["Customize chart content", "Control active state", "Fix a Recharts-to-Vue API mismatch"],
|
|
22
|
+
"keywords": ["slots", "events", "v-model", "active-index", "brush", "tooltip", "responsive", "theme", "插槽", "事件", "主题"]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "typed-rows",
|
|
26
|
+
"title": "Typed chart rows",
|
|
27
|
+
"description": "Make data-key and tooltip payload types follow the application's row type.",
|
|
28
|
+
"category": "core",
|
|
29
|
+
"path": "guides/core/typed-rows.md",
|
|
30
|
+
"components": [],
|
|
31
|
+
"useCases": ["Reject wrong data keys at compile time", "Type tooltip payloads"],
|
|
32
|
+
"keywords": ["typescript", "types", "generic", "defineChartComponents", "row", "类型", "类型安全"]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "ssr-testing",
|
|
36
|
+
"title": "SSR and deterministic testing",
|
|
37
|
+
"description": "Render charts on the server and disable motion for stable SSR and geometry assertions.",
|
|
38
|
+
"category": "core",
|
|
39
|
+
"path": "guides/core/ssr-testing.md",
|
|
40
|
+
"components": [],
|
|
41
|
+
"useCases": ["Render charts in Nuxt SSR", "Write deterministic chart tests"],
|
|
42
|
+
"keywords": ["ssr", "server", "hydration", "test", "animation", "服务端渲染", "测试"]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "area-chart",
|
|
46
|
+
"title": "AreaChart",
|
|
47
|
+
"description": "Show a filled trend, accumulated magnitude, or stacked total over an ordered axis.",
|
|
48
|
+
"category": "chart",
|
|
49
|
+
"path": "guides/charts/area-chart.md",
|
|
50
|
+
"components": ["AreaChart", "Area"],
|
|
51
|
+
"useCases": ["Show a filled trend over time", "Show stacked totals over an ordered axis", "用面积展示趋势或堆积总量"],
|
|
52
|
+
"keywords": ["area", "filled line", "stacked area", "trend", "time series", "面积图", "趋势", "堆积"]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "bar-chart",
|
|
56
|
+
"title": "BarChart",
|
|
57
|
+
"description": "Compare categories with vertical or horizontal bars, including stacked and negative values.",
|
|
58
|
+
"category": "chart",
|
|
59
|
+
"path": "guides/charts/bar-chart.md",
|
|
60
|
+
"components": ["BarChart", "Bar"],
|
|
61
|
+
"useCases": ["Compare values across categories", "Rank categories or show a stacked composition", "用柱状图或条形图比较分类"],
|
|
62
|
+
"keywords": ["bar", "column", "comparison", "ranking", "stacked", "柱状图", "条形图", "对比", "排名"]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"id": "line-chart",
|
|
66
|
+
"title": "LineChart",
|
|
67
|
+
"description": "Show one or more trends over an ordered numeric or categorical axis.",
|
|
68
|
+
"category": "chart",
|
|
69
|
+
"path": "guides/charts/line-chart.md",
|
|
70
|
+
"components": ["LineChart", "Line"],
|
|
71
|
+
"useCases": ["Show a time series", "Compare trends across series", "用折线展示趋势"],
|
|
72
|
+
"keywords": ["line", "trend", "time series", "spark alternative", "折线图", "趋势", "时间序列"]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "scatter-chart",
|
|
76
|
+
"title": "ScatterChart",
|
|
77
|
+
"description": "Show relationships between numeric variables with points or bubbles.",
|
|
78
|
+
"category": "chart",
|
|
79
|
+
"path": "guides/charts/scatter-chart.md",
|
|
80
|
+
"components": ["ScatterChart", "Scatter", "ZAxis"],
|
|
81
|
+
"useCases": ["Show correlation or distribution", "Encode a third numeric value as bubble size", "用散点展示相关性或分布"],
|
|
82
|
+
"keywords": ["scatter", "correlation", "distribution", "bubble", "散点图", "气泡图", "相关性"]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "composed-chart",
|
|
86
|
+
"title": "ComposedChart",
|
|
87
|
+
"description": "Combine Bar, Line, Area, and Scatter series on shared Cartesian axes.",
|
|
88
|
+
"category": "chart",
|
|
89
|
+
"path": "guides/charts/composed-chart.md",
|
|
90
|
+
"components": ["ComposedChart", "Bar", "Line", "Area", "Scatter"],
|
|
91
|
+
"useCases": ["Compare actual bars with a target line", "Mix series types on one chart", "在同一坐标系混合柱状和折线"],
|
|
92
|
+
"keywords": ["composed", "mixed", "combo", "bar and line", "组合图", "混合图"]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"id": "funnel-chart",
|
|
96
|
+
"title": "FunnelChart",
|
|
97
|
+
"description": "Show values and drop-off across ordered conversion stages.",
|
|
98
|
+
"category": "chart",
|
|
99
|
+
"path": "guides/charts/funnel-chart.md",
|
|
100
|
+
"components": ["FunnelChart", "Funnel"],
|
|
101
|
+
"useCases": ["Show conversion across stages", "Expose drop-off in a process", "展示阶段转化和流失"],
|
|
102
|
+
"keywords": ["funnel", "conversion", "drop-off", "stages", "漏斗图", "转化率"]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "pie-chart",
|
|
106
|
+
"title": "PieChart",
|
|
107
|
+
"description": "Show a small number of part-to-whole proportions as a pie or donut.",
|
|
108
|
+
"category": "chart",
|
|
109
|
+
"path": "guides/charts/pie-chart.md",
|
|
110
|
+
"components": ["PieChart", "Pie", "Cell"],
|
|
111
|
+
"useCases": ["Show proportions of a total", "Build a donut chart", "展示少量分类的占比"],
|
|
112
|
+
"keywords": ["pie", "donut", "proportion", "part-to-whole", "饼图", "环形图", "占比"]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"id": "radar-chart",
|
|
116
|
+
"title": "RadarChart",
|
|
117
|
+
"description": "Compare multivariate profiles across a shared set of dimensions.",
|
|
118
|
+
"category": "chart",
|
|
119
|
+
"path": "guides/charts/radar-chart.md",
|
|
120
|
+
"components": ["RadarChart", "Radar", "PolarAngleAxis", "PolarGrid"],
|
|
121
|
+
"useCases": ["Compare scores across dimensions", "Show a multivariate profile", "比较多维评分"],
|
|
122
|
+
"keywords": ["radar", "spider", "multivariate", "profile", "雷达图", "多维"]
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "radial-bar-chart",
|
|
126
|
+
"title": "RadialBarChart",
|
|
127
|
+
"description": "Show progress or category values as concentric or stacked radial bars.",
|
|
128
|
+
"category": "chart",
|
|
129
|
+
"path": "guides/charts/radial-bar-chart.md",
|
|
130
|
+
"components": ["RadialBarChart", "RadialBar"],
|
|
131
|
+
"useCases": ["Show progress toward a goal", "Compare values on polar tracks", "展示环形进度或径向分类值"],
|
|
132
|
+
"keywords": ["radial bar", "progress", "gauge", "polar bar", "径向条形图", "进度", "仪表盘"]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "bar-list",
|
|
136
|
+
"title": "BarList",
|
|
137
|
+
"description": "Render a lightweight plain-HTML ranked list with inline value bars.",
|
|
138
|
+
"category": "chart",
|
|
139
|
+
"path": "guides/charts/bar-list.md",
|
|
140
|
+
"components": ["BarList"],
|
|
141
|
+
"useCases": ["Build a compact ranking list", "Show labeled values without SVG axes", "用 HTML 列表展示排行"],
|
|
142
|
+
"keywords": ["bar list", "ranking", "html", "leaderboard", "条形列表", "排行榜"]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"id": "sparkline",
|
|
146
|
+
"title": "Sparkline",
|
|
147
|
+
"description": "Place a tiny inline trend in a table, KPI tile, or dense dashboard row.",
|
|
148
|
+
"category": "chart",
|
|
149
|
+
"path": "guides/charts/sparkline.md",
|
|
150
|
+
"components": ["Sparkline"],
|
|
151
|
+
"useCases": ["Show a compact trend without axes", "Add a trend to a KPI or table row", "在指标卡或表格中展示迷你趋势"],
|
|
152
|
+
"keywords": ["sparkline", "mini line", "kpi", "inline trend", "火花线", "迷你趋势"]
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"id": "tracker",
|
|
156
|
+
"title": "Tracker",
|
|
157
|
+
"description": "Show a compact sequence of discrete activity or status cells.",
|
|
158
|
+
"category": "chart",
|
|
159
|
+
"path": "guides/charts/tracker.md",
|
|
160
|
+
"components": ["Tracker"],
|
|
161
|
+
"useCases": ["Show service or activity status over a sequence", "Render compact status cells", "展示一组状态或活动点"],
|
|
162
|
+
"keywords": ["tracker", "status", "activity", "cells", "状态", "活动点", "追踪"]
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "heatmap",
|
|
166
|
+
"title": "Heatmap",
|
|
167
|
+
"description": "Show magnitude or density across two categorical dimensions.",
|
|
168
|
+
"category": "chart",
|
|
169
|
+
"path": "guides/charts/heatmap.md",
|
|
170
|
+
"components": ["Heatmap"],
|
|
171
|
+
"useCases": ["Show a matrix of values", "Find concentration across two categories", "展示两个分类维度的密度或强度"],
|
|
172
|
+
"keywords": ["heatmap", "matrix", "density", "intensity", "热力图", "矩阵", "密度"]
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"id": "calendar-heatmap",
|
|
176
|
+
"title": "CalendarHeatmap",
|
|
177
|
+
"description": "Show daily activity or intensity on a calendar.",
|
|
178
|
+
"category": "chart",
|
|
179
|
+
"path": "guides/charts/calendar-heatmap.md",
|
|
180
|
+
"components": ["CalendarHeatmap"],
|
|
181
|
+
"useCases": ["Show daily activity over weeks or months", "Build a contribution calendar", "展示每日活动或贡献日历"],
|
|
182
|
+
"keywords": ["calendar heatmap", "daily", "contribution", "activity calendar", "日历热力图", "贡献图"]
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"id": "cohort-chart",
|
|
186
|
+
"title": "CohortChart",
|
|
187
|
+
"description": "Show retention or another metric by cohort and elapsed period.",
|
|
188
|
+
"category": "chart",
|
|
189
|
+
"path": "guides/charts/cohort-chart.md",
|
|
190
|
+
"components": ["CohortChart"],
|
|
191
|
+
"useCases": ["Analyze retention by signup cohort", "Compare behavior across elapsed periods", "分析分群留存"],
|
|
192
|
+
"keywords": ["cohort", "retention", "signup", "period", "队列图", "留存", "分群"]
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"id": "journey-sankey",
|
|
196
|
+
"title": "JourneySankey",
|
|
197
|
+
"description": "Show how entities move through ordered journey steps and where they drop off.",
|
|
198
|
+
"category": "chart",
|
|
199
|
+
"path": "guides/charts/journey-sankey.md",
|
|
200
|
+
"components": ["JourneySankey"],
|
|
201
|
+
"useCases": ["Visualize a user journey", "Compare paths through ordered steps", "展示用户旅程和路径流失"],
|
|
202
|
+
"keywords": ["journey", "path", "conversion", "sankey", "用户旅程", "路径", "桑基图"]
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"id": "sankey",
|
|
206
|
+
"title": "Sankey",
|
|
207
|
+
"description": "Show weighted flows between arbitrary source and target nodes.",
|
|
208
|
+
"category": "chart",
|
|
209
|
+
"path": "guides/charts/sankey.md",
|
|
210
|
+
"components": ["Sankey"],
|
|
211
|
+
"useCases": ["Show transfers or flows between nodes", "Visualize weighted relationships in a network", "展示节点之间的加权流动"],
|
|
212
|
+
"keywords": ["sankey", "flow", "nodes", "links", "桑基图", "流量", "流向"]
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"id": "treemap",
|
|
216
|
+
"title": "Treemap",
|
|
217
|
+
"description": "Show hierarchical part-to-whole values as nested rectangles.",
|
|
218
|
+
"category": "chart",
|
|
219
|
+
"path": "guides/charts/treemap.md",
|
|
220
|
+
"components": ["Treemap"],
|
|
221
|
+
"useCases": ["Show hierarchy and magnitude together", "Compare branches of a whole", "用嵌套矩形展示层级和占比"],
|
|
222
|
+
"keywords": ["treemap", "hierarchy", "nested rectangles", "矩形树图", "层级", "占比"]
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"id": "sunburst-chart",
|
|
226
|
+
"title": "SunburstChart",
|
|
227
|
+
"description": "Show hierarchical part-to-whole values as concentric radial rings.",
|
|
228
|
+
"category": "chart",
|
|
229
|
+
"path": "guides/charts/sunburst-chart.md",
|
|
230
|
+
"components": ["SunburstChart"],
|
|
231
|
+
"useCases": ["Show hierarchy as radial rings", "Explore nested proportions", "用同心环展示层级和占比"],
|
|
232
|
+
"keywords": ["sunburst", "hierarchy", "radial rings", "旭日图", "层级", "环形"]
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# AreaChart
|
|
2
|
+
|
|
3
|
+
Use `AreaChart` for a filled trend or a stacked total over an ordered axis. Use `LineChart` when the fill would overemphasize magnitude; use `BarChart` for discrete category comparisons.
|
|
4
|
+
|
|
5
|
+
## Data shape
|
|
6
|
+
|
|
7
|
+
- `data` is an array of flat rows on the chart root.
|
|
8
|
+
- `XAxis data-key` names the ordered category or time value.
|
|
9
|
+
- Each `Area data-key` selects one numeric series from the same row.
|
|
10
|
+
- Use one `Area` per series and set `name` when the legend or tooltip needs a different label.
|
|
11
|
+
|
|
12
|
+
## Minimal example
|
|
13
|
+
|
|
14
|
+
```vue
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import { Area, AreaChart, CartesianGrid, Tooltip, XAxis, YAxis } from 'vccs'
|
|
17
|
+
|
|
18
|
+
const data = [
|
|
19
|
+
{ month: 'Jan', visitors: 186 },
|
|
20
|
+
{ month: 'Feb', visitors: 305 },
|
|
21
|
+
{ month: 'Mar', visitors: 237 },
|
|
22
|
+
]
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<AreaChart
|
|
27
|
+
:data="data"
|
|
28
|
+
:height="300"
|
|
29
|
+
>
|
|
30
|
+
<CartesianGrid />
|
|
31
|
+
<XAxis data-key="month" />
|
|
32
|
+
<YAxis />
|
|
33
|
+
<Tooltip :cursor="false" />
|
|
34
|
+
<Area
|
|
35
|
+
type="monotone"
|
|
36
|
+
data-key="visitors"
|
|
37
|
+
stroke="#f97316"
|
|
38
|
+
fill="#f97316"
|
|
39
|
+
:fill-opacity="0.3"
|
|
40
|
+
/>
|
|
41
|
+
</AreaChart>
|
|
42
|
+
</template>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Animation is enabled by default; retrieve `ssr-testing` before taking screenshots or asserting exact geometry.
|
|
46
|
+
|
|
47
|
+
## Chart-specific rules
|
|
48
|
+
|
|
49
|
+
- Keep all series on the shared root `data` array; do not put a separate array on each `Area`.
|
|
50
|
+
- Give areas the same `stack-id` to stack them; omit it when the areas should remain independent.
|
|
51
|
+
- Use `connect-nulls` only when a gap should be bridged; otherwise missing values stay visible as gaps.
|
|
52
|
+
- Retrieve `composed-chart` when bars, lines, or scatter points must share the same axes.
|
|
53
|
+
|
|
54
|
+
## Related guides
|
|
55
|
+
|
|
56
|
+
`installation`, `vue-api`, `typed-rows`, `ssr-testing`, `line-chart`, `bar-chart`, `composed-chart`.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# BarChart
|
|
2
|
+
|
|
3
|
+
Use `BarChart` to compare or rank values across categories. Use `BarList` for a compact HTML ranking without axes; use `LineChart` when the main point is a continuous trend.
|
|
4
|
+
|
|
5
|
+
## Data shape
|
|
6
|
+
|
|
7
|
+
- `data` is an array of flat rows on the chart root.
|
|
8
|
+
- `XAxis data-key` names the category for vertical bars.
|
|
9
|
+
- Each `Bar data-key` selects one numeric series from the same row.
|
|
10
|
+
- Use one `Bar` per series and set `name` when the legend or tooltip needs a different label.
|
|
11
|
+
|
|
12
|
+
## Minimal example
|
|
13
|
+
|
|
14
|
+
```vue
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import { Bar, BarChart, CartesianGrid, Legend, Tooltip, XAxis, YAxis } from 'vccs'
|
|
17
|
+
|
|
18
|
+
const data = [
|
|
19
|
+
{ month: 'Jan', desktop: 186, mobile: 80 },
|
|
20
|
+
{ month: 'Feb', desktop: 305, mobile: 120 },
|
|
21
|
+
{ month: 'Mar', desktop: 237, mobile: 160 },
|
|
22
|
+
]
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<BarChart
|
|
27
|
+
:data="data"
|
|
28
|
+
:height="300"
|
|
29
|
+
>
|
|
30
|
+
<CartesianGrid />
|
|
31
|
+
<XAxis data-key="month" />
|
|
32
|
+
<YAxis />
|
|
33
|
+
<Tooltip :cursor="false" />
|
|
34
|
+
<Legend />
|
|
35
|
+
<Bar
|
|
36
|
+
data-key="desktop"
|
|
37
|
+
name="Desktop"
|
|
38
|
+
fill="#f97316"
|
|
39
|
+
/>
|
|
40
|
+
<Bar
|
|
41
|
+
data-key="mobile"
|
|
42
|
+
name="Mobile"
|
|
43
|
+
fill="#14b8a6"
|
|
44
|
+
/>
|
|
45
|
+
</BarChart>
|
|
46
|
+
</template>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Animation is enabled by default; retrieve `ssr-testing` before taking screenshots or asserting exact geometry.
|
|
50
|
+
|
|
51
|
+
## Chart-specific rules
|
|
52
|
+
|
|
53
|
+
- Keep grouped or stacked series on the shared root `data` array, with one `Bar` per numeric field.
|
|
54
|
+
- Give bars the same `stack-id` to stack them; for stacks containing negative values, set `stack-offset="sign"` on `BarChart`.
|
|
55
|
+
- Use `layout="vertical"` for horizontal bars, with a numeric `XAxis` and a categorical `YAxis` carrying the category `data-key`.
|
|
56
|
+
- Use `bar-size` for a fixed bar width or `max-bar-size` for an upper limit.
|
|
57
|
+
|
|
58
|
+
## Related guides
|
|
59
|
+
|
|
60
|
+
`installation`, `vue-api`, `typed-rows`, `ssr-testing`, `bar-list`, `line-chart`, `composed-chart`.
|