Giter VIP home page Giter VIP logo

fresh_charts's Introduction

fresh_charts

A charting library for Fresh based on Chart.js, which supports server and client side rendering.

Usage

There are several ways to render a chart.

For server side rendering there is the JSX/TSX component Chart which can be used to inline a chart on a page, and the renderChart() function which can be used to respond in a handler with an SVG image.

For client side rendering there is also a JSX/TSX island component Chart.

[SSR] Inline chart example

This provides a chart rendered within the router page itself.

import { Head } from "$fresh/runtime.ts";
import { Chart } from "$fresh_charts/mod.ts";
import { ChartColors, transparentize } from "$fresh_charts/utils.ts";

export default function Home() {
  return (
    <>
      <Head>
        <title>Example Chart</title>
      </Head>
      <div class="p-4 mx-auto max-w-screen-md">
        <Chart
          type="line"
          options={{
            devicePixelRatio: 1,
            scales: { y: { beginAtZero: true } },
          }}
          data={{
            labels: ["1", "2", "3"],
            datasets: [
              {
                label: "Sessions",
                data: [123, 234, 234],
                borderColor: ChartColors.Red,
                backgroundColor: transparentize(ChartColors.Red, 0.5),
                borderWidth: 1,
              },
              {
                label: "Users",
                data: [346, 233, 123],
                borderColor: ChartColors.Blue,
                backgroundColor: transparentize(ChartColors.Blue, 0.5),
                borderWidth: 1,
              },
            ],
          }}
        />
      </div>
    </>
  );
}

[SSR] Responding as an image

This route will provide the landing page of the site, which has an image link to a route, which will send a request to /routes/chart.ts to render the chart.

/routes/index.tsx

import { Head } from "$fresh/runtime.ts";
import { Chart } from "$fresh_charts/mod.ts";
import { ChartColors, transparentize } from "$fresh_charts/utils.ts";

export default function Home() {
  return (
    <>
      <Head>
        <title>Example Chart</title>
      </Head>
      <div class="p-4 mx-auto max-w-screen-md">
        <img
          src="/chart"
          class="mx-auto my-4 h-96"
          alt="an example chart provided as an image"
        />
      </div>
    </>
  );
}

/routes/chart.ts

import { type Handlers } from "$fresh/server.ts";
import { renderChart } from "$fresh_charts/mod.ts";
import { ChartColors, transparentize } from "$fresh_charts/utils.ts";

export const handler: Handlers = {
  GET() {
    return renderChart({
      type: "line",
      data: {
        labels: ["1", "2", "3"],
        datasets: [
          {
            label: "Sessions",
            data: [123, 234, 234],
            borderColor: ChartColors.Red,
            backgroundColor: transparentize(ChartColors.Red, 0.5),
            borderWidth: 1,
          },
          {
            label: "Users",
            data: [346, 233, 123],
            borderColor: ChartColors.Blue,
            backgroundColor: transparentize(ChartColors.Blue, 0.5),
            borderWidth: 1,
          },
        ],
      },
      options: {
        devicePixelRatio: 1,
        scales: { y: { beginAtZero: true } },
      },
    });
  },
};

[CSR] Inline chart example

This provides a client side rendered and interactive chart island within the router page itself.

/islands/chart.tsx

import { Chart } from "$fresh_charts/island.tsx";
export default Chart;

/routes/index.tsx

import { Head } from "$fresh/runtime.ts";
import { ChartColors } from "$fresh_charts/utils.ts";
import Chart from "../islands/chart.tsx";

export default function Home() {
  return (
    <>
      <Head>
        <title>Example Chart</title>
      </Head>
      <div class="p-4 mx-auto max-w-screen-md">
        <Chart
          type="line"
          options={{
            scales: { y: { beginAtZero: true } },
          }}
          data={{
            labels: ["1", "2", "3"],
            datasets: [
              {
                label: "Sessions",
                data: [123, 234, 234],
                borderColor: ChartColors.Red,
                borderWidth: 1,
              },
              {
                label: "Users",
                data: [346, 233, 123],
                borderColor: ChartColors.Blue,
                borderWidth: 1,
              },
            ],
          }}
        />
      </div>
    </>
  );
}

Copyright 2018-2023 the Deno authors. All rights reserved. MIT Licensed.

fresh_charts's People

Contributors

iuioiua avatar kitsonk avatar kt3k avatar mbhrznr avatar ooker777 avatar timharek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fresh_charts's Issues

