generated from thedanchez/template-solidjs-library
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
feat: adds uplot-solid implementation
1 parent
7b7705c
commit 6ab9dbb
Showing
8 changed files
with
335 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,24 @@ | ||
{ | ||
"name": "template-solidjs-library", | ||
"version": "0.0.0", | ||
"description": "Template for SolidJS library using tsup for bundling. Configured with Bun, NVM, TypeScript, ESLint, Prettier, Vitest, and GHA", | ||
"name": "uplot-solid", | ||
"version": "1.0.0", | ||
"description": "Solid wrapper for μPlot", | ||
"type": "module", | ||
"author": "Daniel Sanchez <[email protected]>", | ||
"license": "MIT", | ||
"homepage": "https://github.com/thedanchez/uplot-solid#readme", | ||
"bugs": { | ||
"url": "https://github.com/thedanchez/uplot-solid/issues" | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"keywords": [ | ||
"uPlot", | ||
"Solid", | ||
"SolidJS", | ||
"charts", | ||
"plot" | ||
], | ||
"scripts": { | ||
"build": "tsup", | ||
"build:watch": "tsup --watch", | ||
|
@@ -17,27 +33,42 @@ | |
"test:cov": "vitest run --coverage", | ||
"typecheck": "tsc --noEmit" | ||
}, | ||
"license": "MIT", | ||
"devDependencies": { | ||
"@solidjs/testing-library": "^0.8.10", | ||
"@testing-library/jest-dom": "^6.5.0", | ||
"@types/bun": "^1.1.10", | ||
"@typescript-eslint/eslint-plugin": "^8.7.0", | ||
"@typescript-eslint/parser": "^8.7.0", | ||
"@vitest/coverage-istanbul": "^2.1.1", | ||
"esbuild-css-modules-plugin": "^3.1.2", | ||
"eslint": "^8.57.0", | ||
"eslint-plugin-simple-import-sort": "^12.1.1", | ||
"eslint-plugin-solid": "^0.14.3", | ||
"jsdom": "^25.0.1", | ||
"prettier": "^3.3.3", | ||
"solid-js": "^1.9.1", | ||
"tsup": "^8.3.0", | ||
"tsup-preset-solid": "^2.2.0", | ||
"typescript": "^5.6.2", | ||
"uplot": "^1.6.31", | ||
"vite": "^5.4.8", | ||
"vite-plugin-solid": "^2.10.2", | ||
"vitest": "^2.1.1" | ||
}, | ||
"peerDependencies": { | ||
"solid-js": ">=1.8.0" | ||
} | ||
"solid-js": ">=1.8.0", | ||
"uplot": ">=1.6.31" | ||
}, | ||
"main": "./dist/index.js", | ||
"module": "./dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"browser": {}, | ||
"exports": { | ||
"solid": "./dist/index.jsx", | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
} | ||
}, | ||
"typesVersions": {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,99 @@ | ||
import { createSignal, For } from "solid-js"; | ||
import { createStore } from "solid-js/store"; | ||
import { createSignal } from "solid-js"; | ||
|
||
type Todo = { id: number; text: string; completed: boolean }; | ||
import UplotSolid from "../dist"; | ||
import fakeData from "./resource/uplot_fake_data.json"; | ||
|
||
const isNil = (value: unknown): value is null | undefined => value === null || value === undefined; | ||
|
||
export const App = () => { | ||
let input!: HTMLInputElement; | ||
const [size, setSize] = createSignal({ width: 1000, height: 300 }); | ||
const [position, setPosition] = createSignal({ left: 0, top: 0 }); | ||
const [content, setContent] = createSignal(""); | ||
|
||
const [count, setCount] = createSignal(0); | ||
const [todos, setTodos] = createStore<Todo[]>([]); | ||
const alignedData = [fakeData.time, fakeData.y_series_1, fakeData.y_series_2] as uPlot.AlignedData; | ||
|
||
const addTodo = (text: string) => { | ||
setTodos(todos.length, { id: todos.length, text, completed: false }); | ||
}; | ||
return ( | ||
<div id="app-playground"> | ||
<button | ||
onClick={() => { | ||
setSize({ width: 1000, height: size().height === 300 ? 600 : 300 }); | ||
}} | ||
> | ||
toggle height | ||
</button> | ||
<UplotSolid | ||
id="snapshot-plot" | ||
data={alignedData} | ||
width={size().width} | ||
height={size().height} | ||
series={[ | ||
{ | ||
label: "Time", | ||
stroke: "green", | ||
}, | ||
{ | ||
label: "Series 2", | ||
stroke: "blue", | ||
}, | ||
{ | ||
label: "Series 3", | ||
stroke: "red", | ||
}, | ||
]} | ||
hooks={{ | ||
setCursor: [ | ||
(u) => { | ||
const { idx } = u.cursor; | ||
|
||
const toggleTodo = (id: number) => { | ||
setTodos(id, "completed", (c) => !c); | ||
}; | ||
const left = u.cursor.left as number; | ||
const top = u.cursor.top as number; | ||
|
||
return ( | ||
<> | ||
<div> | ||
<div>Count: {count()}</div> | ||
<button | ||
onClick={() => { | ||
setCount((prev) => prev + 1); | ||
}} | ||
> | ||
Increment Count | ||
</button> | ||
<input placeholder="new todo here" ref={input} /> | ||
<button | ||
onClick={() => { | ||
if (!input.value.trim()) return; | ||
addTodo(input.value); | ||
input.value = ""; | ||
}} | ||
> | ||
Add Todo | ||
</button> | ||
</div> | ||
<For each={todos}> | ||
{(todo) => { | ||
const { id, text } = todo; | ||
return ( | ||
<div> | ||
<input type="checkbox" checked={todo.completed} onChange={[toggleTodo, id]} /> | ||
<span | ||
style={{ | ||
"text-decoration": todo.completed ? "line-through" : "none", | ||
}} | ||
> | ||
{text} | ||
</span> | ||
</div> | ||
); | ||
if (!isNil(idx)) { | ||
const xValue = u.data[0][idx] as number; | ||
const yValue = u.data[1]?.[idx] as number; | ||
const yValue2 = u.data[2]?.[idx] as number; | ||
|
||
setPosition({ left: left - 90, top: top + 40 }); | ||
// setContent(`x: ${xValue}, y: ${yValue}`); | ||
setContent( | ||
`x: ${new Date(xValue).toLocaleTimeString()}, y1: ${yValue}, y2: ${yValue2}. Pluse randome number: ${Math.random()}`, | ||
); | ||
} else { | ||
setContent(""); // Hide tooltip | ||
} | ||
}, | ||
], | ||
}} | ||
</For> | ||
</> | ||
/> | ||
<Tooltip position={position()} content={content()} /> | ||
</div> | ||
); | ||
}; | ||
|
||
type TooltipProps = { | ||
readonly position: { left: number; top: number }; | ||
readonly content: string; | ||
}; | ||
|
||
function Tooltip(props: TooltipProps) { | ||
return ( | ||
<div | ||
id="tooltip" | ||
style={{ | ||
position: "absolute", | ||
background: "black", | ||
color: "white", | ||
padding: "5px", | ||
border: "1px solid black", | ||
"border-radius": "3px", | ||
"pointer-events": "none", | ||
display: props.content ? "block" : "none", | ||
left: `${props.position.left}px`, | ||
top: `${props.position.top}px`, | ||
"z-index": 100, | ||
}} | ||
> | ||
{props.content} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
{ | ||
"time": [ | ||
1727395200000, 1727395500000, 1727395800000, 1727396100000, 1727396400000, 1727396700000, 1727397000000, | ||
1727397300000, 1727397600000, 1727397900000, 1727398200000, 1727398500000, 1727398800000, 1727399100000, | ||
1727399400000, 1727399700000, 1727400000000, 1727400300000, 1727400600000, 1727400900000, 1727401200000, | ||
1727401500000, 1727401800000, 1727402100000, 1727402400000, 1727402700000, 1727403000000, 1727403300000, | ||
1727403600000, 1727403900000, 1727404200000, 1727404500000, 1727404800000, 1727405100000, 1727405400000, | ||
1727405700000, 1727406000000, 1727406300000, 1727406600000, 1727406900000, 1727407200000, 1727407500000, | ||
1727407800000, 1727408100000, 1727408400000, 1727408700000, 1727409000000, 1727409300000, 1727409600000, | ||
1727409900000, 1727410200000, 1727410500000, 1727410800000, 1727411100000, 1727411400000, 1727411700000, | ||
1727412000000, 1727412300000, 1727412600000, 1727412900000, 1727413200000, 1727413500000, 1727413800000, | ||
1727414100000, 1727414400000, 1727414700000, 1727415000000, 1727415300000, 1727415600000, 1727415900000, | ||
1727416200000, 1727416500000, 1727416800000, 1727417100000, 1727417400000, 1727417700000, 1727418000000, | ||
1727418300000, 1727418600000, 1727418900000, 1727419200000, 1727419500000, 1727419800000, 1727420100000, | ||
1727420400000, 1727420700000, 1727421000000, 1727421300000, 1727421600000, 1727421900000, 1727422200000, | ||
1727422500000, 1727422800000, 1727423100000, 1727423400000, 1727423700000, 1727424000000, 1727424300000, | ||
1727424600000, 1727424900000, 1727425200000, 1727425500000, 1727425800000, 1727426100000, 1727426400000, | ||
1727426700000, 1727427000000, 1727427300000, 1727427600000, 1727427900000, 1727428200000, 1727428500000, | ||
1727428800000, 1727429100000, 1727429400000, 1727429700000, 1727430000000, 1727430300000, 1727430600000, | ||
1727430900000, 1727431200000, 1727431500000, 1727431800000, 1727432100000, 1727432400000, 1727432700000, | ||
1727433000000, 1727433300000, 1727433600000, 1727433900000, 1727434200000, 1727434500000, 1727434800000, | ||
1727435100000, 1727435400000, 1727435700000, 1727436000000, 1727436300000, 1727436600000, 1727436900000, | ||
1727437200000, 1727437500000, 1727437800000, 1727438100000, 1727438400000, 1727438700000, 1727439000000, | ||
1727439300000, 1727439600000, 1727439900000, 1727440200000, 1727440500000, 1727440800000, 1727441100000, | ||
1727441400000, 1727441700000, 1727442000000, 1727442300000, 1727442600000, 1727442900000, 1727443200000, | ||
1727443500000, 1727443800000, 1727444100000, 1727444400000, 1727444700000, 1727445000000, 1727445300000, | ||
1727445600000, 1727445900000, 1727446200000, 1727446500000, 1727446800000, 1727447100000, 1727447400000, | ||
1727447700000, 1727448000000, 1727448300000, 1727448600000, 1727448900000, 1727449200000, 1727449500000, | ||
1727449800000, 1727450100000, 1727450400000, 1727450700000, 1727451000000, 1727451300000, 1727451600000, | ||
1727451900000, 1727452200000, 1727452500000, 1727452800000, 1727453100000, 1727453400000, 1727453700000, | ||
1727454000000, 1727454300000, 1727454600000, 1727454900000, 1727455200000, 1727455500000, 1727455800000, | ||
1727456100000, 1727456400000, 1727456700000, 1727457000000, 1727457300000, 1727457600000, 1727457900000, | ||
1727458200000, 1727458500000, 1727458800000, 1727459100000, 1727459400000, 1727459700000, 1727460000000, | ||
1727460300000, 1727460600000, 1727460900000, 1727461200000, 1727461500000, 1727461800000, 1727462100000, | ||
1727462400000, 1727462700000, 1727463000000, 1727463300000, 1727463600000, 1727463900000, 1727464200000, | ||
1727464500000, 1727464800000, 1727465100000, 1727465400000, 1727465700000, 1727466000000, 1727466300000, | ||
1727466600000, 1727466900000, 1727467200000, 1727467500000, 1727467800000, 1727468100000, 1727468400000, | ||
1727468700000, 1727469000000, 1727469300000, 1727469600000, 1727469900000, 1727470200000, 1727470500000, | ||
1727470800000, 1727471100000, 1727471400000, 1727471700000, 1727472000000, 1727472300000, 1727472600000, | ||
1727472900000, 1727473200000, 1727473500000, 1727473800000, 1727474100000, 1727474400000, 1727474700000, | ||
1727475000000, 1727475300000, 1727475600000, 1727475900000, 1727476200000, 1727476500000, 1727476800000, | ||
1727477100000, 1727477400000, 1727477700000, 1727478000000, 1727478300000, 1727478600000, 1727478900000, | ||
1727479200000, 1727479500000, 1727479800000, 1727480100000, 1727480400000, 1727480700000, 1727481000000, | ||
1727481300000 | ||
], | ||
"y_series_1": [ | ||
73, 75, 74, 94, 90, 78, 64, 94, 50, 74, 56, 58, 73, 50, 93, 57, 73, 60, 66, 57, 84, 84, 82, 54, 91, 88, 90, 77, 56, | ||
58, 57, 61, 83, 82, 97, 72, 73, 86, 84, 93, 89, 71, 76, 84, 50, 84, 86, 96, 63, 52, 50, 54, 75, 63, 88, 76, 58, 64, | ||
64, 75, 91, 62, 81, 88, 98, 81, 53, 79, 86, 72, 88, 94, 64, 92, 78, 85, 62, 81, 56, 71, 77, 51, 91, 94, 55, 77, 77, | ||
93, 93, 69, 79, 60, 77, 74, 88, 82, 50, 76, 62, 90, 52, 88, 55, 57, 76, 58, 86, 82, 91, 93, 73, 64, 81, 81, 73, 90, | ||
98, 98, 61, 88, 51, 52, 98, 86, 98, 66, 98, 51, 51, 77, 72, 86, 81, 82, 50, 68, 51, 93, 75, 81, 55, 81, 53, 60, 66, | ||
87, 73, 54, 83, 55, 71, 60, 97, 65, 82, 58, 55, 65, 78, 52, 69, 85, 68, 75, 52, 68, 69, 81, 56, 90, 82, 89, 88, 67, | ||
89, 50, 60, 77, 74, 99, 72, 80, 79, 91, 84, 56, 65, 75, 97, 98, 51, 50, 97, 61, 54, 86, 81, 58, 90, 84, 68, 97, 65, | ||
52, 69, 73, 82, 73, 60, 98, 57, 85, 87, 89, 69, 84, 97, 74, 84, 74, 78, 67, 95, 67, 51, 84, 65, 90, 85, 82, 53, 82, | ||
63, 70, 97, 69, 57, 56, 52, 66, 82, 97, 61, 71, 71, 95, 79, 87, 87, 94, 57, 76, 76, 83, 70, 79, 82, 77, 96, 82, 54, | ||
97, 68, 53, 84, 98, 66, 93, 77, 79, 78, 95, 55, 84, 90, 86, 73, 78, 98, 95, 80, 84, 82, 70, 81, 72, 82, 52 | ||
], | ||
"y_series_2": [ | ||
37, 44, 61, 50, 73, 77, 22, 59, 65, 43, 69, 51, 66, 41, 42, 21, 46, 61, 21, 45, 36, 59, 52, 28, 62, 73, 67, 58, 48, | ||
61, 74, 45, 54, 69, 44, 43, 32, 79, 77, 26, 76, 55, 64, 39, 20, 27, 65, 35, 33, 31, 70, 42, 34, 47, 53, 21, 51, 42, | ||
41, 70, 44, 77, 41, 77, 77, 41, 68, 71, 61, 25, 34, 73, 62, 79, 56, 52, 27, 72, 79, 63, 63, 24, 58, 23, 25, 64, 51, | ||
71, 49, 66, 54, 74, 59, 71, 35, 32, 69, 79, 61, 49, 38, 36, 75, 38, 47, 77, 74, 45, 56, 45, 72, 42, 28, 31, 72, 20, | ||
77, 77, 20, 66, 53, 51, 73, 67, 44, 59, 64, 72, 20, 35, 58, 24, 41, 48, 74, 22, 31, 45, 35, 70, 56, 41, 76, 48, 33, | ||
47, 24, 66, 68, 49, 65, 71, 24, 31, 35, 45, 45, 67, 40, 58, 55, 52, 49, 56, 42, 77, 29, 73, 24, 55, 53, 71, 50, 29, | ||
77, 38, 77, 51, 20, 75, 24, 64, 23, 35, 43, 35, 74, 21, 68, 47, 51, 46, 39, 43, 31, 69, 54, 79, 52, 52, 70, 62, 56, | ||
31, 22, 20, 52, 59, 29, 62, 63, 48, 32, 31, 50, 65, 21, 70, 69, 54, 42, 36, 45, 27, 48, 45, 29, 45, 53, 70, 60, 26, | ||
23, 77, 72, 69, 64, 30, 48, 75, 55, 44, 40, 76, 55, 29, 56, 28, 43, 54, 68, 54, 67, 55, 37, 68, 58, 51, 43, 42, 51, | ||
56, 31, 68, 74, 32, 42, 44, 54, 60, 49, 36, 68, 39, 67, 44, 41, 32, 78, 38, 68, 55, 31, 60, 38, 31, 28, 26 | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import "uplot/dist/uPlot.min.css"; | ||
|
||
import { createEffect, type JSX, mergeProps, onCleanup, type ParentProps, splitProps, untrack } from "solid-js"; | ||
import uPlot from "uplot"; | ||
|
||
type Props = uPlot.Options & { | ||
readonly class?: string; | ||
/** Callback when uPlot instance is created */ | ||
readonly onCreate?: (u: uPlot, container: HTMLDivElement) => void; | ||
/** Apply scale reset on redraw triggered by updated plot data (default: `true`) */ | ||
readonly resetScales?: boolean; | ||
readonly style?: JSX.CSSProperties | string; | ||
}; | ||
|
||
const DEFAULT_PROPS = { | ||
data: [] as uPlot.AlignedData, | ||
resetScales: true, | ||
}; | ||
|
||
const UplotSolid = (props: ParentProps<Props>) => { | ||
let chartContainerRef!: HTMLDivElement; | ||
|
||
const mergedProps = mergeProps(DEFAULT_PROPS, props); | ||
const [_props, options] = splitProps(mergedProps, [ | ||
"class", | ||
"children", | ||
"data", | ||
"height", | ||
"width", | ||
"onCreate", | ||
"resetScales", | ||
"style", | ||
]); | ||
|
||
const size = () => ({ width: _props.width, height: _props.height }); | ||
|
||
// Untrack size to avoid re-creating the chart on size changes | ||
const uplotOptions = () => ({ ...options, ...untrack(size) }); | ||
|
||
createEffect(() => { | ||
const chart = new uPlot( | ||
uplotOptions(), | ||
// Untrack data to avoid re-creating the chart on data changes | ||
untrack(() => _props.data), | ||
chartContainerRef, | ||
); | ||
|
||
_props.onCreate?.(chart, chartContainerRef); | ||
|
||
createEffect(() => { | ||
chart.setSize(size()); | ||
}); | ||
|
||
createEffect(() => { | ||
chart.setData(_props.data, _props.resetScales); | ||
}); | ||
|
||
onCleanup(() => { | ||
chart.destroy(); | ||
}); | ||
}); | ||
|
||
return ( | ||
<div id="uplot-solid" class={_props.class} ref={chartContainerRef} style={_props.style}> | ||
{_props.children} | ||
</div> | ||
); | ||
}; | ||
|
||
export default UplotSolid; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
// Main library export site | ||
// Use playground app (via Vite) to test and document the library | ||
export { default } from "./UplotSolid"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters