Skip to content

Commit 1ea3168

Browse files
committed
feat: initial implementation of solid-highcharts
1 parent d25bc09 commit 1ea3168

File tree

15 files changed

+2075
-79
lines changed

15 files changed

+2075
-79
lines changed

README.md

Lines changed: 364 additions & 57 deletions
Large diffs are not rendered by default.

bun.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jsr.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "template-solidjs-library",
2+
"name": "@dschz/solid-highcharts",
33
"version": "0.0.0",
44
"license": "MIT",
55
"exports": "./src/index.tsx",

package.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
{
2-
"name": "template-solidjs-library",
2+
"name": "@dschz/solid-highcharts",
33
"version": "0.0.0",
4-
"description": "Template for SolidJS library using tsup for bundling. Configured with Bun, NVM, TypeScript, ESLint, Prettier, Vitest, and GHA",
4+
"description": "SolidJS wrapper for Highcharts",
55
"type": "module",
66
"author": "Daniel Sanchez <dsanc89@icloud.com>",
77
"license": "MIT",
8-
"homepage": "https://github.com/thedanchez/template-solidjs-library#readme",
8+
"homepage": "https://github.com/dsnchz/solid-highcharts#readme",
99
"repository": {
1010
"type": "git",
11-
"url": "https://github.com/thedanchez/template-solidjs-library.git"
11+
"url": "https://github.com/dsnchz/solid-highcharts.git"
1212
},
1313
"bugs": {
14-
"url": "https://github.com/thedanchez/template-solidjs-library/issues"
14+
"url": "https://github.com/dsnchz/solid-highcharts/issues"
1515
},
1616
"publishConfig": {
1717
"access": "public"
@@ -63,6 +63,7 @@
6363
"eslint-plugin-simple-import-sort": "^12.1.1",
6464
"eslint-plugin-solid": "^0.14.5",
6565
"globals": "^16.1.0",
66+
"highcharts": "^12.2.0",
6667
"jiti": "^2.4.2",
6768
"jsdom": "^26.1.0",
6869
"prettier": "^3.5.3",
@@ -77,6 +78,7 @@
7778
"vitest": "^3.1.3"
7879
},
7980
"peerDependencies": {
81+
"highcharts": ">=11.0.0",
8082
"solid-js": ">=1.6.0"
8183
}
8284
}

playground/App.tsx

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ import { Route, Router } from "@solidjs/router";
22
import { ErrorBoundary, For, type JSX, type ParentProps } from "solid-js";
33

44
import { Navbar } from "./Navbar";
5+
import { BasicChart } from "./pages/BasicChart";
56
import { ErrorPage } from "./pages/Error";
7+
import { GanttChartPage } from "./pages/GanttChart";
68
import { Home } from "./pages/Home";
9+
import { MapChartPage } from "./pages/MapChart";
710
import { NotFound } from "./pages/NotFound";
11+
import { StockChartPage } from "./pages/StockChart";
812

913
type Page = {
1014
readonly path: string;
@@ -16,23 +20,37 @@ const PAGES: readonly Page[] = [
1620
path: "/",
1721
component: Home,
1822
},
23+
{
24+
path: "/basic-charts",
25+
component: BasicChart,
26+
},
27+
{
28+
path: "/stock-charts",
29+
component: StockChartPage,
30+
},
31+
{
32+
path: "/map-charts",
33+
component: MapChartPage,
34+
},
35+
{
36+
path: "/gantt-charts",
37+
component: GanttChartPage,
38+
},
1939
{
2040
path: "*",
2141
component: NotFound,
2242
},
2343
];
2444

2545
const MainContent = (props: ParentProps) => {
26-
return (
27-
<main class="flex flex-col h-full w-full grow overflow-auto bg-app-background">
28-
{props.children}
29-
</main>
30-
);
46+
return <main class="flex-1 overflow-auto bg-gray-50">{props.children}</main>;
3147
};
3248

3349
const RootLayout = (props: ParentProps) => (
34-
<div id="root-screen" class="h-screen w-screen">
35-
<Navbar />
50+
<div id="root-screen" class="h-screen w-screen flex">
51+
<div class="w-80 h-full overflow-auto">
52+
<Navbar />
53+
</div>
3654
<MainContent>{props.children}</MainContent>
3755
</div>
3856
);