It doesn't draw multiple plots correct

I created several bar plots however it does not draw all of them it will draw the first ones until, it then draws everything besides the bar. So all the labels and axes are drawn. It usually happens when the previous graph had more elements on the x axis however sometimes it can also draw that, if the y values are the same.

Is there any way to use signals in a Chart island?

I'd like to redraw my chart when the data changes, but I'm afraid I can't figure out how to do it. The aim is something like this that works:

import { signal } from "@preact/signals";

const data = signal({ labels: ["a", "b"], datasets: [{ data: [1, 2] }] }); 

...
<ChartIsland type="bar" data={data} />

From my rough understanding of the fresh charts code, I think it would mean a change to the library to thread a Signal into useChart in island.tsx, then unwrap it in the call to the ChartJS constructor. I couldn't get that working locally though.

Any advice much appreciated.

Using Timeseries Scales from chart js

This method is not implemented: Check that a complete date adapter is provided.

scales: {
x: {
type: 'time',
time: {
unit: 'second'
}
},
y: {beginAtZero: true}
},

how to add adapter, or can one be provided by default

What is `import { Chart as default } from "$fresh_charts/island.tsx"`?

This syntax is strange to me, I've never seen it. Even import - JavaScript | MDN doesn't mention it. The closest is import { default as alias }.

Using import { Chart as default } from "$fresh_charts/island.tsx"; I get:

