@katlux/block-charts 0.1.0-beta.0 → 0.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.d.mts +6 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +23 -0
- package/dist/runtime/components/KAreaChart/KAreaChart.d.vue.ts +53 -0
- package/dist/runtime/components/KAreaChart/KAreaChart.vue +382 -0
- package/dist/runtime/components/KAreaChart/KAreaChart.vue.d.ts +53 -0
- package/dist/runtime/components/KBarChart/KBarChart.d.vue.ts +55 -0
- package/dist/runtime/components/KBarChart/KBarChart.vue +398 -0
- package/dist/runtime/components/KBarChart/KBarChart.vue.d.ts +55 -0
- package/dist/runtime/components/KHeatMap/KHeatMap.d.vue.ts +36 -0
- package/dist/runtime/components/KHeatMap/KHeatMap.vue +263 -0
- package/dist/runtime/components/KHeatMap/KHeatMap.vue.d.ts +36 -0
- package/dist/runtime/components/KLineChart/KLineChart.d.vue.ts +51 -0
- package/dist/runtime/components/KLineChart/KLineChart.vue +407 -0
- package/dist/runtime/components/KLineChart/KLineChart.vue.d.ts +51 -0
- package/dist/runtime/components/KPieChart/KPieChart.d.vue.ts +32 -0
- package/dist/runtime/components/KPieChart/KPieChart.vue +273 -0
- package/dist/runtime/components/KPieChart/KPieChart.vue.d.ts +32 -0
- package/dist/runtime/components/KScatterChart/KScatterChart.d.vue.ts +55 -0
- package/dist/runtime/components/KScatterChart/KScatterChart.vue +356 -0
- package/dist/runtime/components/KScatterChart/KScatterChart.vue.d.ts +55 -0
- package/dist/runtime/composables/useChartAnimation.d.ts +9 -0
- package/dist/runtime/composables/useChartAnimation.js +32 -0
- package/dist/runtime/composables/useChartAxes.d.ts +40 -0
- package/dist/runtime/composables/useChartAxes.js +58 -0
- package/dist/runtime/composables/useChartCanvas.d.ts +11 -0
- package/dist/runtime/composables/useChartCanvas.js +47 -0
- package/dist/runtime/composables/useChartData.d.ts +14 -0
- package/dist/runtime/composables/useChartData.js +45 -0
- package/dist/runtime/composables/useChartExport.d.ts +5 -0
- package/dist/runtime/composables/useChartExport.js +32 -0
- package/dist/runtime/composables/useChartHitTest.d.ts +11 -0
- package/dist/runtime/composables/useChartHitTest.js +39 -0
- package/dist/runtime/composables/useChartSvg.d.ts +17 -0
- package/dist/runtime/composables/useChartSvg.js +22 -0
- package/dist/runtime/composables/useChartViewport.d.ts +25 -0
- package/dist/runtime/composables/useChartViewport.js +92 -0
- package/dist/types.d.mts +3 -0
- package/package.json +7 -3
- package/build.config.ts +0 -4
- package/src/module.ts +0 -25
- package/src/runtime/components/KAreaChart/KAreaChart.vue +0 -410
- package/src/runtime/components/KBarChart/KBarChart.vue +0 -427
- package/src/runtime/components/KHeatMap/KHeatMap.vue +0 -301
- package/src/runtime/components/KLineChart/KLineChart.vue +0 -493
- package/src/runtime/components/KPieChart/KPieChart.vue +0 -307
- package/src/runtime/components/KScatterChart/KScatterChart.vue +0 -375
- package/src/runtime/composables/useChartAnimation.ts +0 -45
- package/src/runtime/composables/useChartAxes.ts +0 -105
- package/src/runtime/composables/useChartCanvas.ts +0 -67
- package/src/runtime/composables/useChartData.ts +0 -79
- package/src/runtime/composables/useChartExport.ts +0 -40
- package/src/runtime/composables/useChartHitTest.ts +0 -71
- package/src/runtime/composables/useChartSvg.ts +0 -45
- package/src/runtime/composables/useChartViewport.ts +0 -140
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export function useChartExport() {
|
|
2
|
+
const download = (href, filename) => {
|
|
3
|
+
const a = document.createElement("a");
|
|
4
|
+
a.href = href;
|
|
5
|
+
a.download = filename;
|
|
6
|
+
a.style.display = "none";
|
|
7
|
+
document.body.appendChild(a);
|
|
8
|
+
a.click();
|
|
9
|
+
document.body.removeChild(a);
|
|
10
|
+
};
|
|
11
|
+
const exportPng = (canvas, filename = "chart.png") => {
|
|
12
|
+
try {
|
|
13
|
+
const dataUrl = canvas.toDataURL("image/png");
|
|
14
|
+
download(dataUrl, filename);
|
|
15
|
+
} catch (e) {
|
|
16
|
+
console.error("[KChart] PNG export failed:", e);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const exportSvg = (svgEl, filename = "chart.svg") => {
|
|
20
|
+
try {
|
|
21
|
+
const serializer = new XMLSerializer();
|
|
22
|
+
const svgStr = serializer.serializeToString(svgEl);
|
|
23
|
+
const blob = new Blob([svgStr], { type: "image/svg+xml;charset=utf-8" });
|
|
24
|
+
const url = URL.createObjectURL(blob);
|
|
25
|
+
download(url, filename);
|
|
26
|
+
URL.revokeObjectURL(url);
|
|
27
|
+
} catch (e) {
|
|
28
|
+
console.error("[KChart] SVG export failed:", e);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return { exportPng, exportSvg };
|
|
32
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type IChartAxesContext } from './useChartAxes.js';
|
|
2
|
+
export declare function useChartHitTest(): {
|
|
3
|
+
findNearestX: (items: any[], mouseX: number, xField: string, axes: IChartAxesContext) => {
|
|
4
|
+
item: any;
|
|
5
|
+
index: number;
|
|
6
|
+
} | null;
|
|
7
|
+
findNearestEuclidean: (items: any[], mouseX: number, mouseY: number, axes: IChartAxesContext, xField: string, yField: string, threshold?: number) => {
|
|
8
|
+
item: any;
|
|
9
|
+
index: number;
|
|
10
|
+
} | null;
|
|
11
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { parseValue } from "./useChartAxes.js";
|
|
2
|
+
export function useChartHitTest() {
|
|
3
|
+
const findNearestX = (items, mouseX, xField, axes) => {
|
|
4
|
+
if (!items.length) return null;
|
|
5
|
+
const dataX = axes.fromX(mouseX);
|
|
6
|
+
let nearestIdx = 0;
|
|
7
|
+
let minDiff = Math.abs(parseValue(items[0][xField]) - dataX);
|
|
8
|
+
for (let i = 1; i < items.length; i++) {
|
|
9
|
+
const val = parseValue(items[i][xField]);
|
|
10
|
+
const diff = Math.abs(val - dataX);
|
|
11
|
+
if (diff < minDiff) {
|
|
12
|
+
minDiff = diff;
|
|
13
|
+
nearestIdx = i;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return { item: items[nearestIdx], index: nearestIdx };
|
|
17
|
+
};
|
|
18
|
+
const findNearestEuclidean = (items, mouseX, mouseY, axes, xField, yField, threshold = 20) => {
|
|
19
|
+
if (!items.length) return null;
|
|
20
|
+
let nearestIdx = -1;
|
|
21
|
+
let minDistanceSq = threshold * threshold;
|
|
22
|
+
items.forEach((item, i) => {
|
|
23
|
+
const px = axes.toX(parseValue(item[xField]));
|
|
24
|
+
const py = axes.toY(parseValue(item[yField]));
|
|
25
|
+
const dx = mouseX - px;
|
|
26
|
+
const dy = mouseY - py;
|
|
27
|
+
const distSq = dx * dx + dy * dy;
|
|
28
|
+
if (distSq < minDistanceSq) {
|
|
29
|
+
minDistanceSq = distSq;
|
|
30
|
+
nearestIdx = i;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return nearestIdx !== -1 ? { item: items[nearestIdx], index: nearestIdx } : null;
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
findNearestX,
|
|
37
|
+
findNearestEuclidean
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Ref } from 'vue';
|
|
2
|
+
export interface ITooltipState {
|
|
3
|
+
visible: boolean;
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
content: string;
|
|
7
|
+
item: any;
|
|
8
|
+
index: number;
|
|
9
|
+
}
|
|
10
|
+
export interface IChartSvgContext {
|
|
11
|
+
hoveredIndex: Ref<number>;
|
|
12
|
+
tooltipState: Ref<ITooltipState>;
|
|
13
|
+
showTooltip: (x: number, y: number, content: string, item: any, index: number) => void;
|
|
14
|
+
hideTooltip: () => void;
|
|
15
|
+
setHovered: (index: number) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function useChartSvg(): IChartSvgContext;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
export function useChartSvg() {
|
|
3
|
+
const hoveredIndex = ref(-1);
|
|
4
|
+
const tooltipState = ref({
|
|
5
|
+
visible: false,
|
|
6
|
+
x: 0,
|
|
7
|
+
y: 0,
|
|
8
|
+
content: "",
|
|
9
|
+
item: null,
|
|
10
|
+
index: -1
|
|
11
|
+
});
|
|
12
|
+
const showTooltip = (x, y, content, item, index) => {
|
|
13
|
+
tooltipState.value = { visible: true, x, y, content, item, index };
|
|
14
|
+
};
|
|
15
|
+
const hideTooltip = () => {
|
|
16
|
+
tooltipState.value.visible = false;
|
|
17
|
+
};
|
|
18
|
+
const setHovered = (index) => {
|
|
19
|
+
hoveredIndex.value = index;
|
|
20
|
+
};
|
|
21
|
+
return { hoveredIndex, tooltipState, showTooltip, hideTooltip, setHovered };
|
|
22
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Ref } from 'vue';
|
|
2
|
+
export interface IViewportState {
|
|
3
|
+
scale: Ref<number>;
|
|
4
|
+
panOffset: Ref<{
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
}>;
|
|
8
|
+
isDragging: Ref<boolean>;
|
|
9
|
+
canPan: Ref<boolean>;
|
|
10
|
+
}
|
|
11
|
+
export interface IChartViewportContext extends IViewportState {
|
|
12
|
+
zoomIn: () => void;
|
|
13
|
+
zoomOut: () => void;
|
|
14
|
+
resetZoom: () => void;
|
|
15
|
+
onWheel: (e: WheelEvent) => void;
|
|
16
|
+
onMouseDown: (e: MouseEvent) => void;
|
|
17
|
+
onMouseMove: (e: MouseEvent) => void;
|
|
18
|
+
onMouseUp: (e: MouseEvent) => void;
|
|
19
|
+
onMouseLeave: (e: MouseEvent) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function useChartViewport(options: {
|
|
22
|
+
maxZoom?: Ref<number>;
|
|
23
|
+
plotWidth: Ref<number>;
|
|
24
|
+
plotLeft?: Ref<number>;
|
|
25
|
+
}): IChartViewportContext;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
const ZOOM_STEP = 0.25;
|
|
3
|
+
const MIN_SCALE = 1;
|
|
4
|
+
const PAN_CLAMP_THRESHOLD = 0.01;
|
|
5
|
+
export function useChartViewport(options) {
|
|
6
|
+
const maxZoom = options.maxZoom ?? ref(10);
|
|
7
|
+
const scale = ref(1);
|
|
8
|
+
const panOffset = ref({ x: 0, y: 0 });
|
|
9
|
+
const isDragging = ref(false);
|
|
10
|
+
const canPan = ref(false);
|
|
11
|
+
let dragStart = { x: 0, y: 0 };
|
|
12
|
+
let panStart = { x: 0, y: 0 };
|
|
13
|
+
const clampPan = () => {
|
|
14
|
+
const maxPanX = plotWidth() * (1 - 1 / scale.value);
|
|
15
|
+
panOffset.value.x = Math.max(0, Math.min(panOffset.value.x, maxPanX));
|
|
16
|
+
panOffset.value.y = 0;
|
|
17
|
+
};
|
|
18
|
+
const plotWidth = () => options.plotWidth.value;
|
|
19
|
+
const updateCanPan = () => {
|
|
20
|
+
canPan.value = scale.value > MIN_SCALE + PAN_CLAMP_THRESHOLD;
|
|
21
|
+
};
|
|
22
|
+
const resetPan = () => {
|
|
23
|
+
panOffset.value = { x: 0, y: 0 };
|
|
24
|
+
};
|
|
25
|
+
const zoomTo = (newScale, anchorX) => {
|
|
26
|
+
const prev = scale.value;
|
|
27
|
+
const clamped = Math.min(Math.max(newScale, MIN_SCALE), maxZoom.value);
|
|
28
|
+
if (anchorX !== void 0 && prev !== clamped) {
|
|
29
|
+
panOffset.value.x += anchorX * (1 / prev - 1 / clamped);
|
|
30
|
+
}
|
|
31
|
+
scale.value = clamped;
|
|
32
|
+
if (scale.value <= MIN_SCALE) resetPan();
|
|
33
|
+
else clampPan();
|
|
34
|
+
updateCanPan();
|
|
35
|
+
};
|
|
36
|
+
const zoomIn = () => zoomTo(scale.value + ZOOM_STEP);
|
|
37
|
+
const zoomOut = () => zoomTo(scale.value - ZOOM_STEP);
|
|
38
|
+
const resetZoom = () => {
|
|
39
|
+
scale.value = MIN_SCALE;
|
|
40
|
+
resetPan();
|
|
41
|
+
updateCanPan();
|
|
42
|
+
};
|
|
43
|
+
const onWheel = (e) => {
|
|
44
|
+
if (e.ctrlKey) {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
47
|
+
const plotLeft = options.plotLeft?.value ?? 0;
|
|
48
|
+
const anchorX = e.clientX - rect.left - plotLeft;
|
|
49
|
+
const delta = e.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP;
|
|
50
|
+
zoomTo(scale.value + delta, anchorX);
|
|
51
|
+
} else if (e.shiftKey) {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
if (!canPan.value) return;
|
|
54
|
+
const delta = e.deltaX !== 0 ? e.deltaX : e.deltaY;
|
|
55
|
+
const dx = delta / scale.value;
|
|
56
|
+
panOffset.value.x += dx;
|
|
57
|
+
clampPan();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const onMouseDown = (e) => {
|
|
61
|
+
if (e.button !== 0 || !canPan.value) return;
|
|
62
|
+
isDragging.value = true;
|
|
63
|
+
dragStart = { x: e.clientX, y: e.clientY };
|
|
64
|
+
panStart = { x: panOffset.value.x, y: panOffset.value.y };
|
|
65
|
+
};
|
|
66
|
+
const onMouseMove = (e) => {
|
|
67
|
+
if (!isDragging.value || !canPan.value) return;
|
|
68
|
+
const dx = -(e.clientX - dragStart.x) / scale.value;
|
|
69
|
+
panOffset.value.x = panStart.x + dx;
|
|
70
|
+
clampPan();
|
|
71
|
+
};
|
|
72
|
+
const onMouseUp = (_e) => {
|
|
73
|
+
isDragging.value = false;
|
|
74
|
+
};
|
|
75
|
+
const onMouseLeave = (_e) => {
|
|
76
|
+
isDragging.value = false;
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
scale,
|
|
80
|
+
panOffset,
|
|
81
|
+
isDragging,
|
|
82
|
+
canPan,
|
|
83
|
+
zoomIn,
|
|
84
|
+
zoomOut,
|
|
85
|
+
resetZoom,
|
|
86
|
+
onWheel,
|
|
87
|
+
onMouseDown,
|
|
88
|
+
onMouseMove,
|
|
89
|
+
onMouseUp,
|
|
90
|
+
onMouseLeave
|
|
91
|
+
};
|
|
92
|
+
}
|
package/dist/types.d.mts
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@katlux/block-charts",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.2",
|
|
4
4
|
"description": "Pre-built charting block components for Katlux toolkit",
|
|
5
5
|
"author": "Katlux",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"main": "./dist/module.mjs",
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "nuxt-module-build build",
|
|
13
|
-
"dev": "nuxt-module-build build --stub"
|
|
13
|
+
"dev": "nuxt-module-build build --stub",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
14
15
|
},
|
|
15
16
|
"exports": {
|
|
16
17
|
".": {
|
|
@@ -27,5 +28,8 @@
|
|
|
27
28
|
"@nuxt/kit": "^3.20.1",
|
|
28
29
|
"pug": "^3.0.0",
|
|
29
30
|
"sass": "^1.80.0"
|
|
30
|
-
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
]
|
|
31
35
|
}
|
package/build.config.ts
DELETED
package/src/module.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addComponentsDir } from '@nuxt/kit'
|
|
2
|
-
|
|
3
|
-
export interface ModuleOptions { }
|
|
4
|
-
|
|
5
|
-
export default defineNuxtModule<ModuleOptions>({
|
|
6
|
-
meta: {
|
|
7
|
-
name: '@katlux/block-charts',
|
|
8
|
-
configKey: 'katluxCharts',
|
|
9
|
-
compatibility: {
|
|
10
|
-
nuxt: '^3.0.0'
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
defaults: {},
|
|
14
|
-
async setup(options, nuxt) {
|
|
15
|
-
const resolver = createResolver(import.meta.url)
|
|
16
|
-
|
|
17
|
-
// Add components directory
|
|
18
|
-
addComponentsDir({
|
|
19
|
-
path: resolver.resolve('./runtime/components'),
|
|
20
|
-
pathPrefix: false,
|
|
21
|
-
prefix: '',
|
|
22
|
-
global: true
|
|
23
|
-
})
|
|
24
|
-
}
|
|
25
|
-
})
|