playground/Navbar.tsx

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,54 @@
1-
import { A } from "@solidjs/router";
1+
import { A, useLocation } from "@solidjs/router";
22

33
export const Navbar = () => {
4+
const location = useLocation();
5+
6+
const isActive = (path: string) => {
7+
if (path === "/") {
8+
return location.pathname === "/";
9+
}
10+
return location.pathname === path;
11+
};
12+
13+
const getLinkClass = (path: string) => {
14+
const baseClass = "block px-3 py-2 rounded-md hover:bg-gray-700 transition-colors";
15+
if (isActive(path)) {
16+
return `${baseClass} bg-gray-700 text-white`;
17+
}
18+
return `${baseClass} text-gray-300 hover:text-white`;
19+
};
20+
421
return (
5-
<nav class="bg-gray-800 text-white p-2 flex items-center">
6-
<div class="text-lg font-semibold mr-6">Playground</div>
7-
<div>
8-
<A href="/" class="hover:text-gray-300">
9-
Home
22+
<nav class="bg-gray-800 text-white h-full flex flex-col">
23+
<div class="px-4 py-3 border-b border-gray-700">
24+
<div class="text-xl font-bold">Solid Highcharts Playground</div>
25+
<div class="text-sm text-gray-300">Interactive examples of all chart types</div>
26+
</div>
27+
28+
<div class="p-4 space-y-2 flex-1">
29+
<A href="/" class={getLinkClass("/")}>
30+
🏠 Home
31+
</A>
32+
33+
<A href="/basic-charts" class={getLinkClass("/basic-charts")}>
34+
📊 Basic Charts
1035
</A>
36+
37+
<A href="/stock-charts" class={getLinkClass("/stock-charts")}>
38+
📈 Stock Charts
39+
</A>
40+
41+
<A href="/map-charts" class={getLinkClass("/map-charts")}>
42+
🗺️ Map Charts
43+
</A>
44+
45+
<A href="/gantt-charts" class={getLinkClass("/gantt-charts")}>
46+
📅 Gantt Charts
47+
</A>
48+
</div>
49+
50+
<div class="p-4 border-t border-gray-700 mt-auto">
51+
<div class="text-xs text-gray-400">Built with SolidJS + Highcharts</div>
1152
</div>
1253
</nav>
1354
);

playground/pages/BasicChart.tsx

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
import Highcharts from "highcharts/esm/highcharts";
2+
import { createSignal, For } from "solid-js";
3+
4+
import { createChart } from "../../src/index";
5+
6+
const Chart = createChart(Highcharts);
7+
8+
type ChartType = "line" | "column" | "area" | "pie";
9+
10+
export const BasicChart = () => {
11+
const [chartType, setChartType] = createSignal<ChartType>("line");
12+
const [data, setData] = createSignal([
13+
{ name: "Jan", y: 29.9 },
14+
{ name: "Feb", y: 71.5 },
15+
{ name: "Mar", y: 106.4 },
16+
{ name: "Apr", y: 129.2 },
17+
{ name: "May", y: 144.0 },
18+
{ name: "Jun", y: 176.0 },
19+
]);
20+
21+
const [isAnimating, setIsAnimating] = createSignal(false);
22+
23+
const animateData = () => {
24+
if (isAnimating()) return;
25+
26+
setIsAnimating(true);
27+
const interval = setInterval(() => {
28+
setData((prev) =>
29+
prev.map((item) => ({
30+
...item,
31+
y: Math.round(Math.random() * 200),
32+
})),
33+
);
34+
}, 500);
35+
36+
setTimeout(() => {
37+
clearInterval(interval);
38+
setIsAnimating(false);
39+
}, 3000);
40+
};
41+
42+
const chartTypes: ChartType[] = ["line", "column", "area", "pie"];
43+
44+
// Create properly typed series objects for each chart type
45+
const getSeriesConfig = (): Highcharts.SeriesOptionsType[] => {
46+
const currentData = data();
47+
48+
switch (chartType()) {
49+
case "line":
50+
return [
51+
{
52+
type: "line",
53+
name: "Sample Data",
54+
data: currentData,
55+
},
56+
];
57+
58+
case "column":
59+
return [
60+
{
61+
type: "column",
62+
name: "Sample Data",
63+
data: currentData,
64+
},
65+
];
66+
67+
case "area":
68+
return [
69+
{
70+
type: "area",
71+
name: "Sample Data",
72+
data: currentData,
73+
},
74+
];
75+
76+
case "pie":
77+
return [
78+
{
79+
type: "pie",
80+
name: "Sample Data",
81+
data: currentData.map((item) => ({ name: item.name, y: item.y })),
82+
},
83+
];
84+
85+
default:
86+
return [
87+
{
88+
type: "line",
89+
name: "Sample Data",
90+
data: currentData,
91+
},
92+
];
93+
}
94+
};
95+
96+
return (
97+
<div class="p-6 space-y-6">
98+
<div class="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4">
99+
<h1 class="text-3xl font-bold text-gray-900">Basic Charts</h1>
100+
<div class="flex gap-2">
101+
<button
102+
onClick={animateData}
103+
disabled={isAnimating()}
104+
class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
105+
>
106+
{isAnimating() ? "Animating..." : "Animate Data"}
107+
</button>
108+
</div>
109+
</div>
110+
111+
{/* Chart Type Selector */}
112+
<div class="bg-white p-4 rounded-lg shadow">
113+
<label class="block text-sm font-medium text-gray-700 mb-2">Chart Type:</label>
114+
<div class="flex gap-2 flex-wrap">
115+
<For each={chartTypes}>
116+
{(type) => (
117+
<button
118+
onClick={() => setChartType(type)}
119+
class={`px-3 py-2 rounded ${
120+
chartType() === type
121+
? "bg-blue-600 text-white"
122+
: "bg-gray-200 text-gray-700 hover:bg-gray-300"
123+
}`}
124+
>
125+
{type.charAt(0).toUpperCase() + type.slice(1)}
126+
</button>
127+
)}
128+
</For>
129+
</div>
130+
</div>
131+
132+
{/* Chart Container */}
133+
<div class="bg-white p-6 rounded-lg shadow">
134+
<Chart
135+
accessibility={{
136+
enabled: true,
137+
}}
138+
exporting={{
139+
enabled: true,
140+
}}
141+
chart={{ type: chartType() }}
142+
title={{
143+
text: `${chartType().charAt(0).toUpperCase() + chartType().slice(1)} Chart Example`,
144+
}}
145+
xAxis={chartType() === "pie" ? undefined : { type: "category" }}
146+
yAxis={
147+
chartType() === "pie"
148+
? undefined
149+
: {
150+
title: { text: "Values" },
151+
min: 0,
152+
}
153+
}
154+
series={getSeriesConfig()}
155+
plotOptions={{
156+
pie: {
157+
allowPointSelect: true,
158+
cursor: "pointer",
159+
dataLabels: {
160+
enabled: true,
161+
format: "<b>{point.name}</b>: {point.percentage:.1f} %",
162+
},
163+
},
164+
}}
165+
tooltip={
166+
chartType() === "pie"
167+
? {
168+
pointFormat: "{series.name}: <b>{point.percentage:.1f}%</b>",
169+
}
170+
: {
171+
valueSuffix: " units",
172+
}
173+
}
174+
onCreateChart={(chart) => {
175+
console.log("Basic chart created:", chart);
176+
}}
177+
class="w-full"
178+
style={{ height: "400px" }}
179+
/>
180+
</div>
181+
182+
{/* Chart Info */}
183+
<div class="bg-gray-50 p-4 rounded-lg">
184+
<h3 class="text-lg font-semibold mb-2">Chart Information</h3>
185+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
186+
<div>
187+
<strong>Type:</strong> {chartType()}
188+
</div>
189+
<div>
190+
<strong>Data Points:</strong> {data().length}
191+
</div>
192+
<div>
193+
<strong>Animation:</strong> {isAnimating() ? "Active" : "Inactive"}
194+
</div>
195+
<div>
196+
<strong>Library:</strong> Highcharts Core
197+
</div>
198+
</div>
199+
</div>
200+
</div>
201+
);
202+
};

0 commit comments

Comments
 (0)