TypeError: The module's source code could not be parsed: Expected ident at file:///D:/Programming/web/test/fresh%20init/islands/chart.tsx:1:19

  import { Chart as default } from "$fresh_charts/island.tsx";
                    ~~~~~~~
  const manifest = (await import(toFileUrl(join(dir, "fresh.gen.ts")).href))
                    ^
    at async dev (https://deno.land/x/[email protected]/src/dev/dev_command.ts:38:21)
    at async file:///D:/Programming/web/test/fresh%20init/dev.ts:8:1

This works however:

import { Chart } from "$fresh_charts/island.tsx";
export default Chart

Unclear Plugins support

Hi together,

so far I tried to get two different ChartJS plugins to work with deno fresh_charts, with mixed results:

This is my deno imports stetup:

 "$fresh_charts/" : "https://deno.land/x/[email protected]/"

Zoom - First attempt

import { ChartJs } from "$fresh_charts/deps.ts";
import plugin from "npm:[email protected]";

export default function (props: MenuProps) {
  if (IS_BROWSER) { 
    ChartJs.Chart.register(plugin);
  }
}

Crashes on start:

error: Uncaught (in promise) ReferenceError: document is not defined
    at Object.<anonymous> (file:///I:/Workspace/deno/monstat/node_modules/.deno/[email protected]/node_modules/hammerjs/hammer.js:2643:12)
    at Object.<anonymous> (file:///I:/Workspace/deno/monstat/node_modules/.deno/[email protected]/node_modules/hammerjs/hammer.js:2645:4) 
    at Module._compile (node:module:732:34)
    at Object.Module._extensions..js (node:module:746:10)
    at Module.load (node:module:657:32)
    at Function.Module._load (node:module:538:12)
    at Module.require (node:module:676:19)
    at require (node:module:790:16)
    at file:///I:/Workspace/deno/monstat/node_modules/.deno/[email protected]/node_modules/chartjs-plugin-zoom/dist/chartjs-plugin-zoom.js:8:110
    at Object.<anonymous> (file:///I:/Workspace/deno/monstat/node_modules/.deno/[email protected]/node_modules/chartjs-plugin-zoom/dist/chartjs-plugin-zoom.js:11:3)

The error makes sense that on server-side it should not work.
Are there something like client-only imports for deno?

Zoom - Second attempt (working)

import { ChartJs } from "$fresh_charts/deps.ts";
import plugin from "npm:[email protected]";

export default function (props: MenuProps) {
  if (IS_BROWSER) { 
    import("npm:[email protected]").then((plugin) => {
      ChartJs.Chart.register(plugin.default);
    });
  }
}

Feels and seems ugly, since the import is only done on client runtime.
Also the editor will show the following error:

Argument of type 'typeof import("file:///I:/Workspace/deno/monstat/node_modules/.deno/[email protected]/node_modules/chartjs-plugin-zoom/types/index")' is not assignable to parameter of type 'ChartComponentLike'.

However, it somehow works on client-side and zooming&panning is finally possible in the charts

... so I tried to do the same thing with the sankey plugin:

Sankey - First attempt

import { ChartJs } from "$fresh_charts/deps.ts";
import {SankeyController, Flow} from "npm:[email protected]";

export default function (props: MenuProps) {
  if (IS_BROWSER) { 
   ChartJs.Chart.register(SankeyController, Flow);
  }
}

No error in the editor, but crashes on the start:

The requested module 'npm:[email protected]' does not provide an export named 'Flow' at file:///I:/Workspace/deno/monstat/islands/Menu.tsx:13:27

Sankey - Second attempt

import { ChartJs } from "$fresh_charts/deps.ts";
import sankey from "npm:[email protected]";

export default function (props: MenuProps) {
  if (IS_BROWSER) { 
    ChartJs.Chart.register(sankey.SankeyController, sankey.Flow);
  }
}

No error in the editor, but crashes on the start:

islands/Menu.tsx:14:7: ERROR: No matching export in "C:/Users/Roland/AppData/Local/deno/deno_esbuild/[email protected][email protected]/node_modules/chartjs-chart-sankey/dist/chartjs-chart-sankey.esm.js" for import "default"

Sankey - Third attempt

import { ChartJs } from "$fresh_charts/deps.ts";

export default function (props: MenuProps) {
 if (IS_BROWSER) { 
      import("npm:[email protected]").then((plugin) => {
      ChartJs.Chart.register(plugin.SankeyController, plugin.Flow);
   });
 }
}

No problems server side, also what previously worked with the zoom-plugin.
However, in the browser it gives the following problem:

auto.js:2 Uncaught Error: "sankey" is not a registered controller.

So somehow it seems registering this plugin did not really work, or happens too late.

Sankey - Last attempt

To exclude possible problems with loading the plugin after the chart is created:

import { ChartJs } from "$fresh_charts/deps.ts";
import { useSignal } from "@preact/signals";

export default function (props: MenuProps) {
const loading = useSignal(true);
 if (IS_BROWSER) { 
      import("npm:[email protected]").then((plugin) => {
      ChartJs.Chart.register(plugin.SankeyController, plugin.Flow);
     console.log("imported sankey plugin", plugin);
     loading.value = false;
   });
 }

return (<>
         {!loading.value&&  <SankeyTest />}
     </>);
}

Still, same error in the browser, that sankey is not a registered chart type.

At this point im out of ideas, it just feels wrong what ive tried so far, even though ive got the zoom plugin working.
Anyone here who has an idea or knows what the problem is?
Could it be the npm repos of the plugins, or is there some deno/fresh-specific loading behavior im missing?

Thank you very much

Error in example charts on respository's README.md

It might be a bit of a silly issue, but using the Chart examples from the repository's main README gave me a small error.

The error was due to the options parameter for the charts code. The current code is scales: { yAxes: [{ ticks: { beginAtZero: true } }] } when I guess it should be (as far as I tried) scales: { yAxes: { beginAtZero: true } }.

The error made VSCode give me the following error message:

Type '{ ticks: { beginAtZero: true; }; }[]' is not assignable to type '_DeepPartialObject<{ type: "linear"; } & CartesianScaleOptions & { beginAtZero: boolean; suggestedMin?: number | undefined; suggestedMax?: number | undefined; grace?: string | number | undefined; ticks: { ...; }; }> | ... 5 more ... | undefined'.
  Type '{ ticks: { beginAtZero: true; }; }[]' is not assignable to type '_DeepPartialObject<{ type: "radialLinear"; } & CoreScaleOptions & { animate: boolean; startAngle: number; angleLines: { display: boolean; color: Scriptable<Color, ScriptableScaleContext>; lineWidth: Scriptable<...>; borderDash: Scriptable<...>; borderDashOffset: Scriptable<...>; }; ... 7 more ...; ticks: RadialTickO...'.
    Types of property 'reverse' are incompatible.
      Type '() => { ticks: { beginAtZero: true; }; }[]' is not assignable to type 'boolean | undefined'.deno-ts(2322)

And the charts were created, but the yAxis did not start at 0.

I checked and in the examples folder this does not happen, so I don't really know if this should be checked or not.
So it's just the examples on the README and it might not be much of a problem, but just wanted to notify this!

Support client-side rendering

When I ran this on the browser side (in islands), an error Cannot find name 'Deno' occurred and I could not draw.
Is it possible to make this library support client side rendering?

preact-chartjs-2, a library for using Chart.js with Preact, is archived, so it would be nice to be able to do client-side rendering with this library as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.