@dschz/solid-uplot 0.1.7 → 0.3.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 +23 -14
- package/dist/chunk/IV6D7K4M.js +24 -0
- package/dist/chunk/{A3AZKFSW.jsx → QELYARMN.js} +16 -4
- package/dist/{getSeriesData-D1zBqQ9Y.d.ts → getSeriesData-04wGQord.d.ts} +44 -1
- package/dist/index/index.d.ts +40 -19
- package/dist/index/index.js +47 -22
- package/dist/plugins/index.d.ts +30 -7
- package/dist/plugins/index.js +19 -15
- package/dist/utils/index.d.ts +1 -2
- package/dist/utils/index.js +2 -26
- package/package.json +31 -31
- package/dist/chunk/3TJS44N7.js +0 -15
- package/dist/chunk/ZISGD6FJ.js +0 -25
- package/dist/getCursorData-2qxURGuZ.d.ts +0 -44
- package/dist/index/index.jsx +0 -135
- package/dist/plugins/index.jsx +0 -347
package/README.md
CHANGED
|
@@ -462,26 +462,35 @@ const MyDashboard = () => {
|
|
|
462
462
|
### SolidUplot Component
|
|
463
463
|
|
|
464
464
|
```tsx
|
|
465
|
+
type SolidUplotEvents = {
|
|
466
|
+
/** Callback fired when the uPlot instance is created */
|
|
467
|
+
readonly onCreate?: (u: uPlot, meta: OnCreateMeta) => void;
|
|
468
|
+
/** Callback fired when the cursor moves */
|
|
469
|
+
readonly onCursorMove?: (params: OnCursorMoveParams) => void;
|
|
470
|
+
};
|
|
471
|
+
|
|
465
472
|
// Main component props (extends all uPlot.Options except plugins, width, height)
|
|
466
|
-
type SolidUplotProps<T extends VoidStruct = VoidStruct> = SolidUplotOptions<T> &
|
|
467
|
-
|
|
468
|
-
|
|
473
|
+
type SolidUplotProps<T extends VoidStruct = VoidStruct> = SolidUplotOptions<T> &
|
|
474
|
+
SolidUplotEvents & {
|
|
475
|
+
// Ref callback to access the chart container element
|
|
476
|
+
ref?: Ref<HTMLDivElement>;
|
|
469
477
|
|
|
470
|
-
|
|
471
|
-
|
|
478
|
+
// CSS class name for the chart container (default: "solid-uplot")
|
|
479
|
+
// Additional classes will be appended to the default class
|
|
480
|
+
class?: string;
|
|
472
481
|
|
|
473
|
-
|
|
474
|
-
|
|
482
|
+
// CSS styles for the chart container (position is managed internally)
|
|
483
|
+
style?: Omit<JSX.CSSProperties, "position">;
|
|
475
484
|
|
|
476
|
-
|
|
477
|
-
|
|
485
|
+
// Enable automatic resizing to fit container (default: false)
|
|
486
|
+
autoResize?: boolean;
|
|
478
487
|
|
|
479
|
-
|
|
480
|
-
|
|
488
|
+
// Whether to reset scales when chart data is updated (default: true)
|
|
489
|
+
resetScales?: boolean;
|
|
481
490
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
};
|
|
491
|
+
// Where to place children components relative to the chart (default: "top")
|
|
492
|
+
childrenPlacement?: "top" | "bottom";
|
|
493
|
+
};
|
|
485
494
|
|
|
486
495
|
// Configuration options extending uPlot.Options with SolidJS enhancements
|
|
487
496
|
type SolidUplotOptions<T extends VoidStruct = VoidStruct> = Omit<
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import 'uplot';
|
|
2
|
+
|
|
3
|
+
// src/utils/getColorString.ts
|
|
4
|
+
var getColorString = (fillOrStroke, fallback = "#888") => {
|
|
5
|
+
return typeof fillOrStroke === "string" ? fillOrStroke : fallback;
|
|
6
|
+
};
|
|
7
|
+
function getNewCalendarDayIndices(u) {
|
|
8
|
+
const xValues = u.data[0];
|
|
9
|
+
if (!xValues || !xValues.length) return [];
|
|
10
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11
|
+
const indices = [];
|
|
12
|
+
for (let i = 0; i < xValues.length; i++) {
|
|
13
|
+
const ts = xValues[i];
|
|
14
|
+
const date = new Date(ts);
|
|
15
|
+
const dayString = date.toISOString().split("T")[0];
|
|
16
|
+
if (!seen.has(dayString)) {
|
|
17
|
+
seen.add(dayString);
|
|
18
|
+
indices.push(i);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return indices;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { getColorString, getNewCalendarDayIndices };
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
// src/utils/getCursorData.ts
|
|
2
|
+
var getCursorData = (u) => {
|
|
3
|
+
const idx = u.cursor.idx;
|
|
4
|
+
const xValues = u.data[0];
|
|
5
|
+
const isValid = idx != null && xValues && idx < xValues.length;
|
|
6
|
+
return !isValid ? void 0 : {
|
|
7
|
+
plotId: u.root.id,
|
|
8
|
+
idx,
|
|
9
|
+
xValue: xValues[idx],
|
|
10
|
+
visible: Boolean(u.cursor.show),
|
|
11
|
+
position: { left: u.cursor.left || 0, top: u.cursor.top || 0 }
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
|
|
1
15
|
// src/utils/getSeriesData.ts
|
|
2
16
|
var getSeriesData = (u, options = {}) => {
|
|
3
17
|
const series = [];
|
|
@@ -20,8 +34,6 @@ var getSeriesData = (u, options = {}) => {
|
|
|
20
34
|
}
|
|
21
35
|
return series;
|
|
22
36
|
};
|
|
23
|
-
|
|
24
|
-
export {
|
|
25
|
-
getSeriesData
|
|
26
|
-
};
|
|
27
37
|
// istanbul ignore next -- @preserve
|
|
38
|
+
|
|
39
|
+
export { getCursorData, getSeriesData };
|
|
@@ -1,3 +1,46 @@
|
|
|
1
|
+
type CursorPosition = {
|
|
2
|
+
/**
|
|
3
|
+
* The cursor position left offset in CSS pixels (relative to plotting area)
|
|
4
|
+
*/
|
|
5
|
+
readonly left: number;
|
|
6
|
+
/**
|
|
7
|
+
* The cursor position top offset in CSS pixels (relative to plotting area)
|
|
8
|
+
*/
|
|
9
|
+
readonly top: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The cursor index data for a given uPlot instance.
|
|
13
|
+
*/
|
|
14
|
+
type CursorData = {
|
|
15
|
+
/**
|
|
16
|
+
* The id of the plot instance that the cursor message originates from.
|
|
17
|
+
*/
|
|
18
|
+
readonly plotId: string;
|
|
19
|
+
/**
|
|
20
|
+
* The closest x-axis data index to cursor (closestIdx)
|
|
21
|
+
*/
|
|
22
|
+
readonly idx: number;
|
|
23
|
+
/**
|
|
24
|
+
* The x-axis value of the cursor idx.
|
|
25
|
+
*/
|
|
26
|
+
readonly xValue: number;
|
|
27
|
+
/**
|
|
28
|
+
* The position of the cursor.
|
|
29
|
+
*/
|
|
30
|
+
readonly position: CursorPosition;
|
|
31
|
+
/**
|
|
32
|
+
* The visibility of the cursor.
|
|
33
|
+
*/
|
|
34
|
+
readonly visible: boolean;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Get the cursor index data for a given uPlot instance.
|
|
38
|
+
*
|
|
39
|
+
* @param u - The uPlot instance.
|
|
40
|
+
* @returns The cursor data.
|
|
41
|
+
*/
|
|
42
|
+
declare const getCursorData: (u: uPlot) => CursorData | undefined;
|
|
43
|
+
|
|
1
44
|
/**
|
|
2
45
|
* Summary data for a given series.
|
|
3
46
|
*/
|
|
@@ -34,4 +77,4 @@ type GetSeriesDataOptions = {
|
|
|
34
77
|
*/
|
|
35
78
|
declare const getSeriesData: (u: uPlot, options?: GetSeriesDataOptions) => SeriesDatum[];
|
|
36
79
|
|
|
37
|
-
export { type SeriesDatum as S, getSeriesData as g };
|
|
80
|
+
export { type CursorData as C, type SeriesDatum as S, getSeriesData as a, getCursorData as g };
|
package/dist/index/index.d.ts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { V as VoidStruct, S as SolidUplotPluginBus, U as UplotPluginFactory } from '../createPluginBus-DdrjQANs.js';
|
|
2
2
|
export { a as UplotPluginFactoryContext, c as createPluginBus } from '../createPluginBus-DdrjQANs.js';
|
|
3
|
+
import { Ref } from '@solid-primitives/refs';
|
|
3
4
|
import { ParentProps, JSX } from 'solid-js';
|
|
4
|
-
import uPlot from 'uplot';
|
|
5
|
-
import { S as SeriesDatum } from '../getSeriesData-
|
|
5
|
+
import uPlot$1 from 'uplot';
|
|
6
|
+
import { C as CursorData, S as SeriesDatum } from '../getSeriesData-04wGQord.js';
|
|
6
7
|
import 'solid-js/store';
|
|
7
8
|
|
|
9
|
+
type OnCursorMoveParams = {
|
|
10
|
+
/** The uPlot instance */
|
|
11
|
+
readonly u: uPlot;
|
|
12
|
+
/** The cursor data */
|
|
13
|
+
readonly cursor: CursorData;
|
|
14
|
+
/** Array of series data extracted from the chart configuration */
|
|
15
|
+
readonly seriesData: SeriesDatum[];
|
|
16
|
+
};
|
|
17
|
+
|
|
8
18
|
/** Placement options for children components relative to the chart */
|
|
9
19
|
type ChildrenPlacement = "top" | "bottom";
|
|
10
20
|
/**
|
|
@@ -13,18 +23,20 @@ type ChildrenPlacement = "top" | "bottom";
|
|
|
13
23
|
*
|
|
14
24
|
* @template T - The type of the plugin bus data structure
|
|
15
25
|
*/
|
|
16
|
-
type SolidUplotPlugin<T extends VoidStruct = VoidStruct> = uPlot.Plugin | UplotPluginFactory<T>;
|
|
26
|
+
type SolidUplotPlugin<T extends VoidStruct = VoidStruct> = uPlot$1.Plugin | UplotPluginFactory<T>;
|
|
17
27
|
/**
|
|
18
28
|
* Configuration options for the SolidUplot component, extending uPlot.Options
|
|
19
29
|
* with SolidJS-specific enhancements
|
|
20
30
|
*
|
|
21
31
|
* @template T - The type of the plugin bus data structure
|
|
22
32
|
*/
|
|
23
|
-
type SolidUplotOptions<T extends VoidStruct = VoidStruct> = Omit<uPlot.Options, "plugins" | "width" | "height"> & {
|
|
33
|
+
type SolidUplotOptions<T extends VoidStruct = VoidStruct> = Omit<uPlot$1.Options, "plugins" | "width" | "height" | "data"> & {
|
|
24
34
|
/** Chart width in pixels */
|
|
25
35
|
readonly width?: number;
|
|
26
36
|
/** Chart height in pixels */
|
|
27
37
|
readonly height?: number;
|
|
38
|
+
/** Chart data - accepts AlignedData or number[][] */
|
|
39
|
+
readonly data?: uPlot$1.AlignedData | number[][];
|
|
28
40
|
/** Plugin communication bus for coordinating between plugins */
|
|
29
41
|
readonly pluginBus?: SolidUplotPluginBus<T>;
|
|
30
42
|
/** Array of plugins to apply to the chart */
|
|
@@ -37,28 +49,27 @@ type OnCreateMeta = {
|
|
|
37
49
|
/** Array of series data extracted from the chart configuration */
|
|
38
50
|
readonly seriesData: SeriesDatum[];
|
|
39
51
|
};
|
|
52
|
+
/**
|
|
53
|
+
* Events that can be passed to the SolidUplot component
|
|
54
|
+
*/
|
|
55
|
+
type SolidUplotEvents = {
|
|
56
|
+
/** Callback fired when the uPlot instance is created */
|
|
57
|
+
readonly onCreate?: (u: uPlot$1, meta: OnCreateMeta) => void;
|
|
58
|
+
/** Callback fired when the cursor moves */
|
|
59
|
+
readonly onCursorMove?: (params: OnCursorMoveParams) => void;
|
|
60
|
+
};
|
|
40
61
|
/**
|
|
41
62
|
* Props for the SolidUplot component
|
|
42
63
|
*
|
|
43
64
|
* @template T - The type of the plugin bus data structure
|
|
44
65
|
*/
|
|
45
|
-
type SolidUplotProps<T extends VoidStruct = VoidStruct> = SolidUplotOptions<T> & {
|
|
46
|
-
/**
|
|
47
|
-
readonly
|
|
48
|
-
/** Callback fired when the uPlot instance is created */
|
|
49
|
-
readonly onCreate?: (u: uPlot, meta: OnCreateMeta) => void;
|
|
50
|
-
/**
|
|
51
|
-
* Whether to reset scales when chart data is updated
|
|
52
|
-
* @default true
|
|
53
|
-
*/
|
|
54
|
-
readonly resetScales?: boolean;
|
|
66
|
+
type SolidUplotProps<T extends VoidStruct = VoidStruct> = SolidUplotOptions<T> & SolidUplotEvents & {
|
|
67
|
+
/** Class name for the chart container */
|
|
68
|
+
readonly class?: string;
|
|
55
69
|
/** CSS styles for the chart container (position is managed internally) */
|
|
56
70
|
readonly style?: Omit<JSX.CSSProperties, "position">;
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
* @default "top"
|
|
60
|
-
*/
|
|
61
|
-
readonly childrenPlacement?: ChildrenPlacement;
|
|
71
|
+
/** Ref callback to access the chart container element */
|
|
72
|
+
readonly ref?: Ref<HTMLDivElement>;
|
|
62
73
|
/**
|
|
63
74
|
* Enable automatic resizing to fit container.
|
|
64
75
|
*
|
|
@@ -70,6 +81,16 @@ type SolidUplotProps<T extends VoidStruct = VoidStruct> = SolidUplotOptions<T> &
|
|
|
70
81
|
* @default false
|
|
71
82
|
*/
|
|
72
83
|
readonly autoResize?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Whether to reset scales when chart data is updated
|
|
86
|
+
* @default true
|
|
87
|
+
*/
|
|
88
|
+
readonly resetScales?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Where to place children components relative to the chart
|
|
91
|
+
* @default "top"
|
|
92
|
+
*/
|
|
93
|
+
readonly childrenPlacement?: ChildrenPlacement;
|
|
73
94
|
};
|
|
74
95
|
/**
|
|
75
96
|
* A SolidJS wrapper component for uPlot charts with enhanced features
|
package/dist/index/index.js
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
|
-
import
|
|
1
|
+
import '../chunk/IV6D7K4M.js';
|
|
2
|
+
import { getSeriesData, getCursorData } from '../chunk/QELYARMN.js';
|
|
2
3
|
import { createStore } from 'solid-js/store';
|
|
3
|
-
import { template, use, insert, effect, style } from 'solid-js/web';
|
|
4
|
+
import { template, use, insert, effect, className, style } from 'solid-js/web';
|
|
4
5
|
import 'uplot/dist/uPlot.min.css';
|
|
6
|
+
import { mergeRefs } from '@solid-primitives/refs';
|
|
5
7
|
import { mergeProps, createUniqueId, splitProps, createMemo, createEffect, untrack, onCleanup } from 'solid-js';
|
|
6
8
|
import uPlot from 'uplot';
|
|
7
9
|
|
|
8
10
|
var createPluginBus = (initialData = {}) => {
|
|
9
11
|
const [data, setData] = createStore(initialData);
|
|
12
|
+
return { data, setData };
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// src/eventPlugins.ts
|
|
16
|
+
var createCursorMovePlugin = (onCursorMove) => {
|
|
10
17
|
return {
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
hooks: {
|
|
19
|
+
setCursor: (u) => {
|
|
20
|
+
const cursor = getCursorData(u);
|
|
21
|
+
if (!cursor) return;
|
|
22
|
+
onCursorMove?.({ u, cursor, seriesData: getSeriesData(u) });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
13
25
|
};
|
|
14
26
|
};
|
|
27
|
+
|
|
28
|
+
// src/SolidUplot.tsx
|
|
15
29
|
var _tmpl$ = /* @__PURE__ */ template(`<div id=solid-uplot-root>`);
|
|
16
30
|
var SolidUplot = (props) => {
|
|
17
31
|
let container;
|
|
@@ -28,7 +42,7 @@ var SolidUplot = (props) => {
|
|
|
28
42
|
show: false
|
|
29
43
|
}
|
|
30
44
|
}, props);
|
|
31
|
-
const [local, options] = splitProps(_props, ["children", "childrenPlacement", "autoResize", "onCreate", "style", "ref"]);
|
|
45
|
+
const [local, options] = splitProps(_props, ["children", "childrenPlacement", "class", "autoResize", "onCreate", "onCursorMove", "style", "ref"]);
|
|
32
46
|
const [updateableOptions, newChartOptions] = splitProps(options, ["data", "width", "height", "resetScales"]);
|
|
33
47
|
const [system, chartOptions] = splitProps(newChartOptions, ["pluginBus", "plugins"]);
|
|
34
48
|
const size = () => ({
|
|
@@ -36,9 +50,13 @@ var SolidUplot = (props) => {
|
|
|
36
50
|
height: updateableOptions.height
|
|
37
51
|
});
|
|
38
52
|
const chartPlugins = createMemo(() => {
|
|
39
|
-
|
|
53
|
+
const plugins = system.plugins.map((plugin) => typeof plugin === "function" ? plugin({
|
|
40
54
|
bus: system.pluginBus
|
|
41
55
|
}) : plugin);
|
|
56
|
+
if (local.onCursorMove) {
|
|
57
|
+
plugins.push(createCursorMovePlugin(local.onCursorMove));
|
|
58
|
+
}
|
|
59
|
+
return plugins;
|
|
42
60
|
});
|
|
43
61
|
createEffect(() => {
|
|
44
62
|
const getInitialSize = () => {
|
|
@@ -91,25 +109,32 @@ var SolidUplot = (props) => {
|
|
|
91
109
|
chart.destroy();
|
|
92
110
|
});
|
|
93
111
|
});
|
|
112
|
+
const classes = () => local.class ? `solid-uplot ${local.class}` : "solid-uplot";
|
|
94
113
|
return (() => {
|
|
95
114
|
var _el$ = _tmpl$();
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
local.ref?.(el);
|
|
99
|
-
}, _el$);
|
|
115
|
+
var _ref$ = mergeRefs(local.ref, (el) => container = el);
|
|
116
|
+
typeof _ref$ === "function" && use(_ref$, _el$);
|
|
100
117
|
insert(_el$, () => local.children);
|
|
101
|
-
effect((
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
effect((_p$) => {
|
|
119
|
+
var _v$ = classes(), _v$2 = {
|
|
120
|
+
display: "flex",
|
|
121
|
+
"flex-direction": local.childrenPlacement === "top" ? "column" : "column-reverse",
|
|
122
|
+
// When autoResize is enabled, fill the parent container
|
|
123
|
+
...local.autoResize && {
|
|
124
|
+
width: "100%",
|
|
125
|
+
height: "100%",
|
|
126
|
+
"min-width": "0",
|
|
127
|
+
"min-height": "0"
|
|
128
|
+
},
|
|
129
|
+
...local.style
|
|
130
|
+
};
|
|
131
|
+
_v$ !== _p$.e && className(_el$, _p$.e = _v$);
|
|
132
|
+
_p$.t = style(_el$, _v$2, _p$.t);
|
|
133
|
+
return _p$;
|
|
134
|
+
}, {
|
|
135
|
+
e: void 0,
|
|
136
|
+
t: void 0
|
|
137
|
+
});
|
|
113
138
|
return _el$;
|
|
114
139
|
})();
|
|
115
140
|
};
|
package/dist/plugins/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { U as UplotPluginFactory, S as SolidUplotPluginBus } from '../createPluginBus-DdrjQANs.js';
|
|
2
|
-
import { C as CursorData } from '../
|
|
2
|
+
import { C as CursorData, S as SeriesDatum } from '../getSeriesData-04wGQord.js';
|
|
3
3
|
import { Component, JSX } from 'solid-js';
|
|
4
|
-
import uPlot from 'uplot';
|
|
5
|
-
import { S as SeriesDatum } from '../getSeriesData-D1zBqQ9Y.js';
|
|
4
|
+
import uPlot$1 from 'uplot';
|
|
6
5
|
import 'solid-js/store';
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -157,7 +156,7 @@ type FocusSeriesPluginMessageBus = {
|
|
|
157
156
|
/**
|
|
158
157
|
* Configuration options for the focus series plugin.
|
|
159
158
|
*/
|
|
160
|
-
type FocusSeriesPluginOptions = {
|
|
159
|
+
type FocusSeriesPluginOptions<T extends CursorPluginMessageBus & FocusSeriesPluginMessageBus> = {
|
|
161
160
|
/**
|
|
162
161
|
* The vertical distance in pixels required to focus a series.
|
|
163
162
|
* If the cursor's Y position is within this threshold of a Y value, that series is considered focused.
|
|
@@ -184,6 +183,24 @@ type FocusSeriesPluginOptions = {
|
|
|
184
183
|
* @default false
|
|
185
184
|
*/
|
|
186
185
|
readonly rebuildPaths?: boolean;
|
|
186
|
+
/**
|
|
187
|
+
*
|
|
188
|
+
* For charts that are configured with this plugin, this callback is used to determine if the chart
|
|
189
|
+
* should redraw when the plugin bus updates. It is an additional condition to the base condition `cursor?.sourceId !== u.root.id`
|
|
190
|
+
* which is always applied first to prevent the source chart from redrawing twice.
|
|
191
|
+
*
|
|
192
|
+
* This can be used to add filtering logic, such as only reacting to specific source charts.
|
|
193
|
+
*
|
|
194
|
+
* @default undefined (always redraw for non-source charts)
|
|
195
|
+
*/
|
|
196
|
+
readonly shouldRedrawOnBusUpdate?: (params: {
|
|
197
|
+
/** The current chart instance (the one evaluating whether to redraw) */
|
|
198
|
+
readonly u: uPlot;
|
|
199
|
+
/** Current cursor state from the bus (may be from another chart) */
|
|
200
|
+
readonly cursor: T["cursor"];
|
|
201
|
+
/** Current focus series state from the bus */
|
|
202
|
+
readonly focusSeries: T["focusSeries"];
|
|
203
|
+
}) => boolean;
|
|
187
204
|
};
|
|
188
205
|
/**
|
|
189
206
|
* Creates a focus series plugin that visually highlights series based on cursor proximity.
|
|
@@ -220,7 +237,7 @@ type FocusSeriesPluginOptions = {
|
|
|
220
237
|
* @param options - Configuration options for focus behavior
|
|
221
238
|
* @returns A plugin factory function that creates the focus series plugin instance
|
|
222
239
|
*/
|
|
223
|
-
declare const focusSeries: (options?: FocusSeriesPluginOptions) => UplotPluginFactory<CursorPluginMessageBus & FocusSeriesPluginMessageBus>;
|
|
240
|
+
declare const focusSeries: (options?: FocusSeriesPluginOptions<CursorPluginMessageBus & FocusSeriesPluginMessageBus>) => UplotPluginFactory<CursorPluginMessageBus & FocusSeriesPluginMessageBus>;
|
|
224
241
|
|
|
225
242
|
/**
|
|
226
243
|
* Simple legend placement options - only top corners to avoid axis conflicts
|
|
@@ -234,7 +251,7 @@ type LegendPlacement = "top-left" | "top-right";
|
|
|
234
251
|
* data flow where series data changes immediately trigger legend updates with fresh data information.
|
|
235
252
|
*/
|
|
236
253
|
type LegendProps = {
|
|
237
|
-
readonly u: uPlot;
|
|
254
|
+
readonly u: uPlot$1;
|
|
238
255
|
readonly seriesData: SeriesDatum[];
|
|
239
256
|
readonly bus: SolidUplotPluginBus<CursorPluginMessageBus & FocusSeriesPluginMessageBus>;
|
|
240
257
|
};
|
|
@@ -307,7 +324,7 @@ type TooltipCursorPlacement = "top-left" | "top-right" | "bottom-left" | "bottom
|
|
|
307
324
|
*/
|
|
308
325
|
type TooltipProps = {
|
|
309
326
|
/** The uPlot instance for accessing chart configuration and data */
|
|
310
|
-
readonly u: uPlot;
|
|
327
|
+
readonly u: uPlot$1;
|
|
311
328
|
/**
|
|
312
329
|
* Current cursor data including position and data index, automatically updated
|
|
313
330
|
* by the cursor plugin and passed via the plugin bus system
|
|
@@ -361,6 +378,12 @@ type TooltipConfigOptions = {
|
|
|
361
378
|
* @default "top-left"
|
|
362
379
|
*/
|
|
363
380
|
readonly placement?: TooltipCursorPlacement;
|
|
381
|
+
/**
|
|
382
|
+
* Use fixed positioning for the tooltip. Set to true when the chart is in a
|
|
383
|
+
* fixed positioning context (like a dialog or modal) to prevent tooltip clipping.
|
|
384
|
+
* @default false
|
|
385
|
+
*/
|
|
386
|
+
readonly fixed?: boolean;
|
|
364
387
|
};
|
|
365
388
|
/**
|
|
366
389
|
* Combined options for the tooltip plugin including container props and behavior config.
|
package/dist/plugins/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { getCursorData } from '../chunk/
|
|
2
|
-
import { getSeriesData } from '../chunk/ZISGD6FJ.js';
|
|
1
|
+
import { getCursorData, getSeriesData } from '../chunk/QELYARMN.js';
|
|
3
2
|
import { createRoot, createEffect, mergeProps, splitProps, Show } from 'solid-js';
|
|
4
3
|
import { render, createComponent, template, use, insert, effect, setAttribute, className, style } from 'solid-js/web';
|
|
5
4
|
|
|
@@ -59,7 +58,7 @@ var seriesFocusRedraw = (u, options = {}) => {
|
|
|
59
58
|
} = options;
|
|
60
59
|
for (let i = 1; i < u.series.length; i++) {
|
|
61
60
|
const s = u.series[i];
|
|
62
|
-
if (!focusTargets
|
|
61
|
+
if (!focusTargets?.length) {
|
|
63
62
|
s.alpha = 1;
|
|
64
63
|
continue;
|
|
65
64
|
}
|
|
@@ -105,13 +104,15 @@ var focusSeries = (options = {}) => {
|
|
|
105
104
|
dispose = createRoot((dispose2) => {
|
|
106
105
|
createEffect(() => {
|
|
107
106
|
const cursor2 = bus.data.cursor;
|
|
108
|
-
const
|
|
109
|
-
|
|
107
|
+
const focusSeries2 = bus.data.focusSeries;
|
|
108
|
+
const isNotSourceChart = cursor2?.sourceId !== u.root.id;
|
|
109
|
+
const userRedrawCondition = options.shouldRedrawOnBusUpdate?.({ u, cursor: cursor2, focusSeries: focusSeries2 }) ?? true;
|
|
110
|
+
if (isNotSourceChart && userRedrawCondition) {
|
|
110
111
|
seriesFocusRedraw(u, {
|
|
111
112
|
unfocusedAlpha,
|
|
112
113
|
focusedAlpha,
|
|
113
114
|
rebuildPaths,
|
|
114
|
-
focusTargets:
|
|
115
|
+
focusTargets: focusSeries2?.targets
|
|
115
116
|
});
|
|
116
117
|
}
|
|
117
118
|
});
|
|
@@ -232,11 +233,11 @@ var legend = (Component, options = {}) => {
|
|
|
232
233
|
var _tmpl$2 = /* @__PURE__ */ template(`<div role=tooltip aria-label="Chart tooltip">`);
|
|
233
234
|
var TOOLTIP_OFFSET_X = 8;
|
|
234
235
|
var TOOLTIP_OFFSET_Y = 8;
|
|
235
|
-
var getTooltipPosition = (placement, left, top, tooltipWidth, tooltipHeight) => {
|
|
236
|
+
var getTooltipPosition = (placement, left, top, tooltipWidth, tooltipHeight, isFixed = false) => {
|
|
236
237
|
const baseX = placement.includes("left") ? left - tooltipWidth - TOOLTIP_OFFSET_X : left + TOOLTIP_OFFSET_X;
|
|
237
238
|
const baseY = placement.includes("top") ? top - tooltipHeight - TOOLTIP_OFFSET_Y : top + TOOLTIP_OFFSET_Y;
|
|
238
|
-
const viewportX = baseX - window.scrollX;
|
|
239
|
-
const viewportY = baseY - window.scrollY;
|
|
239
|
+
const viewportX = isFixed ? baseX : baseX - window.scrollX;
|
|
240
|
+
const viewportY = isFixed ? baseY : baseY - window.scrollY;
|
|
240
241
|
const overflowsLeft = viewportX < 0;
|
|
241
242
|
const overflowsRight = viewportX + tooltipWidth > window.innerWidth;
|
|
242
243
|
const overflowsTop = viewportY < 0;
|
|
@@ -272,12 +273,13 @@ var tooltip = (Component, options = {}) => {
|
|
|
272
273
|
const TooltipRoot = () => {
|
|
273
274
|
const _options = mergeProps({
|
|
274
275
|
placement: "top-left",
|
|
276
|
+
fixed: false,
|
|
275
277
|
id: "solid-uplot-tooltip-root",
|
|
276
278
|
style: {},
|
|
277
279
|
zIndex: 20
|
|
278
280
|
}, options);
|
|
279
281
|
const chartCursorData = () => bus.data.cursor?.state[u.root.id];
|
|
280
|
-
const [tooltipOptions, containerProps] = splitProps(_options, ["placement"]);
|
|
282
|
+
const [tooltipOptions, containerProps] = splitProps(_options, ["placement", "fixed"]);
|
|
281
283
|
return createComponent(Show, {
|
|
282
284
|
get when() {
|
|
283
285
|
return chartCursorData();
|
|
@@ -285,11 +287,13 @@ var tooltip = (Component, options = {}) => {
|
|
|
285
287
|
children: (cursor2) => {
|
|
286
288
|
const position = () => {
|
|
287
289
|
const overRect = u.over.getBoundingClientRect();
|
|
288
|
-
const absoluteLeft = overRect.left + cursor2().position.left + window.scrollX;
|
|
289
|
-
const absoluteTop = overRect.top + cursor2().position.top + window.scrollY;
|
|
290
290
|
const tooltipWidth = tooltipRoot.offsetWidth ?? 0;
|
|
291
291
|
const tooltipHeight = tooltipRoot.offsetHeight ?? 0;
|
|
292
|
-
|
|
292
|
+
const cursorLeft = overRect.left + cursor2().position.left;
|
|
293
|
+
const cursorTop = overRect.top + cursor2().position.top;
|
|
294
|
+
const absoluteLeft = tooltipOptions.fixed ? cursorLeft : cursorLeft + window.scrollX;
|
|
295
|
+
const absoluteTop = tooltipOptions.fixed ? cursorTop : cursorTop + window.scrollY;
|
|
296
|
+
return getTooltipPosition(tooltipOptions.placement, absoluteLeft, absoluteTop, tooltipWidth, tooltipHeight, tooltipOptions.fixed);
|
|
293
297
|
};
|
|
294
298
|
return (() => {
|
|
295
299
|
var _el$ = _tmpl$2();
|
|
@@ -307,11 +311,11 @@ var tooltip = (Component, options = {}) => {
|
|
|
307
311
|
}));
|
|
308
312
|
effect((_p$) => {
|
|
309
313
|
var _v$ = containerProps.id, _v$2 = containerProps.class, _v$3 = {
|
|
310
|
-
position: "absolute",
|
|
314
|
+
position: tooltipOptions.fixed ? "fixed" : "absolute",
|
|
311
315
|
"z-index": containerProps.zIndex,
|
|
316
|
+
"pointer-events": "none",
|
|
312
317
|
left: `${position().left}px`,
|
|
313
318
|
top: `${position().top}px`,
|
|
314
|
-
"pointer-events": "none",
|
|
315
319
|
...containerProps.style
|
|
316
320
|
};
|
|
317
321
|
_v$ !== _p$.e && setAttribute(_el$, "id", _p$.e = _v$);
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export { C as CursorData, g as getCursorData } from '../
|
|
1
|
+
export { C as CursorData, S as SeriesDatum, g as getCursorData, a as getSeriesData } from '../getSeriesData-04wGQord.js';
|
|
2
2
|
import uPlot from 'uplot';
|
|
3
|
-
export { S as SeriesDatum, g as getSeriesData } from '../getSeriesData-D1zBqQ9Y.js';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Utility to get a color string from uPlot stroke or fill values
|
package/dist/utils/index.js
CHANGED
|
@@ -1,26 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { getSeriesData } from '../chunk/
|
|
3
|
-
import 'uplot';
|
|
4
|
-
|
|
5
|
-
// src/utils/getColorString.ts
|
|
6
|
-
var getColorString = (fillOrStroke, fallback = "#888") => {
|
|
7
|
-
return typeof fillOrStroke === "string" ? fillOrStroke : fallback;
|
|
8
|
-
};
|
|
9
|
-
function getNewCalendarDayIndices(u) {
|
|
10
|
-
const xValues = u.data[0];
|
|
11
|
-
if (!xValues || !xValues.length) return [];
|
|
12
|
-
const seen = /* @__PURE__ */ new Set();
|
|
13
|
-
const indices = [];
|
|
14
|
-
for (let i = 0; i < xValues.length; i++) {
|
|
15
|
-
const ts = xValues[i];
|
|
16
|
-
const date = new Date(ts);
|
|
17
|
-
const dayString = date.toISOString().split("T")[0];
|
|
18
|
-
if (!seen.has(dayString)) {
|
|
19
|
-
seen.add(dayString);
|
|
20
|
-
indices.push(i);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return indices;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export { getColorString, getNewCalendarDayIndices };
|
|
1
|
+
export { getColorString, getNewCalendarDayIndices } from '../chunk/IV6D7K4M.js';
|
|
2
|
+
export { getCursorData, getSeriesData } from '../chunk/QELYARMN.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dschz/solid-uplot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "SolidJS wrapper for uPlot — ultra-fast, tiny time-series & charting library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Daniel Sanchez <dsanc89@pm.me>",
|
|
@@ -59,14 +59,12 @@
|
|
|
59
59
|
"browser": {},
|
|
60
60
|
"exports": {
|
|
61
61
|
".": {
|
|
62
|
-
"solid": "./dist/index/index.jsx",
|
|
63
62
|
"import": {
|
|
64
63
|
"types": "./dist/index/index.d.ts",
|
|
65
64
|
"default": "./dist/index/index.js"
|
|
66
65
|
}
|
|
67
66
|
},
|
|
68
67
|
"./plugins": {
|
|
69
|
-
"solid": "./dist/plugins/index.jsx",
|
|
70
68
|
"import": {
|
|
71
69
|
"types": "./dist/plugins/index.d.ts",
|
|
72
70
|
"default": "./dist/plugins/index.js"
|
|
@@ -107,44 +105,46 @@
|
|
|
107
105
|
"typecheck": "tsc --noEmit"
|
|
108
106
|
},
|
|
109
107
|
"devDependencies": {
|
|
110
|
-
"@changesets/cli": "^2.29.
|
|
111
|
-
"@dschz/solid-auto-sizer": "^0.1.
|
|
112
|
-
"@solidjs/router": "^0.15.
|
|
108
|
+
"@changesets/cli": "^2.29.7",
|
|
109
|
+
"@dschz/solid-auto-sizer": "^0.1.3",
|
|
110
|
+
"@solidjs/router": "^0.15.4",
|
|
113
111
|
"@solidjs/testing-library": "^0.8.10",
|
|
114
|
-
"@tailwindcss/vite": "^4.1.
|
|
115
|
-
"@testing-library/jest-dom": "^6.
|
|
112
|
+
"@tailwindcss/vite": "^4.1.17",
|
|
113
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
116
114
|
"@testing-library/user-event": "^14.6.1",
|
|
117
|
-
"@types/bun": "^1.
|
|
118
|
-
"@types/prismjs": "^1.26.
|
|
119
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
120
|
-
"@typescript-eslint/parser": "^8.
|
|
121
|
-
"@vitest/coverage-istanbul": "^
|
|
115
|
+
"@types/bun": "^1.3.3",
|
|
116
|
+
"@types/prismjs": "^1.26.5",
|
|
117
|
+
"@typescript-eslint/eslint-plugin": "^8.47.0",
|
|
118
|
+
"@typescript-eslint/parser": "^8.47.0",
|
|
119
|
+
"@vitest/coverage-istanbul": "^4.0.13",
|
|
122
120
|
"@wessberg/pointer-events": "^1.0.9",
|
|
123
|
-
"canvas": "^3.
|
|
124
|
-
"eslint": "^9.
|
|
121
|
+
"canvas": "^3.2.0",
|
|
122
|
+
"eslint": "^9.39.1",
|
|
125
123
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
126
124
|
"eslint-plugin-solid": "^0.14.5",
|
|
127
|
-
"globals": "^16.
|
|
128
|
-
"jiti": "^2.
|
|
129
|
-
"jsdom": "^
|
|
130
|
-
"path2d": "^0.
|
|
131
|
-
"prettier": "^3.
|
|
132
|
-
"prismjs": "^1.
|
|
133
|
-
"solid-js": "^1.9.
|
|
134
|
-
"solid-prism-editor": "^2.
|
|
135
|
-
"tailwindcss": "^4.1.
|
|
136
|
-
"tsup": "^8.
|
|
125
|
+
"globals": "^16.5.0",
|
|
126
|
+
"jiti": "^2.6.1",
|
|
127
|
+
"jsdom": "^27.2.0",
|
|
128
|
+
"path2d": "^0.3.1",
|
|
129
|
+
"prettier": "^3.6.2",
|
|
130
|
+
"prismjs": "^1.30.0",
|
|
131
|
+
"solid-js": "^1.9.10",
|
|
132
|
+
"solid-prism-editor": "^2.1.0",
|
|
133
|
+
"tailwindcss": "^4.1.17",
|
|
134
|
+
"tsup": "^8.5.1",
|
|
137
135
|
"tsup-preset-solid": "^2.2.0",
|
|
138
|
-
"typescript": "^5.
|
|
139
|
-
"typescript-eslint": "^8.
|
|
136
|
+
"typescript": "^5.9.3",
|
|
137
|
+
"typescript-eslint": "^8.47.0",
|
|
140
138
|
"uplot": "^1.6.32",
|
|
141
|
-
"vite": "^
|
|
142
|
-
"vite-plugin-solid": "^2.11.
|
|
143
|
-
"vitest": "^
|
|
139
|
+
"vite": "^7.2.4",
|
|
140
|
+
"vite-plugin-solid": "^2.11.10",
|
|
141
|
+
"vitest": "^4.0.13"
|
|
144
142
|
},
|
|
145
143
|
"peerDependencies": {
|
|
146
144
|
"solid-js": ">=1.6.0",
|
|
147
145
|
"uplot": ">=1.6.32"
|
|
148
146
|
},
|
|
149
|
-
"dependencies": {
|
|
147
|
+
"dependencies": {
|
|
148
|
+
"@solid-primitives/refs": "^1.1.2"
|
|
149
|
+
}
|
|
150
150
|
}
|
package/dist/chunk/3TJS44N7.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// src/utils/getCursorData.ts
|
|
2
|
-
var getCursorData = (u) => {
|
|
3
|
-
const idx = u.cursor.idx;
|
|
4
|
-
const xValues = u.data[0];
|
|
5
|
-
const isValid = idx != null && xValues && idx < xValues.length;
|
|
6
|
-
return !isValid ? void 0 : {
|
|
7
|
-
plotId: u.root.id,
|
|
8
|
-
idx,
|
|
9
|
-
xValue: xValues[idx],
|
|
10
|
-
visible: Boolean(u.cursor.show),
|
|
11
|
-
position: { left: u.cursor.left || 0, top: u.cursor.top || 0 }
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export { getCursorData };
|
package/dist/chunk/ZISGD6FJ.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// src/utils/getSeriesData.ts
|
|
2
|
-
var getSeriesData = (u, options = {}) => {
|
|
3
|
-
const series = [];
|
|
4
|
-
for (let i = 1; i < u.series.length; i++) {
|
|
5
|
-
const s = u.series[i];
|
|
6
|
-
const stroke = typeof s.stroke === "function" ? s.stroke(u, i) : s.stroke;
|
|
7
|
-
const fill = typeof s.fill === "function" ? s.fill(u, i) : s.fill;
|
|
8
|
-
const label = options.labelTransform?.(s.label) || s.label?.toString() || `Series ${i}`;
|
|
9
|
-
series.push({
|
|
10
|
-
idx: i - 1,
|
|
11
|
-
seriesIdx: i,
|
|
12
|
-
label,
|
|
13
|
-
stroke: stroke ?? "#000",
|
|
14
|
-
fill: fill ?? "transparent",
|
|
15
|
-
width: s.width,
|
|
16
|
-
dash: s.dash,
|
|
17
|
-
scale: s.scale,
|
|
18
|
-
visible: Boolean(s.show)
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
return series;
|
|
22
|
-
};
|
|
23
|
-
// istanbul ignore next -- @preserve
|
|
24
|
-
|
|
25
|
-
export { getSeriesData };
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
type CursorPosition = {
|
|
2
|
-
/**
|
|
3
|
-
* The cursor position left offset in CSS pixels (relative to plotting area)
|
|
4
|
-
*/
|
|
5
|
-
readonly left: number;
|
|
6
|
-
/**
|
|
7
|
-
* The cursor position top offset in CSS pixels (relative to plotting area)
|
|
8
|
-
*/
|
|
9
|
-
readonly top: number;
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* The cursor index data for a given uPlot instance.
|
|
13
|
-
*/
|
|
14
|
-
type CursorData = {
|
|
15
|
-
/**
|
|
16
|
-
* The id of the plot instance that the cursor message originates from.
|
|
17
|
-
*/
|
|
18
|
-
readonly plotId: string;
|
|
19
|
-
/**
|
|
20
|
-
* The closest x-axis data index to cursor (closestIdx)
|
|
21
|
-
*/
|
|
22
|
-
readonly idx: number;
|
|
23
|
-
/**
|
|
24
|
-
* The x-axis value of the cursor idx.
|
|
25
|
-
*/
|
|
26
|
-
readonly xValue: number;
|
|
27
|
-
/**
|
|
28
|
-
* The position of the cursor.
|
|
29
|
-
*/
|
|
30
|
-
readonly position: CursorPosition;
|
|
31
|
-
/**
|
|
32
|
-
* The visibility of the cursor.
|
|
33
|
-
*/
|
|
34
|
-
readonly visible: boolean;
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* Get the cursor index data for a given uPlot instance.
|
|
38
|
-
*
|
|
39
|
-
* @param u - The uPlot instance.
|
|
40
|
-
* @returns The cursor data.
|
|
41
|
-
*/
|
|
42
|
-
declare const getCursorData: (u: uPlot) => CursorData | undefined;
|
|
43
|
-
|
|
44
|
-
export { type CursorData as C, getCursorData as g };
|
package/dist/index/index.jsx
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getSeriesData
|
|
3
|
-
} from "../chunk/A3AZKFSW.jsx";
|
|
4
|
-
|
|
5
|
-
// src/createPluginBus.tsx
|
|
6
|
-
import { createStore } from "solid-js/store";
|
|
7
|
-
var createPluginBus = (initialData = {}) => {
|
|
8
|
-
const [data, setData] = createStore(initialData);
|
|
9
|
-
return { data, setData };
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
// src/SolidUplot.tsx
|
|
13
|
-
import "uplot/dist/uPlot.min.css";
|
|
14
|
-
import {
|
|
15
|
-
createEffect,
|
|
16
|
-
createMemo,
|
|
17
|
-
createUniqueId,
|
|
18
|
-
mergeProps,
|
|
19
|
-
onCleanup,
|
|
20
|
-
splitProps,
|
|
21
|
-
untrack
|
|
22
|
-
} from "solid-js";
|
|
23
|
-
import uPlot from "uplot";
|
|
24
|
-
var SolidUplot = (props) => {
|
|
25
|
-
let container;
|
|
26
|
-
const _props = mergeProps(
|
|
27
|
-
{
|
|
28
|
-
id: createUniqueId(),
|
|
29
|
-
childrenPlacement: "top",
|
|
30
|
-
width: 600,
|
|
31
|
-
height: 300,
|
|
32
|
-
autoResize: false,
|
|
33
|
-
data: [],
|
|
34
|
-
resetScales: true,
|
|
35
|
-
plugins: [],
|
|
36
|
-
legend: {
|
|
37
|
-
show: false
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
props
|
|
41
|
-
);
|
|
42
|
-
const [local, options] = splitProps(_props, [
|
|
43
|
-
"children",
|
|
44
|
-
"childrenPlacement",
|
|
45
|
-
"autoResize",
|
|
46
|
-
"onCreate",
|
|
47
|
-
"style",
|
|
48
|
-
"ref"
|
|
49
|
-
]);
|
|
50
|
-
const [updateableOptions, newChartOptions] = splitProps(options, [
|
|
51
|
-
"data",
|
|
52
|
-
"width",
|
|
53
|
-
"height",
|
|
54
|
-
"resetScales"
|
|
55
|
-
]);
|
|
56
|
-
const [system, chartOptions] = splitProps(newChartOptions, ["pluginBus", "plugins"]);
|
|
57
|
-
const size = () => ({ width: updateableOptions.width, height: updateableOptions.height });
|
|
58
|
-
const chartPlugins = createMemo(() => {
|
|
59
|
-
return system.plugins.map(
|
|
60
|
-
(plugin) => typeof plugin === "function" ? plugin({ bus: system.pluginBus }) : plugin
|
|
61
|
-
);
|
|
62
|
-
});
|
|
63
|
-
createEffect(() => {
|
|
64
|
-
const getInitialSize = () => {
|
|
65
|
-
if (local.autoResize) {
|
|
66
|
-
const rect = container.getBoundingClientRect();
|
|
67
|
-
return {
|
|
68
|
-
width: rect.width > 0 ? Math.floor(rect.width) : 600,
|
|
69
|
-
height: rect.height > 0 ? Math.floor(rect.height) : 300
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
return untrack(size);
|
|
73
|
-
};
|
|
74
|
-
const initialSize = getInitialSize();
|
|
75
|
-
const initialData = untrack(() => updateableOptions.data);
|
|
76
|
-
const chart = new uPlot(
|
|
77
|
-
{
|
|
78
|
-
...chartOptions,
|
|
79
|
-
...initialSize,
|
|
80
|
-
plugins: chartPlugins()
|
|
81
|
-
},
|
|
82
|
-
initialData,
|
|
83
|
-
container
|
|
84
|
-
);
|
|
85
|
-
local.onCreate?.(chart, { seriesData: getSeriesData(chart) });
|
|
86
|
-
createEffect(() => {
|
|
87
|
-
if (local.autoResize) return;
|
|
88
|
-
chart.setSize(size());
|
|
89
|
-
});
|
|
90
|
-
createEffect(() => {
|
|
91
|
-
if (!local.autoResize) return;
|
|
92
|
-
const resizeObserver = new ResizeObserver((entries) => {
|
|
93
|
-
for (const entry of entries) {
|
|
94
|
-
const { width, height } = entry.contentRect;
|
|
95
|
-
chart.setSize({ width: Math.floor(width), height: Math.floor(height) });
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
resizeObserver.observe(container);
|
|
99
|
-
onCleanup(() => {
|
|
100
|
-
resizeObserver.disconnect();
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
createEffect(() => {
|
|
104
|
-
chart.setData(updateableOptions.data, updateableOptions.resetScales);
|
|
105
|
-
});
|
|
106
|
-
onCleanup(() => {
|
|
107
|
-
chart.destroy();
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
return <div
|
|
111
|
-
id="solid-uplot-root"
|
|
112
|
-
style={{
|
|
113
|
-
display: "flex",
|
|
114
|
-
"flex-direction": local.childrenPlacement === "top" ? "column" : "column-reverse",
|
|
115
|
-
// When autoResize is enabled, fill the parent container
|
|
116
|
-
...local.autoResize && {
|
|
117
|
-
width: "100%",
|
|
118
|
-
height: "100%",
|
|
119
|
-
"min-width": "0",
|
|
120
|
-
"min-height": "0"
|
|
121
|
-
},
|
|
122
|
-
...local.style
|
|
123
|
-
}}
|
|
124
|
-
ref={(el) => {
|
|
125
|
-
container = el;
|
|
126
|
-
local.ref?.(el);
|
|
127
|
-
}}
|
|
128
|
-
>
|
|
129
|
-
{local.children}
|
|
130
|
-
</div>;
|
|
131
|
-
};
|
|
132
|
-
export {
|
|
133
|
-
SolidUplot,
|
|
134
|
-
createPluginBus
|
|
135
|
-
};
|
package/dist/plugins/index.jsx
DELETED
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getSeriesData
|
|
3
|
-
} from "../chunk/A3AZKFSW.jsx";
|
|
4
|
-
|
|
5
|
-
// src/utils/getCursorData.ts
|
|
6
|
-
var getCursorData = (u) => {
|
|
7
|
-
const idx = u.cursor.idx;
|
|
8
|
-
const xValues = u.data[0];
|
|
9
|
-
const isValid = idx != null && xValues && idx < xValues.length;
|
|
10
|
-
return !isValid ? void 0 : {
|
|
11
|
-
plotId: u.root.id,
|
|
12
|
-
idx,
|
|
13
|
-
xValue: xValues[idx],
|
|
14
|
-
visible: Boolean(u.cursor.show),
|
|
15
|
-
position: { left: u.cursor.left || 0, top: u.cursor.top || 0 }
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// src/plugins/cursor.ts
|
|
20
|
-
var cursor = () => {
|
|
21
|
-
return ({ bus }) => {
|
|
22
|
-
if (!bus) {
|
|
23
|
-
return { hooks: {} };
|
|
24
|
-
}
|
|
25
|
-
bus.setData("cursor", {
|
|
26
|
-
state: {}
|
|
27
|
-
});
|
|
28
|
-
let pointerEnter;
|
|
29
|
-
let pointerLeave;
|
|
30
|
-
return {
|
|
31
|
-
hooks: {
|
|
32
|
-
ready: (u) => {
|
|
33
|
-
pointerEnter = () => {
|
|
34
|
-
bus.setData("cursor", { sourceId: u.root.id });
|
|
35
|
-
};
|
|
36
|
-
pointerLeave = () => {
|
|
37
|
-
bus.setData("cursor", { sourceId: void 0 });
|
|
38
|
-
};
|
|
39
|
-
u.over.addEventListener("pointerenter", pointerEnter);
|
|
40
|
-
u.over.addEventListener("pointerleave", pointerLeave);
|
|
41
|
-
},
|
|
42
|
-
setCursor: (u) => {
|
|
43
|
-
bus.setData("cursor", "state", u.root.id, getCursorData(u));
|
|
44
|
-
},
|
|
45
|
-
setData: (u) => {
|
|
46
|
-
bus.setData("cursor", (prev) => ({
|
|
47
|
-
...prev ?? {},
|
|
48
|
-
state: {
|
|
49
|
-
...prev?.state ?? {},
|
|
50
|
-
[u.root.id]: getCursorData(u)
|
|
51
|
-
}
|
|
52
|
-
}));
|
|
53
|
-
},
|
|
54
|
-
destroy: (u) => {
|
|
55
|
-
bus.setData("cursor", "state", u.root.id, void 0);
|
|
56
|
-
u.over.removeEventListener("pointerenter", pointerEnter);
|
|
57
|
-
u.over.removeEventListener("pointerleave", pointerLeave);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// src/plugins/focusSeries.ts
|
|
65
|
-
import { createEffect, createRoot } from "solid-js";
|
|
66
|
-
var DEFAULT_UNFOCUSED_ALPHA = 0.1;
|
|
67
|
-
var DEFAULT_FOCUSED_ALPHA = 1;
|
|
68
|
-
var DEFAULT_REBUILD_PATHS = false;
|
|
69
|
-
var seriesFocusRedraw = (u, options = {}) => {
|
|
70
|
-
const {
|
|
71
|
-
unfocusedAlpha = DEFAULT_UNFOCUSED_ALPHA,
|
|
72
|
-
focusedAlpha = DEFAULT_FOCUSED_ALPHA,
|
|
73
|
-
rebuildPaths = DEFAULT_REBUILD_PATHS,
|
|
74
|
-
focusTargets
|
|
75
|
-
} = options;
|
|
76
|
-
for (let i = 1; i < u.series.length; i++) {
|
|
77
|
-
const s = u.series[i];
|
|
78
|
-
if (!focusTargets || !focusTargets.length) {
|
|
79
|
-
s.alpha = 1;
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
const target = focusTargets.find((t) => {
|
|
83
|
-
if ("label" in t) return t.label === s.label;
|
|
84
|
-
if ("zeroIndex" in t) return t.zeroIndex === i - 1;
|
|
85
|
-
if ("index" in t) return t.index === i;
|
|
86
|
-
});
|
|
87
|
-
s.alpha = target ? focusedAlpha : unfocusedAlpha;
|
|
88
|
-
}
|
|
89
|
-
u.redraw(rebuildPaths);
|
|
90
|
-
};
|
|
91
|
-
var focusSeries = (options = {}) => {
|
|
92
|
-
return ({ bus }) => {
|
|
93
|
-
if (!bus) {
|
|
94
|
-
return { hooks: {} };
|
|
95
|
-
}
|
|
96
|
-
const {
|
|
97
|
-
pxThreshold = 5,
|
|
98
|
-
unfocusedAlpha = DEFAULT_UNFOCUSED_ALPHA,
|
|
99
|
-
focusedAlpha = DEFAULT_FOCUSED_ALPHA,
|
|
100
|
-
rebuildPaths = DEFAULT_REBUILD_PATHS
|
|
101
|
-
} = options;
|
|
102
|
-
let dispose;
|
|
103
|
-
let pointerLeave;
|
|
104
|
-
return {
|
|
105
|
-
hooks: {
|
|
106
|
-
ready: (u) => {
|
|
107
|
-
pointerLeave = () => {
|
|
108
|
-
bus.setData("focusSeries", void 0);
|
|
109
|
-
};
|
|
110
|
-
queueMicrotask(() => {
|
|
111
|
-
if (bus.data.focusSeries) {
|
|
112
|
-
seriesFocusRedraw(u, {
|
|
113
|
-
unfocusedAlpha,
|
|
114
|
-
focusedAlpha,
|
|
115
|
-
rebuildPaths,
|
|
116
|
-
focusTargets: bus.data.focusSeries.targets
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
u.over.addEventListener("pointerleave", pointerLeave);
|
|
121
|
-
dispose = createRoot((dispose2) => {
|
|
122
|
-
createEffect(() => {
|
|
123
|
-
const cursor2 = bus.data.cursor;
|
|
124
|
-
const focus = bus.data.focusSeries;
|
|
125
|
-
if (cursor2?.sourceId !== u.root.id) {
|
|
126
|
-
seriesFocusRedraw(u, {
|
|
127
|
-
unfocusedAlpha,
|
|
128
|
-
focusedAlpha,
|
|
129
|
-
rebuildPaths,
|
|
130
|
-
focusTargets: focus?.targets
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
return dispose2;
|
|
135
|
-
});
|
|
136
|
-
},
|
|
137
|
-
setCursor: (u) => {
|
|
138
|
-
const cursor2 = bus.data.cursor;
|
|
139
|
-
const chartCursor = cursor2?.state[u.root.id];
|
|
140
|
-
if (!cursor2 || !chartCursor || cursor2.sourceId !== u.root.id) return;
|
|
141
|
-
const focusTargets = [];
|
|
142
|
-
for (let i = 1; i < u.series.length; i++) {
|
|
143
|
-
const s = u.series[i];
|
|
144
|
-
const yVals = u.data[i];
|
|
145
|
-
const val = yVals?.[chartCursor.idx];
|
|
146
|
-
if (!s.show || !yVals || val == null) continue;
|
|
147
|
-
const yPos = u.valToPos(val, s.scale);
|
|
148
|
-
const dist = Math.abs(yPos - chartCursor.position.top);
|
|
149
|
-
if (dist <= pxThreshold) {
|
|
150
|
-
if (s.label != null) {
|
|
151
|
-
focusTargets.push({ label: s.label });
|
|
152
|
-
} else {
|
|
153
|
-
focusTargets.push({ index: i });
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
seriesFocusRedraw(u, {
|
|
158
|
-
unfocusedAlpha,
|
|
159
|
-
focusedAlpha,
|
|
160
|
-
rebuildPaths,
|
|
161
|
-
focusTargets
|
|
162
|
-
});
|
|
163
|
-
bus.setData("focusSeries", {
|
|
164
|
-
sourceId: u.root.id,
|
|
165
|
-
targets: focusTargets
|
|
166
|
-
});
|
|
167
|
-
},
|
|
168
|
-
destroy: (u) => {
|
|
169
|
-
dispose();
|
|
170
|
-
u.over.removeEventListener("pointerleave", pointerLeave);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
};
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
// src/plugins/legend.tsx
|
|
178
|
-
import { mergeProps, splitProps } from "solid-js";
|
|
179
|
-
import { render } from "solid-js/web";
|
|
180
|
-
import "uplot";
|
|
181
|
-
var legend = (Component, options = {}) => {
|
|
182
|
-
return ({ bus }) => {
|
|
183
|
-
if (!bus) {
|
|
184
|
-
return { hooks: {} };
|
|
185
|
-
}
|
|
186
|
-
let legendRoot;
|
|
187
|
-
let dispose;
|
|
188
|
-
return {
|
|
189
|
-
hooks: {
|
|
190
|
-
ready: (u) => {
|
|
191
|
-
const seriesData = getSeriesData(u);
|
|
192
|
-
const LegendRoot = () => {
|
|
193
|
-
const _options = mergeProps(
|
|
194
|
-
{
|
|
195
|
-
placement: "top-left",
|
|
196
|
-
pxOffset: 8,
|
|
197
|
-
id: "solid-uplot-legend-root",
|
|
198
|
-
zIndex: 10
|
|
199
|
-
},
|
|
200
|
-
options
|
|
201
|
-
);
|
|
202
|
-
const [legendOptions, containerProps] = splitProps(_options, ["placement", "pxOffset"]);
|
|
203
|
-
const containerStyle = () => {
|
|
204
|
-
const overRect = u.over.getBoundingClientRect();
|
|
205
|
-
const offset = legendOptions.pxOffset;
|
|
206
|
-
return {
|
|
207
|
-
position: "absolute",
|
|
208
|
-
[legendOptions.placement === "top-left" ? "left" : "right"]: `${offset}px`,
|
|
209
|
-
top: `${offset}px`,
|
|
210
|
-
"max-width": `${overRect.width - offset * 2}px`,
|
|
211
|
-
"max-height": `${overRect.height - offset * 2}px`,
|
|
212
|
-
"z-index": containerProps.zIndex,
|
|
213
|
-
"pointer-events": "auto",
|
|
214
|
-
overflow: "auto",
|
|
215
|
-
...containerProps.style
|
|
216
|
-
};
|
|
217
|
-
};
|
|
218
|
-
return <div
|
|
219
|
-
ref={legendRoot}
|
|
220
|
-
id={containerProps.id}
|
|
221
|
-
class={containerProps.class}
|
|
222
|
-
role="group"
|
|
223
|
-
aria-label="Chart legend"
|
|
224
|
-
style={containerStyle()}
|
|
225
|
-
>
|
|
226
|
-
<Component u={u} seriesData={seriesData} bus={bus} />
|
|
227
|
-
</div>;
|
|
228
|
-
};
|
|
229
|
-
dispose = render(() => <LegendRoot />, u.over);
|
|
230
|
-
},
|
|
231
|
-
destroy: () => {
|
|
232
|
-
dispose();
|
|
233
|
-
legendRoot?.remove();
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
};
|
|
237
|
-
};
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
// src/plugins/tooltip.tsx
|
|
241
|
-
import { mergeProps as mergeProps2, Show, splitProps as splitProps2 } from "solid-js";
|
|
242
|
-
import { render as render2 } from "solid-js/web";
|
|
243
|
-
import "uplot";
|
|
244
|
-
var TOOLTIP_OFFSET_X = 8;
|
|
245
|
-
var TOOLTIP_OFFSET_Y = 8;
|
|
246
|
-
var getTooltipPosition = (placement, left, top, tooltipWidth, tooltipHeight) => {
|
|
247
|
-
const baseX = placement.includes("left") ? left - tooltipWidth - TOOLTIP_OFFSET_X : left + TOOLTIP_OFFSET_X;
|
|
248
|
-
const baseY = placement.includes("top") ? top - tooltipHeight - TOOLTIP_OFFSET_Y : top + TOOLTIP_OFFSET_Y;
|
|
249
|
-
const viewportX = baseX - window.scrollX;
|
|
250
|
-
const viewportY = baseY - window.scrollY;
|
|
251
|
-
const overflowsLeft = viewportX < 0;
|
|
252
|
-
const overflowsRight = viewportX + tooltipWidth > window.innerWidth;
|
|
253
|
-
const overflowsTop = viewportY < 0;
|
|
254
|
-
const overflowsBottom = viewportY + tooltipHeight > window.innerHeight;
|
|
255
|
-
let flipX = false;
|
|
256
|
-
let flipY = false;
|
|
257
|
-
if (placement.includes("left") && overflowsLeft) flipX = true;
|
|
258
|
-
if (placement.includes("right") && overflowsRight) flipX = true;
|
|
259
|
-
if (placement.includes("top") && overflowsTop) flipY = true;
|
|
260
|
-
if (placement.includes("bottom") && overflowsBottom) flipY = true;
|
|
261
|
-
const finalX = flipX && placement.includes("left") ? left + TOOLTIP_OFFSET_X : flipX && placement.includes("right") ? left - tooltipWidth - TOOLTIP_OFFSET_X : baseX;
|
|
262
|
-
const finalY = flipY && placement.includes("top") ? top + TOOLTIP_OFFSET_Y : flipY && placement.includes("bottom") ? top - tooltipHeight - TOOLTIP_OFFSET_Y : baseY;
|
|
263
|
-
return {
|
|
264
|
-
left: finalX,
|
|
265
|
-
top: finalY
|
|
266
|
-
};
|
|
267
|
-
};
|
|
268
|
-
var tooltip = (Component, options = {}) => {
|
|
269
|
-
return ({ bus }) => {
|
|
270
|
-
if (!bus) {
|
|
271
|
-
return { hooks: {} };
|
|
272
|
-
}
|
|
273
|
-
let tooltipRoot;
|
|
274
|
-
let dispose;
|
|
275
|
-
return {
|
|
276
|
-
hooks: {
|
|
277
|
-
ready: (u) => {
|
|
278
|
-
const seriesData = getSeriesData(u);
|
|
279
|
-
const TooltipRoot = () => {
|
|
280
|
-
const _options = mergeProps2(
|
|
281
|
-
{
|
|
282
|
-
placement: "top-left",
|
|
283
|
-
id: "solid-uplot-tooltip-root",
|
|
284
|
-
style: {},
|
|
285
|
-
zIndex: 20
|
|
286
|
-
},
|
|
287
|
-
options
|
|
288
|
-
);
|
|
289
|
-
const chartCursorData = () => bus.data.cursor?.state[u.root.id];
|
|
290
|
-
const [tooltipOptions, containerProps] = splitProps2(_options, ["placement"]);
|
|
291
|
-
return <Show when={chartCursorData()}>
|
|
292
|
-
{(cursor2) => {
|
|
293
|
-
const position = () => {
|
|
294
|
-
const overRect = u.over.getBoundingClientRect();
|
|
295
|
-
const absoluteLeft = overRect.left + cursor2().position.left + window.scrollX;
|
|
296
|
-
const absoluteTop = overRect.top + cursor2().position.top + window.scrollY;
|
|
297
|
-
const tooltipWidth = tooltipRoot.offsetWidth ?? 0;
|
|
298
|
-
const tooltipHeight = tooltipRoot.offsetHeight ?? 0;
|
|
299
|
-
return getTooltipPosition(
|
|
300
|
-
tooltipOptions.placement,
|
|
301
|
-
absoluteLeft,
|
|
302
|
-
absoluteTop,
|
|
303
|
-
tooltipWidth,
|
|
304
|
-
tooltipHeight
|
|
305
|
-
);
|
|
306
|
-
};
|
|
307
|
-
return <div
|
|
308
|
-
ref={tooltipRoot}
|
|
309
|
-
id={containerProps.id}
|
|
310
|
-
class={containerProps.class}
|
|
311
|
-
role="tooltip"
|
|
312
|
-
aria-label="Chart tooltip"
|
|
313
|
-
style={{
|
|
314
|
-
position: "absolute",
|
|
315
|
-
"z-index": containerProps.zIndex,
|
|
316
|
-
left: `${position().left}px`,
|
|
317
|
-
top: `${position().top}px`,
|
|
318
|
-
"pointer-events": "none",
|
|
319
|
-
...containerProps.style
|
|
320
|
-
}}
|
|
321
|
-
>
|
|
322
|
-
<Component
|
|
323
|
-
u={u}
|
|
324
|
-
seriesData={seriesData}
|
|
325
|
-
cursor={cursor2()}
|
|
326
|
-
focusedSeries={bus.data.focusSeries}
|
|
327
|
-
/>
|
|
328
|
-
</div>;
|
|
329
|
-
}}
|
|
330
|
-
</Show>;
|
|
331
|
-
};
|
|
332
|
-
dispose = render2(() => <TooltipRoot />, u.root);
|
|
333
|
-
},
|
|
334
|
-
destroy: () => {
|
|
335
|
-
dispose();
|
|
336
|
-
tooltipRoot?.remove();
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
};
|
|
341
|
-
};
|
|
342
|
-
export {
|
|
343
|
-
cursor,
|
|
344
|
-
focusSeries,
|
|
345
|
-
legend,
|
|
346
|
-
tooltip
|
|
347
|
-
};
|